- name: Ensure `ansible_certs` directory exists ansible.builtin.file: path: /etc/ansible_certs state: directory owner: root group: root mode: "755" become: true - name: Ensure `certs` sub-directory exists ansible.builtin.file: path: /etc/ansible_certs/certs state: directory owner: root group: root mode: "755" become: true - name: Ensure sub-directory for the certificate exists ansible.builtin.file: path: "/etc/ansible_certs/certs/{{ item }}" state: directory owner: "{{ cert__owner }}" group: "{{ cert__group }}" mode: "755" become: true - name: Ensure private key for certificate exists community.crypto.openssl_privatekey: path: "/etc/ansible_certs/certs/{{ item }}/privkey.pem" size: 4096 type: RSA owner: "{{ cert__owner }}" group: "{{ cert__group }}" mode: "{{ cert__privkey_pem_permissions }}" become: true - name: Ensure certificate signing request is created community.crypto.openssl_csr: path: "/etc/ansible_certs/certs/{{ item }}/csr.pem" privatekey_path: "/etc/ansible_certs/certs/{{ item }}/privkey.pem" common_name: "{{ item }}" owner: "{{ cert__owner }}" group: "{{ cert__group }}" mode: "0660" become: true register: cert__csr_result - name: Ensure private key for ACME account exists community.crypto.openssl_privatekey: path: "/etc/ansible_certs/account_key.pem" size: 4096 type: RSA owner: root group: root mode: "0600" become: true - name: Check certificate status and create ACME challenge if needed community.crypto.acme_certificate: account_email: "{{ cert__acme_account_email }}" account_key_src: "/etc/ansible_certs/account_key.pem" acme_directory: https://acme-v02.api.letsencrypt.org/directory acme_version: 2 remaining_days: 28 terms_agreed: true challenge: dns-01 csr: "/etc/ansible_certs/certs/{{ item }}/csr.pem" dest: "/etc/ansible_certs/certs/{{ item }}/cert.pem" fullchain_dest: "/etc/ansible_certs/certs/{{ item }}/fullchain.pem" become: true register: cert__acme_challenge - name: Retrieve certificate and fulfill challenge if needed # noqa no-handler when: cert__acme_challenge.changed # Can't be put in a handler, because then the block "always" tasks won't be executed for some reason block: - name: Add file containing nsupdate commands for adding TXT record for DNS-01 challenge ansible.builtin.template: src: nsupdate_add_txt_record.j2 dest: /root/nsupdate_add_txt_record owner: root group: root mode: "0600" vars: cert__nsupdate_domain: "{{ cert__acme_challenge.challenge_data[item]['dns-01'].record }}" cert__nsupdate_txt_data: "{{ cert__acme_challenge.challenge_data[item]['dns-01'].resource_value }}" delegate_to: "{{ cert__bind_9_host }}" - name: Add DNS record to BIND 9 server via nsupdate # noqa: no-changed-when ansible.builtin.command: /usr/bin/nsupdate -l /root/nsupdate_add_txt_record delegate_to: "{{ cert__bind_9_host }}" - name: Retrieve certificate community.crypto.acme_certificate: account_email: "{{ cert__acme_account_email }}" account_key_src: "/etc/ansible_certs/account_key.pem" acme_directory: https://acme-v02.api.letsencrypt.org/directory acme_version: 2 terms_agreed: true remaining_days: 28 challenge: dns-01 csr: "/etc/ansible_certs/certs/{{ item }}/csr.pem" dest: "/etc/ansible_certs/certs/{{ item }}/cert.pem" fullchain_dest: "/etc/ansible_certs/certs/{{ item }}/fullchain.pem" data: "{{ cert__acme_challenge }}" become: true notify: "{{ cert__handlers }}" always: - name: Remove file containing nsupdate commands for adding TXT record again ansible.builtin.file: path: /root/nsupdate_add_txt_record state: absent delegate_to: "{{ cert__bind_9_host }}" - name: Remove TXT record again block: - name: Add file containing nsupdate commands for deleting TXT record for DNS-01 challenge ansible.builtin.template: src: nsupdate_delete_txt_record.j2 dest: /root/nsupdate_delete_txt_record owner: root group: root mode: "0600" vars: cert__nsupdate_domain: "{{ cert__acme_challenge.challenge_data[item]['dns-01'].record }}" cert__nsupdate_txt_data: "{{ cert__acme_challenge.challenge_data[item]['dns-01'].resource_value }}" delegate_to: "{{ cert__bind_9_host }}" - name: Remove DNS record from BIND 9 server via nsupdate # noqa: no-changed-when ansible.builtin.command: /usr/bin/nsupdate -l /root/nsupdate_delete_txt_record delegate_to: "{{ cert__bind_9_host }}" always: - name: Remove file containing nsupdate commands for deleting TXT record again ansible.builtin.file: path: /root/nsupdate_delete_txt_record state: absent delegate_to: "{{ cert__bind_9_host }}" - name: Ensure correct permissions for certificate are set ansible.builtin.file: path: "/etc/ansible_certs/certs/{{ item }}/cert.pem" owner: "{{ cert__owner }}" group: "{{ cert__group }}" mode: "{{ cert__cert_pem_permissions }}" become: true - name: Ensure correct permissions for fullchain cert are set ansible.builtin.file: path: "/etc/ansible_certs/certs/{{ item }}/fullchain.pem" owner: "{{ cert__owner }}" group: "{{ cert__group }}" mode: "{{ cert__fullchain_pem_permissions }}" become: true - name: Get content of cert.pem ansible.builtin.slurp: src: "/etc/ansible_certs/certs/{{ item }}/cert.pem" become: true register: cert__cert_slurp - name: Get content of fullchain.pem ansible.builtin.slurp: src: "/etc/ansible_certs/certs/{{ item }}/fullchain.pem" become: true register: cert__fullchain_slurp - name: Ensure chain.pem is created ansible.builtin.copy: content: "{{ cert__fullchain_slurp.content | b64decode | replace(cert__cert_slurp.content | b64decode, '') }}" dest: "/etc/ansible_certs/certs/{{ item }}/chain.pem" owner: "{{ cert__owner }}" group: "{{ cert__group }}" mode: "{{ cert__chain_pem_permissions }}" become: true