- name: Ensure certs directory exists ansible.builtin.file: path: /etc/ansible_certs state: directory owner: root group: root mode: "755" - name: Ensure sub-directory for the certificate exists ansible.builtin.file: path: "/etc/ansible_certs/{{ item }}" state: directory owner: "{{ cert__owner }}" group: "{{ cert__group }}" mode: "755" - name: Ensure private key is generated community.crypto.openssl_privatekey: path: "/etc/ansible_certs/{{ item }}/key.pem" size: 4096 type: RSA owner: "{{ cert__owner }}" group: "{{ cert__group }}" mode: "0600" - name: Ensure certificate signing request is created community.crypto.openssl_csr: path: "/etc/ansible_certs/{{ item }}/csr.pem" privatekey_path: "/etc/ansible_certs/{{ item }}/key.pem" common_name: "{{ item }}" owner: "{{ cert__owner }}" group: "{{ cert__group }}" mode: "0660" register: cert__csr_result - name: Check certificate status and create ACME challenge if needed community.crypto.acme_certificate: account_email: "{{ cert__acme_account.email }}" account_key_content: "{{ cert__acme_account.key }}" 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/{{ item }}/csr.pem" dest: "/etc/ansible_certs/{{ item }}/cert.pem" fullchain_dest: "/etc/ansible_certs/{{ item }}/fullchain.pem" 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: Set DNS record via Cloudflare API to fulfill the challenge when: not cert__acme_challenge.authorizations[item].status == "valid" community.general.cloudflare_dns: api_token: "{{ cert__cloudflare_dns.api_token }}" zone: "{{ cert__cloudflare_dns.zone }}" record: "{{ cert__acme_challenge.challenge_data[item]['dns-01'].record }}" value: "{{ cert__acme_challenge.challenge_data[item]['dns-01'].resource_value }}" type: TXT ttl: 60 solo: true state: present - name: Retrieve certificate community.crypto.acme_certificate: account_email: "{{ cert__acme_account.email }}" account_key_content: "{{ cert__acme_account.key }}" 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/{{ item }}/csr.pem" dest: "/etc/ansible_certs/{{ item }}/cert.pem" fullchain_dest: "/etc/ansible_certs/{{ item }}/fullchain.pem" data: "{{ cert__acme_challenge }}" notify: "{{ cert__handlers }}" always: - name: Ensure DNS record is removed when: not cert__acme_challenge.authorizations[item].status == "valid" community.general.cloudflare_dns: api_token: "{{ cert__cloudflare_dns.api_token }}" zone: "{{ cert__cloudflare_dns.zone }}" record: "{{ cert__acme_challenge.challenge_data[item]['dns-01'].record }}" value: "{{ cert__acme_challenge.challenge_data[item]['dns-01'].resource_value }}" type: TXT ttl: 60 state: absent - name: Ensure correct permissions for certificate are set ansible.builtin.file: path: "/etc/ansible_certs/{{ item }}/cert.pem" owner: "{{ cert__owner }}" group: "{{ cert__group }}" mode: "0660" - name: Ensure correct permissions for fullchain cert are set ansible.builtin.file: path: "/etc/ansible_certs/{{ item }}/fullchain.pem" owner: "{{ cert__owner }}" group: "{{ cert__group }}" mode: "0660" - name: Get content of cert.pem ansible.builtin.slurp: src: "/etc/ansible_certs/{{ item }}/cert.pem" register: cert__cert_slurp - name: Get content of fullchain.pem ansible.builtin.slurp: src: "/etc/ansible_certs/{{ item }}/fullchain.pem" register: cert__fullchain_slurp - name: Ensure ca.pem is created ansible.builtin.copy: content: "{{ cert__fullchain_slurp.content | b64decode | replace(cert__cert_slurp.content | b64decode, '') }}" dest: "/etc/ansible_certs/{{ item }}/ca.pem" owner: "{{ cert__owner }}" group: "{{ cert__group }}" mode: "0660"