Better SSL management

- Use filter plugins
- Acme: can use proxy protocol
- Acme: uses all sites name
- Acme: add more tests while crashing
py3
Emilien Mantel 2019-12-31 12:43:43 +01:00
parent 2f8ce00067
commit 729173c46c
6 changed files with 56 additions and 23 deletions

View File

@ -25,6 +25,29 @@ def nginx_cert_path(pair, ssl_dir):
else: else:
return nginx_ssl_dir(pair, ssl_dir) + '/' + nginx_site_filename(pair) + '.crt' return nginx_ssl_dir(pair, ssl_dir) + '/' + nginx_site_filename(pair) + '.crt'
def nginx_all_site_names(site):
all_sites = []
if isinstance(site['name'], list):
all_sites = all_sites + site['name']
else:
all_sites.append(site['name'])
if site.has_key('redirect_from'):
if isinstance(site['redirect_from'], list):
all_sites = all_sites + site['redirect_from']
else:
all_sites.append(site['redirect_from'])
return all_sites
def nginx_search_by_ssl_name(sites, ssl_name):
res = None
for site in sites:
if site.has_key('ssl_name') and site['ssl_name'] == ssl_name:
res = site
break
return res
class FilterModule(object): class FilterModule(object):
''' Nginx module ''' ''' Nginx module '''
@ -34,5 +57,7 @@ class FilterModule(object):
'nginx_site_name': nginx_site_name, 'nginx_site_name': nginx_site_name,
'nginx_ssl_dir': nginx_ssl_dir, 'nginx_ssl_dir': nginx_ssl_dir,
'nginx_key_path': nginx_key_path, 'nginx_key_path': nginx_key_path,
'nginx_cert_path': nginx_cert_path 'nginx_cert_path': nginx_cert_path,
'nginx_all_site_names': nginx_all_site_names,
'nginx_search_by_ssl_name': nginx_search_by_ssl_name
} }

View File

@ -1,12 +1,12 @@
--- ---
- name: SET_FACT | Assign default.. - name: SET_FACT | Assign default...
set_fact: set_fact:
acme_create: [] acme_create: []
- name: STAT | Check if certificates are already installed - name: STAT | Check if certificates are already installed
stat: stat:
path: "{{ nginx_ssl_dir }}/{{ item | nginx_site_name }}/{{ item | nginx_site_name }}.crt" path: "{{ item | nginx_cert_path(nginx_ssl_dir) }}"
loop: "{{ nginx_ssl_pairs }}" loop: "{{ nginx_ssl_pairs }}"
when: item.acme is defined and item.acme when: item.acme is defined and item.acme
register: acme_installed_certs register: acme_installed_certs
@ -15,7 +15,7 @@
set_fact: set_fact:
acme_create: "{{ acme_create | default([]) + [ (item.item) ] }}" acme_create: "{{ acme_create | default([]) + [ (item.item) ] }}"
loop: "{{ acme_installed_certs.results }}" loop: "{{ acme_installed_certs.results }}"
when: item.skipped is not defined and not item.stat.exists when: item.skipped is not defined and (not item.stat.exists or item.stat.size == 0)
- name: BLOCK | Start acme - name: BLOCK | Start acme
block: block:
@ -50,11 +50,11 @@
command: | command: |
{{ nginx_acmesh_bin }} {{ nginx_acmesh_bin }}
--home {{ nginx_acmesh_dir }} --home {{ nginx_acmesh_dir }}
--issue{% if item.name is string %} -d {{ item.name }}{% else %}{% for name in item.name %} -d {{ name }}{% endfor %}{% endif %} --issue{% for s in nginx_sites | nginx_search_by_ssl_name(item.name) | nginx_all_site_names %} -d {{ s }}{% endfor %}
--nginx --nginx
{% if nginx_acmesh_test %}--test{% endif %} {% if nginx_acmesh_test %}--test --log{% endif %}
args: args:
creates: "{{ nginx_acmesh_dir }}/{{ item | nginx_site_name }}/{{ item | nginx_site_name }}.key" creates: "{{ nginx_acmesh_dir }}/{{ item | nginx_site_name }}/fullchain.cer"
loop: "{{ acme_create }}" loop: "{{ acme_create }}"
register: acme_get register: acme_get
failed_when: acme_get.rc != 0 and acme_get.rc != 2 failed_when: acme_get.rc != 0 and acme_get.rc != 2
@ -69,12 +69,12 @@
command: | command: |
{{ nginx_acmesh_bin }} {{ nginx_acmesh_bin }}
--home {{ nginx_acmesh_dir }} --home {{ nginx_acmesh_dir }}
--install-cert -d {{ item | nginx_site_name }} --install-cert -d {{ nginx_sites | nginx_search_by_ssl_name(item | nginx_site_name) | nginx_site_name }}
--fullchain-file {{ nginx_ssl_dir }}/{{ item | nginx_site_name }}/{{ item | nginx_site_name }}.crt --fullchain-file {{ item | nginx_cert_path(nginx_ssl_dir) }}
--key-file {{ nginx_ssl_dir }}/{{ item | nginx_site_name }}/{{ item | nginx_site_name }}.key --key-file {{ item | nginx_key_path(nginx_ssl_dir) }}
--reloadcmd "service nginx reload" --reloadcmd "service nginx reload"
args: args:
creates: "{{ nginx_ssl_dir }}/{{ item | nginx_site_name }}/{{ item | nginx_site_name }}.key" creates: "{{ item | nginx_cert_path(nginx_ssl_dir) }}"
loop: "{{ nginx_ssl_pairs }}" loop: "{{ nginx_ssl_pairs }}"
when: item.acme is defined and item.acme when: item.acme is defined and item.acme
notify: restart nginx notify: restart nginx

View File

@ -1,8 +1,16 @@
server { {% set site = nginx_sites | nginx_search_by_ssl_name(item.name) %}
listen {{ item.acme_port | default('80') }}; {% set __listen = site.listen | default(['80', '[::]:80']) %}
listen [::]:{{ item.acme_port | default('80') }}; {% set __http_proxy_protocol_port = site.http_proxy_protocol_port | default([]) %}
server_name {% if item.name is string %}{{ item.name }}{% else %}{{ item.name | join(" ") }}{% endif %}{% if item.redirect_from is defined %} {% if item.redirect_from is string %}{{ item.redirect_from }}{% else %}{{ item.redirect_from | join(" ") }}{% endif %}{% endif %}; server {
{% for port in __listen %}
listen {{ port }};
{% endfor %}
{% for port in __http_proxy_protocol_port %}
listen {{ port }} proxy_protocol;
{% endfor %}
server_name {{ site | nginx_all_site_names | join(" ") }};
location / { location / {
return 503; return 503;

View File

@ -43,7 +43,7 @@
{%- endif %} {%- endif %}
{%- endmacro %} {%- endmacro %}
{% macro ssl(ssl_name) %} {% macro ssl(ssl_name) %}
{% for sn in nginx_ssl_pairs if ((sn.name is string and sn.name == ssl_name) or (sn.name.0 == ssl_name)) %} {% for sn in nginx_ssl_pairs if (sn.name is defined and sn.name == ssl_name) %}
ssl_certificate {{ sn | nginx_cert_path(nginx_ssl_dir) }}; ssl_certificate {{ sn | nginx_cert_path(nginx_ssl_dir) }};
ssl_certificate_key {{ sn | nginx_key_path(nginx_ssl_dir) }}; ssl_certificate_key {{ sn | nginx_key_path(nginx_ssl_dir) }};
{% endfor %} {% endfor %}

View File

@ -1,7 +1,7 @@
--- ---
- name: SHELL | Start ngrok - name: SHELL | Start ngrok
shell: daemonize -l /tmp/ngrok.lock {{ ngrok_path }} http 8888 -bind-tls=false shell: daemonize -l /tmp/ngrok.lock {{ ngrok_path }} http 80 -bind-tls=false
failed_when: false failed_when: false
changed_when: ngrok.stderr.find("Can't lock the lock file") == -1 changed_when: ngrok.stderr.find("Can't lock the lock file") == -1
register: ngrok register: ngrok

View File

@ -24,7 +24,6 @@
src: "file/test.key" src: "file/test.key"
dest: "{{ int_ansible_ssl_dir }}/test.key" dest: "{{ int_ansible_ssl_dir }}/test.key"
- debug: var=nginx_sites
- name: COPY | Add all hosts in /etc/hosts - name: COPY | Add all hosts in /etc/hosts
copy: copy:
content: | content: |
@ -79,10 +78,8 @@
nginx_acmesh: true nginx_acmesh: true
nginx_acmesh_test: true nginx_acmesh_test: true
nginx_ssl_pairs: nginx_ssl_pairs:
- name: - name: '{{ ngrok.stdout }}'
- '{{ ngrok.stdout }}'
acme: true acme: true
acme_port: 8888
- name: 'test-ssl-selfsigned.local' - name: 'test-ssl-selfsigned.local'
self_signed: true self_signed: true
force: false force: false
@ -236,7 +233,9 @@
- name: 'test-ssl.local' - name: 'test-ssl.local'
proto: ['http', 'https'] proto: ['http', 'https']
template: '_base' template: '_base'
- name: 'test-ssl-selfsigned.local' - name:
- 'test-ssl-selfsigned.local'
- 'www.test-ssl-selfsigned.local'
proto: ['http', 'https'] proto: ['http', 'https']
template: '_base' template: '_base'
- name: 'test-ssl-predeployed.local' - name: 'test-ssl-predeployed.local'
@ -272,12 +271,13 @@
'X-Proxy-Protocol': '1' 'X-Proxy-Protocol': '1'
- name: '{{ ngrok.stdout }}' - name: '{{ ngrok.stdout }}'
proto: ['http', 'https'] proto: ['http', 'https']
http_proxy_protocol_port: [21080]
https_proxy_protocol_port: [21443]
template: '_base' template: '_base'
ssl_name: '{{ ngrok.stdout }}' ssl_name: '{{ ngrok.stdout }}'
headers: headers:
'X-acme': '1' 'X-acme': '1'
#nginx_php: "{{ __nginx_php + [{'upstream_name': 'manual', 'sockets': [{'host': '127.0.0.1', 'port': '9636' }] }] }}"
nginx_php: "{{ [{'upstream_name': 'manual', 'sockets': [{'host': '127.0.0.1', 'port': '9636' }] }] }}" nginx_php: "{{ [{'upstream_name': 'manual', 'sockets': [{'host': '127.0.0.1', 'port': '9636' }] }] }}"
nginx_dh_length: 1024 nginx_dh_length: 1024
roles: roles: