#!/bin/sh
#
# fleetserver-gen-selfsigned-cert — produce a self-signed TLS cert+key
# for fleetserver's REST API.  Linux variant; mirrors the FreeBSD
# helper.
#
# Usage:
#   fleetserver-gen-selfsigned-cert [output-dir] [CN]
#
# Defaults:
#   output-dir = /etc/marlinos/fleet/tls
#   CN         = the output of `hostname -f`
#
# Creates cert.pem + key.pem (mode 0600 for key, owned by
# _fleetserver).  To rotate: run again and restart fleetserver.  To
# replace with a CA-issued cert, drop your fullchain into cert.pem
# and your key into key.pem at the same path — fleetserver just
# reads the files; it doesn't care how they were made.

set -eu

OUT="${1:-/etc/marlinos/fleet/tls}"
CN="${2:-$(hostname -f 2>/dev/null || hostname)}"
DAYS="${CERT_DAYS:-3650}"   # 10-year self-signed default — rotate via re-run

mkdir -p "${OUT}"

# SAN entries.  Keep it permissive so fleet-cli TOFU can match against
# whatever host/IP the operator uses.  Operators who want strict
# hostname matching should replace the cert with a CA-issued one.
SAN="DNS:${CN}"
if [ "${CN}" != "localhost" ]; then
    SAN="${SAN},DNS:localhost"
fi
SAN="${SAN},IP:127.0.0.1,IP:::1"

# If we can get the host's primary IPv4, add that too.  ``hostname
# -I`` is GNU coreutils-specific (Debian, Ubuntu, RHEL); fall back to
# ``ip addr`` if missing.
HOST_IP=""
if command -v hostname >/dev/null 2>&1; then
    HOST_IP="$(hostname -I 2>/dev/null | awk '{print $1}')"
fi
if [ -z "${HOST_IP}" ] && command -v ip >/dev/null 2>&1; then
    HOST_IP="$(ip -4 -o addr show scope global 2>/dev/null | awk '{print $4}' | cut -d/ -f1 | head -1)"
fi
if [ -n "${HOST_IP}" ]; then
    SAN="${SAN},IP:${HOST_IP}"
fi

# Also pin the canonical WireGuard hub address so racing-boat fleetd
# can dial in over the tunnel without TOFU flagging the cert.
SAN="${SAN},IP:10.8.0.1"

openssl req -x509 \
    -newkey ec -pkeyopt ec_paramgen_curve:P-256 \
    -keyout "${OUT}/key.pem" \
    -out "${OUT}/cert.pem" \
    -days "${DAYS}" \
    -nodes \
    -subj "/CN=${CN}" \
    -addext "subjectAltName=${SAN}" \
    -addext "keyUsage=digitalSignature,keyEncipherment" \
    -addext "extendedKeyUsage=serverAuth"

chmod 0600 "${OUT}/key.pem"
chmod 0644 "${OUT}/cert.pem"

# Chown TLS material to the unprivileged service user so the
# dropped-priv fleetserver can read it.  Falls back gracefully when
# the user isn't created yet (early bootstrap).
SVC_USER="${FLEETSERVER_USER:-_fleetserver}"
SVC_GROUP="${FLEETSERVER_GROUP:-_fleetserver}"
if id -u "${SVC_USER}" >/dev/null 2>&1; then
    chown "${SVC_USER}:${SVC_GROUP}" "${OUT}/key.pem" "${OUT}/cert.pem"
fi

echo
echo "Self-signed cert written:"
echo "  ${OUT}/cert.pem  (CN=${CN}, SAN=${SAN})"
echo "  ${OUT}/key.pem   (mode 0600)"
echo
echo "fleetserver picks these up automatically on next start when"
echo "FLEETSERVER_TLS_CERT / FLEETSERVER_TLS_KEY in /etc/default/"
echo "fleetserver point at this directory (default).  Rotate via:"
echo "  systemctl restart fleetserver"
echo
echo "On first fleet-cli contact, the operator is prompted to trust"
echo "the cert by SHA-256 fingerprint:"
openssl x509 -in "${OUT}/cert.pem" -noout -fingerprint -sha256
