#!/bin/bash -e # # freeipa-letsencrypt.sh - script to setup Let's Encrypt's Certbot for FreeIPA # # Version 1.0, latest version, documentation and bugtracker available at: # https://gitlab.lindenaar.net/scripts/freeipa # # Copyright (c) 2018 Frederik Lindenaar # # This script is free software: you can redistribute and/or modify it under the # terms of version 3 of the GNU General Public License as published by the Free # Software Foundation, or (at your option) any later version of the license. # # This script 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 # this program. If not, visit <http://www.gnu.org/licenses/> to download it. # Sanity checks, ensure we have a valid Kerberos ticket, current host is a # FreeIPA server, certbot is installed and that we can run priviliged commands die() { echo $* >&2; exit 1; } if ! klist -s; then die no valid Kerberos ticket, please login to FreeIPA using kinit first elif ! ipa server-show ${HOSTNAME:=$(hostname --fqdn)} > /dev/null; then die this script should be run on an active IPA server elif ! which certbot > /dev/null; then die this script requires Certbot to be installed, please install that first elif [ $(id -u) == 0 ]; then unset SUDO elif ! ${SUDO:=sudo} -v; then die Error: this script must be run by root and $SUDO does not seem to work else $SUDO kinit -k fi # Set KRB5CCNAME to ensure the current ticket cache will be used : ${KRB5CCNAME:=$(klist -l | head -3 | tail -1 | cut -d\ -f2-)} # Set parameters : ${CERTNAME:=$(ipa host-show $HOSTNAME --raw | fgrep "krbcanonicalname: host/" | cut -d/ -f2 | cut -d@ -f1)} : ${DNSALTNAMES:=$(ipa host-show $HOSTNAME --raw | fgrep "krbprincipalname: host/" | cut -d/ -f2 | cut -d@ -f1 | paste -sd,)} : ${EMAIL:=hostmaster@${HOSTNAME#*.}} : ${SERVICE:=letsencrypt/$(ipa host-show $HOSTNAME --raw | fgrep "krbcanonicalname: host/" | cut -d/ -f2)} # Ensure the user consents with changing his system. if tty > /dev/null; then cat << EOT This script modifies this host's FreeIPA setup so that its web interface will use a Let's Encrypt certificate and will automatically renew that when needed. The following changes will be made for this: 1. Add Let's Encrypt Root and Intermediate CAs as trusted CAs 2. Create DNS Administrator role in FreeIPA that can edit any DNS Record 3. Create host service: $SERVICE 4. Allow letsencrypt host service to manage DNS entries 5. Register with Let's encrypt as: $EMAIL 6. Request a Let's Encrypt SSL certificate for: $CERTNAME with DNS Alternative names: $DNSALTNAMES 7. install the Let's Encrypt certificate in apache as host SSL certificate, storing renewal config in: /etc/letsencrypt/renewal/$HOSTNAME.conf 8. configure the Fedora Certbot renew timer so that certbot is run daily to renew the certificate when needed. EOT while ! [[ "${REPLY:-}" =~ ^[YyNn]$ ]]; do echo read -rp "Please confirm these changes should be applied (y/n): " -n 1 done echo [[ "${REPLY}" =~ ^[Nn]$ ]] && die aborted fi echo echo Download and importing Let\'s Encrypt certificates, this may take a while declare -A LETSENCRYPTCERTS=( [ISRGRootCAX1]=https://letsencrypt.org/certs/isrgrootx1.pem [LetsEncryptX3]=https://letsencrypt.org/certs/letsencryptauthorityx3.pem ) for certname in ${!LETSENCRYPTCERTS[@]}; do certfile=$(mktemp -u ${TMPDIR:-/tmp}/$0.XXXXXXX.cert) curl -s "${LETSENCRYPTCERTS[$certname]}" -o $certfile $SUDO ipa-cacert-manage install $certfile -n "$certname" -t C,, rm -f $certfile done $SUDO ipa-certupdate echo if ! ipa role-show "DNS Administrator" > /dev/null 2>&1; then echo Creating DNS Administrator role ipa role-add "DNS Administrator" ipa role-add-privilege "DNS Administrator" --privileges="DNS Administrators" else echo DNS Administrator role already exists fi echo if ! ipa service-show "$SERVICE" > /dev/null 2>&1; then echo Add service user $SERVICE ipa service-add "$SERVICE" ipa role-add-member "DNS Administrator" --services="$SERVICE" else echo Service user $SERVICE already exists fi echo if [ ! -f "${KEYTAB:=/etc/letsencrypt/keytab}" ]; then echo creating keytab file $KEYTAB $SUDO ipa-getkeytab -p "$SERVICE" -k "$KEYTAB" else echo not touching existing keytab file $KEYTAB fi echo echo Requesting Let\'s Encrypt SSL certificate and setup renewals $SUDO certbot certonly --expand --manual --preferred-challenges dns \ --manual-public-ip-logging-ok --agree-tos --email "${EMAIL}" \ --cert-name ${HOSTNAME} --domains "${DNSALTNAMES}" \ --pre-hook "kinit -k -t $KEYTAB \"$SERVICE\"" --post-hook "kdestroy" \ --manual-auth-hook "ipa dnsrecord-add ${DOMAIN:-\${CERTBOT_DOMAIN#*.\}}. _acme-challenge.\${CERTBOT_DOMAIN}. \"--txt-rec=\${CERTBOT_VALIDATION}\"; sleep 3" \ --manual-cleanup-hook "ipa dnsrecord-del ${DOMAIN:-\${CERTBOT_DOMAIN#*.\}}. _acme-challenge.\${CERTBOT_DOMAIN}. --del-all" \ --deploy-hook 'echo | ipa-server-certinstall --http "${RENEWED_LINEAGE}/fullchain.pem" "${RENEWED_LINEAGE}/privkey.pem" --dirman-password="" --pin="" && service httpd restart' echo echo Enabling Certbot package\'s renewal timer $SUDO systemctl enable --now certbot-renew.timer cat << EOT FreeIPA was successfully setup to use a Let's Encrypt certificate for its web interface. This certificate will be renewed automatically when needed. EOT