#!/usr/bin/env bash
# Swap the self-signed certificate for the customer's real one. Independent of the Cilium upgrade.
#   curl ... tls-swap.sh | bash -s -- /data/cert_mdm.idnow.vodafone.de.crt /data/cert_mdm.idnow.vodafone.de.key /data/cert_mdm.idnow.vodafone.de.p7b.pem
# Arg 3 = anything holding the CA chain: a PKCS#7 PEM (.p7b.pem), a PEM bundle, or a DER .p7b.
# Builds  fullchain.pem (leaf + intermediates -> served by ingress and the MQTTS broker) and
#         chain.pem     (CA certs only -> appended to the in-cluster trust bundle).
# Uses ./seed-secrets.sh + ./smoke.sh from the current dir, else fetches them into /data/tls-tools.
set -euo pipefail
CRT="${1:?leaf cert}"; KEY="${2:?key}"; SRC="${3:?chain source (.p7b.pem / .pem / .p7b)}"
B="${B:-/data}"; SRV="${SRV:-http://23.88.61.31}"; K="/usr/local/bin/k3s kubectl"
step() { printf '\n==> %s  [%s]\n' "$*" "$(date -u +%H:%M:%S)"; }
if [ ! -x ./seed-secrets.sh ]; then
  step "fetching seed-secrets.sh, smoke.sh, BUNDLE.txt into $B/tls-tools (no bundle dir present)"
  mkdir -p "$B/tls-tools" && cd "$B/tls-tools"
  for f in seed-secrets.sh smoke.sh BUNDLE.txt; do curl -fsS ${PROXY_ARG:-} -O "$SRV/tools/$f"; done; chmod +x ./*.sh
fi
grep -q '^cluster: *vodafone/idnow' BUNDLE.txt || { echo "!! BUNDLE.txt here is not vodafone/idnow - prefix would be wrong"; exit 1; }
W="$(mktemp -d)"; trap 'rm -rf "$W"' EXIT
step "splitting the chain source: $SRC"
if grep -q 'BEGIN PKCS7' "$SRC"; then openssl pkcs7 -in "$SRC" -print_certs -out "$W/all.pem"
elif grep -q 'BEGIN CERTIFICATE' "$SRC"; then cp "$SRC" "$W/all.pem"
else openssl pkcs7 -inform DER -in "$SRC" -print_certs -out "$W/all.pem"; fi
awk 'BEGIN{n=0} /BEGIN CERTIFICATE/{n++; f=sprintf("'"$W"'/part-%02d.pem",n)} /BEGIN CERTIFICATE/,/END CERTIFICATE/{print > f}' "$W/all.pem"
LEAF_FP="$(openssl x509 -noout -fingerprint -sha256 -in "$CRT" | cut -d= -f2)"
: > "$W/chain.pem"
for c in "$W"/part-*.pem; do
  fp="$(openssl x509 -noout -fingerprint -sha256 -in "$c" | cut -d= -f2)"
  subj="$(openssl x509 -noout -subject -in "$c" | sed 's/^subject=//')"
  if [ "$fp" = "$LEAF_FP" ]; then echo "   leaf:  $subj"; else echo "   CA:    $subj"; cat "$c" >> "$W/chain.pem"; fi
done
[ -s "$W/chain.pem" ] || { echo "!! no CA certificates found in $SRC"; exit 1; }
# The delivered .crt may be DER; normalise the leaf to PEM before concatenating.
openssl x509 -in "$CRT" -out "$W/leaf.pem" 2>/dev/null || openssl x509 -inform DER -in "$CRT" -out "$W/leaf.pem"
head -1 "$W/leaf.pem" | grep -q 'BEGIN CERTIFICATE' || { echo "!! could not convert $CRT to PEM"; exit 1; }
cat "$W/leaf.pem" "$W/chain.pem" > "$W/fullchain.pem"
echo "   fullchain.pem: $(grep -c 'BEGIN CERTIFICATE' "$W/fullchain.pem") certs, first subject: $(openssl x509 -in "$W/fullchain.pem" -noout -subject | sed 's/subject=//')"
step "certificate details - SANs MUST include api. hub. AND mdm.idnow.vodafone.de"
openssl x509 -noout -subject -issuer -dates -ext subjectAltName -in "$CRT"
for h in api hub mdm; do openssl x509 -noout -ext subjectAltName -in "$CRT" | grep -q "$h.idnow.vodafone.de" && echo "   SAN $h: ok" || { echo "!! SAN $h.idnow.vodafone.de MISSING"; exit 1; }; done
step "diagnostics: key format, key algorithms, public-key digests, fingerprints of every delivered cert"
echo "   key header : $(head -1 "$KEY")"
echo "   key algo   : $(openssl pkey -in "$KEY" -noout -text 2>/dev/null | head -1)"
echo "   cert algo  : $(openssl x509 -in "$CRT" -noout -text | grep -E 'Public Key Algorithm' | sed 's/^ *//')"
echo "   cert pubkey: $(openssl x509 -pubkey -noout -in "$CRT" | openssl md5 | cut -d' ' -f2)"
echo "   key  pubkey: $(openssl pkey -in "$KEY" -pubout 2>/dev/null | openssl md5 | cut -d' ' -f2)   <- must equal the line above"
echo "   cert RSA modulus md5 (what seed-secrets compares): $(openssl x509 -noout -modulus -in "$CRT" 2>/dev/null | openssl md5 | cut -d' ' -f2)"
echo "   key  RSA modulus md5                             : $(openssl rsa -noout -modulus -in "$KEY" 2>/dev/null | openssl md5 | cut -d' ' -f2)"
for f in "$(dirname "$CRT")"/cert_mdm.idnow.vodafone.de.*; do case "$f" in *.key) ;; *)
  printf '   %-38s ' "$(basename "$f")"
  if grep -q 'BEGIN PKCS7' "$f" 2>/dev/null; then echo "PKCS7 PEM, $(openssl pkcs7 -in "$f" -print_certs | grep -c 'BEGIN CERT') certs";
  elif grep -q 'BEGIN CERTIFICATE' "$f" 2>/dev/null; then echo "$(grep -c 'BEGIN CERT' "$f") cert(s), first: $(openssl x509 -in "$f" -noout -fingerprint -sha256 | cut -d= -f2 | cut -c1-23)... $(openssl x509 -in "$f" -noout -subject | sed 's/subject=//')";
  else echo "DER/PKCS7 binary, $(openssl pkcs7 -inform DER -in "$f" -print_certs 2>/dev/null | grep -c 'BEGIN CERT') certs"; fi;; esac; done
step "key matches certificate?"
echo "   key type: $(head -1 "$KEY")"; echo "   cert key: $(openssl x509 -in "$CRT" -noout -text | grep -E 'Public Key Algorithm' | sed 's/^ *//')"
if diff <(openssl x509 -pubkey -noout -in "$CRT") <(openssl pkey -in "$KEY" -pubout 2>/dev/null); then echo "   yes"; else
  echo "!! public key of $KEY does not equal the one in $CRT"; echo "   fingerprints of every cert delivered:"
  for f in "$(dirname "$CRT")"/cert_mdm.idnow.vodafone.de.*; do case "$f" in *.key) ;; *) printf '   %-50s ' "$(basename "$f")"; openssl x509 -in "$f" -noout -fingerprint -sha256 2>/dev/null | cut -d= -f2 || echo "(not a single cert)";; esac; done
  exit 1; fi
step "chain verifies? (untrusted = intermediates from the chain source; system roots as trust)"
openssl verify -untrusted "$W/chain.pem" "$CRT" || openssl verify -CAfile "$W/chain.pem" -untrusted "$W/chain.pem" "$CRT"
step "DNS (set by Vodafone) - expect 172.16.25.70"
getent hosts api.idnow.vodafone.de hub.idnow.vodafone.de mdm.idnow.vodafone.de || echo "!! some name does not resolve from this node"
step "state BEFORE"
$K -n argocd get applications --no-headers | awk '{print $2,$3}' | sort | uniq -c
step "seeding: seed-secrets.sh --cert fullchain.pem --key ... --ca-chain chain.pem --force  (replaces ONLY tls + ca-bundle)"
read -r -p "    proceed? [y/N] " a </dev/tty; [ "$a" = y ] || { echo "aborted"; exit 1; }
cp "$KEY" "$W/key.pem"; chmod 600 "$W/key.pem"
# The bundled seed-secrets.sh compares RSA moduli via `openssl rsa` and rejects valid pairs; use the
# patched copy (public-key comparison) next to this cluster's BUNDLE.txt so the idnow- prefix is kept.
mkdir -p "$W/tools"; curl -fsS ${PROXY_ARG:-} -o "$W/tools/seed-secrets.sh" "$SRV/tools/seed-secrets.sh"; chmod +x "$W/tools/seed-secrets.sh"; cp BUNDLE.txt "$W/tools/"
"$W/tools/seed-secrets.sh" --cert "$W/fullchain.pem" --key "$W/key.pem" --ca-chain "$W/chain.pem" --force
step "force-sync the two ExternalSecrets (else 1h refresh)"
$K -n default annotate externalsecret emteria-tls force-sync="$(date +%s)" --overwrite
$K -n default annotate externalsecret customer-ca-bundle force-sync="$(date +%s)" --overwrite
sleep 20
echo -n "   emteria-tls now: "; { $K -n default get secret emteria-tls -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -noout -issuer -enddate | tr "\n" " "; } || true; echo
step "restart website (mounts ca-bundle via subPath) and mdm broker (reads PEM at startup)"
$K -n default rollout restart deployment/website daemonset/mdm
$K -n default rollout status deployment/website --timeout=300s
$K -n default rollout status daemonset/mdm --timeout=300s
step "what is served now (ingress-nginx reloads live)"
for h in api hub mdm; do printf '   %s:443   ' "$h"; openssl s_client -connect 127.0.0.1:443 -servername "$h.idnow.vodafone.de" </dev/null 2>/dev/null | openssl x509 -noout -issuer -enddate | tr '\n' ' '; echo; done
printf '   mdm:8883  '; openssl s_client -connect 127.0.0.1:8883 -servername mdm.idnow.vodafone.de </dev/null 2>/dev/null | openssl x509 -noout -issuer -enddate | tr '\n' ' '; echo
echo -n "   chain depth served on 443: "; openssl s_client -connect 127.0.0.1:443 -servername api.idnow.vodafone.de -showcerts </dev/null 2>/dev/null | grep -c 'BEGIN CERTIFICATE'
step "applications after the swap (want 14/14 Synced Healthy)"
sleep 30; $K -n argocd get applications
step "smoke with the real chain (dns.* rows and mdm.cert-match must PASS now)"
./smoke.sh || true
step "done. The key stays only in the cluster secret-store; consider: shred -u $KEY"
