From 03be69d4985731e10c2c168a8f50431eff18a0f7 Mon Sep 17 00:00:00 2001 From: Andrew Cady Date: Fri, 4 Sep 2020 16:21:58 -0400 Subject: initial commit --- selfpublish.sh | 267 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 selfpublish.sh diff --git a/selfpublish.sh b/selfpublish.sh new file mode 100644 index 0000000..8a17c67 --- /dev/null +++ b/selfpublish.sh @@ -0,0 +1,267 @@ +#!/bin/sh +set -e + +DEFAULT_AUTH_TYPE=ed25519 + +force() +{ + [ "$FORCE" ] +} + +in_group() +{ + local g + for g in $(groups) + do + [ "$g" = "$1" ] && return + done + false +} + +as_root() +{ + if [ "$(id -u)" = 0 ] + then + "$@" + elif in_group sudo + then + sudo "$@" + else + su -c "$*" + fi +} + +apt_install() +{ + as_root apt-get install "$@" +} + +dpkg_install() +{ + as_root dpkg -i "$@" +} + +control_file() +{ + cat <= 2.4.46), libssl1.1 (>= 1.1.1d) +Description: selfpublish.sh dependency package + This package depends on the dependencies of the + selfpublish.sh script, and is installed by that + script to self-satisfy those dependencies. + +EOF +} + +equivocate() +{ + dpkg-query -s selfpublish-dot-sh-deps >/dev/null 2>&1 && return || true + which equivs-build >/dev/null 2>&1 || apt_install equivs + ( + destdir=$(mktemp -d) + cd "$destdir" + control_file > ./control + equivs-build ./control >/dev/null 2>&1 + dpkg_install selfpublish-dot-sh-deps_1.0_all.deb + ) +} + +ssh_keytag_to_path_fragment() +{ + case "$1" in + ssh-dss) echo dsa ;; + ecdsa-sha2-nistp256) echo ecdsa ;; + ssh-rsa|ssh-ed25519) echo ${1#ssh-} ;; + *) return 1 ;; + esac +} + +path_fragment_to_ssh_keytag() +{ + case "$1" in + ssh-dss|ecdsa-sha2-nistp256|ssh-rsa|ssh-ed25519) echo $1;; + dss|rsa|ed25519) echo ssh-$1 ;; + dsa) echo ssh-dss ;; + ecdsa) echo ecdsa-sha2-nistp256 ;; + *) return 1 ;; + esac +} + +get_dyndns_domain() +{ + fragment=$(ssh_keytag_to_path_fragment "$1") || return + + host_keyfile=/etc/ssh/ssh_host_${fragment}_key + user_keyfile=$HOME/.ssh/id_${fragment} + + set -- -q dyndns@cryptonomic.net + + if [ -r "$host_keyfile" ] + then + set -- ssh -i "$host_keyfile" "$@" + + elif in_group sudo + then + set -- sudo ssh -i "$host_keyfile" "$@" + + elif [ -r "$user_keyfile" ] + then + set -- ssh -i "$user_keyfile" "$@" + + else + set -- ssh "$@" + fi + + "$@" +} + +enable_apache_modules() +{ + for MODULE in $APACHE_MODULES + do + a2enmod $MODULE >/dev/null + done +} + +site_conf_template() +{ +cat < + MDContactEmail webmaster@$DOMAIN + MDCertificateAgreement accepted + MDRequireHttps temporary + + + ServerName $DOMAIN + ServerAlias ${DOMAIN}. + Redirect / https://$DOMAIN + + + + ServerName $DOMAIN + + ServerAdmin webmaster@$DOMAIN + SSLEngine on + + ErrorLog /srv/$DOMAIN/logs/error.log + CustomLog /srv/$DOMAIN/logs/access.log combined + + + SetHandler server-status + + + DocumentRoot /srv/$DOMAIN/public_html/ + + Options Indexes FollowSymLinks MultiViews Includes + + IndexOrderDefault Descending Date + IndexOptions +IgnoreCase FancyIndexing + IndexOptions +HTMLTable SuppressDescription + IndexStyleSheet /css/autoindex.css + IndexIgnore /unindexed /HEADER.html /css /images + + # Using an absolute url for header + HeaderName /HEADER.html + + XBitHack on + AllowOverride None + Require all granted + + + +END +} + +wait_for_certificate_issuance() +{ + local f state + f=/etc/apache2/md/domains/"$1"/md.json + while true + do + if [ -e "$f" ] + then + state=$(sed -ne 's/^ *"state": *\([0-9]\+\),/\1/p' "$f") + + if [ "$state" = 2 ] + then + return + fi + fi + sleep 1 + done +} + +install_apache_site() +{ + if [ -e "$SITE_CONF" ] && ! force + then + return + fi + + for DIR in $APACHE_SITE_DIRS + do + mkdir -p "$SITE_DIR"/"$DIR" + done + + local tmp + tmp=$(mktemp "$SITE_CONF".XXXXXX) + + site_conf_template > "$tmp" + mv -T "$tmp" "$SITE_CONF" || { rm -f "$tmp"; false; } + a2ensite "$DOMAIN" >/dev/null +} + +install_self_to_site() +{ + SOURCE_BASENAME=${0##*/} + [ -d "$SITE_DIR"/public_html ] || return + dst=$SITE_DIR/public_html/$SOURCE_BASENAME + src=$0 + [ -e "$src" ] || return 0 + if [ ! "$src" -ef "$dst" ] + then + cp -Tuv "$src" "$dst" >&2 + cp -Tuv "$src" "$dst".txt >&2 + fi +} + +check_tls() +{ + curl -s -S -I https://"$1" >/dev/null +} + +equivocate + +APACHE_MODULES='status md rewrite ssl include' +APACHE_SITE_DIRS='logs public_html' + +AUTH_TYPE=$(path_fragment_to_ssh_keytag "${1:-$DEFAULT_AUTH_TYPE}") +DYNDNS=$(get_dyndns_domain "$AUTH_TYPE") +DOMAIN=${DYNDNS%% *} +SITE_DIR=/srv/$DOMAIN +SITE_CONF=/etc/apache2/sites-available/$DOMAIN.conf + +case "$DOMAIN" in + *."$AUTH_TYPE".cryptonomic.net) ;; + *) + printf 'Error: %s\n' "Unexpected domain returned by server: $DOMAIN" + exit 1 ;; +esac + +if ! check_tls "$DOMAIN" || force +then + equivocate + enable_apache_modules + install_apache_site + install_self_to_site + systemctl restart apache2 + wait_for_certificate_issuance "$DOMAIN" + systemctl reload apache2 +else + install_self_to_site +fi + +check_tls "$DOMAIN" +printf '%s\n' "https://$DOMAIN/selfpublish.sh" + -- cgit v1.2.3