Add initial cert role

This commit is contained in:
yuri 2023-04-25 13:49:45 +02:00
parent 9670b6494c
commit c407f93b0a
No known key found for this signature in database
GPG key ID: E646779AC54AEC64
5 changed files with 169 additions and 0 deletions

View file

@ -0,0 +1,3 @@
cert__handlers: []
cert__owner: root
cert__group: root

View file

@ -0,0 +1,46 @@
---
argument_specs:
main:
short_description: Orders and renews certificates from Let's Encrypt
options:
cert__domains:
description: Domains for which to issue a certificate. Must be in the same DNS zone.
required: true
type: list
elements: str
cert__owner:
description: Owner of the certificate files.
required: false
type: str
default: root
cert__group:
description: Group of the certificate files.
required: false
type: str
default: root
cert__acme_account:
description: ACME account details
required: true
type: dict
options:
email:
description: E-mail address to send certificate expiary notifications to
required: true
type: str
key:
description: Private RSA or Elliptic Curve key of the ACME account
required: true
type: str
cert__cloudflare_dns:
description: Cloudflare DNS API details
required: true
type: dict
options:
api_token:
description: Cloudflare API token
required: true
type: str
zone:
description: DNS zone the domain is in
required: true
type: str

View file

@ -0,0 +1,7 @@
dependencies: # noqa meta-no-info
- role: distribution_check
vars:
distribution_check__supported_distributions:
- name: Debian
versions:
- "11"

View file

@ -0,0 +1,110 @@
- name: Ensure certs directory exists
ansible.builtin.file:
path: /certs
state: directory
owner: root
group: root
mode: "755"
- name: Ensure sub-directory for the certificate exists
ansible.builtin.file:
path: "/certs/{{ item }}"
state: directory
owner: "{{ cert__owner }}"
group: "{{ cert__group }}"
mode: "755"
- name: Ensure private key is generated
community.crypto.openssl_privatekey:
path: "/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: "/certs/{{ item }}/csr.pem"
privatekey_path: "/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: "/certs/{{ item }}/csr.pem"
dest: "/certs/{{ item }}/cert.pem"
fullchain_dest: "/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: "/certs/{{ item }}/csr.pem"
dest: "/certs/{{ item }}/cert.pem"
fullchain_dest: "/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: "/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: "/certs/{{ item }}/fullchain.pem"
owner: "{{ cert__owner }}"
group: "{{ cert__group }}"
mode: "0660"
- name: Get content of cert.pem
ansible.builtin.slurp:
src: "/certs/{{ item }}/cert.pem"
register: cert__cert_slurp
- name: Get content of fullchain.pem
ansible.builtin.slurp:
src: "/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: "/certs/{{ item }}/ca.pem"
owner: "{{ cert__owner }}"
group: "{{ cert__group }}"
mode: "0660"

View file

@ -0,0 +1,3 @@
- name: Deploy cert
ansible.builtin.include_tasks: deploy_cert.yml
loop: "{{ cert__domains }}"