Switch from acmetool to certbot for SSL certificate retrieval

This commit is contained in:
Slavi Pantaleev
2018-08-29 09:37:44 +03:00
parent d5346656e3
commit 23e4a4734b
9 changed files with 164 additions and 75 deletions

View File

@ -20,46 +20,32 @@
- https
when: ansible_os_family == 'RedHat'
- name: Ensure acmetool Docker image is pulled
- name: Ensure certbot Docker image is pulled
docker_image:
name: willwill/acme-docker
name: "{{ matrix_ssl_certbot_docker_image }}"
# Granting +rx to others as well, because the `nginx` user from within
# matrix-nginx-proxy needs to be able to read the acme-challenge files inside
# for renewal purposes.
#
# This should not be causing security trouble outside of the container,
# as the parent directory (/matrix) does not allow "others" to access it or any of its children.
# Still, it works when the /ssl subtree is mounted in the container.
- name: Ensure SSL certificates path exists
- name: Ensure SSL certificate paths exists
file:
path: "{{ matrix_ssl_certs_path }}"
path: "{{ item }}"
state: directory
mode: 0775
mode: 0770
owner: "{{ matrix_user_username }}"
group: "{{ matrix_user_username }}"
with_items:
- "{{ matrix_ssl_log_dir_path }}"
- "{{ matrix_ssl_config_dir_path }}"
- name: Check matrix-nginx-proxy state
service: name=matrix-nginx-proxy
register: matrix_nginx_proxy_state
- name: Ensure matrix-nginx-proxy is stopped (if previously installed & started)
service: name=matrix-nginx-proxy state=stopped
when: "matrix_nginx_proxy_state.status.ActiveState|default('missing') == 'active'"
- name: Ensure SSL certificates are marked as wanted in acmetool
shell: >-
/usr/bin/docker run --rm --name acmetool --net=host
-v {{ matrix_ssl_certs_path }}:/certs
-v {{ matrix_ssl_certs_path }}/run:/var/run/acme
-e ACME_EMAIL={{ matrix_ssl_support_email }}
willwill/acme-docker
acmetool want {{ item }} --xlog.severity=debug
- name: Obtain initial certificates
include_tasks: "setup_ssl_for_domain.yml"
with_items: "{{ domains_to_obtain_certificate_for }}"
loop_control:
loop_var: domain_name
- name: Ensure matrix-nginx-proxy is started (if previously installed & started)
service: name=matrix-nginx-proxy state=started
when: "matrix_nginx_proxy_state.status.ActiveState|default('missing') == 'active'"
- name: Ensure SSL renewal script installed
template:
src: "{{ role_path }}/templates/usr-local-bin/matrix-ssl-certificates-renew.j2"
dest: "/usr/local/bin/matrix-ssl-certificates-renew"
mode: 0750
- name: Ensure periodic SSL renewal cronjob configured
template:

View File

@ -0,0 +1,70 @@
- debug:
msg: "Dealing with SSL certificate retrieval for domain: {{ domain_name }}"
- set_fact:
domain_name_certificate_path: "{{ matrix_ssl_config_dir_path }}/live/{{ domain_name }}/cert.pem"
- name: Check if a certificate for the domain already exists
stat:
path: "{{ domain_name_certificate_path }}"
register: domain_name_certificate_path_stat
- set_fact:
domain_name_needs_cert: "{{ not domain_name_certificate_path_stat.stat.exists }}"
# This will fail if there is something running on port 80 (like matrix-nginx-proxy).
# We suppress the error, as we'll try another method below.
- name: Attempt initial SSL certificate retrieval with standalone authenticator (directly)
shell: >-
/usr/bin/docker run
--rm
--name=matrix-certbot
--net=host
-v {{ matrix_ssl_config_dir_path }}:/etc/letsencrypt
-v {{ matrix_ssl_log_dir_path }}:/var/log/letsencrypt
{{ matrix_ssl_certbot_docker_image }}
certonly
--non-interactive
{% if matrix_ssl_use_staging %}--staging{% endif %}
--standalone
--preferred-challenges http
--agree-tos
--email={{ matrix_ssl_support_email }}
-d {{ domain_name }}
when: "domain_name_needs_cert"
register: result_certbot_direct
ignore_errors: true
# If matrix-nginx-proxy is configured from a previous run of this playbook,
# and it's running now, it may be able to proxy requests to `matrix_ssl_certbot_standalone_http_port`.
- name: Attempt initial SSL certificate retrieval with standalone authenticator (via proxy)
shell: >-
/usr/bin/docker run
--rm
--name=matrix-certbot
-p 127.0.0.1:{{ matrix_ssl_certbot_standalone_http_port }}:80
--network={{ matrix_docker_network }}
-v {{ matrix_ssl_config_dir_path }}:/etc/letsencrypt
-v {{ matrix_ssl_log_dir_path }}:/var/log/letsencrypt
{{ matrix_ssl_certbot_docker_image }}
certonly
--non-interactive
{% if matrix_ssl_use_staging %}--staging{% endif %}
--standalone
--preferred-challenges http
--agree-tos
--email={{ matrix_ssl_support_email }}
-d {{ domain_name }}
when: "domain_name_needs_cert and result_certbot_direct.failed"
register: result_certbot_proxy
ignore_errors: true
- name: Fail if all SSL certificate retrieval attempts failed
fail:
msg: |
Failed to obtain a certificate directly (by listening on port 80)
and also failed to obtain by relying on the server at port 80 to proxy the request.
See above for details.
You may wish to set up proxying of /.well-known/acme-challenge to {{ matrix_ssl_certbot_standalone_http_port }} or,
more easily, stop the server on port 80 while this playbook runs.
when: "domain_name_needs_cert and result_certbot_direct.failed and result_certbot_proxy.failed"