Blame view

freeipa-letsencrypt.sh 5.55 KB
Frederik Lindenaar authored
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#!/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
Frederik Lindenaar authored
39
40
41
42
43
44
45
: ${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)}
Frederik Lindenaar authored
46
47
48
49
50
51
52
53
54

# 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
Frederik Lindenaar authored
55
  3. Create host service: $SERVICE
Frederik Lindenaar authored
56
  4. Allow letsencrypt host service to manage DNS entries
Frederik Lindenaar authored
57
58
59
  5. Register with Let's encrypt as: $EMAIL
  6. Request a Let's Encrypt SSL certificate for: $CERTNAME
     with DNS Alternative names: $DNSALTNAMES
Frederik Lindenaar authored
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
  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
Frederik Lindenaar authored
129
FreeIPA was successfully setup to use a Let's Encrypt certificate for its web
Frederik Lindenaar authored
130
131
132
133
interface. This certificate will be renewed automatically when needed.

EOT