summaryrefslogtreecommitdiffstats
path: root/satellit_installer/static_files/lighttpd/opt/openslx/slx-cert
diff options
context:
space:
mode:
Diffstat (limited to 'satellit_installer/static_files/lighttpd/opt/openslx/slx-cert')
-rwxr-xr-xsatellit_installer/static_files/lighttpd/opt/openslx/slx-cert232
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