2024-01-10 07:11:16 -05:00
|
|
|
---
|
|
|
|
|
2024-01-11 00:15:16 -05:00
|
|
|
- name: Install required python libraries system wide
|
|
|
|
when: ansible_facts['os_family'] == "Archlinux"
|
|
|
|
community.general.pacman:
|
|
|
|
name:
|
|
|
|
- python-cryptography
|
|
|
|
- python-dnspython
|
|
|
|
state: latest
|
|
|
|
update_cache: true
|
|
|
|
|
|
|
|
- name: Set certificate path facts
|
|
|
|
ansible.builtin.set_fact:
|
|
|
|
acme_certificate_certificate_path: "/etc/ssl/private/{{ acme_certificate_subject }}.pem"
|
|
|
|
acme_certificate_chain_path: "/etc/ssl/private/{{ acme_certificate_subject }}.chain.pem"
|
|
|
|
acme_certificate_combined_path: "/etc/ssl/private/{{ acme_certificate_subject }}.combined.pem"
|
|
|
|
acme_certificate_csr_path: "/etc/ssl/private/{{ acme_certificate_subject }}.csr"
|
|
|
|
acme_certificate_fullchain_path: "/etc/ssl/private/{{ acme_certificate_subject }}.fullchain.pem"
|
|
|
|
acme_certificate_key_path: "/etc/ssl/private/{{ acme_certificate_subject }}.key"
|
|
|
|
acme_certificate_plain_combined_path: "/etc/ssl/private/{{ acme_certificate_subject }}.plain.combined.pem"
|
|
|
|
acme_certificate_plain_key_path: "/etc/ssl/private/{{ acme_certificate_subject }}.plain.key"
|
|
|
|
|
|
|
|
- name: Create ACME account key directory
|
2024-01-10 07:11:16 -05:00
|
|
|
ansible.builtin.file:
|
|
|
|
group: root
|
|
|
|
mode: '0700'
|
|
|
|
owner: root
|
|
|
|
path: /etc/ssl/private/ACME
|
|
|
|
state: directory
|
|
|
|
|
|
|
|
- name: Create ACME account key
|
|
|
|
community.crypto.openssl_privatekey:
|
|
|
|
cipher: auto
|
|
|
|
curve: secp384r1
|
2024-01-11 00:15:16 -05:00
|
|
|
format: auto_ignore
|
2024-01-10 07:11:16 -05:00
|
|
|
group: root
|
|
|
|
mode: '0600'
|
|
|
|
owner: root
|
|
|
|
passphrase: "{{ acme_certificate_account_key_passphrase }}"
|
|
|
|
path: /etc/ssl/private/ACME/account.key
|
2024-01-11 00:15:16 -05:00
|
|
|
size: 4096
|
2024-01-10 07:11:16 -05:00
|
|
|
state: present
|
2024-01-11 00:15:16 -05:00
|
|
|
type: RSA
|
2024-01-10 07:11:16 -05:00
|
|
|
|
|
|
|
- name: Generate RSA private key
|
|
|
|
community.crypto.openssl_privatekey:
|
|
|
|
cipher: auto
|
|
|
|
curve: secp384r1
|
2024-01-11 00:15:16 -05:00
|
|
|
format: auto_ignore
|
2024-01-10 07:11:16 -05:00
|
|
|
group: root
|
|
|
|
mode: '0600'
|
|
|
|
owner: root
|
|
|
|
passphrase: "{{ ssl_passphrase }}"
|
2024-01-11 00:15:16 -05:00
|
|
|
path: "{{ acme_certificate_key_path }}"
|
2024-01-10 07:11:16 -05:00
|
|
|
size: 4096
|
|
|
|
state: present
|
|
|
|
type: RSA
|
2024-01-11 00:15:16 -05:00
|
|
|
register: genrsa_private_key
|
2024-01-10 07:11:16 -05:00
|
|
|
|
|
|
|
- name: Generate CSR
|
|
|
|
community.crypto.openssl_csr:
|
|
|
|
common_name: "{{ acme_certificate_subject }}"
|
|
|
|
country_name: "{{ acme_certificate_csr_country }}"
|
|
|
|
digest: sha256
|
|
|
|
email_address: "{{ acme_certificate_csr_email }}"
|
|
|
|
group: root
|
|
|
|
locality_name: "{{ acme_certificate_csr_locality }}"
|
|
|
|
mode: '0600'
|
|
|
|
organization_name: "{{ acme_certificate_csr_organization }}"
|
|
|
|
owner: root
|
2024-01-11 00:15:16 -05:00
|
|
|
path: "{{ acme_certificate_csr_path }}"
|
|
|
|
privatekey_passphrase: "{{ ssl_passphrase }}"
|
|
|
|
privatekey_path: "{{ acme_certificate_key_path }}"
|
2024-01-10 07:11:16 -05:00
|
|
|
state: present
|
|
|
|
state_or_province_name: "{{ acme_certificate_csr_state }}"
|
|
|
|
use_common_name_for_san: true
|
|
|
|
|
|
|
|
- name: Submit ACME certificate request
|
|
|
|
community.crypto.acme_certificate:
|
|
|
|
account_email: "{{ acme_certificate_account_email }}"
|
|
|
|
account_key_passphrase: "{{ acme_certificate_account_key_passphrase }}"
|
|
|
|
account_key_src: /etc/ssl/private/ACME/account.key
|
|
|
|
acme_directory: "{{ acme_certificate_directory }}"
|
|
|
|
acme_version: 2
|
2024-01-11 00:15:16 -05:00
|
|
|
chain_dest: "{{ acme_certificate_chain_path }}"
|
2024-01-10 07:11:16 -05:00
|
|
|
challenge: dns-01
|
2024-01-11 00:15:16 -05:00
|
|
|
csr: "{{ acme_certificate_csr_path }}"
|
|
|
|
dest: "{{ acme_certificate_certificate_path }}"
|
|
|
|
fullchain_dest: "{{ acme_certificate_fullchain_path }}"
|
2024-01-10 07:11:16 -05:00
|
|
|
modify_account: true
|
|
|
|
select_crypto_backend: cryptography
|
|
|
|
terms_agreed: true
|
|
|
|
validate_certs: true
|
|
|
|
register: challenge
|
|
|
|
|
|
|
|
- name: Debug ACME certificate challenge
|
|
|
|
ansible.builtin.debug:
|
|
|
|
var: challenge
|
|
|
|
|
|
|
|
- name: Proceed if challenge is changed
|
|
|
|
when:
|
|
|
|
- challenge is changed
|
|
|
|
- acme_certificate_subject in challenge.challenge_data
|
|
|
|
block:
|
|
|
|
|
|
|
|
- name: Answer ACME certificate challenge
|
|
|
|
community.general.nsupdate:
|
|
|
|
key_algorithm: "{{ rfc2136_key_algorithm }}"
|
|
|
|
key_name: "{{ rfc2136_key_name }}"
|
|
|
|
key_secret: "{{ rfc2136_key_secret }}"
|
|
|
|
port: 53
|
|
|
|
protocol: tcp
|
2024-01-11 00:15:16 -05:00
|
|
|
record: "{{ challenge.challenge_data[acme_certificate_subject]['dns-01'].record }}."
|
2024-01-10 07:11:16 -05:00
|
|
|
server: "{{ rfc2136_server_address }}"
|
|
|
|
state: present
|
|
|
|
ttl: 3600
|
|
|
|
type: TXT
|
|
|
|
value: "{{ challenge.challenge_data[acme_certificate_subject]['dns-01'].resource_value }}"
|
2024-01-11 00:15:16 -05:00
|
|
|
# zone: "{{ acme_certificate_zone }}"
|
|
|
|
register: nsupdate_result
|
|
|
|
|
|
|
|
- name: Debug nsupdate result
|
|
|
|
ansible.builtin.debug:
|
|
|
|
var: nsupdate_result
|
2024-01-10 07:11:16 -05:00
|
|
|
|
|
|
|
- name: Retrieve ACME certificate
|
|
|
|
community.crypto.acme_certificate:
|
|
|
|
account_email: "{{ acme_certificate_account_email }}"
|
|
|
|
account_key_passphrase: "{{ acme_certificate_account_key_passphrase }}"
|
|
|
|
account_key_src: /etc/ssl/private/ACME/account.key
|
|
|
|
acme_directory: "{{ acme_certificate_directory }}"
|
|
|
|
acme_version: 2
|
2024-01-11 00:15:16 -05:00
|
|
|
chain_dest: "{{ acme_certificate_chain_path }}"
|
2024-01-10 07:11:16 -05:00
|
|
|
challenge: dns-01
|
2024-01-11 00:15:16 -05:00
|
|
|
csr: "{{ acme_certificate_csr_path }}"
|
2024-01-10 07:11:16 -05:00
|
|
|
data: "{{ challenge }}"
|
2024-01-11 00:15:16 -05:00
|
|
|
dest: "{{ acme_certificate_certificate_path }}"
|
|
|
|
fullchain_dest: "{{ acme_certificate_fullchain_path }}"
|
2024-01-10 07:11:16 -05:00
|
|
|
select_crypto_backend: cryptography
|
|
|
|
terms_agreed: true
|
|
|
|
validate_certs: true
|
|
|
|
|
|
|
|
- name: Cleanup ACME challenge
|
|
|
|
community.general.nsupdate:
|
|
|
|
key_algorithm: "{{ rfc2136_key_algorithm }}"
|
|
|
|
key_name: "{{ rfc2136_key_name }}"
|
|
|
|
key_secret: "{{ rfc2136_key_secret }}"
|
|
|
|
port: 53
|
|
|
|
protocol: tcp
|
2024-01-11 00:15:16 -05:00
|
|
|
record: "{{ challenge.challenge_data[acme_certificate_subject]['dns-01'].record }}."
|
2024-01-10 07:11:16 -05:00
|
|
|
server: "{{ rfc2136_server_address }}"
|
|
|
|
state: absent
|
|
|
|
ttl: 3600
|
|
|
|
type: TXT
|
|
|
|
value: "{{ challenge.challenge_data[acme_certificate_subject]['dns-01'].resource_value }}"
|
|
|
|
zone: "{{ acme_certificate_zone }}"
|
2024-01-11 00:15:16 -05:00
|
|
|
|
|
|
|
- name: Slurp fullchain contents
|
|
|
|
ansible.builtin.slurp:
|
|
|
|
src: "{{ acme_certificate_fullchain_path }}"
|
|
|
|
register: acme_certificate_fullchain_content
|
|
|
|
|
|
|
|
- name: Slurp private key contents
|
|
|
|
ansible.builtin.slurp:
|
|
|
|
src: "{{ acme_certificate_key_path }}"
|
|
|
|
register: acme_certificate_key_content
|
|
|
|
|
|
|
|
- name: Create combined cert file
|
|
|
|
ansible.builtin.template:
|
|
|
|
dest: "{{ acme_certificate_combined_path }}"
|
|
|
|
group: root
|
|
|
|
mode: '0600'
|
|
|
|
owner: root
|
|
|
|
src: combined.pem.j2
|
|
|
|
|
|
|
|
- name: Check if plain key file exists
|
|
|
|
ansible.builtin.stat:
|
|
|
|
path: "{{ acme_certificate_plain_key_path }}"
|
|
|
|
register: plain_key_file
|
|
|
|
|
|
|
|
- name: Create a plain text copy of the SSL private key # noqa: no-handler
|
|
|
|
when: |
|
|
|
|
genrsa_private_key.changed or
|
|
|
|
not plain_key_file.stat.exists
|
|
|
|
ansible.builtin.command:
|
|
|
|
cmd: openssl rsa -in {{ acme_certificate_key_path }} -passin pass:{{ ssl_passphrase }} -out {{ acme_certificate_plain_key_path }}
|
|
|
|
changed_when: true
|
|
|
|
|
|
|
|
- name: Slurp plain text private key contents
|
|
|
|
ansible.builtin.slurp:
|
|
|
|
src: "{{ acme_certificate_plain_key_path }}"
|
|
|
|
register: acme_certificate_key_content
|
|
|
|
|
|
|
|
- name: Create plain text combined cert file
|
|
|
|
ansible.builtin.template:
|
|
|
|
dest: "{{ acme_certificate_plain_combined_path }}"
|
|
|
|
group: root
|
|
|
|
mode: '0600'
|
|
|
|
owner: root
|
|
|
|
src: combined.pem.j2
|
|
|
|
|
|
|
|
- name: Dependant services block
|
|
|
|
when:
|
|
|
|
- (acme_certificate_restart_services | default([]) | length) >= 1
|
|
|
|
- challenge is changed
|
|
|
|
block:
|
|
|
|
|
|
|
|
- name: Check state of running services
|
|
|
|
ansible.builtin.service_facts:
|
|
|
|
|
|
|
|
- name: Restart dependant services
|
|
|
|
when:
|
|
|
|
- ansible_facts.services[item] is defined
|
|
|
|
- ansible_facts.services[item].state in ['running','failed']
|
|
|
|
ansible.builtin.service:
|
|
|
|
name: "{{ item }}"
|
|
|
|
state: restarted
|
|
|
|
loop: "{{ acme_certificate_restart_services }}"
|