diff --git a/roles/create_rootca/tasks/main.yml b/roles/create_rootca/tasks/main.yml index bcf3b83..8a7b791 100644 --- a/roles/create_rootca/tasks/main.yml +++ b/roles/create_rootca/tasks/main.yml @@ -15,30 +15,44 @@ owner: root group: root -- name: Create private key for root ca - community.crypto.openssl_privatekey: - path: /etc/pki/konchin.com/rootca.key - cipher: auto - passphrase: "{{ secret_ca_passphrase }}" - -- name: Create CSR for root ca - community.crypto.openssl_csr_pipe: - privatekey_path: /etc/pki/konchin.com/rootca.key - privatekey_passphrase: "{{ secret_ca_passphrase }}" - common_name: Konchin.com CA - use_common_name_for_san: false - basic_constraints: - - 'CA:TRUE' - basic_constraints_critical: true - key_usage: - - keyCertSign - key_usage_critical: true - register: create_rootca_ca_csr - -- name: Create cert for root ca - community.crypto.x509_certificate: +- name: Check for existing root ca certificate + ansible.builtin.stat: path: /etc/pki/konchin.com/rootca.pem - csr_content: "{{ create_rootca_ca_csr.csr }}" - privatekey_path: /etc/pki/konchin.com/rootca.key - privatekey_passphrase: "{{ secret_ca_passphrase }}" - provider: selfsigned + register: create_rootca_existing + +# The x509_certificate/openssl_privatekey modules recompute their relative +# validity/date options on every run, which never exactly matches the fixed +# timestamps baked into an already-issued certificate. Left unguarded, that +# makes them "regenerate" the CA (and invalidate every certificate it +# signed) on every playbook run. The CA is not meant to auto-rotate, so we +# only ever create it once. +- name: Create root ca + when: not create_rootca_existing.stat.exists + block: + - name: Create private key for root ca + community.crypto.openssl_privatekey: + path: /etc/pki/konchin.com/rootca.key + cipher: auto + passphrase: "{{ secret_ca_passphrase }}" + + - name: Create CSR for root ca + community.crypto.openssl_csr_pipe: + privatekey_path: /etc/pki/konchin.com/rootca.key + privatekey_passphrase: "{{ secret_ca_passphrase }}" + common_name: Konchin.com CA + use_common_name_for_san: false + basic_constraints: + - 'CA:TRUE' + basic_constraints_critical: true + key_usage: + - keyCertSign + key_usage_critical: true + register: create_rootca_ca_csr + + - name: Create cert for root ca + community.crypto.x509_certificate: + path: /etc/pki/konchin.com/rootca.pem + csr_content: "{{ create_rootca_ca_csr.csr }}" + privatekey_path: /etc/pki/konchin.com/rootca.key + privatekey_passphrase: "{{ secret_ca_passphrase }}" + provider: selfsigned diff --git a/roles/pki_cert/tasks/main.yml b/roles/pki_cert/tasks/main.yml index 747d45b..77165c7 100644 --- a/roles/pki_cert/tasks/main.yml +++ b/roles/pki_cert/tasks/main.yml @@ -72,31 +72,38 @@ label: "{{ item.item }}" when: item.stat.exists -- 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: Create full chain +# 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