diff options
-rw-r--r-- | group_vars/all.yml | 15 | ||||
-rw-r--r-- | host_vars/dc0.yml | 1 | ||||
-rw-r--r-- | roles/acme/defaults/main.yml | 10 | ||||
-rw-r--r-- | roles/acme/meta/main.yml | 53 | ||||
-rw-r--r-- | roles/acme/tasks/main.yml | 19 | ||||
-rw-r--r-- | roles/acme/templates/acme-client.conf.j2 | 27 |
6 files changed, 90 insertions, 35 deletions
diff --git a/group_vars/all.yml b/group_vars/all.yml index 2ae2bbc..35abefd 100644 --- a/group_vars/all.yml +++ b/group_vars/all.yml @@ -9,13 +9,11 @@ ansible_become_method: su wireguard_domain_controller: "{{ __global_domain_controller }}" relayd_domain_name: "{{ __domain_name }}" -acme_domain_name: "{{ __global_domain_name }}" nfsclient_server: stack0 httpd_use_nfs: true -relayd_rules: "[ - {% for rule in __services if - 'domain' in rule and 'port' in rule %} - {{ {'name': rule.name, 'domain': rule.domain, 'port': rule.port} }}, +acme_rules: "[ + {% for rule in __services if 'domain' in rule %} + {{ {'domain': rule.domain} }}, {% endfor %} ]" pf_rules: "[ @@ -24,7 +22,12 @@ pf_rules: "[ {{ {'name': rule.name, 'port': rule.port, 'protocol': rule.protocol} }}, {% endfor %} ]" -acme_rules: "{{ __services }}" +relayd_rules: "[ + {% for rule in __services if + 'domain' in rule and 'port' in rule %} + {{ {'name': rule.name, 'domain': rule.domain, 'port': rule.port} }}, + {% endfor %} + ]" # playbook specific diff --git a/host_vars/dc0.yml b/host_vars/dc0.yml index 1ab8872..f0866ff 100644 --- a/host_vars/dc0.yml +++ b/host_vars/dc0.yml @@ -6,6 +6,7 @@ httpd_use_nfs: false git_dir: /var/www/data/git sshd_listen_port: "{{ ansible_port }}" relayd_connected_hosts: servers +acme_connected_hosts: servers __is_vm: true diff --git a/roles/acme/defaults/main.yml b/roles/acme/defaults/main.yml index 66ca704..cd713c6 100644 --- a/roles/acme/defaults/main.yml +++ b/roles/acme/defaults/main.yml @@ -1,6 +1,10 @@ --- -acme_rules: {} - acme_configuration_file: /etc/acme-client.conf -acme_domain_name: null +acme_certificates_dir: /etc/ssl +acme_keys_dir: /etc/ssl/private + +acme_authority: + name: letsencrypt + url: https://acme-v02.api.letsencrypt.org/directory + key: /etc/acme/letsencrypt-privkey.pem diff --git a/roles/acme/meta/main.yml b/roles/acme/meta/main.yml new file mode 100644 index 0000000..924fd90 --- /dev/null +++ b/roles/acme/meta/main.yml @@ -0,0 +1,53 @@ +--- + +argument_specs: + main: + short_description: acme main entrypoint. + options: + + acme_rules: + type: list + elements: dict + required: true + options: + domain: + type: str + required: true + description: Acme domain name + + acme_authority: + type: dict + required: true + options: + name: + type: str + required: true + description: Acme authority name + url: + type: str + required: true + description: Acme authority api url + key: + type: path + required: true + description: Acme authority key file + + acme_certificates_dir: + type: path + required: true + description: Acme certificates directory + + acme_keys_dir: + type: path + required: true + description: Acme keys directory + + acme_configuration_file: + type: path + required: true + description: Acme configuration file + + relayd_connected_hosts: + type: str + required: true + description: Group name of hosts for generating certificates diff --git a/roles/acme/tasks/main.yml b/roles/acme/tasks/main.yml index f2d4ba3..c068ab5 100644 --- a/roles/acme/tasks/main.yml +++ b/roles/acme/tasks/main.yml @@ -8,23 +8,24 @@ group: 0 mode: "0644" -- name: retrieve enabled domains # noqa: no-changed-when +- name: retrieve enabled domains ansible.builtin.shell: | set -o pipefail grep "^domain" /etc/acme-client.conf | cut -d " " -f 2 - register: subdomains + register: acme_result_subdomains + changed_when: false -- name: generate acme certificates # noqa: no-changed-when +- name: generate acme certificates ansible.builtin.command: acme-client -v {{ item }} - loop: "{{ subdomains.stdout_lines }}" + loop: "{{ acme_result_subdomains.stdout_lines }}" register: acme_result_generation - failed_when: - - acme_result_generation.rc != 0 - - "'certificate valid' not in acme_result_generation.stderr" + failed_when: acme_result_generation.rc == 1 + changed_when: acme_result_generation.rc != 2 - name: display registered certificates ansible.builtin.debug: - msg: "{{ acme_result_generation.results | map(attribute='stderr') }}" + msg: "{{ acme_result_generation.results | map(attribute='stderr') + | join('\n') }}" - name: enable automatic acme certificates update ansible.builtin.cron: @@ -32,4 +33,4 @@ minute: 0 hour: 6,18 job: "acme-client -v {{ item }} && rcctl reload relayd" - loop: "{{ subdomains.stdout_lines }}" + loop: "{{ acme_result_subdomains.stdout_lines }}" diff --git a/roles/acme/templates/acme-client.conf.j2 b/roles/acme/templates/acme-client.conf.j2 index 583c3d5..a6516c6 100644 --- a/roles/acme/templates/acme-client.conf.j2 +++ b/roles/acme/templates/acme-client.conf.j2 @@ -1,26 +1,19 @@ # managed by Ansible {% import 'macros.j2' as macros with context %} -authority letsencrypt { - api url "https://acme-v02.api.letsencrypt.org/directory" - account key "/etc/acme/letsencrypt-privkey.pem" +authority {{ acme_authority.name }} { + api url "{{ acme_authority.url }}" + account key "{{ acme_authority.key }}" } -domain {{ acme_domain_name }} { - alternative names { www.{{ acme_domain_name }} } - domain key "/etc/ssl/private/{{ acme_domain_name }}.key" - domain full chain certificate "/etc/ssl/{{ acme_domain_name }}.crt" - sign with letsencrypt -} +{% call(h) macros.loop_valid_hosts(relayd_connected_hosts) -%} +{% for rule in h.acme_rules %} -{% call(h) macros.loop_valid_hosts("servers") -%} -{% for name, rules in h.acme_rules.items() if rules.domain is defined %} -domain {{ rules.domain }}.{{ acme_domain_name }} { - {% set domain = rules.domain ~ "." ~ acme_domain_name %} - alternative names { www.{{ domain }} } - domain key "/etc/ssl/private/{{ domain }}.key" - domain full chain certificate "/etc/ssl/{{ domain }}.crt" - sign with letsencrypt +domain {{ rule.domain }} { + alternative names { www.{{ rule.domain }} } + domain key "{{ acme_keys_dir }}/{{ rule.domain }}.key" + domain full chain certificate "{{ acme_certificates_dir }}/{{ rule.domain }}.crt" + sign with {{ acme_authority.name }} } {% endfor %} {%- endcall %} |