Commit e717eaa9 authored by HgO's avatar HgO
Browse files

import letsencrypt role in haproxy role

parent 2f5cea2e
--- ---
mail_notification: letsencrypt@exemple.com
letsencrypt:
dns_gandi_api_key: !vault |
$ANSIBLE_VAULT;1.1;AES256
37623065386338343831383566336134303861396663666631656563633730613434633231343336
3132646565373162613537646538353933363161363036650a343634633932373362336134636139
34313539353938393164353034653366303664613332333038663266656466323265303130333035
3430613234383662640a313864386230646137383637343263356236633434356335383335353935
64623839396433346235383264613534383130386433363931306662663063306665
dns_gandi_sharing_id: !vault |
$ANSIBLE_VAULT;1.1;AES256
38396332333438316166356332636166623231653165396138373938613734663766366231396564
6238353638383965393837356339353864323333376532610a643738376136626335653835323638
66363537646637373130376630326365336433393161303861383163383766656166396566366530
3139626262313437640a623462346133303264393234366665663838663931653062616130643639
31303535323864323031353032346664643562626563633864366237373935386438353138643337
6632383964373738663761343065306137313163303838633763
staging: true
domains_gandi:
- neutrinet.be
haproxy: haproxy:
- hostname: neutrinet.be - hostname: neutrinet.be
target: target:
......
...@@ -35,7 +35,7 @@ if not result: ...@@ -35,7 +35,7 @@ if not result:
domain = result.group(1) domain = result.group(1)
# Define a path for HAproxy where you want to write the .pem file. # Define a path for HAproxy where you want to write the .pem file.
deploy_path="/etc/haproxy/ssl/" + domain.replace('.', '-') + ".pem" deploy_path="/etc/haproxy/ssl/" + domain + ".pem"
# The source files can be found in below paths, constructed with the lineage # The source files can be found in below paths, constructed with the lineage
# path # path
......
letsencrypt_domains:
- name: neutrinet.be
hooks:
deploy:
- /etc/letsencrypt/hooks.d/haproxy.py
post:
- systemctl reload haproxy
---
- name: Test si le certificat {{ domain }} ecdsa existe
stat:
path: /etc/letsencrypt/live/{{ domain }}-ecdsa/cert.pem
register: letsencrypt_domain_ecdsa
- name: Création du certificat {{ domain }} ecdsa # noqa command-instead-of-shell
shell:
cmd: |
/opt/letsencrypt/bin/certbot certonly \
--non-interactive \
{% if letsencrypt.staging | default(true) %}--staging \{% endif %}
--authenticator dns-gandi \
--dns-gandi-credentials /etc/letsencrypt/gandi/gandi.ini \
--key-type ecdsa \
--cert-name {{ domain }}-ecdsa \
--domain {{ domain }} \
--domain *\.{{ domain }} \
--post-hook 'systemctl restart haproxy' \
--deploy-hook /etc/letsencrypt/haproxy.py
when: not letsencrypt_domain_ecdsa.stat.exists
---
- name: Test si le certificat {{ domain }} rsa existe
stat:
path: /etc/letsencrypt/live/{{ domain }}/cert.pem
register: letsencrypt_domain_rsa
- name: Création du certificat {{ domain }} rsa # noqa command-instead-of-shell
shell:
cmd: |
/opt/letsencrypt/bin/certbot certonly \
--non-interactive \
{% if letsencrypt.staging | default(true) %}--staging \{% endif %}
--authenticator dns-gandi \
--dns-gandi-credentials /etc/letsencrypt/gandi/gandi.ini \
--key-type rsa \
--rsa-key-size 4096 \
--cert-name {{ domain }} \
--domain {{ domain }} \
--domain *\.{{ domain }} \
--post-hook 'systemctl restart haproxy' \
--deploy-hook /etc/letsencrypt/haproxy.py
when: not letsencrypt_domain_rsa.stat.exists
---
- name: Installation des dépendances python
ansible.builtin.package:
name:
- python3-dev
- python3-virtualenv
- virtualenv
state: present
- name: Création des dossiers Let's Encrypt
file:
path: "{{ item }}"
owner: root
group: root
mode: "u=rw,go=r"
state: directory
with_items:
- /etc/letsencrypt
- /etc/letsencrypt/gandi
- /opt/letsencrypt
- name: Installation de pip et certbot # noqa package-latest
ansible.builtin.pip:
name:
- pip
- certbot
- certbot-plugin-gandi
virtualenv: /opt/letsencrypt
virtualenv_python: python3
state: latest
chdir: /opt/letsencrypt
- name: Création d'un cron job pour renouveler les certificats
cron:
name: "letsencrypt-update"
cron_file: letsencrypt-update
special_time: daily
user: "root"
job: "/opt/letsencrypt/bin/certbot renew"
- name: Test si le compte Let's Encrypt existe
stat:
path: /etc/letsencrypt/accounts
register: letsencrypt_accounts
- name: Enregistrement du compte Let's Encrypt # noqa command-instead-of-shell
shell:
cmd: |
/opt/letsencrypt/bin/certbot register \
--non-interactive \
{% if letsencrypt.staging | default(true) %}--staging \{% endif %}
--email {{ mail_notification }} \
--no-eff-email \
--agree-tos
when: not letsencrypt_accounts.stat.exists
- name: Placement du hook pour haproxy
copy:
src: haproxy.py
dest: /etc/letsencrypt/haproxy.py
mode: "u=rwx,go=rx"
owner: root
group: root
- name: Config de Gandi pour Let's Encrypt
template:
dest: /etc/letsencrypt/gandi/gandi.ini
src: gandi.ini.j2
owner: root
group: root
mode: "u=rw,go="
- name: Création des certificats rsa par challenge gandi
include_tasks: letsencrypt-gandi-rsa.yml
loop: "{{ letsencrypt.domains_gandi }}"
loop_control:
loop_var: domain
when: '"domains_gandi" in letsencrypt'
- name: Création des certificats ecdsa par challenge gandi
include_tasks: letsencrypt-gandi-ecdsa.yml
loop: "{{ letsencrypt.domains_gandi }}"
loop_control:
loop_var: domain
when: '"domains_gandi" in letsencrypt'
...@@ -2,9 +2,13 @@ ...@@ -2,9 +2,13 @@
- import_tasks: haproxy.yml - import_tasks: haproxy.yml
tags: ['haproxy'] tags: ['haproxy']
- import_tasks: letsencrypt.yml - name: Création des certificats Let's Encrypt
import_role:
name: letsencrypt
vars:
letsencrypt_hook_scripts:
- haproxy.py
tags: ['letsencrypt'] tags: ['letsencrypt']
- name: Installation des plugins Telegraf - name: Installation des plugins Telegraf
import_role: import_role:
name: telegraf_plugin name: telegraf_plugin
......
{{ ansible_managed | comment }}
# live dns v5 api key
dns_gandi_api_key={{ letsencrypt.dns_gandi_api_key }}
# optional organization id, remove it if not used
dns_gandi_sharing_id={{ letsencrypt.dns_gandi_sharing_id }}
...@@ -11,9 +11,9 @@ ...@@ -11,9 +11,9 @@
## List certificate sources ## List certificate sources
## Prefix your entry with 'file://' if you intend to use relative paths ## Prefix your entry with 'file://' if you intend to use relative paths
sources = [ sources = [
{% for domain in letsencrypt.domains_gandi %} {% for domain in letsencrypt_domains %}
"/etc/haproxy/ssl/{{ domain | replace('.', '-') }}.pem", "/etc/haproxy/ssl/{{ domain.name | replace('.', '-') }}-rsa.pem",
"/etc/haproxy/ssl/{{ domain | replace('.', '-') }}-ecdsa.pem"{% if not loop.last %},{% endif %} "/etc/haproxy/ssl/{{ domain.name | replace('.', '-') }}-ecdsa.pem"{% if not loop.last %},{% endif %}
{% endfor %} {% endfor %}
] ]
...@@ -15,12 +15,9 @@ letsencrypt_dns_gandi_sharing_id: !vault | ...@@ -15,12 +15,9 @@ letsencrypt_dns_gandi_sharing_id: !vault |
6632383964373738663761343065306137313163303838633763 6632383964373738663761343065306137313163303838633763
letsencrypt_staging: true letsencrypt_staging: true
letsencrypt_hook_scripts: letsencrypt_hook_scripts: []
- haproxy.py
letsencrypt_domains: letsencrypt_domains:
- name: neutrinet.be - name: neutrinet.be
hooks: hooks:
deploy: deploy: []
- /etc/letsencrypt/hooks.d/haproxy.py post: []
post:
- systemctl reload haproxy
#!/usr/bin/env python3
import os
import pwd
import grp
import re
import sys
def chown(path: str, owner: str, group: str, **kwargs) -> None:
"""Change ownership of a file or directory given an username and a group name."""
uid = pwd.getpwnam(owner).pw_uid
gid = grp.getgrnam(group).gr_gid
os.chown(path, uid, gid, **kwargs)
# Certbot sets an environment variable RENEWED_LINEAGE, which points to the
# path of the renewed certificate. We use that path to determine and find
# the files for the currently renewed certificated
lineage=os.environ.get('RENEWED_LINEAGE')
# If nothing renewed, exit
if not lineage:
sys.exit()
# From the linage, we strip the 'domain name', which is the last part
# of the path.
result = re.match(r'.*/live/(.+)$', lineage)
# If we can not recognize the path, we exit with 1
if not result:
sys.exit(1)
# Extract the domain name
domain = result.group(1)
# Define a path for HAproxy where you want to write the .pem file.
deploy_path="/etc/haproxy/ssl/" + domain.replace('.', '-') + ".pem"
# The source files can be found in below paths, constructed with the lineage
# path
source_key = lineage + "/privkey.pem"
source_chain = lineage + "/fullchain.pem"
# HAproxy requires to combine the key and chain in one .pem file
# Open a file descriptor to handle permissions. See https://stackoverflow.com/a/45368120
deploy_fd = os.open(deploy_path, os.O_CREAT | os.O_WRONLY, 0o640)
with os.fdopen(deploy_fd, "w") as deploy, \
open(source_key, "r") as key, \
open(source_chain, "r") as chain:
deploy.write(key.read())
deploy.write(chain.read())
chown(deploy_path, "haproxy", "haproxy")
# Here you can add your service reload command. Which will be executed after
# every renewal, which is fine if you only have a few domains.
# Alternative is to add the reload to the --post-hook. In that case it is only
# run once after all renewals. That would be the use-case if you have a large
# number of different certificates served by HAproxy.
...@@ -60,7 +60,7 @@ ...@@ -60,7 +60,7 @@
- name: Installation des hooks - name: Installation des hooks
copy: copy:
src: "{{ hook_script }}" src: "hooks/{{ hook_script }}"
dest: /etc/letsencrypt/hooks.d/{{ hook_script }} dest: /etc/letsencrypt/hooks.d/{{ hook_script }}
mode: "u=rwx,go=rx" mode: "u=rwx,go=rx"
owner: root owner: root
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment