diff options
-rw-r--r-- | satellit_installer/includes/10-configurations.inc | 3 | ||||
-rwxr-xr-x | satellit_installer/static_files/lighttpd-auto-ssl.sh | 43 | ||||
-rwxr-xr-x | satellit_installer/static_files/slx-cert | 211 | ||||
-rw-r--r-- | satellit_installer/static_files/slxadmin-crontab | 4 | ||||
-rwxr-xr-x | satellit_upgrader/pack-update.sh | 1 | ||||
-rw-r--r-- | satellit_upgrader/updater.template.sh | 1 |
6 files changed, 252 insertions, 11 deletions
diff --git a/satellit_installer/includes/10-configurations.inc b/satellit_installer/includes/10-configurations.inc index 177ad78..5f9312a 100644 --- a/satellit_installer/includes/10-configurations.inc +++ b/satellit_installer/includes/10-configurations.inc @@ -32,12 +32,13 @@ copy_tftpd-hpa_service() { patch_lighttpd_config() { local mod file - service lighttpd stop echo "# Customizing lighttpd config" cp -p "$BASEDIR/static_files/lighttpd.conf" /etc/lighttpd/lighttpd.conf || perror "failed." cp -p "$BASEDIR/static_files/lighttpd-auto-ssl.sh" /usr/share/lighttpd/auto-ssl.sh || perror "failed." cp -p "$BASEDIR/static_files/lighttpd-include-conf-d.sh" /usr/share/lighttpd/include-conf-d.sh || perror "failed." cp -a "$BASEDIR/static_files/patch_lighttpd_phpchildren" /usr/local/sbin/patch_lighttpd_phpchildren || perror "failed." + mkdir -p /opt/openslx + cp -a "$BASEDIR/static_files/slx-cert" /opt/openslx/slx-cert || perror "failed." chmod +x /usr/share/lighttpd/auto-ssl.sh || perror "failed" chmod +x /usr/share/lighttpd/include-conf-d.sh || perror "failed" chmod +x /usr/local/sbin/patch_lighttpd_phpchildren || perror "failed" diff --git a/satellit_installer/static_files/lighttpd-auto-ssl.sh b/satellit_installer/static_files/lighttpd-auto-ssl.sh index 9365a33..0f88864 100755 --- a/satellit_installer/static_files/lighttpd-auto-ssl.sh +++ b/satellit_installer/static_files/lighttpd-auto-ssl.sh @@ -1,15 +1,22 @@ #!/bin/bash -declare -rg CERT="/etc/lighttpd/server.pem" +declare -rg PUBLIC_BOTH="/etc/lighttpd/server.pem" declare -rg CHAIN="/etc/lighttpd/chain.pem" declare -rg DHPARAM="/etc/lighttpd/dhparam.pem" declare -rg REDIR_FLAG="/etc/lighttpd/redirect.flag" +declare -rg INTERNAL_BOTH="/etc/ssl/openslx/lighttpd/server.pem" +declare -g INTERNAL_CHAIN="/etc/ssl/openslx/lighttpd/ca-chain.pem" if ! [ -s "$DHPARAM" ] && ! ps aux | grep 'openssl dhparam' | grep -q -v grep; then - openssl dhparam -out "$DHPARAM" 2048 >/dev/null 2>&1 + openssl dhparam -out "$DHPARAM" 2048 &>/dev/null & fi -[ -s "$CERT" ] || exit 0 +/opt/openslx/slx-cert >&2 & + +wait + +[ -s "$INTERNAL_CHAIN" ] || INTERNAL_CHAIN= +readonly INTERNAL_CHAIN cat <<HEREDOC \$SERVER["socket"] == ":443" { @@ -17,9 +24,6 @@ cat <<HEREDOC ssl.engine = "enable" ssl.disable-client-renegotiation = "enable" - # pemfile is cert+privkey, ca-file is the intermediate chain in one file - ssl.pemfile = "$CERT" - # ECDH/ECDHE ciphers curve strength (see "openssl ecparam -list_curves") ssl.ec-curve = "secp384r1" # Compression is by default off at compile-time, but use if needed @@ -35,10 +39,31 @@ cat <<HEREDOC ssl.use-sslv3 = "disable" ssl.honor-cipher-order = "enable" ssl.cipher-list = "ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS" + + # pemfile is cert+privkey, ca-file is the intermediate chain in one file HEREDOC -[ -s "$CHAIN" ] && echo " ssl.ca-file = \"$CHAIN\"" -[ -s "$DHPARAM" ] && echo " ssl.dh-file = \"$DHPARAM\"" -echo "}" +if [ -s "$PUBLIC_BOTH" ]; then + echo " ssl.pemfile = \"${PUBLIC_BOTH}\"" + [ -s "$CHAIN" ] && echo " ssl.ca-file = \"${CHAIN}\"" +elif [ -s "$INTERNAL_BOTH" ]; then + echo " ssl.pemfile = \"${INTERNAL_BOTH}\"" + echo " ssl.ca-file = \"${INTERNAL_CHAIN}\"" +fi + +[ -s "$DHPARAM" ] && echo " ssl.dh-file = \"${DHPARAM}\"" + +# VHost for server.bwlehrpool +if [ -s "${INTERNAL_BOTH}" ]; then + cat <<HEREDOC + \$HTTP["host"] == "satellite.bwlehrpool" { + ssl.pemfile = "${INTERNAL_BOTH}" + ssl.ca-file = "${INTERNAL_CHAIN}" + } +HEREDOC + # +fi + +echo "}" # End main block [ -f "$REDIR_FLAG" ] && cat <<"HEREDOC" $HTTP["scheme"] == "http" { diff --git a/satellit_installer/static_files/slx-cert b/satellit_installer/static_files/slx-cert new file mode 100755 index 0000000..2d83b3b --- /dev/null +++ b/satellit_installer/static_files/slx-cert @@ -0,0 +1,211 @@ +#!/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..." + tar -c -k -f "/opt/openslx/configs/modules/self-signed-ca.tar" \ + --transform 's#^.*/ca-#/opt/openslx/ssl/sat-ca-#' "${CERT}/"ca-*.crt + 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 + openssl ca -config "$ca_config" -create_serial -policy policy_anything -days "$srv_days" \ + -cert "$in_cert" -keyfile "${PRIV}/intermediate.key" \ + -notext -name CA_openslx -batch -out "${CERT}/srv-${srv_new_ts}.crt" -in "$csr" || exit 4 + rm -rf -- "$ca_dir" + rm -f -- "$csr" + 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" ] && [ -n "$restart" ]; then + echo "Restarting lighttpd..." + systemctl restart lighttpd.service + fi +fi + +echo "Done." +exit 0 diff --git a/satellit_installer/static_files/slxadmin-crontab b/satellit_installer/static_files/slxadmin-crontab index 440ac35..c6ae537 100644 --- a/satellit_installer/static_files/slxadmin-crontab +++ b/satellit_installer/static_files/slxadmin-crontab @@ -3,5 +3,7 @@ SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin +# web-cron runs every 5 minutes */5 * * * * www-data /opt/openslx/slxadmin-cronscript - +# check certificate once a day +12 1 * * * root /opt/openslx/slx-cert --restart diff --git a/satellit_upgrader/pack-update.sh b/satellit_upgrader/pack-update.sh index 3c889f5..bc5e97d 100755 --- a/satellit_upgrader/pack-update.sh +++ b/satellit_upgrader/pack-update.sh @@ -221,6 +221,7 @@ if [ -z "$LEAN" ]; then addinstallfile "slxadmin-bootscript" addinstallfile "slxadmin-boot.service" addinstallfile "patch_lighttpd_phpchildren" + addinstallfile "slx-cert" addinstallfile "dnbd3/dnbd3-server.service" addinstallfile "dnbd3/server.conf" diff --git a/satellit_upgrader/updater.template.sh b/satellit_upgrader/updater.template.sh index b2a9c66..58454c1 100644 --- a/satellit_upgrader/updater.template.sh +++ b/satellit_upgrader/updater.template.sh @@ -554,6 +554,7 @@ if [ "$MAJOR" -lt 10 ]; then fi diffcp "lighttpd.conf" "/etc/lighttpd/lighttpd.conf" && restart["lighttpd.service"]=ja diffcp "lighttpd-auto-ssl.sh" "/usr/share/lighttpd/auto-ssl.sh" && restart["lighttpd.service"]=ja +diffcp "slx-cert" "/opt/openslx/slx-cert" && restart["lighttpd.service"]=ja diffcp "lighttpd-include-conf-d.sh" "/usr/share/lighttpd/include-conf-d.sh" && restart["lighttpd.service"]=ja # ********************** lighttpd php_children ************* |