Import __uacme* and __recycledcloud_nginx* logic
This commit is contained in:
parent
ca4f833a56
commit
2dfb059b20
29 changed files with 792 additions and 0 deletions
33
type/__recycledcloud_nginx/man.rst
Normal file
33
type/__recycledcloud_nginx/man.rst
Normal file
|
@ -0,0 +1,33 @@
|
|||
cdist-type__recycledcloud_nginx(7)
|
||||
===================================
|
||||
|
||||
NAME
|
||||
----
|
||||
cdist-type__recycledcloud_nginx - Serve web content with NGINX
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
Leverages `__recycledcloud_nginx_vhost` to serve web content.
|
||||
|
||||
REQUIRED PARAMETERS
|
||||
-------------------
|
||||
domain
|
||||
Domain name to be served.
|
||||
|
||||
OPTIONAL PARAMETERS
|
||||
-------------------
|
||||
config
|
||||
Custom NGINX logic, templated within a standard `server` section with
|
||||
`server_name` and TLS parameters set. Defaults to simple static hosting.
|
||||
|
||||
AUTHORS
|
||||
-------
|
||||
Timothée Floure <timothee.floure@posteo.net>
|
||||
|
||||
COPYING
|
||||
-------
|
||||
Copyright \(C) 2020 Joachim Desroches. You can redistribute it
|
||||
and/or modify it under the terms of 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.
|
49
type/__recycledcloud_nginx/manifest
Normal file
49
type/__recycledcloud_nginx/manifest
Normal file
|
@ -0,0 +1,49 @@
|
|||
#!/bin/sh
|
||||
|
||||
os="$(cat "${__global:?}"/explorer/os)"
|
||||
case "$os" in
|
||||
alpine)
|
||||
nginx_user=nginx
|
||||
nginx_certdir=/etc/nginx/ssl
|
||||
;;
|
||||
*)
|
||||
echo "This type does not support $os yet. Aborting." >&2;
|
||||
exit 1;
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -f "${__object:?}/parameter/domain" ];
|
||||
then
|
||||
domain="$(cat "${__object:?}/parameter/domain")"
|
||||
else
|
||||
domain="${__object_id:?}"
|
||||
fi
|
||||
|
||||
# Deploy simple HTTP vhost, allowing to serve ACME challenges.
|
||||
__recycledcloud_nginx_vhost "301-to-https-$domain" \
|
||||
--domain "$domain" --to-https
|
||||
|
||||
# Obtaining TLS cert.
|
||||
__uacme_account
|
||||
require="__recycledcloud_nginx_vhost/301-to-https-$domain __uacme_account" \
|
||||
__uacme_obtain "$domain" --owner $nginx_user \
|
||||
--install-key-to "$nginx_certdir/$domain/privkey.pem" \
|
||||
--install-cert-to "/$nginx_certdir/$domain/fullchain.pem" \
|
||||
--renew-hook "service nginx reload"
|
||||
|
||||
# Deploy HTTPS nginx vhost.
|
||||
if [ -f "${__object:?}/parameter/config" ]; then
|
||||
if [ "$(cat "${__object:?}/parameter/config")" = "-" ]; then
|
||||
nginx_logic="${__object:?}/stdin"
|
||||
else
|
||||
nginx_logic="${__object:?}/parameter/config"
|
||||
fi
|
||||
|
||||
mkdir -p "${__object:?}/files"
|
||||
cat "$nginx_logic" > "${__object:?}/files/config"
|
||||
|
||||
require="__uacme_obtain/$domain" __recycledcloud_nginx_vhost "$domain" \
|
||||
--config "${__object:?}/files/config"
|
||||
else
|
||||
require="__uacme_obtain/$domain" __recycledcloud_nginx_vhost "$domain"
|
||||
fi
|
2
type/__recycledcloud_nginx/parameter/optional
Normal file
2
type/__recycledcloud_nginx/parameter/optional
Normal file
|
@ -0,0 +1,2 @@
|
|||
config
|
||||
domain
|
4
type/__recycledcloud_nginx_vhost/files/301-to-https
Normal file
4
type/__recycledcloud_nginx_vhost/files/301-to-https
Normal file
|
@ -0,0 +1,4 @@
|
|||
# Redirect request to this page in HTTPS.
|
||||
location / {
|
||||
return 301 https://$host$request_uri;
|
||||
}
|
37
type/__recycledcloud_nginx_vhost/files/generic.conf.sh
Executable file
37
type/__recycledcloud_nginx_vhost/files/generic.conf.sh
Executable file
|
@ -0,0 +1,37 @@
|
|||
#!/bin/sh
|
||||
# Template for static NGINX hosting.
|
||||
|
||||
echo 'server {'
|
||||
|
||||
# Listen
|
||||
cat <<- EOF
|
||||
listen ${LPORT:?} $TLS;
|
||||
listen [::]:${LPORT:?} $TLS;
|
||||
EOF
|
||||
|
||||
# Name
|
||||
echo "server_name ${DOMAIN:?};"
|
||||
|
||||
# ACME challenges.
|
||||
cat << EOF
|
||||
location /.well-known/acme-challenge/ {
|
||||
alias ${ACME_CHALLENGE_DIR:?};
|
||||
}
|
||||
EOF
|
||||
|
||||
if [ -n "$TLS" ];
|
||||
then
|
||||
if [ -n "$HSTS" ];
|
||||
then
|
||||
echo 'include snippets/hsts;'
|
||||
fi
|
||||
|
||||
cat <<- EOF
|
||||
ssl_certificate ${NGINX_CERTDIR:?}/${DOMAIN:?}/fullchain.pem;
|
||||
ssl_certificate_key ${NGINX_CERTDIR:?}/${DOMAIN:?}/privkey.pem;
|
||||
EOF
|
||||
fi
|
||||
|
||||
echo "${NGINX_LOGIC:?}"
|
||||
|
||||
echo '}'
|
1
type/__recycledcloud_nginx_vhost/files/hsts
Normal file
1
type/__recycledcloud_nginx_vhost/files/hsts
Normal file
|
@ -0,0 +1 @@
|
|||
add_header Strict-Transport-Security "max-age=31536000" always;
|
12
type/__recycledcloud_nginx_vhost/files/index.html
Normal file
12
type/__recycledcloud_nginx_vhost/files/index.html
Normal file
|
@ -0,0 +1,12 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>cdist configured!</title>
|
||||
</head>
|
||||
<body>
|
||||
You have successfully configured a vhost with
|
||||
<a href="https://cdi.st">cdist</a>. You can now upload content!
|
||||
</body>
|
||||
</html>
|
13
type/__recycledcloud_nginx_vhost/files/static.conf.sh
Executable file
13
type/__recycledcloud_nginx_vhost/files/static.conf.sh
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/bin/sh
|
||||
# Template for static NGINX hosting.
|
||||
|
||||
NGINX_LOGIC="$(cat << EOF
|
||||
location / {
|
||||
root ${NGINX_WEBROOT:?}/${DOMAIN:?};
|
||||
index index.html;
|
||||
}
|
||||
EOF
|
||||
)"
|
||||
export NGINX_LOGIC
|
||||
|
||||
"${__object:?}/files/generic.conf.sh"
|
25
type/__recycledcloud_nginx_vhost/files/to-https.conf.sh
Executable file
25
type/__recycledcloud_nginx_vhost/files/to-https.conf.sh
Executable file
|
@ -0,0 +1,25 @@
|
|||
#!/bin/sh
|
||||
# Template for HTTPS redirection.
|
||||
|
||||
echo 'server {'
|
||||
|
||||
# Listen
|
||||
cat <<- EOF
|
||||
listen ${LPORT:?};
|
||||
listen [::]:${LPORT:?};
|
||||
EOF
|
||||
|
||||
# Name
|
||||
echo "server_name ${DOMAIN:?};"
|
||||
|
||||
# ACME challenges.
|
||||
cat << EOF
|
||||
location /.well-known/acme-challenge/ {
|
||||
alias ${ACME_CHALLENGE_DIR:?};
|
||||
}
|
||||
EOF
|
||||
|
||||
# HTTPS redirection.
|
||||
echo 'include snippets/301-to-https;'
|
||||
|
||||
echo '}'
|
15
type/__recycledcloud_nginx_vhost/gencode-remote
Normal file
15
type/__recycledcloud_nginx_vhost/gencode-remote
Normal file
|
@ -0,0 +1,15 @@
|
|||
#!/bin/sh
|
||||
|
||||
# Check configuration and reload if valid.
|
||||
# TODO: only check if configuration was changed (= listen for __file's
|
||||
# messages).
|
||||
cat << EOF
|
||||
if nginx -t; then
|
||||
service nginx --ifstarted reload
|
||||
service nginx --ifstopped start
|
||||
else
|
||||
echo "NGINX configuration is invalid. Exiting." >2&
|
||||
nginx -t >2&
|
||||
exit 1
|
||||
fi
|
||||
EOF
|
80
type/__recycledcloud_nginx_vhost/man.rst
Normal file
80
type/__recycledcloud_nginx_vhost/man.rst
Normal file
|
@ -0,0 +1,80 @@
|
|||
cdist-type__nginx_vhost(7)
|
||||
===================================
|
||||
|
||||
NAME
|
||||
----
|
||||
cdist-type__nginx_vhost - Have nginx serve content for a virtual host
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
This type setups up nginx with reasonable defaults and creates a vhost to be
|
||||
served, optionally with TLS certificates obtained from the Let's Encrypt CA
|
||||
through the ACME HTTP-01 challenge-response mechanism.
|
||||
|
||||
By default, if no rules are specified, then the vhost will serve as-is the
|
||||
contents of the `WEBROOT/foo.com` directory, where WEBROOT is
|
||||
determined depending on the OS, adhering as close to `hier(7)` as possible.
|
||||
|
||||
NGINX expects files in the vhost to be served to be at least readable by the
|
||||
`USER` group, that it creates if it does not exist. It is recommended to have
|
||||
the user owning the files to be someone else, and the files beeing
|
||||
group-readable but not writeable.
|
||||
|
||||
Finally, if TLS is not disabled, then this type makes nginx expect the
|
||||
fullchain certificate and the private key in
|
||||
`CERTDIR/domain/{fullchain,privkey}.pem`.
|
||||
|
||||
+------------------+---------+-------------------+-----------------------------+
|
||||
| Operating System | USER | WEBROOT | CERTDIR |
|
||||
+==================+=========+===================+=============================+
|
||||
| Alpine Linux | `nginx` | `/srv/www/` | `/etc/nginx/ssl/` |
|
||||
+------------------+---------+-------------------+-----------------------------+
|
||||
| Arch Linux | `www` | `/srv/www/` | `/etc/nginx/ssl/` |
|
||||
+------------------+---------+-------------------+-----------------------------+
|
||||
| FreeBSD | `www` | `/usr/local/www/` | `/usr/local/etc/nginx/ssl/` |
|
||||
+------------------+---------+-------------------+-----------------------------+
|
||||
|
||||
OPTIONAL PARAMETERS
|
||||
-------------------
|
||||
|
||||
config
|
||||
A custom configuration file for the vhost, inserted in a server section
|
||||
populated with `server_name` and TLS parameters unless `--standalone-config`
|
||||
is specified. Can be specified either as a file path, or if the value of this
|
||||
flag is '-', then the configuration is read from stdin.
|
||||
|
||||
domain
|
||||
The domain this server will respond to. If this is omitted, then the
|
||||
`__object_id` is used.
|
||||
|
||||
lport
|
||||
The port to which we listen. If this is omitted, the defaults of `80` for
|
||||
HTTP and `443` for HTTPS are used.
|
||||
|
||||
BOOLEAN PARAMETERS
|
||||
------------------
|
||||
|
||||
no-hsts
|
||||
Do not use HSTS pinning.
|
||||
|
||||
no-tls
|
||||
Do not serve over HTTPS.
|
||||
|
||||
to-https
|
||||
Ignore --config flag and redirect to HTTPS. Implies --no-tls.
|
||||
|
||||
standalone-config
|
||||
Insert the content of
|
||||
|
||||
AUTHORS
|
||||
-------
|
||||
Joachim Desroches <joachim.desroches@epfl.ch>
|
||||
Timothée Floure <timothee.floure@posteo.net>
|
||||
|
||||
COPYING
|
||||
-------
|
||||
Copyright \(C) 2020 Joachim Desroches. You can redistribute it
|
||||
and/or modify it under the terms of 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.
|
144
type/__recycledcloud_nginx_vhost/manifest
Normal file
144
type/__recycledcloud_nginx_vhost/manifest
Normal file
|
@ -0,0 +1,144 @@
|
|||
#!/bin/sh
|
||||
#
|
||||
# 2020 Joachim Desroches <joachim.desroches@epfl.ch>
|
||||
#
|
||||
# This file is part of cdist.
|
||||
#
|
||||
# cdist is free software: you can redistribute it and/or modify
|
||||
# it under the terms of 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.
|
||||
#
|
||||
# cdist is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with cdist. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
# Create NGINX vhosts
|
||||
|
||||
os="$(cat "${__global:?}"/explorer/os)"
|
||||
mkdir -p "${__object:?}/files"
|
||||
|
||||
case "$os" in
|
||||
"alpine")
|
||||
__package nginx
|
||||
|
||||
nginx_confdir="/etc/nginx"
|
||||
install_reqs="__package/nginx"
|
||||
|
||||
require="$install_reqs" __service nginx --action start
|
||||
require="$install_reqs" __start_on_boot nginx
|
||||
|
||||
export NGINX_SITEDIR="$nginx_confdir/conf.d"
|
||||
export NGINX_CERTDIR="$nginx_confdir/ssl"
|
||||
export NGINX_SNIPPETSDIR="$nginx_confdir/snippets"
|
||||
export NGINX_WEBROOT="/var/www"
|
||||
export ACME_CHALLENGE_DIR="$NGINX_WEBROOT/.well-known/acme-challenge/"
|
||||
;;
|
||||
*)
|
||||
echo "__nginx_vhost does not support $os yet. Aborting." >&2;
|
||||
exit 1;
|
||||
esac
|
||||
|
||||
# Domain
|
||||
if [ -f "${__object:?}/parameter/domain" ];
|
||||
then
|
||||
DOMAIN="$(cat "${__object:?}/parameter/domain")"
|
||||
else
|
||||
DOMAIN="${__object_id:?}"
|
||||
fi
|
||||
export DOMAIN
|
||||
|
||||
# Use TLS ?
|
||||
if [ -f "${__object:?}/parameter/no-tls" ];
|
||||
then
|
||||
TLS=
|
||||
echo "WARNING: you have disabled TLS for vhost $DOMAIN" >&2
|
||||
else
|
||||
TLS=ssl
|
||||
fi
|
||||
export TLS
|
||||
|
||||
# Use HSTS ?
|
||||
if [ -f "${__object:?}/parameter/no-hsts" ];
|
||||
then
|
||||
HSTS=
|
||||
else
|
||||
HSTS=true
|
||||
fi
|
||||
export HSTS
|
||||
|
||||
# Redirect to HTTPS ?
|
||||
if [ -f "${__object:?}/parameter/to-https" ];
|
||||
then
|
||||
TO_HTTPS=true
|
||||
else
|
||||
TO_HTTPS=
|
||||
fi
|
||||
export HSTS
|
||||
|
||||
# Port to listen on
|
||||
if [ -f "${__object:?}/parameter/lport" ];
|
||||
then
|
||||
LPORT="$(cat "${__object:?}/parameter/lport")"
|
||||
else
|
||||
if [ -n "$TLS" ] && [ -z "$TO_HTTPS" ];
|
||||
then
|
||||
LPORT=443
|
||||
else
|
||||
LPORT=80
|
||||
fi
|
||||
fi
|
||||
export LPORT
|
||||
|
||||
# Server definition
|
||||
if [ -n "$TO_HTTPS" ];
|
||||
then
|
||||
# Ignore configuration, simply serve ACME challenge and redirect to HTTPS.
|
||||
"${__type:?}/files/to-https.conf.sh" > "${__object:?}/files/vhost.conf"
|
||||
vhost_conf="${__object:?}/files/vhost.conf"
|
||||
elif [ -f "${__object:?}/parameter/config" ];
|
||||
then
|
||||
# Extract nginx config from type parameter.
|
||||
if [ "$(cat "${__object:?}/parameter/config")" = "-" ];
|
||||
then
|
||||
vhost_partial="${__object:?}/stdin"
|
||||
else
|
||||
vhost_partial=$(cat "${__object:?}/parameter/config")
|
||||
fi
|
||||
|
||||
# Either use config as-in or template it in generic vhost structure.
|
||||
if [ -f "${__object:?}/parameter/standalone-config" ]; then
|
||||
vhost_conf=$vhost_partial
|
||||
else
|
||||
NGINX_LOGIC=$(cat "$vhost_partial") "${__type:?}/files/generic.conf.sh" \
|
||||
> "${__object:?}/files/vhost.conf"
|
||||
|
||||
vhost_conf="${__object:?}/files/vhost.conf"
|
||||
fi
|
||||
else
|
||||
# Default to simple static configuration.
|
||||
"${__type:?}/files/static.conf.sh" > "${__object:?}/files/vhost.conf"
|
||||
vhost_conf="${__object:?}/files/vhost.conf"
|
||||
|
||||
require="$install_reqs" __directory "$NGINX_WEBROOT/$DOMAIN"
|
||||
require="__directory$NGINX_WEBROOT/$DOMAIN" \
|
||||
__file "$NGINX_WEBROOT/$DOMAIN/index.html" --state exists \
|
||||
--source "${__type:?}/files/index.html" \
|
||||
--mode 0644
|
||||
fi
|
||||
|
||||
# Install snippets.
|
||||
require="$install_reqs" __directory "$NGINX_SNIPPETSDIR"
|
||||
for snippet in hsts 301-to-https; do
|
||||
require="__directory/$NGINX_SNIPPETSDIR" __file \
|
||||
"$NGINX_SNIPPETSDIR/$snippet" --source "${__type:?}/files/$snippet"
|
||||
done
|
||||
|
||||
# Install vhost.
|
||||
require="$install_reqs" __file "$NGINX_SITEDIR/$__object_id.conf" \
|
||||
--source "$vhost_conf" \
|
||||
--mode 0644
|
4
type/__recycledcloud_nginx_vhost/parameter/boolean
Normal file
4
type/__recycledcloud_nginx_vhost/parameter/boolean
Normal file
|
@ -0,0 +1,4 @@
|
|||
no-tls
|
||||
no-hsts
|
||||
to-https
|
||||
standalone-config
|
7
type/__recycledcloud_nginx_vhost/parameter/boolean.orig
Normal file
7
type/__recycledcloud_nginx_vhost/parameter/boolean.orig
Normal file
|
@ -0,0 +1,7 @@
|
|||
<<<<<<< HEAD
|
||||
noindex
|
||||
=======
|
||||
no-tls
|
||||
no-hsts
|
||||
obtain-cert
|
||||
>>>>>>> 65f3457... Move out ungleich legacy type; merge presets, static and vhost.
|
1
type/__recycledcloud_nginx_vhost/parameter/default/index
Normal file
1
type/__recycledcloud_nginx_vhost/parameter/default/index
Normal file
|
@ -0,0 +1 @@
|
|||
index.html index.htm
|
3
type/__recycledcloud_nginx_vhost/parameter/optional
Normal file
3
type/__recycledcloud_nginx_vhost/parameter/optional
Normal file
|
@ -0,0 +1,3 @@
|
|||
domain
|
||||
lport
|
||||
config
|
7
type/__recycledcloud_nginx_vhost/parameter/optional.orig
Normal file
7
type/__recycledcloud_nginx_vhost/parameter/optional.orig
Normal file
|
@ -0,0 +1,7 @@
|
|||
<<<<<<< HEAD
|
||||
index
|
||||
=======
|
||||
domain
|
||||
lport
|
||||
config
|
||||
>>>>>>> 65f3457... Move out ungleich legacy type; merge presets, static and vhost.
|
32
type/__uacme_account/gencode-remote
Normal file
32
type/__uacme_account/gencode-remote
Normal file
|
@ -0,0 +1,32 @@
|
|||
#!/bin/sh
|
||||
|
||||
os="$(cat "${__global:?}"/explorer/os)"
|
||||
|
||||
case "$os" in
|
||||
'alpine')
|
||||
default_confdir=/etc/ssl/uacme
|
||||
;;
|
||||
*)
|
||||
echo "This type currently has no implementation for $os. Aborting." >&2;
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
admin_mail=
|
||||
if [ -f "${__object:?}/parameter/admin-mail" ];
|
||||
then
|
||||
admin_mail="$(cat "${__object:?}/parameter/admin-mail")";
|
||||
fi
|
||||
|
||||
confdir="${default_confdir:?}"
|
||||
if [ -f "${__object:?}/parameter/confdir" ];
|
||||
then
|
||||
confdir="$(cat "${__object:?}/parameter/confdir")"
|
||||
fi
|
||||
|
||||
cat << EOF
|
||||
if ! [ -f "${confdir}/private/key.pem" ];
|
||||
then
|
||||
uacme -y new ${admin_mail}
|
||||
fi
|
||||
EOF
|
50
type/__uacme_account/man.rst
Normal file
50
type/__uacme_account/man.rst
Normal file
|
@ -0,0 +1,50 @@
|
|||
cdist-type__uacme_account(7)
|
||||
============================
|
||||
|
||||
NAME
|
||||
----
|
||||
cdist-type__uacme_account - Install uacme and register Let's Encrypt account.
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
This type is used to bootstrap acquiring certificates from the Let's Encrypt
|
||||
C.A. This type is expected to be used internally, by the `__uacme_obtain`.
|
||||
|
||||
|
||||
OPTIONAL PARAMETERS
|
||||
-------------------
|
||||
confdir
|
||||
An alternative configuration directory for uacme's private keys and
|
||||
certificates.
|
||||
|
||||
admin-mail
|
||||
Administrative contact email to register the account with.
|
||||
|
||||
EXAMPLES
|
||||
--------
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
# Create account with default settings for the OS.
|
||||
__uacme_account
|
||||
|
||||
# Create an account with email and custom location.
|
||||
__uacme_account --confdir /opt/custom/uacme --admin-mail admin@domain.tld
|
||||
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
:strong:`cdist-type__letsencrypt_cert`\ (7)
|
||||
:strong:`cdist-type__uacme_obtain`\ (7)
|
||||
|
||||
AUTHORS
|
||||
-------
|
||||
Joachim Desroches <joachim.desroches@epfl.ch>
|
||||
|
||||
COPYING
|
||||
-------
|
||||
Copyright \(C) 2020 Joachim Desroches. You can redistribute it and/or modify it
|
||||
under the terms of 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.
|
3
type/__uacme_account/manifest
Normal file
3
type/__uacme_account/manifest
Normal file
|
@ -0,0 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
__package uacme
|
2
type/__uacme_account/parameter/optional
Normal file
2
type/__uacme_account/parameter/optional
Normal file
|
@ -0,0 +1,2 @@
|
|||
confdir
|
||||
admin-mail
|
0
type/__uacme_account/singleton
Normal file
0
type/__uacme_account/singleton
Normal file
38
type/__uacme_obtain/files/renew.sh.sh
Executable file
38
type/__uacme_obtain/files/renew.sh.sh
Executable file
|
@ -0,0 +1,38 @@
|
|||
#!/bin/sh
|
||||
|
||||
cat << EOF
|
||||
#!/bin/sh
|
||||
|
||||
set -x
|
||||
|
||||
CERT_SOURCE=$CONFDIR/$MAIN_DOMAIN/cert.pem
|
||||
KEY_SOURCE=$CONFDIR/private/$MAIN_DOMAIN/key.pem
|
||||
|
||||
export UACME_CHALLENGE_PATH=$CHALLENGEDIR
|
||||
|
||||
# Issue certificate.
|
||||
uacme issue -c $CONFDIR -h $HOOKSCRIPT $DISABLE_OCSP $MUST_STABLE $KEYTYPE \
|
||||
$DOMAIN
|
||||
if [ $? -eq 2 ]; then
|
||||
# Note: exit code 0 means that certificate was issued.
|
||||
# Note: exit code 1 means that certificate was still valid, hence not renewed.
|
||||
# Note: exit code 2 means that something went wrong.
|
||||
echo "Failed to renew certificate - exiting." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Re-deploy, if needed.
|
||||
if [ -n "$KEY_TARGET" ] && [ -n "$CERT_TARGET" ]; then
|
||||
set -e
|
||||
|
||||
mkdir -p $(dirname "$CERT_TARGET") $(dirname "$KEY_TARGET")
|
||||
|
||||
if ! cmp \$CERT_SOURCE $CERT_TARGET >/dev/null 2>&1; then
|
||||
install -m 0640 \$KEY_SOURCE $KEY_TARGET
|
||||
install -m 0644 \$CERT_SOURCE $CERT_TARGET
|
||||
chown $OWNER $KEY_TARGET $CERT_TARGET
|
||||
|
||||
$RENEW_HOOK
|
||||
fi
|
||||
fi
|
||||
EOF
|
23
type/__uacme_obtain/gencode-remote
Normal file
23
type/__uacme_obtain/gencode-remote
Normal file
|
@ -0,0 +1,23 @@
|
|||
#!/bin/sh
|
||||
|
||||
# FIXME: this code is duplicated from the manifest -> let's share it somehow.
|
||||
|
||||
os="$(cat "${__global:?}"/explorer/os)"
|
||||
case "$os" in
|
||||
alpine)
|
||||
default_confdir=/etc/ssl/uacme
|
||||
;;
|
||||
*)
|
||||
echo "__uacme_obtain currently has no implementation for $os. Aborting." >&2;
|
||||
exit 1;
|
||||
;;
|
||||
esac
|
||||
|
||||
confdir="${default_confdir:?}"
|
||||
if [ -f "${__object:?}/parameter/confdir" ];
|
||||
then
|
||||
confdir="$(cat "${__object:?}/parameter/confdir")"
|
||||
fi
|
||||
|
||||
# Run renew script 'by hand' - renews will be handled by the cronjob.
|
||||
echo "$confdir/${__object_id:?}/renew.sh"
|
78
type/__uacme_obtain/man.rst
Normal file
78
type/__uacme_obtain/man.rst
Normal file
|
@ -0,0 +1,78 @@
|
|||
cdist-type__uacme_obtain(7)
|
||||
========================
|
||||
|
||||
NAME
|
||||
----
|
||||
cdist-type__uacme_obtain - obtain, renew and deploy Let's Encrypt certificates
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
|
||||
This type leverage uacme to issue abd renew Let's Encrypt certificates and
|
||||
provides a simple deployment mechanism. It is expected to be called after
|
||||
`__uacme_account`.
|
||||
|
||||
REQUIRED PARAMETERS
|
||||
-------------------
|
||||
None.
|
||||
|
||||
OPTIONAL PARAMETERS
|
||||
-------------------
|
||||
challengedir
|
||||
Path to publicly available (served by a third-party HTTP server, under
|
||||
`$DOMAIN/.well-known/acme-challenge`) challenge directory.
|
||||
|
||||
confdir
|
||||
uacme configuration directory.
|
||||
|
||||
hookscript
|
||||
Path to challenge hook program.
|
||||
|
||||
owner
|
||||
Owner of installed certificate (e.g. `www-data`), pass as argument to `chown`.
|
||||
|
||||
install-cert-to
|
||||
Installation path of the issued certificate.
|
||||
|
||||
install-key-to
|
||||
Installation path of the certificate's private key.
|
||||
|
||||
renew-hook
|
||||
Renew hook executed on certificate renewal (e.g. `service nginx reload`).
|
||||
|
||||
OPTIONAL MULTIPLE PARAMETERS
|
||||
-------------------
|
||||
altdomains
|
||||
Alternative domain names for this certificate.
|
||||
|
||||
BOOLEAN PARAMETERS
|
||||
------------------
|
||||
no-ocsp
|
||||
When this flag is *not* specified and the certificate has an Authority
|
||||
Information Access extension with an OCSP server location *uacme* makes an
|
||||
OCSP request to the server; if the certificate is reported as revoked *uacme*
|
||||
forces reissuance regardless of the expiration date.
|
||||
|
||||
must-staple
|
||||
Request certificates with the RFC7633 Certificate Status Request
|
||||
TLS Feature Extension, informally also known as "OCSP Must-Staple".
|
||||
|
||||
use-rsa
|
||||
Use RSA instead of EC for the private key. Only applies to newly generated keys.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
:strong:`cdist-type__letsencrypt_cert`\ (7)
|
||||
:strong:`cdist-type__uacme_account`\ (7)
|
||||
|
||||
AUTHORS
|
||||
-------
|
||||
Joachim Desroches <joachim.desroches@epfl.ch>
|
||||
Timothée Floure <timothee.floure@posteo.net>
|
||||
|
||||
COPYING
|
||||
-------
|
||||
Copyright \(C) 2020 Joachim Desroches. You can redistribute it
|
||||
and/or modify it under the terms of 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.
|
118
type/__uacme_obtain/manifest
Normal file
118
type/__uacme_obtain/manifest
Normal file
|
@ -0,0 +1,118 @@
|
|||
#!/bin/sh
|
||||
|
||||
os="$(cat "${__global:?}"/explorer/os)"
|
||||
case "$os" in
|
||||
alpine)
|
||||
__package uacme
|
||||
|
||||
default_challengedir=/var/www/.well-known/acme-challenge
|
||||
default_hookscript=/usr/share/uacme/uacme.sh
|
||||
default_confdir=/etc/ssl/uacme
|
||||
;;
|
||||
*)
|
||||
echo "__uacme_obtain currently has no implementation for $os. Aborting." >&2;
|
||||
exit 1;
|
||||
;;
|
||||
esac
|
||||
|
||||
CHALLENGEDIR=$default_challengedir
|
||||
if [ -f "${__object:?}/parameter/challengedir" ];
|
||||
then
|
||||
CHALLENGEDIR="$(cat "${__object:?}/parameter/challengedir")"
|
||||
fi
|
||||
export CHALLENGEDIR
|
||||
|
||||
CONFDIR="${default_confdir:?}"
|
||||
if [ -f "${__object:?}/parameter/confdir" ];
|
||||
then
|
||||
CONFDIR="$(cat "${__object:?}/parameter/confdir")"
|
||||
fi
|
||||
export CONFDIR
|
||||
|
||||
DISABLE_OCSP=
|
||||
if [ -f "${__object:?}/parameter/no-ocsp" ];
|
||||
then
|
||||
DISABLE_OCSP="--no-ocsp"
|
||||
fi
|
||||
export DISABLE_OCSP
|
||||
|
||||
MAIN_DOMAIN=${__object_id:?}
|
||||
DOMAIN=$MAIN_DOMAIN
|
||||
if [ -f "${__object:?}/parameter/altdomains" ];
|
||||
then
|
||||
# shellcheck disable=SC2013
|
||||
for altdomain in $(cat "${__object:?}/parameter/altdomains");
|
||||
do
|
||||
DOMAIN="$DOMAIN $altdomain"
|
||||
done
|
||||
fi
|
||||
export MAIN_DOMAIN DOMAIN
|
||||
|
||||
HOOKSCRIPT=${default_hookscript}
|
||||
if [ -f "${__object:?}/parameter/hookscript" ];
|
||||
then
|
||||
HOOKSCRIPT="$(cat "${__object:?}/parameter/hookscript")"
|
||||
fi
|
||||
export HOOKSCRIPT
|
||||
|
||||
KEYTYPE="-t EC"
|
||||
if [ -f "${__object:?}/parameter/use-rsa" ];
|
||||
then
|
||||
KEYTYPE="-t RSA"
|
||||
fi
|
||||
export KEYTYPE
|
||||
|
||||
MUST_STAPLE=
|
||||
if [ -f "${__object:?}/parameter/must-staple" ];
|
||||
then
|
||||
MUST_STAPLE="--must-staple"
|
||||
fi
|
||||
export MUST_STAPLE
|
||||
|
||||
OWNER=root
|
||||
if [ -f "${__object:?}/parameter/owner" ];
|
||||
then
|
||||
OWNER="$(cat "${__object:?}/parameter/owner")"
|
||||
fi
|
||||
export OWNER
|
||||
|
||||
KEY_TARGET=
|
||||
if [ -f "${__object:?}/parameter/install-key-to" ];
|
||||
then
|
||||
KEY_TARGET="$(cat "${__object:?}/parameter/install-key-to")"
|
||||
fi
|
||||
export KEY_TARGET
|
||||
|
||||
CERT_TARGET=
|
||||
if [ -f "${__object:?}/parameter/install-cert-to" ];
|
||||
then
|
||||
CERT_TARGET="$(cat "${__object:?}/parameter/install-cert-to")"
|
||||
fi
|
||||
export CERT_TARGET
|
||||
|
||||
RENEW_HOOK=
|
||||
if [ -f "${__object:?}/parameter/renew-hook" ];
|
||||
then
|
||||
RENEW_HOOK="$(cat "${__object:?}/parameter/renew-hook")"
|
||||
fi
|
||||
export RENEW_HOOK
|
||||
|
||||
if [ -n "$KEY_TARGET" ] && [ -z "$CERT_TARGET" ]; then
|
||||
echo "You cannot specify --install-key-to without --install-cert-to." >&2
|
||||
exit 1
|
||||
elif [ -z "$KEY_TARGET" ] && [ -n "$CERT_TARGET" ]; then
|
||||
echo "You cannot specify --install-cert-to without --install-key-to." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Generate and deploy renew script.
|
||||
mkdir -p "${__object:?}/files"
|
||||
"${__type:?}/files/renew.sh.sh" > "${__object:?}/files/uacme-renew.sh"
|
||||
|
||||
__directory "$CONFDIR/$MAIN_DOMAIN"
|
||||
require="__directory/$CONFDIR/$MAIN_DOMAIN" __file "$CONFDIR/$MAIN_DOMAIN/renew.sh" \
|
||||
--mode 0755 --source "${__object:?}/files/uacme-renew.sh"
|
||||
|
||||
# Set up renew cronjob - initial issue done in gencode-remote.
|
||||
__cron "uacme-$MAIN_DOMAIN" --user root --hour 2 \
|
||||
--command "$CONFDIR/$MAIN_DOMAIN/renew.sh"
|
3
type/__uacme_obtain/parameter/boolean
Normal file
3
type/__uacme_obtain/parameter/boolean
Normal file
|
@ -0,0 +1,3 @@
|
|||
no-ocsp
|
||||
must-staple
|
||||
use-rsa
|
7
type/__uacme_obtain/parameter/optional
Normal file
7
type/__uacme_obtain/parameter/optional
Normal file
|
@ -0,0 +1,7 @@
|
|||
challengedir
|
||||
confdir
|
||||
hookscript
|
||||
owner
|
||||
install-cert-to
|
||||
install-key-to
|
||||
renew-hook
|
1
type/__uacme_obtain/parameter/optional_multiple
Normal file
1
type/__uacme_obtain/parameter/optional_multiple
Normal file
|
@ -0,0 +1 @@
|
|||
altdomains
|
Reference in a new issue