#!/usr/bin/bash
#
# Generate SSL keys & certificates for systemd-journal-(remote|upload)
#
# Usage: $0 (--usage|--help|--force|--auto)
#

function usage {
	[ -n "$1" ] && { echo; echo "ERROR: $1"; echo; }
	echo "Usage: $0 (--usage|--help|--force|--auto)"	
	echo " --auto  generate keys/certs if the \$PROTOCOL environment variable is set to"
	echo "         'https' and they are missing / do not yet exist"
	echo " --force always (re)generate keys/certs overwriting any current copies"
	echo ""
        echo " In --auto mode when \$PROTOCOL==https *OR* always in --force mode"
        echo " /etc/systemd/journal-{upload,remote}.conf will be updated to point to"
        echo " the generated keys/certificates"
	[ -n "$1" ] && exit 1
	exit 0
}

case "x$1" in
	x|x--help|x--usage) usage;;
	x--auto) ;;
	x--force) ;;
	*) usage "Unknown option $1";;
esac

# Not needed unless we're using https
[[ "x$1" == "x--force" || "x$PROTOCOL" == "xhttps" ]] || exit 0

CLUSTERID=$(/usr/libexec/ng-server-config/mk-auth-token journald::cluster::id 72 | sha512sum | cut -c1-24| tr A-Z a-z)

# Generate the CA key if it's not present
if [ "x$1" == "x--force" ] || [ ! -f /etc/pki/tls/private/journal-CA.key ]; then
	/usr/libexec/ng-server-config/mk-rsa-key 'journald::cluster::autoca' 4096 >/etc/pki/tls/private/journal-CA.key 2>/dev/null
	# No one needs this key but us (root)
	chmod 0600 /etc/pki/tls/private/journal-CA.key
fi

# Generate the CA cert if it's not present
if [ "x$1" == "x--force" ] || [ ! -f /etc/pki/tls/certs/journal-CA.crt ]; then
	# TODO: Check CA:TRUE critical, pathlength
	env TZ=UTC faketime "2015-01-01T00:00:00" openssl req 2>/dev/null \
	  -new -batch -x509 \
	  -subj "/C=AU/ST=New South Wales/L=Sydney/O=Noggin Pty Ltd/CN=Journald Cluster $CLUSTERID CA" \
	  -sha256 \
	  -key /etc/pki/tls/private/journal-CA.key \
	  -days $[25*365] \
	  -set_serial 0x${CLUSTERID} \
	  -out /etc/pki/tls/certs/journal-CA.crt
fi

# Generate this host's key if it's not present, this *doesn't* need to be repeatable
if [ "x$1" == "x--force" ] || [ ! -f /etc/pki/tls/private/journal-host.key ]; then
	openssl genrsa -out /etc/pki/tls/private/journal-host.key 2048 2>/dev/null
	# The systemd-journal-{upload,remote} (and maybe -gateway?) need to read this key
	chmod 0640 /etc/pki/tls/private/journal-host.key
	setfacl -m u:systemd-journal-upload:r,u:systemd-journal-remote:r /etc/pki/tls/private/journal-host.key
fi

# Generate this host's cert if it's not present
if [ "x$1" == "x--force" ] || [ ! -f /etc/pki/tls/certs/journal-host.crt ]; then

	SAN=$(
		echo "[sign_ext]"
		echo "basicConstraints=critical,CA:FALSE"
		echo "subjectAltName = @alt_names"
		echo "[alt_names]"
		cat <(hostname --fqdn) <(hostname --all-fqdns) | sed -re 's/ *$//g; s/(^| )/\1DNS=/g; s/ /\n/g' | sort -u | awk -F= '$2!=""{printf("%s.%d=%s\n", $1, NR, $2)}'
                hostname --all-ip-addresses | sed -re 's/ *$//g; s/(^| )/\1IP=/g; s/ /\n/g' | sort -u | awk -F= '$2!=""{printf("%s.%d=%s\n", $1, NR, $2)}'
	)
	SUBJECT="/C=AU/ST=New South Wales/L=Sydney/O=Noggin Pty Ltd/CN=$(hostname --fqdn)"
	SERIAL=$(echo "${CLUSTERID}|$(hostid)|$(uptime)|$(uname -a)|${SAN}|${SUBJECT}" | sha512sum | cut -c1-24 | tr A-Z a-z)

	openssl req \
	  -new -batch \
	  -subj "${SUBJECT}" \
	  -sha256 \
	  -key /etc/pki/tls/private/journal-host.key \
	| openssl x509 -req -sha256 2>/dev/null \
	  -days $[15*365] -set_serial 0x${SERIAL} \
	  -CAkey /etc/pki/tls/private/journal-CA.key \
	  -CA /etc/pki/tls/certs/journal-CA.crt \
	  -out /etc/pki/tls/certs/journal-host.crt \
	  -clrext -extfile <(echo "${SAN}") -extensions sign_ext
	  
fi


# TODO: We really should only update the config(s) if they aren't already populated
augtool --noload --noautoload --autosave 2>/dev/null <<-EOD
        # Use the 'PHP' ini lens
        set /augeas/load/IniFile/lens "php.lns"
        set /augeas/load/IniFile/incl "/etc/systemd/journal-*.conf"
        load

        # Configure systemd-journal-upload
        set /files/etc/systemd/journal-upload.conf/Upload/TrustedCertificateFile /etc/pki/tls/certs/journal-CA.crt
        set /files/etc/systemd/journal-upload.conf/Upload/ServerCertificateFile  /etc/pki/tls/certs/journal-host.crt
        set /files/etc/systemd/journal-upload.conf/Upload/ServerKeyFile          /etc/pki/tls/private/journal-host.key

        # Configure systemd-journal-remote
        set /files/etc/systemd/journal-remote.conf/Remote/TrustedCertificateFile /etc/pki/tls/certs/journal-CA.crt
        set /files/etc/systemd/journal-remote.conf/Remote/ServerCertificateFile  /etc/pki/tls/certs/journal-host.crt
        set /files/etc/systemd/journal-remote.conf/Remote/ServerKeyFile          /etc/pki/tls/private/journal-host.key
EOD

