#!/bin/bash
# init-stepca.sh — provision the PROD step-ca ACME endpoint on tsys-ca [#800]
#
# Run ON tsys-ca as root, from /opt/stepca-prod (this script + compose.yaml
# live there; data/ is created). Refuses to touch an existing data/ unless
# --reinit.
#
# What it does:
#   1. scaffolds a step home (docker one-shot init; throwaway self-signed CA)
#   2. generates an ECDSA P-256 ACME intermediate and signs it with the
#      FLEET ROOT (/root/ca-root) — same constraints as ca-init.sh
#   3. swaps in the fleet chain (root cert + intermediate), adds an ACME
#      provisioner, writes the runtime password
# The root KEY never leaves /root/ca-root. The ACME intermediate key and the
# runtime password live only in /opt/stepca-prod (0700, root-owned).
set -euo pipefail

BASE="/opt/stepca-prod"
DATA="$BASE/data"
ROOT_CRT="/root/ca-root/root.crt"
ROOT_KEY="/root/ca-root/root.key"
IMAGE="smallstep/step-ca@sha256:e9e8fa3262bf37b130962ffddbf6a64ac188f0bbb80959cf3ddc04c6bf294c3d"
TAILNET_IP="$(tailscale ip -4)"

[ -f "$ROOT_CRT" ] && [ -f "$ROOT_KEY" ] || { echo "FAIL: fleet root not found at $ROOT_CRT/$ROOT_KEY" >&2; exit 1; }
[ -n "$TAILNET_IP" ] || { echo "FAIL: no tailscale IP" >&2; exit 1; }
if [ -d "$DATA" ] && [ "${1:-}" != "--reinit" ]; then
  echo "FAIL: $DATA exists (pass --reinit to wipe and redo)" >&2; exit 1
fi

mkdir -p "$BASE" "$BASE/secrets"
chmod 700 "$BASE"; chmod 711 "$BASE/secrets"
rm -rf "$DATA"; mkdir -p "$DATA/certs" "$DATA/secrets" "$DATA/config" "$DATA/db"
# scaffold + runtime run as container uid 1000 (step) — tree must be writable by it
chown -R 1000:1000 "$DATA"

# runtime + provisioner password (generated once; container uid 1000 must read it)
if [ ! -s "$BASE/secrets/password" ]; then
  openssl rand -base64 18 > "$BASE/secrets/password"
fi
chown 1000:1000 "$BASE/secrets/password"
chmod 600 "$BASE/secrets/password"

# 1. scaffold (throwaway self-signed CA; replaced below)
docker run --rm -v "$DATA:/home/step" -v "$BASE/secrets:/secrets:ro" \
  --entrypoint /bin/sh "$IMAGE" -c '
  step ca init --name "KNEL Fleet CA" \
    --dns "localhost" --dns "tsys-ca.knel.net" --dns "'"$TAILNET_IP"'" \
    --address ":9000" --provisioner "admin" \
    --password-file /secrets/password --provisioner-password-file /secrets/password \
    --deployment-type standalone >/dev/null'
echo "scaffold done"

# 2. ACME intermediate signed by the fleet root (ECDSA P-256, pathlen 0)
openssl ecparam -name prime256v1 -genkey -noout -out /tmp/acme-int.key
chmod 400 /tmp/acme-int.key
openssl req -new -key /tmp/acme-int.key -out /tmp/acme-int.csr -sha256 \
  -subj "/C=US/ST=Texas/O=Known Element Enterprises/OU=TechOps/CN=KNEL Fleet ACME Intermediate"
openssl x509 -req -in /tmp/acme-int.csr -CA "$ROOT_CRT" -CAkey "$ROOT_KEY" \
  -CAcreateserial -days 1825 -sha256 -out /tmp/acme-int.crt \
  -extfile <(printf 'basicConstraints=critical,CA:TRUE,pathlen:0\nkeyUsage=critical,keyCertSign,cRLSign\nsubjectKeyIdentifier=hash\nauthorityKeyIdentifier=keyid:always')
openssl verify -CAfile "$ROOT_CRT" /tmp/acme-int.crt
rm -f /tmp/acme-int.csr

# 3. swap in the fleet chain (root KEY stays offline in /root/ca-root)
cp "$ROOT_CRT" "$DATA/certs/root_ca.crt"
cp /tmp/acme-int.crt "$DATA/certs/intermediate_ca.crt"
mv /tmp/acme-int.key "$DATA/secrets/intermediate_ca_key"
rm -f "$DATA/secrets/root_ca_key"

# 4. ACME provisioner (JWK password re-read from the same file)
docker run --rm -v "$DATA:/home/step" -v "$BASE/secrets:/secrets:ro" \
  --entrypoint /bin/sh "$IMAGE" -c '
  step ca provisioner add acme --type ACME --password-file /secrets/password >/dev/null'

# 5. runtime password where the container entrypoint expects it
cp "$BASE/secrets/password" "$DATA/secrets/password"

# ownership to uid 1000 (step)
chown -R 1000:1000 "$DATA"
chmod 400 "$DATA/secrets/intermediate_ca_key"

echo "init complete: $DATA ready — bring up with: cd $BASE && docker compose -f compose.yaml up -d"
