diff options
Diffstat (limited to 'satellit_installer/static_files/lighttpd/opt/openslx')
-rwxr-xr-x | satellit_installer/static_files/lighttpd/opt/openslx/slx-cert | 232 |
1 files changed, 232 insertions, 0 deletions
diff --git a/satellit_installer/static_files/lighttpd/opt/openslx/slx-cert b/satellit_installer/static_files/lighttpd/opt/openslx/slx-cert new file mode 100755 index 0000000..3f5cc3e --- /dev/null +++ b/satellit_installer/static_files/lighttpd/opt/openslx/slx-cert @@ -0,0 +1,232 @@ +#!/bin/bash + +# OpenSLX SSL Certificate management + +if ! mkdir "/run/openslx-cert-manager"; then + echo "Already in progress." + exit 1 +fi +trap 'rm -rf -- /run/openslx-cert-manager' EXIT + +declare -rg BASE="/etc/ssl/openslx" +declare -rg PRIV="$BASE/private" +declare -rg CERT="$BASE/cert" +declare -rg LIGHT="$BASE/lighttpd" + +mkdir -p "$BASE" "$PRIV" "$CERT" + +chown -R root:root "$BASE" || exit 1 +chmod u+rwx,go+rx-w "$BASE" "$CERT" || exit 1 +chmod u+rwx,go-rwx "$PRIV" || exit 1 +# Before doing anything, make sure we have a CA with enough validity left +# File name format for ca is: +# ${PRIV}/ca-FFFFFFFFFF-TTTTTTTTTT.key +# ${CERT}/ca-TTTTTTTTTT.crt +# Where TT is the unix timestamp of "validTo" of that cert +# And FF is the unix timestamp of when we should starting using a CA to +# sign our certificates. This is for a grace period between CA certs. +# We deliver a new CA certificate immediately when it was generated, but +# only start signing server certificates with it after a grace period of +# 180 days. Any client that rebooted within those 180 days will not run +# into any certificate issues, but if you wanted to cover that case too +# you could make it so the client re-downloads trusted CA-certs every +# couple days. + +declare -rg NOW="$( date +%s )" +# PROD +declare -rg ca_days="$(( 10 * 365 ))" # 10y +declare -rg ca_min_remain_s="$(( 400 * 86400 ))" # bit more than 1y +declare -rg ca_new_expire_ts="$(( ca_days * 86400 + NOW ))" +declare -rg srv_days=365 # 1y +declare -rg srv_min_remain_s="$(( 180 * 86400 ))" # half a year +declare -rg srv_new_ts="$(( srv_days * 86400 + NOW ))" +# TEST +#declare -rg ca_days=1825 # 5y +#declare -rg ca_min_remain_s="$(( 1260 ))" # bit more than 1y +#declare -rg ca_new_expire_ts="$(( 1320 + NOW ))" +#declare -rg srv_days=365 # 1y +#declare -rg srv_min_remain_s="$(( 1200 ))" # half a year +#declare -rg srv_new_ts="$(( 1230 + NOW ))" + + +get_ts () { + ts="${1%.*}" + ts="${ts##*/ca-}" + ts="${ts##*/srv-}" + from="${ts%-*}" + if [ "$from" = "$ts" ]; then + from= + else + ts="${ts#*-}" + fi +} + +create_conf () { + ca_dir="$( mktemp -d /tmp/bwlp-XXXXXXXX )" + [ -z "$ca_dir" ] && exit 1 + mkdir "$ca_dir"/{certs,crl,newcerts,private} + touch "$ca_dir"/index.txt + ca_config="$ca_dir/openssl.cnf" + cp -f "/etc/ssl/openssl.cnf" "$ca_config" + cat >> "$ca_config" <<-MYCA + [ CA_openslx ] + dir = $ca_dir + certs = \$dir/certs + crl_dir = \$dir/crl + database = \$dir/index.txt + new_certs_dir = \$dir/newcerts + serial = \$dir/serial + crl = \$dir/crl.pem + x509_extensions = usr_cert + name_opt = ca_default + cert_opt = ca_default + default_md = default + preserve = no + policy = policy_match + MYCA +} + +ca_last= +for i in "${PRIV}"/ca-??????????.key; do + [ -f "$i" ] || continue + get_ts "$i" + if ! [ -f "${CERT}/ca-${ts}.crt" ] || (( ts < NOW )); then + # Missing cert, or expired -> delete + rm -f -- "${CERT}/ca-${ts}.crt" "${PRIV}/ca-${ts}.key" + continue + fi + ca_last="$ts" +done + +mknew= +if [ -z "$ca_last" ] || (( NOW + ca_min_remain_s > ca_last )); then + # Make new CA + echo "Creating new CA..." + openssl req -new -newkey rsa:4096 -x509 -days "$ca_days" -extensions v3_ca \ + -nodes -subj "/C=DE/ST=PewPew/L=HeyHey/O=bwLehrpool/CN=ca-${NOW}.bwlehrpool" \ + -keyout "${PRIV}/ca-${ca_new_expire_ts}.key" -out "${CERT}/ca-${ca_new_expire_ts}.crt" || exit 2 + mknew=1 + # + # Create new intermediate, sign with all CAs + csr="$( mktemp /tmp/bwlp-XXXXXXX.csr )" + # Create request, CA:TRUE + echo "Generate intermediate key+CSR..." + [ -f "${PRIV}/intermediate.key" ] || openssl genrsa -out "${PRIV}/intermediate.key" 4096 + openssl req -new -key "${PRIV}/intermediate.key" \ + -nodes -subj "/C=DE/ST=PewPew/L=HeyHey/O=bwLehrpool/CN=intermediate.bwlehrpool" \ + -out "$csr" || exit 2 + create_conf + # Sign request, CA:TRUE + echo "Sign new intermediate key with CA..." + openssl ca -config "$ca_config" -extensions v3_ca -create_serial \ + -policy policy_anything -days "$ca_days" \ + -cert "${CERT}/ca-${ca_new_expire_ts}.crt" -keyfile "${PRIV}/ca-${ca_new_expire_ts}.key" \ + -notext -name CA_openslx -batch -out "${CERT}/intermediate-${ca_new_expire_ts}.crt" -in "$csr" || exit 2 + rm -rf -- "$ca_dir" "$csr" +fi + +if [ -n "$mknew" ]; then + # Rebuild config module for clients + echo "Updating client config module..." + ( + tmpdir="$( mktemp -d '/tmp/bwlp-XXXXXXX' )" + cp -a "${CERT}/"ca-*.crt "$tmpdir/" + cd "$tmpdir/" || exit 6 + openssl rehash . + tar -c -k -f "/opt/openslx/configs/modules/self-signed-ca.tar" \ + --transform 's#^[./][./]*#/opt/openslx/ssl/#' . + cd /tmp + rm -rf -- "$tmpdir" + sudo -u www-data -n php /srv/openslx/www/slx-admin/api.php sysconfig --action rebuild + echo "." + ) +fi + +# Now check the server certificate + +declare -a srv_list +srv_list=() +for i in "${PRIV}"/srv-??????????.key; do + [ -f "$i" ] || continue + get_ts "$i" + if (( ts < NOW )) || ! [ -f "${CERT}/srv-${ts}.crt" ]; then + rm -f -- "$i" "${CERT}/srv-${ts}.crt" + continue + fi + srv_list+=( "$ts" ) +done + +if [ -n "$mknew" ] || [ "${#srv_list[@]}" = 0 ] \ + || [ "$(( NOW + srv_min_remain_s ))" -gt "${srv_list[-1]}" ]; then + # Request ServerCert + csr="$( mktemp /tmp/bwlp-XXXXXXX.csr )" + echo "Generating new Server Certificate. Key+CSR..." + rm -f -- "${CERT}"/srv-*.crt "${PRIV}/srv.key.tmp" "${PRIV}"/srv-*.key + openssl req -new -nodes -keyout "${PRIV}/srv.key.tmp" -out "$csr" \ + -subj "/C=DE/ST=PewPew/L=HeyHey/O=bwLehrpool/CN=satellite.bwlehrpool" || exit 4 + echo "Signing Server Certificate with intermediate..." + declare -a in_list + in_list=() + for i in "${CERT}"/intermediate-??????????.crt; do + [ -f "$i" ] || continue + get_ts "$i" + if (( ts < NOW )); then + echo "Expired intermediate $i" + rm -f -- "$i" + continue + fi + echo "Have intermediate $i" + in_list+=( "$i" ) + done + if [ "${#in_list[@]}" = 0 ]; then + echo "ERROR: Have no intermediate certificate" + exit 11 + fi + for in_cert in "${in_list[@]}"; do + get_ts "$in_cert" + (( ts < 30 * 86400 + NOW )) && continue # Expiring in a month, ignore + break # Need only one really + done + echo "Signing with $in_cert" + create_conf + # Need extfile for SAN, chromium doesn't honor CN anymore + cat > "${csr}.cnf" <<-END + basicConstraints = CA:FALSE + nsCertType = server + nsComment = "OpenSSL Generated Server Certificate" + subjectKeyIdentifier = hash + authorityKeyIdentifier = keyid,issuer:always + keyUsage = critical, digitalSignature, keyEncipherment + extendedKeyUsage = serverAuth + subjectAltName = @alt_names + [alt_names] + DNS.1 = satellite.bwlehrpool + END + openssl ca -config "$ca_config" -create_serial -policy policy_anything -days "$srv_days" \ + -cert "$in_cert" -keyfile "${PRIV}/intermediate.key" -extfile "${csr}.cnf" \ + -notext -name CA_openslx -batch -out "${CERT}/srv-${srv_new_ts}.crt" -in "$csr" || exit 4 + rm -rf -- "$ca_dir" + rm -f -- "$csr" "${csr}.cnf" + mv "${PRIV}/srv.key.tmp" "${PRIV}/srv-${srv_new_ts}.key" || exit 5 + srv_list+=( "$srv_new_ts" ) + + # Combine and prepare for lighttpd + + mkdir -p "$LIGHT" || exit 10 + + # Combine cert and key, as required by lighttpd + echo "Writing out lighttpd PEMs..." + cat "${CERT}/srv-${srv_new_ts}.crt" "${PRIV}/srv-${srv_new_ts}.key" > "${LIGHT}/server.pem" || exit 10 + chmod 0600 "${LIGHT}/server.pem" + + # Create ca-chain + cat "${in_list[@]}" > "${LIGHT}/ca-chain.pem" + + if [ "$1" = "--restart" ] || [ -t 0 ]; then + echo "Restarting lighttpd..." + systemctl restart lighttpd.service + fi +fi + +echo "Done." +exit 0 |