Merge branch 'certbot' of evolix/ansible-roles into unstable
Let's merge this into unstable and test it on a few servers.
This commit is contained in:
commit
eec8aef129
|
@ -11,6 +11,7 @@ The **patch** part changes incrementally at each release.
|
||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
* certbot : new role to install and configure certbot
|
||||||
* evocheck: explicit PATH
|
* evocheck: explicit PATH
|
||||||
* evolinux-base: On debian 10 and later, add noexec on /dev/shm
|
* evolinux-base: On debian 10 and later, add noexec on /dev/shm
|
||||||
* evolinux-base: default value for "evolinux_ssh_group"
|
* evolinux-base: default value for "evolinux_ssh_group"
|
||||||
|
|
3
certbot/defaults/main.yml
Normal file
3
certbot/defaults/main.yml
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
certbot_work_dir: /var/lib/letsencrypt
|
44
certbot/files/hooks/apache.sh
Normal file
44
certbot/files/hooks/apache.sh
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
error() {
|
||||||
|
>&2 echo "${PROGNAME}: $1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
debug() {
|
||||||
|
if [ "${VERBOSE}" = "1" ] && [ "${QUIET}" != "1" ]; then
|
||||||
|
>&2 echo "${PROGNAME}: $1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
daemon_found_and_running() {
|
||||||
|
test -n "$(pidof apache2)" && test -n "${apache2ctl_bin}"
|
||||||
|
}
|
||||||
|
config_check() {
|
||||||
|
${apache2ctl_bin} configtest > /dev/null 2>&1
|
||||||
|
}
|
||||||
|
letsencrypt_used() {
|
||||||
|
grep -q -r -E "letsencrypt" /etc/apache2/
|
||||||
|
}
|
||||||
|
main() {
|
||||||
|
if daemon_found_and_running; then
|
||||||
|
if letsencrypt_used; then
|
||||||
|
if config_check; then
|
||||||
|
debug "Apache detected... reloading"
|
||||||
|
systemctl reload apache2
|
||||||
|
else
|
||||||
|
error "Apache config is broken, you must fix it !"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "Apache doesn't use Let's Encrypt certificate. Skip."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "Apache is not running or missing. Skip."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly PROGNAME=$(basename "$0")
|
||||||
|
readonly VERBOSE=${VERBOSE:-"0"}
|
||||||
|
readonly QUIET=${QUIET:-"0"}
|
||||||
|
|
||||||
|
readonly apache2ctl_bin=$(command -v apache2ctl)
|
||||||
|
|
||||||
|
main
|
37
certbot/files/hooks/commit-etc.sh
Normal file
37
certbot/files/hooks/commit-etc.sh
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
error() {
|
||||||
|
>&2 echo "${PROGNAME}: $1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
debug() {
|
||||||
|
if [ "${VERBOSE}" = "1" ] && [ "${QUIET}" != "1" ]; then
|
||||||
|
>&2 echo "${PROGNAME}: $1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
main() {
|
||||||
|
export GIT_DIR="/etc/.git"
|
||||||
|
export GIT_WORK_TREE="/etc"
|
||||||
|
|
||||||
|
if test -x "${git_bin}" && test -d "${GIT_DIR}" && test -d "${GIT_WORK_TREE}"; then
|
||||||
|
changed_lines=$(${git_bin} status --porcelain -- ${letsencrypt_dir} | wc -l | tr -d ' ')
|
||||||
|
|
||||||
|
if [ "${changed_lines}" != "0" ]; then
|
||||||
|
debug "Committing for ${RENEWED_DOMAINS}"
|
||||||
|
${git_bin} add --all ${letsencrypt_dir}
|
||||||
|
message="[letsencrypt] certificates renewal (${RENEWED_DOMAINS})"
|
||||||
|
${git_bin} commit --message "${message}" --quiet
|
||||||
|
else
|
||||||
|
error "Weird, nothing has changed but the hook has been executed for '${RENEWED_DOMAINS}'"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly PROGNAME=$(basename "$0")
|
||||||
|
readonly VERBOSE=${VERBOSE:-"0"}
|
||||||
|
readonly QUIET=${QUIET:-"0"}
|
||||||
|
|
||||||
|
readonly git_bin=$(command -v git)
|
||||||
|
readonly letsencrypt_dir=/etc/letsencrypt
|
||||||
|
|
||||||
|
main
|
44
certbot/files/hooks/dovecot.sh
Normal file
44
certbot/files/hooks/dovecot.sh
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
error() {
|
||||||
|
>&2 echo "${PROGNAME}: $1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
debug() {
|
||||||
|
if [ "${VERBOSE}" = "1" ] && [ "${QUIET}" != "1" ]; then
|
||||||
|
>&2 echo "${PROGNAME}: $1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
daemon_found_and_running() {
|
||||||
|
test -n "$(pidof dovecot)" && test -n "${doveconf_bin}"
|
||||||
|
}
|
||||||
|
config_check() {
|
||||||
|
${doveconf_bin} > /dev/null 2>&1
|
||||||
|
}
|
||||||
|
letsencrypt_used() {
|
||||||
|
${doveconf_bin} | grep -E "^ssl_cert[^_]" | grep -q "letsencrypt"
|
||||||
|
}
|
||||||
|
main() {
|
||||||
|
if daemon_found_and_running; then
|
||||||
|
if letsencrypt_used; then
|
||||||
|
if config_check; then
|
||||||
|
debug "Dovecot detected... reloading"
|
||||||
|
systemctl reload dovecot
|
||||||
|
else
|
||||||
|
error "Dovecot config is broken, you must fix it !"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "Dovecot doesn't use Let's Encrypt certificate. Skip."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "Dovecot is not running or missing. Skip."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly PROGNAME=$(basename "$0")
|
||||||
|
readonly VERBOSE=${VERBOSE:-"0"}
|
||||||
|
readonly QUIET=${QUIET:-"0"}
|
||||||
|
|
||||||
|
readonly doveconf_bin=$(command -v doveconf)
|
||||||
|
|
||||||
|
main
|
75
certbot/files/hooks/haproxy.sh
Normal file
75
certbot/files/hooks/haproxy.sh
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
error() {
|
||||||
|
>&2 echo "${PROGNAME}: $1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
debug() {
|
||||||
|
if [ "${VERBOSE}" = "1" ] && [ "${QUIET}" != "1" ]; then
|
||||||
|
>&2 echo "${PROGNAME}: $1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
daemon_found_and_running() {
|
||||||
|
test -n "$(pidof haproxy)" && test -n "${haproxy_bin}"
|
||||||
|
}
|
||||||
|
found_renewed_lineage() {
|
||||||
|
test -f "${RENEWED_LINEAGE}/fullchain.pem" && test -f "${RENEWED_LINEAGE}/privkey.pem"
|
||||||
|
}
|
||||||
|
config_check() {
|
||||||
|
${haproxy_bin} -c -f /etc/haproxy/haproxy.cfg > /dev/null 2>&1
|
||||||
|
}
|
||||||
|
concat_files() {
|
||||||
|
# shellcheck disable=SC2174
|
||||||
|
mkdir --mode=700 --parents "${haproxy_cert_dir}"
|
||||||
|
chown root: "${haproxy_cert_dir}"
|
||||||
|
|
||||||
|
debug "Concatenating certificate files to ${haproxy_cert_file}"
|
||||||
|
cat "${RENEWED_LINEAGE}/fullchain.pem" "${RENEWED_LINEAGE}/privkey.pem" > "${haproxy_cert_file}"
|
||||||
|
chmod 600 "${haproxy_cert_file}"
|
||||||
|
chown root: "${haproxy_cert_file}"
|
||||||
|
}
|
||||||
|
cert_and_key_mismatch() {
|
||||||
|
haproxy_cert_md5=$(openssl x509 -noout -modulus -in "${haproxy_cert_file}" | openssl md5)
|
||||||
|
haproxy_key_md5=$(openssl rsa -noout -modulus -in "${haproxy_cert_file}" | openssl md5)
|
||||||
|
|
||||||
|
test "${haproxy_cert_md5}" != "${haproxy_key_md5}"
|
||||||
|
}
|
||||||
|
main() {
|
||||||
|
if [ -z "${RENEWED_LINEAGE}" ]; then
|
||||||
|
error "This script must be called only by certbot!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if daemon_found_and_running; then
|
||||||
|
if found_renewed_lineage; then
|
||||||
|
haproxy_cert_file="${haproxy_cert_dir}/$(basename "${RENEWED_LINEAGE}").pem"
|
||||||
|
failed_cert_file="/root/$(basename "${RENEWED_LINEAGE}").failed.pem"
|
||||||
|
|
||||||
|
concat_files
|
||||||
|
|
||||||
|
if cert_and_key_mismatch; then
|
||||||
|
mv "${haproxy_cert_file}" "${failed_cert_file}"
|
||||||
|
error "Key and cert don't match, we moved the file to ${failed_cert_file} for inspection"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if config_check; then
|
||||||
|
debug "HAProxy detected... reloading"
|
||||||
|
systemctl reload apache2
|
||||||
|
else
|
||||||
|
error "HAProxy config is broken, you must fix it !"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
error "Couldn't find ${RENEWED_LINEAGE}/fullchain.pem or ${RENEWED_LINEAGE}/privkey.pem"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "HAProxy is not running or missing. Skip."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly PROGNAME=$(basename "$0")
|
||||||
|
readonly VERBOSE=${VERBOSE:-"0"}
|
||||||
|
readonly QUIET=${QUIET:-"0"}
|
||||||
|
|
||||||
|
readonly haproxy_bin=$(command -v haproxy)
|
||||||
|
readonly haproxy_cert_dir="/etc/ssl/haproxy"
|
||||||
|
|
||||||
|
main
|
44
certbot/files/hooks/nginx.sh
Normal file
44
certbot/files/hooks/nginx.sh
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
error() {
|
||||||
|
>&2 echo "${PROGNAME}: $1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
debug() {
|
||||||
|
if [ "${VERBOSE}" = "1" ] && [ "${QUIET}" != "1" ]; then
|
||||||
|
>&2 echo "${PROGNAME}: $1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
daemon_found_and_running() {
|
||||||
|
test -n "$(pidof nginx)" && test -n "${nginx_bin}"
|
||||||
|
}
|
||||||
|
config_check() {
|
||||||
|
${nginx_bin} -t > /dev/null 2>&1
|
||||||
|
}
|
||||||
|
letsencrypt_used() {
|
||||||
|
grep -q --dereference-recursive -E "letsencrypt" /etc/nginx/sites-enabled
|
||||||
|
}
|
||||||
|
main() {
|
||||||
|
if daemon_found_and_running; then
|
||||||
|
if letsencrypt_used; then
|
||||||
|
if config_check; then
|
||||||
|
debug "Nginx detected... reloading"
|
||||||
|
systemctl reload nginx
|
||||||
|
else
|
||||||
|
error "Nginx config is broken, you must fix it !"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "Nginx doesn't use Let's Encrypt certificate. Skip."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "Nginx is not running or missing. Skip."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly PROGNAME=$(basename "$0")
|
||||||
|
readonly VERBOSE=${VERBOSE:-"0"}
|
||||||
|
readonly QUIET=${QUIET:-"0"}
|
||||||
|
|
||||||
|
readonly nginx_bin=$(command -v nginx)
|
||||||
|
|
||||||
|
main
|
44
certbot/files/hooks/postfix.sh
Normal file
44
certbot/files/hooks/postfix.sh
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
error() {
|
||||||
|
>&2 echo "${PROGNAME}: $1"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
debug() {
|
||||||
|
if [ "${VERBOSE}" = "1" ] && [ "${QUIET}" != "1" ]; then
|
||||||
|
>&2 echo "${PROGNAME}: $1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
daemon_found_and_running() {
|
||||||
|
test -n "$(pidof master)" && test -n "${postconf_bin}"
|
||||||
|
}
|
||||||
|
config_check() {
|
||||||
|
${postconf_bin} > /dev/null 2>&1
|
||||||
|
}
|
||||||
|
letsencrypt_used() {
|
||||||
|
${postconf_bin} | grep -E "^smtpd_tls_cert_file" | grep -q "letsencrypt"
|
||||||
|
}
|
||||||
|
main() {
|
||||||
|
if daemon_found_and_running; then
|
||||||
|
if letsencrypt_used; then
|
||||||
|
if config_check; then
|
||||||
|
debug "Postfix detected... reloading"
|
||||||
|
systemctl reload postfix
|
||||||
|
else
|
||||||
|
error "Postfix config is broken, you must fix it !"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "Postfix doesn't use Let's Encrypt certificate. Skip."
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
debug "Postfix is not running or missing. Skip."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
readonly PROGNAME=$(basename "$0")
|
||||||
|
readonly VERBOSE=${VERBOSE:-"0"}
|
||||||
|
readonly QUIET=${QUIET:-"0"}
|
||||||
|
|
||||||
|
readonly postconf_bin=$(command -v postconf)
|
||||||
|
|
||||||
|
main
|
16
certbot/handlers/main.yml
Normal file
16
certbot/handlers/main.yml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: reload nginx
|
||||||
|
service:
|
||||||
|
name: nginx
|
||||||
|
state: reloaded
|
||||||
|
|
||||||
|
- name: reload apache
|
||||||
|
service:
|
||||||
|
name: apache2
|
||||||
|
state: reloaded
|
||||||
|
|
||||||
|
- name: reload haproxy
|
||||||
|
service:
|
||||||
|
name: haproxy
|
||||||
|
state: reloaded
|
50
certbot/tasks/acme-challenge.yml
Normal file
50
certbot/tasks/acme-challenge.yml
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: Certbot work directory is present
|
||||||
|
file:
|
||||||
|
dest: "{{ certbot_work_dir }}"
|
||||||
|
state: directory
|
||||||
|
mode: "0755"
|
||||||
|
|
||||||
|
- name: Check if Nginx is installed
|
||||||
|
stat:
|
||||||
|
path: /etc/nginx
|
||||||
|
register: is_nginx
|
||||||
|
|
||||||
|
- name: ACME challenge for Nginx is installed
|
||||||
|
template:
|
||||||
|
src: acme-challenge/nginx.conf.j2
|
||||||
|
dest: /etc/nginx/snippets/letsencrypt.conf
|
||||||
|
force: yes
|
||||||
|
notify: reload nginx
|
||||||
|
when: is_nginx.stat.exists
|
||||||
|
|
||||||
|
- name: Check if Apache is installed
|
||||||
|
stat:
|
||||||
|
path: /etc/apache2
|
||||||
|
register: is_apache
|
||||||
|
|
||||||
|
- block:
|
||||||
|
- name: ACME challenge for Apache is installed
|
||||||
|
template:
|
||||||
|
src: acme-challenge/apache.conf.j2
|
||||||
|
dest: /etc/apache2/conf-available/letsencrypt.conf
|
||||||
|
force: yes
|
||||||
|
notify: reload apache
|
||||||
|
|
||||||
|
- name: ACME challenge for Apache is enabled
|
||||||
|
command: "a2enconf letsencrypt"
|
||||||
|
register: command_result
|
||||||
|
changed_when: "'Enabling' in command_result.stderr"
|
||||||
|
notify: reload apache
|
||||||
|
when: is_apache.stat.exists
|
||||||
|
|
||||||
|
- name: Check if HAProxy is installed
|
||||||
|
stat:
|
||||||
|
path: /etc/haproxy
|
||||||
|
register: is_haproxy
|
||||||
|
|
||||||
|
- name: ACME challenge for HAProxy is installed
|
||||||
|
debug:
|
||||||
|
msg: "ACME challenge configuration for HAProxy must be configured manually"
|
||||||
|
when: is_haproxy.stat.exists
|
23
certbot/tasks/main.yml
Normal file
23
certbot/tasks/main.yml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
---
|
||||||
|
|
||||||
|
- name: "System compatibility checks"
|
||||||
|
assert:
|
||||||
|
that:
|
||||||
|
- ansible_distribution == "Debian"
|
||||||
|
- ansible_distribution_major_version | version_compare('9', '>=')
|
||||||
|
msg: only compatible with Debian 9+
|
||||||
|
|
||||||
|
- name: certbot package is installed
|
||||||
|
apt:
|
||||||
|
name: certbot
|
||||||
|
state: latest
|
||||||
|
|
||||||
|
- include: acme-challenge.yml
|
||||||
|
|
||||||
|
- name: Deploy hooks are present
|
||||||
|
copy:
|
||||||
|
src: hooks/
|
||||||
|
dest: /etc/letsencrypt/renewal-hooks/deploy/
|
||||||
|
mode: "0700"
|
||||||
|
owner: root
|
||||||
|
group: root
|
6
certbot/templates/acme-challenge/apache.conf.j2
Normal file
6
certbot/templates/acme-challenge/apache.conf.j2
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
Alias /.well-known/acme-challenge {{ certbot_work_dir }}/.well-known/acme-challenge
|
||||||
|
<Directory "{{ certbot_work_dir }}/.well-known/acme-challenge">
|
||||||
|
Options -Indexes
|
||||||
|
Allow from all
|
||||||
|
Require all granted
|
||||||
|
</Directory>
|
5
certbot/templates/acme-challenge/nginx.conf.j2
Normal file
5
certbot/templates/acme-challenge/nginx.conf.j2
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
location ~ /.well-known/acme-challenge {
|
||||||
|
alias {{ certbot_work_dir }}/;
|
||||||
|
try_files $uri =404;
|
||||||
|
allow all;
|
||||||
|
}
|
Loading…
Reference in a new issue