summaryrefslogblamecommitdiffstats
path: root/scripts/install-https
blob: 9c98869c28d5a618c2a302893cf1e2ad4ac4e720 (plain) (tree)
1
2
3
4
5
6

           


                                                      
                                                    




















                                                                  


             

                                           
                                               






                              

                                  

                                                           
                                   
                                
                         

                                                                                                    




                                      
                              

                  
                      

                                  
                              
                           

                        





                                                                                                                        


                            
                                             
                       
                

 










































































                                                                                                                                             


                             



                                                                                                                                                                                    


                
                  
 

                                                                            

 







                                      
 


              









                           










                                  
          
                     
                  













                                           



                                          
                                        


                                                        






                                                    
 



                                  

      
#!/bin/bash

declare -rg CERT_KEY_FILE="/etc/lighttpd/server.pem"
declare -rg PUB_CERT_FILE="/etc/lighttpd/pub-cert.pem"
declare -rg CHAIN_FILE="/etc/lighttpd/chain.pem"
declare -rg REDIR_FLAG="/etc/lighttpd/redirect.flag"
declare -rg RELOAD_FLAG="/home/taskmanager/acme-reload"
declare -rg ACME_KEY="/home/taskmanager/certs/key.pem"
declare -rg ACME_FULLCHAIN="/home/taskmanager/certs/fullchain.pem"
declare -rg WWW="/srv/openslx/www"

declare -rga acme_common=(
	-w "$WWW"
	--key-file "$ACME_KEY"
	--fullchain-file "$ACME_FULLCHAIN"
	--reloadcmd "touch '$RELOAD_FLAG'"
)

declare -a tmpfiles=
trap 'rm -rf -- "${tmpfiles[@]}"' EXIT

is_readable ()
{
	[ -r "$1" ] && [ -f "$1" ] && return 0
	echo "Not a file, or not readable: $1"
	return 1
}

op_disable ()
{
	[ -e "$CERT_KEY_FILE" ] || exit 0
	rm -f -- "$CERT_KEY_FILE" || exit 1
	rm -f -- "$CHAIN_FILE" "$PUB_CERT_FILE"
}

op_test ()
{
	[ $# -eq 2 ] || exit 1
	local K=$1
	local C=$2
	is_readable "$K" || exit 2
	is_readable "$C" || exit 3
	# Encrypt something, then decrypt again and compare
	local TEST_IN=$(mktemp --tmpdir bwlp-XXXXXXXX)
	[ -z "$TEST_IN" ] && exit 4
	tmpfiles+=( "$TEST_IN" )
	date > "$TEST_IN"
	# Try to sign something - output doesn't matter, this is only to check if cert and key match
	openssl smime -sign -in "$TEST_IN" -out /dev/null -signer "$C" -inkey "$K" || exit 7
	exit 0 # No restart either way
}

op_import ()
{
	[ $# -lt 2 ] && exit 1
	local K=$1
	local C=$2
	local CHAIN=$3
	is_readable "$K" || exit 2
	is_readable "$C" || exit 3
	rm -f -- "$CHAIN_FILE"
	# Create server.pem
	{
		cat "$C"
		# If we have a chainfile, try to use it aswell
		if [ -s "$CHAIN" ] && openssl x509 -noout -hash -in "$CHAIN" &> /dev/null \
				&& [ "$( grep -c '^-----END' "$CHAIN" )" = "$( grep -c '^-----BEGIN' "$CHAIN" )" ]; then
			echo
			cat "$CHAIN"
		fi
		echo
		cat "$K"
	} > "$CERT_KEY_FILE"
	chmod 0600 "$CERT_KEY_FILE" || exit 4
	post_setup_hook
	return 0
}

op_acme_issue ()
{
	[ $# -lt 3 ] && exit 1
	local i
	local provider="$1"
	local mail="$2"
	shift 2
	declare -a domains=()
	set -x
	for i; do
		domains+=( -d "$i" )
	done
	rm -f -- "$RELOAD_FLAG"
	if [ -n "$ACME_WIPE" ]; then
		rm -rf -- /home/taskmanager/.acme.sh/*
		rm -rf -- /home/taskmanager/certs/*
		touch /home/taskmanager/.acme.sh/account.conf
		chown taskmanager:taskmanager /home/taskmanager/.acme.sh/account.conf
	else
		rm -rf -- /home/taskmanager/.acme.sh/???*.*
		rm -rf -- /home/taskmanager/certs/*
	fi
	mkdir -p "$WWW/.well-known/acme-challenge"
	chown taskmanager:taskmanager "$WWW/.well-known/acme-challenge"
	chmod 0700 /home/taskmanager/certs
	if [ -n "$ACME_KEY_ID" ] && [ -n "$ACME_HMAC_KEY" ]; then
		sudo -u taskmanager -n ACCOUNT_EMAIL="$mail" \
			/opt/openslx/acme.sh --register-account --server "$provider" --eab-kid "$ACME_KEY_ID" --eab-hmac-key "$ACME_HMAC_KEY"
	fi
	tmpfiles+=( "$RELOAD_FLAG" )
	sudo -u taskmanager -n ACCOUNT_EMAIL="$mail" \
		/opt/openslx/acme.sh --server "$provider" --issue "${domains[@]}" "${acme_common[@]}"
	i=$?
	if [ -e "$RELOAD_FLAG" ]; then
		# Renew must have happened
		op_import "$ACME_KEY" "$ACME_FULLCHAIN"
		return 0
	fi
	# No reload in other case, exit
	exit "$i"
}

op_acme_renew ()
{
	mkdir -p "$WWW/.well-known/acme-challenge"
	chown taskmanager:taskmanager "$WWW/.well-known/acme-challenge"
	rm -f -- "$RELOAD_FLAG"
	tmpfiles+=( "$RELOAD_FLAG" )
	sudo -u taskmanager -n /opt/openslx/acme.sh --renew --domain "$1" "${acme_common[@]}"
	i=$?
	(( i == 2 )) && i=0
	if (( i != 0 )) || ! [ -e "$ACME_FULLCHAIN" ] || ! [ -e "$ACME_KEY" ] \
			|| ! openssl x509 -checkend 600 -in "$ACME_FULLCHAIN"; then
		sudo -u taskmanager -n /opt/openslx/acme.sh --renew --force --domain "$1" "${acme_common[@]}"
		i=$?
	fi
	if [ -e "$RELOAD_FLAG" ]; then
		# Renew must have happened
		op_import "$ACME_KEY" "$ACME_FULLCHAIN"
		return 0
	fi
	# No reload in other case, exit

	exit "$i"
}

op_acme_try_enable ()
{
	[ -s "$ACME_KEY" ] || exit 1
	[ -s "$ACME_FULLCHAIN" ] || exit 2
	openssl x509 -checkend 600 -noout -in "$ACME_FULLCHAIN" || exit 3
	( op_test "$ACME_KEY" "$ACME_FULLCHAIN" ) || exit 4
	op_import "$ACME_KEY" "$ACME_FULLCHAIN"
}

op_random ()
{
	[ -z "$1" ] && exit 1
	rm -f -- "$CHAIN_FILE"
	openssl req -x509 -new -newkey rsa:4096 -keyout "$CERT_KEY_FILE" -out "$CERT_KEY_FILE" -days 5000 -nodes -subj "/C=DE/ST=Nowhere/L=Springfield/O=bwLehrpool/CN=$1" || exit 2
	chmod 0600 "$CERT_KEY_FILE" || exit 3
	post_setup_hook
	return 0
}

post_setup_hook ()
{
	rm -f -- "$PUB_CERT_FILE"
	openssl x509 -outform pem -in "$CERT_KEY_FILE" -out "$PUB_CERT_FILE"
}

setup_redirect ()
{
	if [ -n "$REDIR" ]; then
		touch "$REDIR_FLAG"
	else
		rm -f -- "$REDIR_FLAG"
	fi
}

ACME_KEY_ID=
ACME_HMAC_KEY=
ACME_WIPE=
RE_ONLY=
REDIR=
while true; do
	case "$1" in
	--redirect-only)
		RE_ONLY=tru
		;;
	--redirect)
		REDIR=truh
		;;
	--acme-wipe)
		ACME_WIPE=1
		;;
	--acme-key-id)
		ACME_KEY_ID="$2"
		shift
		;;
	--acme-hmac-key)
		ACME_HMAC_KEY="$2"
		shift
		;;
	*)
		break
		;;
	esac
	shift
done

setup_redirect

if [ -z "$RE_ONLY" ]; then

	OP=$1
	shift

	case "$OP" in
		--random) op_random "$@" ;;
		--test) op_test "$@" ;;
		--import)
			tmpfiles+=( "$@" )
			op_import "$@"
			;;
		--disable) op_disable ;;
		--acme-issue) op_acme_issue "$@" ;;
		--acme-renew) op_acme_renew "$@" ;;
		--acme-try-enable) op_acme_try_enable ;;
		*)
			echo "Invalid operation: $1"
			exit 1
			;;
	esac

fi

(
	sleep .5
	systemctl restart lighttpd
) &

exit 0