Add initial cert role
This commit is contained in:
parent
9670b6494c
commit
c407f93b0a
3
playbooks/roles/cert/defaults/main.yml
Normal file
3
playbooks/roles/cert/defaults/main.yml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
cert__handlers: []
|
||||||
|
cert__owner: root
|
||||||
|
cert__group: root
|
46
playbooks/roles/cert/meta/argument_specs.yml
Normal file
46
playbooks/roles/cert/meta/argument_specs.yml
Normal 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
|
7
playbooks/roles/cert/meta/main.yml
Normal file
7
playbooks/roles/cert/meta/main.yml
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
dependencies: # noqa meta-no-info
|
||||||
|
- role: distribution_check
|
||||||
|
vars:
|
||||||
|
distribution_check__supported_distributions:
|
||||||
|
- name: Debian
|
||||||
|
versions:
|
||||||
|
- "11"
|
110
playbooks/roles/cert/tasks/deploy_cert.yml
Normal file
110
playbooks/roles/cert/tasks/deploy_cert.yml
Normal 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"
|
3
playbooks/roles/cert/tasks/main.yml
Normal file
3
playbooks/roles/cert/tasks/main.yml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
- name: Deploy cert
|
||||||
|
ansible.builtin.include_tasks: deploy_cert.yml
|
||||||
|
loop: "{{ cert__domains }}"
|
Loading…
Reference in a new issue