121 lines
4.1 KiB
YAML
121 lines
4.1 KiB
YAML
---
|
|
- name: Install PKI directory for {{ pki_cert_name }}
|
|
ansible.builtin.file:
|
|
path: "{{ pki_cert_dir }}"
|
|
state: directory
|
|
mode: '0700'
|
|
owner: root
|
|
group: root
|
|
|
|
- name: Check for existing certificate
|
|
ansible.builtin.stat:
|
|
path: "{{ pki_cert_dir }}/cert.pem"
|
|
register: pki_cert_existing
|
|
|
|
- name: Inspect existing certificate expiry
|
|
community.crypto.x509_certificate_info:
|
|
path: "{{ pki_cert_dir }}/cert.pem"
|
|
valid_at:
|
|
still_valid_before_renewal_window: "{{ pki_cert_renew_before }}"
|
|
register: pki_cert_info
|
|
when: pki_cert_existing.stat.exists
|
|
|
|
- name: Determine whether certificate needs rotation
|
|
ansible.builtin.set_fact:
|
|
pki_cert_needs_rotation: "{{ pki_cert_existing.stat.exists and not pki_cert_info.valid_at.still_valid_before_renewal_window }}"
|
|
|
|
- name: Archive certificate nearing expiry
|
|
when: pki_cert_needs_rotation
|
|
block:
|
|
- name: Compute archive directory name
|
|
ansible.builtin.set_fact:
|
|
pki_cert_archive_dir: "{{ pki_cert_dir }}/{{ (pki_cert_info.not_before | to_datetime('%Y%m%d%H%M%SZ')).strftime('%Y-%m') }}"
|
|
|
|
- name: Create archive directory
|
|
ansible.builtin.file:
|
|
path: "{{ pki_cert_archive_dir }}"
|
|
state: directory
|
|
mode: '0700'
|
|
owner: root
|
|
group: root
|
|
|
|
- name: Check which certificate files exist
|
|
ansible.builtin.stat:
|
|
path: "{{ pki_cert_dir }}/{{ item }}"
|
|
register: pki_cert_files
|
|
loop:
|
|
- cert.key
|
|
- cert.pem
|
|
- full-chain.pem
|
|
loop_control:
|
|
label: "{{ item }}"
|
|
|
|
- name: Copy existing certificate files into archive
|
|
ansible.builtin.copy:
|
|
src: "{{ pki_cert_dir }}/{{ item.item }}"
|
|
dest: "{{ pki_cert_archive_dir }}/{{ item.item }}"
|
|
remote_src: true
|
|
mode: preserve
|
|
owner: root
|
|
group: root
|
|
loop: "{{ pki_cert_files.results }}"
|
|
loop_control:
|
|
label: "{{ item.item }}"
|
|
when: item.stat.exists
|
|
|
|
- name: Remove archived certificate files from live directory
|
|
ansible.builtin.file:
|
|
path: "{{ pki_cert_dir }}/{{ item.item }}"
|
|
state: absent
|
|
loop: "{{ pki_cert_files.results }}"
|
|
loop_control:
|
|
label: "{{ item.item }}"
|
|
when: item.stat.exists
|
|
|
|
# community.crypto.x509_certificate recomputes ownca_not_after/not_before
|
|
# relative to "now" on every run, which never exactly matches the fixed
|
|
# timestamps of an already-issued certificate. Left unguarded, that makes it
|
|
# silently reissue (and extend) the certificate on every playbook run,
|
|
# bypassing the archiving above. Only (re)generate when there is no
|
|
# certificate yet, or when we've actually decided it needs rotating.
|
|
- name: Issue certificate
|
|
when: not pki_cert_existing.stat.exists or pki_cert_needs_rotation
|
|
block:
|
|
- name: Create private key for {{ pki_cert_name }}
|
|
community.crypto.openssl_privatekey:
|
|
path: "{{ pki_cert_dir }}/cert.key"
|
|
|
|
- name: Create CSR for {{ pki_cert_name }}
|
|
community.crypto.openssl_csr_pipe:
|
|
privatekey_path: "{{ pki_cert_dir }}/cert.key"
|
|
subject_alt_name: "{{ pki_cert_sans }}"
|
|
register: pki_cert_csr
|
|
|
|
- name: Sign with root ca
|
|
community.crypto.x509_certificate:
|
|
path: "{{ pki_cert_dir }}/cert.pem"
|
|
csr_content: "{{ pki_cert_csr.csr }}"
|
|
provider: ownca
|
|
ownca_path: /etc/pki/konchin.com/rootca.pem
|
|
ownca_privatekey_path: /etc/pki/konchin.com/rootca.key
|
|
ownca_privatekey_passphrase: "{{ secret_ca_passphrase }}"
|
|
ownca_not_after: +365d # valid for one year
|
|
ownca_not_before: -1d # valid since yesterday
|
|
return_content: true
|
|
register: pki_cert_signed
|
|
|
|
- name: Slurp root ca
|
|
ansible.builtin.slurp:
|
|
src: /etc/pki/konchin.com/rootca.pem
|
|
register: pki_cert_rootca
|
|
|
|
- name: Create full chain cert
|
|
ansible.builtin.copy:
|
|
content: |
|
|
{{ pki_cert_signed.certificate | trim }}
|
|
{{ pki_cert_rootca['content'] | b64decode | trim }}
|
|
dest: "{{ pki_cert_dir }}/full-chain.pem"
|
|
mode: '0600'
|
|
owner: root
|
|
group: root
|