forked from ungleich-public/cdist
Rewrite __letsencrypt_cert type
This commit adds the following features: * Ability to expand existing certificate * Ability to manage object state * Ability to obtain test certificate * Ability to promote test certificate to production * Ability to specify custom certificate name * Ability to specify multiple domains per certificate * Ability to use Certbot in standalone mode * Messaging This commit also introduces the following behavioral changes: * Attempt to install Certbot only when it is not installed already * Installation of the cron job has to be enabled using `--automatic-renewal` parameter **Note:** Object ID is now treated as certificate name and new required parameter `--domain` was added.
This commit is contained in:
parent
543bc8fed9
commit
22d570ae60
14 changed files with 239 additions and 105 deletions
3
cdist/conf/type/__letsencrypt_cert/explorer/certbot-path
Executable file
3
cdist/conf/type/__letsencrypt_cert/explorer/certbot-path
Executable file
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
command -v certbot 2>/dev/null || true
|
4
cdist/conf/type/__letsencrypt_cert/explorer/certificate-domains
Executable file
4
cdist/conf/type/__letsencrypt_cert/explorer/certificate-domains
Executable file
|
@ -0,0 +1,4 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
certbot certificates --cert-name "${__object_id:?}" | grep ' Domains: ' | \
|
||||||
|
cut -d ' ' -f 6- | tr ' ' '\n'
|
7
cdist/conf/type/__letsencrypt_cert/explorer/certificate-exists
Executable file
7
cdist/conf/type/__letsencrypt_cert/explorer/certificate-exists
Executable file
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
if certbot certificates | grep -q " Certificate Name: ${__object_id:?}$"; then
|
||||||
|
echo yes
|
||||||
|
else
|
||||||
|
echo no
|
||||||
|
fi
|
8
cdist/conf/type/__letsencrypt_cert/explorer/certificate-is-test
Executable file
8
cdist/conf/type/__letsencrypt_cert/explorer/certificate-is-test
Executable file
|
@ -0,0 +1,8 @@
|
||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
if certbot certificates --cert-name "${__object_id:?}" | \
|
||||||
|
grep -q 'INVALID: TEST_CERT'; then
|
||||||
|
echo yes
|
||||||
|
else
|
||||||
|
echo no
|
||||||
|
fi
|
|
@ -1,5 +0,0 @@
|
||||||
domain=$__object_id
|
|
||||||
|
|
||||||
if [ -f "/etc/letsencrypt/live/$domain/fullchain.pem" ]; then
|
|
||||||
echo yes
|
|
||||||
fi
|
|
77
cdist/conf/type/__letsencrypt_cert/gencode-remote
Normal file → Executable file
77
cdist/conf/type/__letsencrypt_cert/gencode-remote
Normal file → Executable file
|
@ -1,18 +1,75 @@
|
||||||
domain="$__object_id"
|
#!/bin/sh -e
|
||||||
|
|
||||||
exists=$(cat "$__object/explorer/exists")
|
certificate_exists=$(cat "${__object:?}/explorer/certificate-exists")
|
||||||
webroot="$(cat "$__object/parameter/webroot")"
|
name="${__object_id:?}"
|
||||||
admin_email="$(cat "$__object/parameter/admin-email")"
|
state=$(cat "${__object}/parameter/state")
|
||||||
|
|
||||||
if [ -n "$exists" ]; then
|
case "${state}" in
|
||||||
|
absent)
|
||||||
|
if [ "${certificate_exists}" = "no" ]; then
|
||||||
exit 0
|
exit 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cat <<EOF
|
echo "certbot delete --cert-name '${name}' --quiet"
|
||||||
if [ ! -d "$webroot" ]; then
|
|
||||||
mkdir -p "$webroot"
|
echo remove >> "${__messages_out:?}"
|
||||||
|
;;
|
||||||
|
present)
|
||||||
|
requested_domains="${__object}/parameter/domain"
|
||||||
|
|
||||||
|
staging=no
|
||||||
|
if [ -f "${__object}/parameter/staging" ]; then
|
||||||
|
staging=yes
|
||||||
fi
|
fi
|
||||||
|
|
||||||
certbot certonly -n --agree-tos --email '$admin_email' --quiet --webroot \
|
if [ "${certificate_exists}" = "yes" ]; then
|
||||||
-w '$webroot' -d '$domain'
|
existing_domains="${__object}/explorer/certificate-domains"
|
||||||
|
certificate_is_test=$(cat "${__object}/explorer/certificate-is-test")
|
||||||
|
|
||||||
|
sort -uo "${requested_domains}" "${requested_domains}"
|
||||||
|
sort -uo "${existing_domains}" "${existing_domains}"
|
||||||
|
|
||||||
|
if [ -z "$(comm -23 "${requested_domains}" "${existing_domains}")" ] && \
|
||||||
|
[ "${certificate_is_test}" = "${staging}" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
admin_email="$(cat "$__object/parameter/admin-email")"
|
||||||
|
webroot="$(cat "$__object/parameter/webroot")"
|
||||||
|
|
||||||
|
cat <<-EOF
|
||||||
|
certbot certonly \
|
||||||
|
--agree-tos \
|
||||||
|
--cert-name '${name}' \
|
||||||
|
--email '${admin_email}' \
|
||||||
|
--expand \
|
||||||
|
--non-interactive \
|
||||||
|
--quiet \
|
||||||
|
$(if [ "${staging}" = "yes" ]; then
|
||||||
|
echo "--staging"
|
||||||
|
elif [ "${certificate_is_test}" != "${staging}" ]; then
|
||||||
|
echo "--force-renewal"
|
||||||
|
fi) \
|
||||||
|
$(if [ -z "${webroot}" ]; then
|
||||||
|
echo "--standalone"
|
||||||
|
else
|
||||||
|
echo "--webroot --webroot-path '${webroot}'"
|
||||||
|
fi) \
|
||||||
|
$(while read -r domain; do
|
||||||
|
echo "--domain '${domain}' \\"
|
||||||
|
done < "${requested_domains}")
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
if [ "${certificate_exists}" = "no" ]; then
|
||||||
|
echo create >> "${__messages_out}"
|
||||||
|
else
|
||||||
|
echo change >> "${__messages_out}"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unsupported state: ${state}" >&2
|
||||||
|
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
|
@ -3,54 +3,95 @@ cdist-type__letsencrypt_cert(7)
|
||||||
|
|
||||||
NAME
|
NAME
|
||||||
----
|
----
|
||||||
cdist-type__letsencrypt_cert - Get an SSL certificate from Let's Encrypt
|
|
||||||
|
|
||||||
|
cdist-type__letsencrypt_cert - Get an SSL certificate from Let's Encrypt
|
||||||
|
|
||||||
DESCRIPTION
|
DESCRIPTION
|
||||||
-----------
|
-----------
|
||||||
Automatically obtain a Let's Encrypt SSL certificate. Uses certbot's webroot
|
|
||||||
method. You must set up your web server to work with webroot.
|
|
||||||
|
|
||||||
|
Automatically obtain a Let's Encrypt SSL certificate using Certbot.
|
||||||
|
|
||||||
REQUIRED PARAMETERS
|
REQUIRED PARAMETERS
|
||||||
-------------------
|
-------------------
|
||||||
webroot
|
|
||||||
The path to your webroot, as set up in your webserver config.
|
|
||||||
|
|
||||||
admin-email
|
admin-email
|
||||||
Where to send Let's Encrypt emails like "certificate needs renewal".
|
Where to send Let's Encrypt emails like "certificate needs renewal".
|
||||||
|
|
||||||
|
REQUIRED MULTIPLE PARAMETERS
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
domain
|
||||||
|
A domain to be included in the certificate.
|
||||||
|
|
||||||
OPTIONAL PARAMETERS
|
OPTIONAL PARAMETERS
|
||||||
-------------------
|
-------------------
|
||||||
None.
|
|
||||||
|
|
||||||
|
state
|
||||||
|
'present' or 'absent', defaults to 'present' where:
|
||||||
|
|
||||||
|
present
|
||||||
|
if the certificate does not exist, it will be obtained
|
||||||
|
absent
|
||||||
|
the certificate will be removed
|
||||||
|
|
||||||
|
webroot
|
||||||
|
The path to your webroot, as set up in your webserver config. If this
|
||||||
|
parameter is not present, Certbot will be run in standalone mode.
|
||||||
|
|
||||||
OPTIONAL MULTIPLE PARAMETERS
|
OPTIONAL MULTIPLE PARAMETERS
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
renew-hook
|
renew-hook
|
||||||
Renew hook command directly passed to certbot in cron job.
|
Renew hook command directly passed to Certbot in cron job.
|
||||||
|
|
||||||
|
BOOLEAN PARAMETERS
|
||||||
|
------------------
|
||||||
|
|
||||||
|
automatic-renewal
|
||||||
|
Install a cron job, which attempts to renew certificates daily.
|
||||||
|
|
||||||
|
staging
|
||||||
|
Obtain a test certificate from a staging server.
|
||||||
|
|
||||||
|
MESSAGES
|
||||||
|
--------
|
||||||
|
|
||||||
|
change
|
||||||
|
Certificte was changed.
|
||||||
|
|
||||||
|
create
|
||||||
|
Certificte was created.
|
||||||
|
|
||||||
|
remove
|
||||||
|
Certificte was removed.
|
||||||
|
|
||||||
EXAMPLES
|
EXAMPLES
|
||||||
--------
|
--------
|
||||||
|
|
||||||
.. code-block:: sh
|
.. code-block:: sh
|
||||||
|
|
||||||
__letsencrypt_cert example.com --admin-email root@example.com --webroot /data/letsencrypt/root
|
__letsencrypt_cert example.com \
|
||||||
|
--admin-email root@example.com \
|
||||||
__letsencrypt_cert example.com --admin-email root@example.com --webroot /data/letsencrypt/root --renew-hook "service nginx reload"
|
--automatic-renewal \
|
||||||
|
--domain example.com \
|
||||||
|
--domain foo.example.com \
|
||||||
|
--domain bar.example.com \
|
||||||
|
--renew-hook "service nginx reload" \
|
||||||
|
--webroot /data/letsencrypt/root
|
||||||
|
|
||||||
|
|
||||||
AUTHORS
|
AUTHORS
|
||||||
-------
|
-------
|
||||||
|
|
||||||
| Nico Schottelius <nico-cdist--@--schottelius.org>
|
| Nico Schottelius <nico-cdist--@--schottelius.org>
|
||||||
| Kamila Součková <kamila--@--ksp.sk>
|
| Kamila Součková <kamila--@--ksp.sk>
|
||||||
| Darko Poljak <darko.poljak--@--gmail.com>
|
| Darko Poljak <darko.poljak--@--gmail.com>
|
||||||
|
| Ľubomír Kučera <lubomir.kucera.jr at gmail.com>
|
||||||
|
|
||||||
COPYING
|
COPYING
|
||||||
-------
|
-------
|
||||||
Copyright \(C) 2017 Nico Schottelius, Kamila Součková, Darko Poljak. You can redistribute it
|
|
||||||
and/or modify it under the terms of the GNU General Public License as
|
Copyright \(C) 2017-2018 Nico Schottelius, Kamila Součková, Darko Poljak and
|
||||||
published by the Free Software Foundation, either version 3 of the
|
Ľubomír Kučera. You can redistribute it and/or modify it under the terms of
|
||||||
License, or (at your option) any later version.
|
the GNU General Public License as published by the Free Software Foundation,
|
||||||
|
either version 3 of the License, or (at your option) any later version.
|
||||||
|
|
40
cdist/conf/type/__letsencrypt_cert/manifest
Normal file → Executable file
40
cdist/conf/type/__letsencrypt_cert/manifest
Normal file → Executable file
|
@ -1,5 +1,10 @@
|
||||||
os=$(cat "$__global/explorer/os")
|
#!/bin/sh
|
||||||
os_version=$(cat "$__global/explorer/os_version")
|
|
||||||
|
certbot_fullpath="$(cat "${__object:?}/explorer/certbot-path")"
|
||||||
|
|
||||||
|
if [ -z "${certbot_fullpath}" ]; then
|
||||||
|
os="$(cat "${__global:?}/explorer/os")"
|
||||||
|
os_version="$(cat "${__global}/explorer/os_version")"
|
||||||
|
|
||||||
case "$os" in
|
case "$os" in
|
||||||
debian)
|
debian)
|
||||||
|
@ -10,8 +15,10 @@ case "$os" in
|
||||||
--distribution jessie-backports \
|
--distribution jessie-backports \
|
||||||
--component main
|
--component main
|
||||||
|
|
||||||
require="__apt_source/jessie-backports" __package_apt python-certbot --target-release jessie-backports
|
require="__apt_source/jessie-backports" __package_apt python-certbot \
|
||||||
require="__apt_source/jessie-backports" __package_apt certbot --target-release jessie-backports
|
--target-release jessie-backports
|
||||||
|
require="__apt_source/jessie-backports" __package_apt certbot \
|
||||||
|
--target-release jessie-backports
|
||||||
# Seems to be a missing dependency on debian 8
|
# Seems to be a missing dependency on debian 8
|
||||||
__package python-ndg-httpsclient
|
__package python-ndg-httpsclient
|
||||||
;;
|
;;
|
||||||
|
@ -21,8 +28,10 @@ case "$os" in
|
||||||
--distribution stretch-backports \
|
--distribution stretch-backports \
|
||||||
--component main
|
--component main
|
||||||
|
|
||||||
require="__apt_source/stretch-backports" __package_apt python-certbot --target-release stretch-backports
|
require="__apt_source/stretch-backports" __package_apt python-certbot \
|
||||||
require="__apt_source/stretch-backports" __package_apt certbot --target-release stretch-backports
|
--target-release stretch-backports
|
||||||
|
require="__apt_source/stretch-backports" __package_apt certbot \
|
||||||
|
--target-release stretch-backports
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Unsupported OS version: $os_version" >&2
|
echo "Unsupported OS version: $os_version" >&2
|
||||||
|
@ -40,8 +49,10 @@ case "$os" in
|
||||||
--distribution jessie-backports \
|
--distribution jessie-backports \
|
||||||
--component main
|
--component main
|
||||||
|
|
||||||
require="__apt_source/jessie-backports" __package_apt python-certbot --target-release jessie-backports
|
require="__apt_source/jessie-backports" __package_apt python-certbot \
|
||||||
require="__apt_source/jessie-backports" __package_apt certbot --target-release jessie-backports
|
--target-release jessie-backports
|
||||||
|
require="__apt_source/jessie-backports" __package_apt certbot \
|
||||||
|
--target-release jessie-backports
|
||||||
# Seems to be a missing dependency on debian 8
|
# Seems to be a missing dependency on debian 8
|
||||||
__package python-ndg-httpsclient
|
__package python-ndg-httpsclient
|
||||||
;;
|
;;
|
||||||
|
@ -63,17 +74,20 @@ case "$os" in
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
fi
|
||||||
|
|
||||||
renew_hook_param="$__object/parameter/renew-hook"
|
if [ -f "${__object}/parameter/automatic-renewal" ]; then
|
||||||
|
renew_hook_param="${__object}/parameter/renew-hook"
|
||||||
renew_hook=""
|
renew_hook=""
|
||||||
if [ -f "$renew_hook_param" ]; then
|
if [ -f "${renew_hook_param}" ]; then
|
||||||
while read hook; do
|
while read hook; do
|
||||||
renew_hook="$renew_hook --renew-hook \"$hook\""
|
renew_hook="${renew_hook} --renew-hook \"${hook}\""
|
||||||
done < "$renew_hook_param"
|
done < "${renew_hook_param}"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
__cron letsencrypt-certbot \
|
__cron letsencrypt-certbot \
|
||||||
--user root \
|
--user root \
|
||||||
--command "$certbot_fullpath renew -q $renew_hook" \
|
--command "${certbot_fullpath} renew -q ${renew_hook}" \
|
||||||
--hour 0 \
|
--hour 0 \
|
||||||
--minute 47
|
--minute 47
|
||||||
|
fi
|
||||||
|
|
2
cdist/conf/type/__letsencrypt_cert/parameter/boolean
Normal file
2
cdist/conf/type/__letsencrypt_cert/parameter/boolean
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
automatic-renewal
|
||||||
|
staging
|
|
@ -0,0 +1 @@
|
||||||
|
present
|
2
cdist/conf/type/__letsencrypt_cert/parameter/optional
Normal file
2
cdist/conf/type/__letsencrypt_cert/parameter/optional
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
state
|
||||||
|
webroot
|
|
@ -1,2 +1 @@
|
||||||
admin-email
|
admin-email
|
||||||
webroot
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
domain
|
Loading…
Reference in a new issue