Files
net-kingdom/sso-mfa/k8s/keycape/create-secrets.sh
Bernd Worsch 880f89bf98 fix(keycape): NK-WP-0003-T07 — fix deployment image + add demo-app client
- deployment.yaml: image → 92.205.130.254:32166/coulomb/key-cape:latest
  (Gitea OCI registry, delivered by KEY-WP-0002; imagePullPolicy: Always)
- k3s insecure registry hosts.toml: fixed server endpoint to http:// so
  containerd does not attempt HTTPS against the plain-HTTP Gitea NodePort
- create-secrets.sh: add demo-app OIDC client (required for KeyCape to
  start; also needed for T08 acceptance tests)
- keycape-config Secret updated in-place (no re-bootstrap needed)

KeyCape pod 1/1 Running; /healthz OK; OIDC discovery live at
https://kc.coulomb.social/.well-known/openid-configuration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-22 00:30:58 +00:00

126 lines
4.9 KiB
Bash

#!/usr/bin/env bash
# create-secrets.sh — create the keycape-config K8s Secret
#
# Usage:
# ./create-secrets.sh [secrets-dir]
#
# Creates ONE Secret in the sso namespace:
# keycape-config — config.yaml (full KeyCape config) + key.pem (RSA signing key)
#
# The privacyIDEA admin token is a separate Secret (keycape-pi-token) created
# by create-pi-token.sh AFTER privacyIDEA is bootstrapped (T04 complete).
# The PI admin token is read from that Secret at startup via config.yaml.
#
# Re-run this script to:
# - Rotate the Authelia client secret (update secrets/authelia/secrets.env first)
# - Add or modify OIDC client registrations (edit CLIENTS block below)
# - Rotate the RSA signing key (delete and regenerate secrets/keycape/key.pem)
set -euo pipefail
SECRETS_DIR="${1:-../../bootstrap/secrets}"
KEYCAPE_ENV="$SECRETS_DIR/keycape/secrets.env"
LLDAP_ENV="$SECRETS_DIR/lldap/secrets.env"
AUTHELIA_ENV="$SECRETS_DIR/authelia/secrets.env"
KEY_FILE="$SECRETS_DIR/keycape/key.pem"
for f in "$KEYCAPE_ENV" "$LLDAP_ENV" "$AUTHELIA_ENV"; do
if [[ ! -f "$f" ]]; then
echo "ERROR: $f not found — run sso-mfa/bootstrap/gen-secrets.sh first." >&2
exit 1
fi
done
read_env() { bash -c "source '$1' 2>/dev/null; echo \${$2}"; }
LLDAP_BIND_PW=$(read_env "$LLDAP_ENV" LLDAP_LDAP_USER_PASS)
AUTHELIA_CLIENT_SECRET=$(read_env "$AUTHELIA_ENV" AUTHELIA_KEYCAPE_CLIENT_SECRET)
if [[ -z "$LLDAP_BIND_PW" || -z "$AUTHELIA_CLIENT_SECRET" ]]; then
echo "ERROR: could not read LLDAP_LDAP_USER_PASS or AUTHELIA_KEYCAPE_CLIENT_SECRET" >&2
exit 1
fi
# The privacyIDEA admin token is read from a separate Secret at runtime.
# Placeholder here — create-pi-token.sh populates the real value.
PI_ADMIN_TOKEN="PENDING_create-pi-token.sh"
if [[ -f "$SECRETS_DIR/keycape/pi_admin_token" ]]; then
PI_ADMIN_TOKEN=$(cat "$SECRETS_DIR/keycape/pi_admin_token")
echo "INFO: Using privacyIDEA admin token from $SECRETS_DIR/keycape/pi_admin_token"
fi
# ── RSA signing key ───────────────────────────────────────────────────────────
if [[ ! -f "$KEY_FILE" ]]; then
echo "Generating RSA-2048 signing key for KeyCape JWT tokens..."
mkdir -p "$(dirname "$KEY_FILE")"
openssl genrsa -out "$KEY_FILE" 2048 2>/dev/null
chmod 600 "$KEY_FILE"
echo " Generated: $KEY_FILE"
echo " IMPORTANT: Store this key in KeePassXC → net-kingdom/KeyCape/jwt-signing-key"
echo " as a binary attachment. It cannot be recovered if lost."
else
echo "INFO: Using existing key: $KEY_FILE"
fi
KEY_CONTENT=$(cat "$KEY_FILE")
# ── Build config.yaml ─────────────────────────────────────────────────────────
# Edit the OIDC clients block below to register downstream applications.
# Re-run this script after any change.
CONFIG_YAML=$(cat <<EOF
issuer: "https://kc.coulomb.social"
port: 8080
tokenLifetime: "15m"
privateKeyPem: "/etc/keycape/key.pem"
environment: "production"
lldap:
url: "ldap://lldap.sso.svc.cluster.local:3890"
bindDN: "uid=admin,ou=people,dc=netkingdom,dc=local"
bindPW: "${LLDAP_BIND_PW}"
baseDN: "dc=netkingdom,dc=local"
authelia:
baseURL: "http://authelia.sso.svc.cluster.local:9091"
clientId: "keycape"
clientSecret: "${AUTHELIA_CLIENT_SECRET}"
redirectURI: "https://kc.coulomb.social/authorize/callback"
privacyidea:
baseURL: "http://privacyidea.mfa.svc.cluster.local:8080"
adminToken: "${PI_ADMIN_TOKEN}"
realm: "netkingdom"
# ── OIDC client registrations ─────────────────────────────────────────────────
# clientType: "public" for SPAs/native apps (PKCE, no client secret)
# "confidential" for server-side apps (client secret required)
clients:
- clientId: "demo-app"
displayName: "Demo Application"
redirectUris:
- "http://localhost:3000/callback"
- "https://demo.coulomb.social/callback"
allowedScopes: ["openid", "profile", "email", "groups"]
grantTypes: ["authorization_code"]
clientType: "public"
EOF
)
echo "Creating K8s Secret: keycape-config (namespace: sso)"
kubectl create secret generic keycape-config \
--namespace=sso \
--from-literal=config.yaml="$CONFIG_YAML" \
--from-literal=key.pem="$KEY_CONTENT" \
--dry-run=client -o yaml | kubectl apply -f -
echo ""
echo "Done. Secret keycape-config created in namespace: sso"
echo ""
if [[ "$PI_ADMIN_TOKEN" == "PENDING_create-pi-token.sh" ]]; then
echo "WARN: privacyIDEA admin token is a placeholder."
echo " After T04 bootstrap is complete, run:"
echo " ./create-pi-token.sh"
echo " Then re-run this script to update keycape-config."
echo ""
fi
echo "Next: apply deployment.yaml, middleware.yaml, ingress.yaml"