Forum Discussion
Stefan_Engel
Cirrus
Jun 01, 2021Extract 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...
StephanManthey
Nacreous
Jul 08, 2021Exporting key material is not supported as far as I know. Using the CLI is the only option I am aware of.
Only a CSR can be exported.
Creating a CSR:
- 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: "{{ hostvars[inventory_hostname].certificates.server[0].subject_alternative_names | selectattr('name', 'defined') | list }}"
when: hostvars[inventory_hostname].certificates.server[0].subject_alternative_names is defined
- name: add signing request name and properties to data structure
set_fact:
csr_data: "{{ {
'csr_consumer': 'ltm',
'csr_prefix': 'cert',
'csr_suffix': device_info[inventory_hostname].ansible_host_time,
'csr_name': hostvars[inventory_hostname].certificates.server[0].name,
'csr_cn': hostvars[inventory_hostname].certificates.server[0].subject.common_name,
'csr_san': san_list | default(['DNS:%s' | format(hostvars[inventory_hostname].certificates.server[0].name)]) | join(','),
'csr_country': hostvars[inventory_hostname].certificates.server[0].subject.location_country | default('US'),
'csr_state': hostvars[inventory_hostname].certificates.server[0].subject.location_state | default(''),
'csr_city': hostvars[inventory_hostname].certificates.server[0].subject.location_city | default(''),
'csr_organization': hostvars[inventory_hostname].certificates.server[0].subject.organization_name | default(''),
} }}"
- name: create certificate signing request on load balancer
uri:
validate_certs: no
url: https://{{ inventory_hostname }}/mgmt/tm/sys/crypto/csr
method: POST
headers:
X-F5-Auth-Token: "{{ device_info[inventory_hostname].token }}"
body_format: json
body:
'name': "{{ csr_data.csr_prefix + '_' + csr_data.csr_name + '_' + csr_data.csr_suffix }}"
'key': "{{ csr_data.csr_prefix + '_' + csr_data.csr_name + '_' + csr_data.csr_suffix }}"
'common-name': "{{ csr_data.csr_cn }}"
'subject-alternative-name': "{{ csr_data.csr_san }}"
'country': "{{ csr_data.csr_country }}"
'state': "{{ csr_data.csr_state }}"
'city': "{{ csr_data.csr_city }}"
'organization': "{{ csr_data.csr_organization }}"
'consumer': "{{ csr_data.csr_consumer }}"
register: result
until: result.status == 200
retries: 40
delay: 5
when: csr_data is definedExporting a CSR:
- name: add certificate signing request name to data structure
set_fact:
csr_data: "{{ {
'csr_prefix': 'cert',
'csr_suffix': device_info[inventory_hostname].ansible_host_time,
'csr_name': hostvars[inventory_hostname].certificates.server[0].name,
'csr_file_extension': 'csr'
} }}"
- name: debug data
debug:
msg: "{{ csr_data }}"
- name: export certificate signing request
uri:
validate_certs: no
url: https://{{ inventory_hostname }}/mgmt/tm/util/bash
method: POST
headers:
X-F5-Auth-Token: "{{ device_info[inventory_hostname].token }}"
body_format: json
body:
command: run
utilCmdArgs: "-c 'tmsh list sys crypto csr {{ csr_data.csr_prefix + '_' + csr_data.csr_name + '_' + csr_data.csr_suffix }} | sed -re \'/-----/,/-----/!d\''"
register: csr_result
- name: debug data
debug:
msg: "{{ csr_result.json.commandResult }}"
- name: save certificate signing request to local file and replace encoded new line characters
copy:
content: "{{ csr_result.json.commandResult | regex_replace('\\n', '\n') }}"
dest: "{{ '~/ssl/server/csr/%s.%s' | format(csr_data.csr_prefix + '_' + csr_data.csr_name + '_' + csr_data.csr_suffix, csr_data.csr_file_extension) }}"
force: yesUploading all key material:
- name: register cert file properties
stat:
path: "{{ crt_file_path }}"
register: crt_properties
when: crt_file_path is defined
- name: set certificate file size information
set_fact:
crt_file_size: "{{ crt_properties.stat.size }}"
when: crt_properties is defined
- name: register key file properties
stat:
path: "{{ key_file_path }}"
register: key_properties
when: key_file_path is defined
- name: set key file size information
set_fact:
key_file_size: "{{ key_properties.stat.size }}"
when: key_properties is defined
- name: register chain file properties
stat:
path: "{{ chain_file_path }}"
register: chain_properties
when: chain_file_path is defined
- name: set chain file size information
set_fact:
chain_file_size: "{{ chain_properties.stat.size }}"
when: chain_properties is defined
- name: copy certificate to temp directory
uri:
validate_certs: no
url: https://{{ inventory_hostname }}/mgmt/shared/file-transfer/uploads/{{ crt_file_name }}
method: POST
headers:
Content-Range: "0-{{ crt_file_size | int - 2 }}/{{ crt_file_size }}"
Content-Type: "application/octet-stream"
X-F5-Auth-Token: "{{ device_info[inventory_hostname].token }}"
body: "{{ lookup('file', crt_file_path) }}"
- name: copy key to temp directory
uri:
validate_certs: no
url: https://{{ inventory_hostname }}/mgmt/shared/file-transfer/uploads/{{ key_file_name }}
method: POST
headers:
Content-Range: "0-{{ key_file_size | int - 2 }}/{{ key_file_size }}"
Content-Type: "application/octet-stream"
X-F5-Auth-Token: "{{ device_info[inventory_hostname].token }}"
body: "{{ lookup('file', key_file_path) }}"
- name: copy chain to temp directory
uri:
validate_certs: no
url: https://{{ inventory_hostname }}/mgmt/shared/file-transfer/uploads/{{ chain_file_name }}
method: POST
headers:
Content-Range: "0-{{ chain_file_size | int - 2 }}/{{ chain_file_size }}"
Content-Type: "application/octet-stream"
X-F5-Auth-Token: "{{ device_info[inventory_hostname].token }}"
body: "{{ lookup('file', chain_file_path) }}"
- name: copy certificate to TMOS filestore (TMOS v14+)
uri:
validate_certs: no
url: https://{{ inventory_hostname }}/mgmt/tm/sys/crypto/cert
method: POST
headers:
X-F5-Auth-Token: "{{ device_info[inventory_hostname].token }}"
body_format: json
body:
command: install
name: "{{ '%s_%s_%s' | format(crt_prefix,crt_name,crt_suffix) }}"
from-local-file: "/var/config/rest/downloads/tmp/{{ '%s_%s_%s.%s' | format(crt_prefix,crt_name,crt_suffix,crt_file_extension) }}"
- name: copy key to TMOS filestore (TMOS v14+)
uri:
validate_certs: no
url: https://{{ inventory_hostname }}/mgmt/tm/sys/crypto/key
method: POST
headers:
X-F5-Auth-Token: "{{ device_info[inventory_hostname].token }}"
body_format: json
body:
command: install
name: "{{ '%s_%s_%s' | format(crt_prefix,crt_name,crt_suffix) }}"
from-local-file: "/var/config/rest/downloads/tmp/{{ '%s_%s_%s.%s' | format(crt_prefix,crt_name,crt_suffix,key_file_extension) }}"
- name: copy chain to TMOS filestore (TMOS v14+)
uri:
validate_certs: no
url: https://{{ inventory_hostname }}/mgmt/tm/sys/crypto/cert
method: POST
headers:
X-F5-Auth-Token: "{{ device_info[inventory_hostname].token }}"
body_format: json
body:
command: install
name: "{{ '%s_%s_%s' | format(chain_prefix,crt_name,crt_suffix) }}"
from-local-file: "/var/config/rest/downloads/tmp/{{ '%s_%s_%s.%s' | format(chain_prefix,crt_name,crt_suffix,crt_file_extension) }}"
- name: specifiy name of profile (TMOS v14+ does not use the file extension)
set_fact:
profile: "{{ '%s_%s_%s' | format(profile_prefix,crt_name,profile_suffix) }}"
- name: lookup current cert, key and chain assignments in client-ssl profile
uri:
validate_certs: no
url: https://{{ inventory_hostname }}/mgmt/tm/ltm/profile/client-ssl/{{ profile }}?$select=cert,key,chain
method: GET
headers:
X-F5-Auth-Token: "{{ device_info[inventory_hostname].token }}"
register: lookup_result
- name: modify existing client-ssl persistence
uri:
validate_certs: no
url: https://{{ inventory_hostname }}/mgmt/tm/ltm/profile/client-ssl/{{ profile }}
method: PATCH
headers:
X-F5-Auth-Token: "{{ device_info[inventory_hostname].token }}"
body_format: json
body:
cert: "{{ '%s_%s_%s' | format(crt_prefix,crt_name,crt_suffix) }}"
key: "{{ '%s_%s_%s' | format(crt_prefix,crt_name,crt_suffix) }}"
chain: "{{ '%s_%s_%s' | format(chain_prefix,crt_name,crt_suffix) }}"
If you are exporting the key material anyway, why not creating the key pair and CSR outside the F5? (see next reply, please)
Help guide the future of your DevCentral Community!
What tools do you use to collaborate? (1min - anonymous)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