#!/usr/bin/env bash
set -Eeuo pipefail

CONFIG_FILE="${LEGO_CONFIG_FILE:-/etc/lego/.lego.yml}"
CERT_DIR="${LEGO_CERT_DIR:-/etc/lego/certificates}"

log() { printf 'lego proxmox hook: %s\n' "$*"; }
die() { printf 'lego proxmox hook: ERROR: %s\n' "$*" >&2; exit 1; }

command -v pvenode >/dev/null 2>&1 || die "pvenode is not available"
command -v openssl >/dev/null 2>&1 || die "openssl is not available"
command -v systemctl >/dev/null 2>&1 || die "systemctl is not available"
[[ -r "${CONFIG_FILE}" ]] || die "cannot read ${CONFIG_FILE}"

mapfile -t certificate_names < <(
    awk '
        /^[[:space:]]*certificates:[[:space:]]*$/ { in_certificates=1; next }
        in_certificates && /^[^[:space:]]/ { exit }
        in_certificates && /^  [^[:space:]][^:]*:[[:space:]]*$/ {
            line=$0
            sub(/^  /, "", line)
            sub(/:[[:space:]]*$/, "", line)
            if ((substr(line,1,1) == "\047" && substr(line,length(line),1) == "\047") ||
                (substr(line,1,1) == "\042" && substr(line,length(line),1) == "\042")) {
                line=substr(line,2,length(line)-2)
            }
            print line
        }
    ' "${CONFIG_FILE}"
)

if [[ -n "${PVE_CERT_NAME:-}" ]]; then
    cert_name="${PVE_CERT_NAME}"
elif ((${#certificate_names[@]} == 1)); then
    cert_name="${certificate_names[0]}"
elif ((${#certificate_names[@]} == 0)); then
    die "no certificate entries found in ${CONFIG_FILE}"
else
    die "multiple certificate entries found; set PVE_CERT_NAME"
fi

crt="${CERT_DIR}/${cert_name}.crt"
issuer="${CERT_DIR}/${cert_name}.issuer.crt"
key="${CERT_DIR}/${cert_name}.key"
fullchain="${CERT_DIR}/${cert_name}.fullchain.pem"

[[ -s "${crt}" ]] || die "missing certificate: ${crt}"
[[ -s "${issuer}" ]] || die "missing issuer certificate: ${issuer}"
[[ -s "${key}" ]] || die "missing private key: ${key}"

openssl x509 -in "${crt}" -noout -checkend 0 >/dev/null 2>&1 ||
    die "certificate is expired or not yet valid: ${crt}"

cert_fingerprint="$(openssl x509 -in "${crt}" -pubkey -noout | openssl pkey -pubin -outform DER 2>/dev/null | openssl sha256)"
key_fingerprint="$(openssl pkey -in "${key}" -pubout -outform DER 2>/dev/null | openssl sha256)"
[[ "${cert_fingerprint}" == "${key_fingerprint}" ]] || die "certificate and private key do not match"

tmp="$(mktemp "${CERT_DIR}/.${cert_name}.fullchain.XXXXXX")"
trap 'rm -f -- "${tmp}"' EXIT
cat "${crt}" "${issuer}" > "${tmp}"
chmod 0644 "${tmp}"
mv -f -- "${tmp}" "${fullchain}"
trap - EXIT

log "installing ${cert_name} for the port 8006 interface"
pvenode cert set "${fullchain}" "${key}" --force
systemctl restart pveproxy.service
log "certificate activated and pveproxy restarted"
