diff --git a/available/README.md b/available/README.md new file mode 100644 index 0000000..3b26e1a --- /dev/null +++ b/available/README.md @@ -0,0 +1,77 @@ +# Hooks + +The hooks in this directory are ready to be symlinked to from whichever hook points you wish to use them for. + +## `reload_` + +Reload a specific service. To use, create a symlink to it in the appropriate hook directory, with the name `reload_{service}` where `{service}` is the name of the service you wish to reload. For example, to reload postfix when a certificate is deployed, create a symlink to `reload_` with the name `reload_postfix` in the `deploy-cert` directory. Combine with `ifdomain_` (see below) to reload services only when the SSL certficiate they use is updated. + +By default will restart the service with `/bin/systemctl`. This can be configured by setting `SYSTEMCTL_CMD` in the dehydrated configuration, for example to use with sudo: + +```bash +echo 'export SYSTEMCTL_CMD="/usr/bin/sudo /bin/systemctl"' >> /etc/dehydrated/conf.d/systemctl_cmd.sh +``` + +## `docker-restart_` + +Restart a specific docker conatiner. To use, create a symlink to it in the appropriate hook directory, with the name `docker-restart_{container}` where `{container}` is the name of the container you wish to restart. For example, to restart the omada container when a certificate is deployed, create a symlink to `docker-restart_` with the name `docker-restart_omada` in the `deploy-cert` directory. Combine with `ifdomain_` (see below) to restart containers only when the SSL certficiate they use is updated. + +By default will restart the container with `/usr/bin/docker`. This can be configured by setting `DOCKER_CMD` in the dehydrated configuration, for example to use with sudo: + +```bash +echo 'export DOCKER_CMD="/usr/bin/sudo /usr/bin/docker"' >> /etc/dehydrated/conf.d/docker_cmd.sh +``` + +## `ifdomain_` + +Only runs the hook if the domain triggering it matches. + +Due to the restrictions of run-parts (only letters, numbers, dashes and underscores are permitted), domains in the filenames need to have the periods replaced with dashes. For example, 'google.co.uk' would be 'google-co-uk' in the filename. + +Use it by creating a symlink with the name `ifdomain_{domain}_{hook to run}`. The hook you want to run must exist in the same directory as the `ifdomain_` script your symlink points to. For example, `ifdomain_myilo-my-domain-tld_hp-ilo-csr` will call the `hp-ilo-csr` hook (in the same directory as `ifdomain_`) only if the domain of the certificate being processed is myilo.my.domain.tld. In this example, you would want to use hp-ilo-csr at the gemerate-csr point so the files could be laid out like this: + +* `available/ifdomain_` +* `available/hp-ilo-csr` +* `generate-csr/ifdomain_myilo-my-domain-tld_hp-ilo-csr` (symlink)=> `../available/ifdomain_` + +This can be combined with other 'chain' hooks, for example `ifdomain_google-co-uk_reload_nginx` will call the `reload_nginx` hook if the domain is 'google.co.uk'. Note that this means you need to create a symlink, in the same place as `ifdomain_` is, called `reload_nginx` pointing to `reload_`, if you want to use that. So, to reload nginx only if the certficate for 'google.co.uk' is updated, this layout of files that would work: + +* `available/ifdomain_` +* `available/reload_` +* `available/reload_nginx` (symlink)=> `reload_` +* `deploy-cert/ifdomain_google-co-uk_reload_nginx` (symlink)=> `../available/ifdomain_` + +## HP iLO scripts + +### Configuration + +To use these scripts, create an ini-style configuration file in _/etc/dehydrated/hp-ilo_ called `{domain}.ini` - for example `my-server-ilo.my-domain.tld.ini` for _my-server-ilo.my-domain.tld_ (note there is no substituion of periods in the domain in this filename) - that looks like this: + +```ini +[ilo] +login = username +password = password + +[certificate] +organizational_unit = my department +organization = my organisation +locality = My city +state = My county +country = GB +``` + +It seems the certificate settings are essentially ignored by Let's Encrypt, however without them you get the HP iLO's built in defaults and I wrote it to use them before I realised it was pointless so they are currently required for the script to work. + +**Make sure to secure the ini file** so only the dehydrated user can read it, as it contains the username and password for your iLO. I highly recommend creating a dedicated user for dehydrated, so it is easy to revoke rights if compromised and it does not need the ability to modify users, access the console or any of the other ilo features (just configure the iLO). + +### `hp-ilo-csr` + +Gets a CSR from a HP iLO out-of-band management controller at the address of the certificate domain (which is the only sensible way - you would not want an iLO certificate for the domain if there were no iLO there). + +You will want to use this at the _generate-csr_ hook stage. + +### `hp-ilo-deploy` + +Deploy a certificate to the HP iLO located at the domain's address. + +You will want to use this at the _deploy-cert_ hook stage. diff --git a/available/docker-restart_ b/available/docker-restart_ new file mode 100644 index 0000000..483c040 --- /dev/null +++ b/available/docker-restart_ @@ -0,0 +1,16 @@ +#!/bin/bash + +# symlink this file to 'docker-restart_' + +filename="$(basename "$0")" +container="${filename#*_}" + +# Override in a config file if needed, e.g. to use sudo: +# echo 'export DOCKER_CMD="/usr/bin/sudo /usr/bin/docker"' >> /etc/dehydrated/conf.d/docker_cmd.sh +if [ -z "$DOCKER_CMD" ] +then + DOCKER_CMD=/usr/bin/docker +fi + +echo "Restarting docker container $service..." +$DOCKER_CMD restart "$container" diff --git a/available/hp-ilo-csr b/available/hp-ilo-csr new file mode 100644 index 0000000..576750d --- /dev/null +++ b/available/hp-ilo-csr @@ -0,0 +1,45 @@ +#!/bin/bash + +ILO_CONF_DIR=/etc/dehydrated/hp-ilo + +ILO_CONF_FILE="$ILO_CONF_DIR/$DOMAIN.ini" + +# Check config file exists +if [ ! -f "$ILO_CONF_FILE" ] +then + echo "No iLO configuration file for $DOMAIN (looked for $DOMAIN.ini in $ILO_CONF_DIR)" >&2 + exit 1 +fi + +# Sanity check connection is working by checking UID light status +if ! hpilo_cli -c "$ILO_CONF_FILE" "$DOMAIN" get_uid_status >/dev/null +then + echo "Error checking connectivity to iLO (failed to get UID light status) for $DOMAIN" >&2 + exit 1 +fi + +# If that succeeded, request certificate +if ! hpilo_cli -c "$ILO_CONF_FILE" "$DOMAIN" certificate_signing_request country='$certificate.country' state='$certificate.state' locality='$certificate.locality' organization='$certificate.organization' organizational_unit='$certificate.organizational_unit' common_name="$DOMAIN" | grep -v '^>>>' +then + echo "CSR request failed, retrying..." >&2 + # If request failed, assume iLO is still generating certificate and retry every 5 seconds for upto 10 minutes + succeeded=0 + i=0 + while [ $i -lt 120 ] # 120 * 5s waiting = 10 minutes + do + sleep 5 + if hpilo_cli -c "$ILO_CONF_FILE" "$DOMAIN" certificate_signing_request country='$certificate.country' state='$certificate.state' locality='$certificate.locality' organization='$certificate.organization' organizational_unit='$certificate.organizational_unit' common_name="$DOMAIN" 2>/dev/null | grep -v '^>>>' + then + # succeeded this time + succeeded=1 + echo "Got CSR after $i re-attempts." >&2 + break + fi + i=$(( i + 1 )) + done + if [ $succeeded -eq 0 ] + then + echo "ERROR: unable to obtain CSR from iLO!" >&2 + exit 1 + fi +fi diff --git a/available/hp-ilo-deploy b/available/hp-ilo-deploy new file mode 100644 index 0000000..f94b8e5 --- /dev/null +++ b/available/hp-ilo-deploy @@ -0,0 +1,16 @@ +#!/bin/bash + +ILO_CONF_DIR=/etc/dehydrated/hp-ilo + +ILO_CONF_FILE="$ILO_CONF_DIR/$DOMAIN.ini" + +# Check config file exists +if [ ! -f "$ILO_CONF_FILE" ] +then + echo "No iLO configuration file for $DOMAIN (looked for $DOMAIN.ini in $ILO_CONF_DIR)" >&2 + exit 1 +fi + +hpilo_cli -c "$ILO_CONF_FILE" "$DOMAIN" import_certificate certificate="$( cat $CERTFILE )" + +exit $? # use the hpilo_cli exit status as this script's exit status diff --git a/available/ifdomain_ b/available/ifdomain_ new file mode 100644 index 0000000..65364d5 --- /dev/null +++ b/available/ifdomain_ @@ -0,0 +1,19 @@ +#!/bin/bash + +# symlink this file to 'ifdomain__' + +filename="$(basename "$0")" + +next_hook_dir="$(dirname "$( realpath $0 )")" + +name_without_prefix="${filename#*-}" +dash_domain="${name_without_prefix%%_*}" +next_hook="${name_without_prefix#*_}" + +if [[ ${DOMAIN//./-} = $dash_domain ]] +then + echo "Running $next_hook for domain $DOMAIN" + $next_hook_dir/$next_hook +else + echo "Skipping $next_hook, domain ${DOMAIN//./-} is not $dash_domain" +fi diff --git a/available/reload_ b/available/reload_ new file mode 100644 index 0000000..997128d --- /dev/null +++ b/available/reload_ @@ -0,0 +1,16 @@ +#!/bin/bash + +# symlink this file to 'reload_> /etc/dehydrated/conf.d/systemctl_cmd.sh +if [ -z "$SYSTEMCTL_CMD" ] +then + SYSTEMCTL_CMD=/bin/systemctl +fi + +echo "Reloading $service..." +$SYSTEMCTL_CMD reload "$service"