#!/usr/bin/env bash # create-pi-token.sh — fetch a privacyIDEA admin JWT and store it for KeyCape # # Usage: # ./create-pi-token.sh [secrets-dir] # # Run this script AFTER T04 bootstrap (privacyIDEA admin account created). # It authenticates to the privacyIDEA API, fetches a long-lived admin JWT, # and writes it to secrets/keycape/pi_admin_token. # # After running this script, re-run create-secrets.sh to update the # keycape-config K8s Secret with the real token, then restart KeyCape: # ./create-secrets.sh # kubectl rollout restart deployment/keycape -n sso # # The privacyIDEA admin token does NOT expire by default (it is a permanent # service account token). Store it in KeePassXC as: # net-kingdom/KeyCape/pi-admin-token # # Requires: kubectl, curl, jq set -euo pipefail SECRETS_DIR="${1:-../../bootstrap/secrets}" PI_ENV="$SECRETS_DIR/privacyidea/secrets.env" TOKEN_FILE="$SECRETS_DIR/keycape/pi_admin_token" if [[ ! -f "$PI_ENV" ]]; then echo "ERROR: $PI_ENV not found — run sso-mfa/bootstrap/gen-secrets.sh first." >&2 exit 1 fi read_env() { bash -c "source '$1' 2>/dev/null; echo \${$2}"; } PI_ADMIN_PASSWORD=$(read_env "$PI_ENV" PI_ADMIN_PASSWORD) if [[ -z "$PI_ADMIN_PASSWORD" ]]; then echo "ERROR: PI_ADMIN_PASSWORD is empty in $PI_ENV" >&2 exit 1 fi # Fetch token by exec-ing into the privacyIDEA pod (localhost call, bypasses # NetworkPolicy which restricts external ingress to the service). PI_POD=$(kubectl get pod -n mfa \ -l app.kubernetes.io/name=privacyidea \ --field-selector=status.phase=Running \ -o jsonpath='{.items[0].metadata.name}' 2>/dev/null || echo "") if [[ -z "$PI_POD" ]]; then # Fall back to public hostname if pod is not directly accessible PI_POD="" fi echo "Fetching privacyIDEA admin token..." if [[ -n "$PI_POD" ]]; then echo " Method: kubectl exec into $PI_POD (avoids NetworkPolicy restriction)" # Pass the password via env var. Retry up to 3 times — the PostgreSQL connection # pool can return 500 if the idle SSL connection was dropped; it recovers on retry. TOKEN="" for _ATTEMPT in 1 2 3; do TOKEN=$(kubectl exec -n mfa "$PI_POD" -- \ env PI_ADMIN_PASSWORD="${PI_ADMIN_PASSWORD}" \ python3 -c ' import urllib.request, urllib.parse, json, os, sys pw = os.environ["PI_ADMIN_PASSWORD"] data = urllib.parse.urlencode({"username": "pi-admin", "password": pw}).encode() req = urllib.request.Request("http://localhost:8080/auth", data=data) try: with urllib.request.urlopen(req, timeout=10) as r: body = json.load(r) print(body["result"]["value"]["token"]) except Exception as e: print(str(e), file=__import__("sys").stderr) sys.exit(1) ' 2>/dev/null || echo "") if [[ -n "$TOKEN" ]]; then break; fi echo " Attempt $_ATTEMPT failed (likely transient DB connection drop) — retrying in 5s..." sleep 5 done else echo " Method: public URL https://pink.coulomb.social" TOKEN=$(curl -sf \ -X POST "https://pink.coulomb.social/auth" \ -H "Content-Type: application/x-www-form-urlencoded" \ -d "username=pi-admin&password=${PI_ADMIN_PASSWORD}" \ | python3 -c "import sys,json; data=json.load(sys.stdin); print(data['result']['value']['token'])" \ 2>/dev/null || echo "") fi if [[ -z "$TOKEN" ]]; then echo "ERROR: failed to fetch token from privacyIDEA." >&2 echo " Verify that privacyIDEA is Running and the pi-admin account exists." >&2 echo " Check: kubectl logs -n mfa \$(kubectl get pod -n mfa -l app.kubernetes.io/name=privacyidea -o name | head -1)" >&2 exit 1 fi mkdir -p "$(dirname "$TOKEN_FILE")" echo -n "$TOKEN" > "$TOKEN_FILE" chmod 600 "$TOKEN_FILE" # Create the keycape-pi-token K8s Secret (KeyCape reads it at startup) echo "Creating K8s Secret: keycape-pi-token (namespace: sso)" kubectl create secret generic keycape-pi-token \ --namespace=sso \ --from-literal=token="$TOKEN" \ --dry-run=client -o yaml | kubectl apply -f - echo " Done." echo "" echo "Token written to: $TOKEN_FILE" echo "Token preview : ${TOKEN:0:32}…" echo "" echo "IMPORTANT: Store this token in KeePassXC → net-kingdom/KeyCape/pi-admin-token" echo " as a password entry. It cannot be recovered without re-authenticating." echo "" echo "Next steps:" echo " 1. Re-run create-secrets.sh to update keycape-config with the real token." echo " 2. Restart KeyCape: kubectl rollout restart deployment/keycape -n sso"