168 lines
7.0 KiB
YAML
168 lines
7.0 KiB
YAML
---
|
|
# Copyright 2021, BBC
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
- name: Create certificate {{ cert.name }}
|
|
vars:
|
|
next_serial_no: "{{ serial_no['content'] | b64decode | int + 1 }}"
|
|
ansible_python_interpreter: "{{ pki_setup_host_python_interpreter }}"
|
|
delegate_to: "{{ pki_setup_host }}"
|
|
block:
|
|
|
|
- name: Create directories for certificate authority {{ ca.name }}
|
|
file:
|
|
state: directory
|
|
path: "{{ item.path }}"
|
|
owner: "{{ item.owner | default(pki_owner) | default(omit) }}"
|
|
group: "{{ item.group | default(pki_group) | default(omit) }}"
|
|
mode: "{{ item.mode | default('0755') }}"
|
|
with_items:
|
|
- path: "{{ ca_dir }}"
|
|
- path: "{{ ca_dir ~ '/csr' }}"
|
|
mode: "{{ pki_key_dir_mode }}"
|
|
- path: "{{ ca_dir ~ '/private' }}"
|
|
mode: "{{ pki_key_dir_mode }}"
|
|
- path: "{{ ca_dir ~ '/certs' }}"
|
|
mode: "{{ pki_cert_dir_mode }}"
|
|
|
|
# NOTE(noonedeadpunk): Incorrect permissions lead to CA certs re-generation as
|
|
# openssl_privatekey gets changed when harmonizing ownership/permissions
|
|
- name: Ensure private key has proper ownership
|
|
file:
|
|
state: file
|
|
path: "{{ ca_dir ~ '/private/' ~ ca.name ~ '.key.pem' }}"
|
|
mode: "{{ ca.key_mode | default(pki_key_mode) }}"
|
|
owner: "{{ ca.key_owner | default(pki_owner) | default(omit) }}"
|
|
group: "{{ ca.key_group | default(pki_group) | default(omit) }}"
|
|
failed_when: false
|
|
|
|
- name: Initialise the serial number for {{ ca.name }}
|
|
copy:
|
|
content: "999"
|
|
dest : "{{ ca_dir ~ '/serial' }}"
|
|
force: no
|
|
|
|
- name: Generate CA private key for {{ ca.name }}
|
|
community.crypto.openssl_privatekey:
|
|
path: "{{ ca_dir ~ '/private/' ~ ca.name ~ '.key.pem' }}"
|
|
passphrase: "{{ ca.key_passphrase | default(omit) }}"
|
|
cipher: "{{ ('key_passphrase' in ca and ca.key_passphrase) | ternary('auto', omit) }}"
|
|
backup: "{{ ca.backup | default(True) }}"
|
|
mode: "{{ ca.key_mode | default(pki_key_mode) }}"
|
|
owner: "{{ ca.key_owner | default(pki_owner) | default(omit) }}"
|
|
group: "{{ ca.key_group | default(pki_group) | default(omit) }}"
|
|
register: ca_privkey
|
|
|
|
- name: Read the serial number for {{ ca.name }}
|
|
slurp:
|
|
src: "{{ pki_dir ~ '/roots/' ~ ca.name ~ '/serial' }}"
|
|
register: serial_no
|
|
|
|
- name: Create the CA CSR for {{ ca.name }}
|
|
community.crypto.openssl_csr:
|
|
path: "{{ ca_dir }}/csr/ca_csr-{{ next_serial_no }}.csr"
|
|
privatekey_path: "{{ ca_privkey.filename }}"
|
|
privatekey_passphrase: "{{ ca.key_passphrase | default(omit) }}"
|
|
common_name: "{{ ca.cn }}"
|
|
basic_constraints_critical: yes
|
|
basic_constraints: "{{ ca.basic_constraints }}"
|
|
key_usage: "{{ ca.key_usage }}"
|
|
country_name: "{{ ca.country_name | default(omit) }}"
|
|
state_or_province_name: "{{ ca.state_or_province_name | default(omit) }}"
|
|
locality_name: "{{ ca.locality_name | default(omit) }}"
|
|
organization_name: "{{ ca.organizataion_name | default(omit) }}"
|
|
organizational_unit_name: "{{ ca.organization_unit_name | default(omit) }}"
|
|
subject: "{{ cert.subject | default(omit) }}"
|
|
backup: "{{ ca.backup | default(True) }}"
|
|
register: ca_csr
|
|
when:
|
|
- ca_privkey is changed or pki_regen_ca == ca.name or (pki_regen_ca | lower) == 'true'
|
|
|
|
- name: Write out the new serial number for {{ ca.name }}
|
|
copy:
|
|
content: "{{ next_serial_no }}"
|
|
dest: "{{ ca_dir }}/serial"
|
|
when: ca_csr is changed
|
|
|
|
- name: Sign the selfsigned Root CA CSR for {{ ca.name }}
|
|
community.crypto.x509_certificate:
|
|
path: "{{ ca_cert_prefix ~ '-' ~ next_serial_no ~ '.crt' }}"
|
|
csr_path: "{{ ca_csr.filename }}"
|
|
provider: 'selfsigned'
|
|
privatekey_path: "{{ ca_privkey.filename }}"
|
|
privatekey_passphrase: "{{ ca.key_passphrase | default(omit) }}"
|
|
selfsigned_not_after: "{{ ca.not_after }}"
|
|
backup: "{{ ca.backup | default(True) }}"
|
|
register: ca_selfsigned_crt
|
|
when:
|
|
- ca.provider == 'selfsigned'
|
|
- ca_csr is changed
|
|
notify:
|
|
- "{{ pki_handler_ca_changed }}"
|
|
|
|
- name: Sign the intermediate CA CSR for {{ ca.name }}
|
|
vars:
|
|
community.crypto.x509_certificate:
|
|
path: "{{ ca_cert_prefix ~ '-' ~ next_serial_no ~ '.crt' }}"
|
|
csr_path: "{{ ca_csr.filename }}"
|
|
provider: 'ownca'
|
|
ownca_privatekey_path: "{{ pki_dir ~ '/roots/' ~ ca.signed_by ~ '/private/' ~ ca.signed_by ~ '.key.pem' }}"
|
|
ownca_privatekey_passphrase: "{{ ca.ownca_key_passphrase | default(omit) }}"
|
|
ownca_path: "{{ pki_dir ~ '/roots/' ~ ca.signed_by ~ '/certs/' ~ ca.signed_by ~ '.crt' }}"
|
|
ownca_not_after: "{{ ca.not_after }}"
|
|
backup: "{{ ca.backup | default(True) }}"
|
|
register: ca_ownca_crt
|
|
when:
|
|
- ca.provider == 'ownca'
|
|
- ca_csr is changed
|
|
notify:
|
|
- "{{ pki_handler_ca_changed }}"
|
|
|
|
- name: Symlink the certificate name to the most recently generated
|
|
file:
|
|
src: "{{ (ca_selfsigned_crt.filename | default(ca_ownca_crt.filename)) | basename }}"
|
|
dest: "{{ ca_cert_prefix ~ '.crt' }}"
|
|
state: link
|
|
when: ca_ownca_crt is changed or ca_selfsigned_crt is changed
|
|
|
|
- name: Get certificate info for {{ ca.name }}
|
|
community.crypto.x509_certificate_info:
|
|
path: "{{ ca_selfsigned_crt.filename | default(ca_ownca_crt.filename) }}"
|
|
register: ca_cert_info
|
|
when: ca_ownca_crt is changed or ca_selfsigned_crt is changed
|
|
|
|
- name: Save certificate info for {{ ca.name }}
|
|
copy:
|
|
content: "{{ ca_cert_info | to_nice_yaml }}"
|
|
dest: "{{ (ca_selfsigned_crt.filename | default(ca_ownca_crt.filename)) ~ '.info' }}"
|
|
when: ca_ownca_crt is changed or ca_selfsigned_crt is changed
|
|
|
|
- name: Check if intermediate certificate chain exists
|
|
stat:
|
|
path: "{{ ca_cert_prefix ~ '-chain.crt' }}"
|
|
register: chain_result
|
|
when:
|
|
- ca.provider == 'ownca'
|
|
|
|
- name: Create intermediate certificate chain
|
|
vars:
|
|
ownca_path: "{{ pki_dir ~ '/roots/' ~ ca.signed_by ~ '/certs/' ~ ca.signed_by ~ '.crt' }}"
|
|
cert_path: "{{ ca_cert_prefix ~ '.crt' }}"
|
|
cert_chain_path: "{{ ca_cert_prefix ~ '-chain.crt' }}"
|
|
shell:
|
|
cmd: "cat {{ cert_path }} {{ ownca_path }} > {{ cert_chain_path }}"
|
|
when:
|
|
- ca_ownca_crt is changed or not (chain_result.stat.exists | default(true))
|
|
- ca.provider == 'ownca'
|