Forum Discussion
Stefan_Engel
Jun 01, 2021Cirrus
Extract content of Certificate key file with REST or Ansible
Hi Community, I'm working on an automation for renewing Certificates on multiple BIG-IP's using Ansible. As not all available Ansible F5 modules provide what is required, I'm currently using a m...
Jul 08, 2021
As mentioned before, I prefer creating the private/public key pair outside the BIG-IP and finally upload the signed certificate and chain to the BIG-IP device(s).
Here is how I create the key material and CSR (and sign it locally for testing purposes):
- hosts: localhost
gather_facts: yes
tasks:
- name: retrieve system time information (YYYYMMDD_HHMMSS)
set_fact:
ansible_clock_information: "{{ '%s%s%s_%s%s%s' | format(ansible_date_time.year, ansible_date_time.month, ansible_date_time.day, ansible_date_time.hour, ansible_date_time.minute, ansible_date_time.second) }}"
delegate_to: localhost
- name: debug ansible_clock_information
debug:
msg: "{{ ansible_clock_information }}"
- name: include variables file (required for local CA access)
no_log: true
include_vars: sample_credentials.yml
- name: include certificate variables file and suppress logging
include_vars:
file: "{{ certificate_data }}"
name: certificate_config
- name: debug variables
debug:
msg: "{{ certificate_config.server_certificate }}"
- name: create string of subject alternative names when defined in inventory
set_fact:
san_list: "{{ san_list | default([]) + ['DNS:%s' | format(item.name)] }}"
with_items: "{{ certificate_config.server_certificate.subject_alternative_names | selectattr('name', 'defined') | list }}"
when: certificate_config.server_certificate.subject_alternative_names is defined
- name: debug string of subject alternative names
debug:
msg: "{{ san_list }}"
- name: add signing request name and properties to data structure
set_fact:
csr_data: "{{ {
'csr_type': certificate_config.server_certificate.key_type,
'csr_length': certificate_config.server_certificate.key_length,
'csr_prefix': 'cert',
'csr_suffix': ansible_clock_information,
'csr_name': certificate_config.server_certificate.name,
'csr_cn': certificate_config.server_certificate.subject.common_name,
'csr_san': san_list | default(['DNS:%s' | format(certificate_config.server_certificate.name)]) | join(','),
'csr_country': certificate_config.server_certificate.subject.location_country | default('US'),
'csr_state': server_certificate.subject.location_state | default(''),
'csr_city': certificate_config.server_certificate.subject.location_city | default(''),
'csr_organization': certificate_config.server_certificate.subject.organization_name | default(''),
} }}"
- name: debug data
debug:
msg: "{{ csr_data }}"
- name: assemble key material file name
set_fact:
key_file_name: "{{ csr_data.csr_prefix + '_' + csr_data.csr_name + '_' + csr_data.csr_suffix }}"
- name: assemble certificate subject
set_fact:
certificate_subject: "{{ '/C=' + csr_data.csr_country + '/ST=' + csr_data.csr_state + '/L=' + csr_data.csr_city + '/O=' +csr_data.csr_organization + '/CN=' + csr_data.csr_cn }}"
- name: generate a new private/public key pair
command: openssl gen{{ csr_data.csr_type | lower }} -out ~/ssl/server/material/{{ key_file_name }}.key {{ csr_data.csr_length }}
- name: generate temporary config files with subject alternative names
copy:
dest: "~/ssl/server/tmp/{{ key_file_name }}.cnf"
content: |
[SAN]
subjectAltName={{ csr_data.csr_san }}
[ req ]
distinguished_name = req_distinguished_name
[ req_distinguished_name ]
- name: generate CSRs
command: openssl req -new -sha256 -reqexts SAN -key ~/ssl/server/material/{{ key_file_name }}.key -out ~/ssl/server/material/{{ key_file_name }}.csr -subj '{{ certificate_subject }}' -config ~/ssl/server/tmp/{{ key_file_name }}.cnf
- name: generate key/csr information
set_fact:
key_csr_info:
reference: "{{ csr_data.csr_name }}"
timestamp: "{{ csr_data.csr_suffix }}"
new_key: "{{ key_file_name + '.key' }}"
new_csr: "{{ key_file_name + '.csr' }}"
- name: save timestamp information to local file
copy:
content: "{{ key_csr_info | to_nice_yaml }}"
dest: "{{ '~/ssl/server/material/cert_%s.info' | format(csr_data.csr_name) }}"
force: yes
- name: print file locations
debug:
msg:
- "{{ 'new private key created: ~/ssl/server/material/' + key_file_name + '.key' }}"
- "{{ 'new signing req created: ~/ssl/server/material/' + key_file_name + '.csr' }}"
- "{{ 'new key/csr information: ~/ssl/server/material/cert_%s.info' | format(csr_data.csr_name) }}"
- name: sign certificate with local CA
command: openssl ca -notext -md sha256 -days 730 -batch -passin pass:{{ intermediate_ca_credentials.secret }} -out ~/ssl/server/material/{{ key_file_name }}.crt -config ~/ssl/intermediate/openssl.cnf -extensions server_cert -in ~/ssl/server/material/{{ key_file_name }}.csr
- name: save intermediate CA chain (src is referencing the locally saved chain of intermediate CAs)
copy:
src: "~/ssl/intermediate/crt/intermediate-ca.crt"
dest: "{{ '~/ssl/server/material/chain_' + csr_data.csr_name + '_' + csr_data.csr_suffix + '.crt' }}"
- name: print file locations
debug:
msg:
- "{{ 'new signed cert created: ~/ssl/server/material/' + key_file_name + '.csr' }}"
- "{{ 'new intermediate saved: ~/ssl/server/material/chain_' + csr_data.csr_name + '_' + csr_data.csr_suffix + '.crt' }}"
Cheers, Stephan
Recent Discussions
Related Content
DevCentral Quicklinks
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com
Discover DevCentral Connects