Files
net-kingdom/sso-mfa/k8s/keycloak/bootstrap-realm.sh
Bernd Worsch d0ed7d9cd6 feat(sso-mfa): T05 Keycloak manifests (NK-WP-0001-T05)
Deploys Keycloak (SSO core) in the sso namespace.

Files:
  sso-mfa/k8s/keycloak/pvc.yaml          — keycloak-data PVC (build cache)
  sso-mfa/k8s/keycloak/middleware.yaml   — rate-limit, admin-allowlist, HSTS
  sso-mfa/k8s/keycloak/deployment.yaml   — Deployment + Service; init container
                                           downloads privacyIDEA provider JAR
  sso-mfa/k8s/keycloak/ingress.yaml      — Ingress for kc.coulomb.social (CP-NK-004)
  sso-mfa/k8s/keycloak/create-secrets.sh — keycloak-config Secret
  sso-mfa/k8s/keycloak/bootstrap-realm.sh— hardens master realm, creates net-kingdom realm
  sso-mfa/k8s/keycloak/README.md         — apply order, custom image guide, DR
  sso-mfa/k8s/verify-t05.sh              — T05 done-criteria verification script

Config points added: CP-NK-004 (kc.coulomb.social), CP-NK-005 (provider JAR URL).
CP-NK-005 must be set before applying deployment.yaml.

Pending: apply to live cluster, set CP-NK-005, run bootstrap-realm.sh, verify-t05.sh.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-19 02:00:51 +00:00

151 lines
6.5 KiB
Bash
Executable File

#!/usr/bin/env bash
# bootstrap-realm.sh — Phase 1 Keycloak bootstrap for T05
#
# Runs AFTER the Keycloak pod is Running and Ready (verify with verify-t05.sh).
#
# Actions (T05 scope):
# 1. Authenticate to Keycloak admin REST API via kcadm.sh in the pod
# 2. Harden master realm: brute-force protection, token lifetimes, SSL required
# 3. Create the net-kingdom application realm
# 4. Enable realm-level brute-force protection and SSL
#
# Out of scope for T05 (handled in T06):
# - privacyIDEA authentication flow configuration
# - User federation / LDAP resolver setup
# - Per-client OIDC settings
# - Break-glass admin account (T07)
#
# Usage:
# chmod +x bootstrap-realm.sh
# ./bootstrap-realm.sh [--realm-name NAME]
#
# Options:
# --realm-name NAME Name for the application realm (default: net-kingdom)
#
# Prerequisites:
# - kubectl configured with cluster access
# - Keycloak pod Running+Ready in the sso namespace
# - KC_ADMIN_PASSWORD available (prompted interactively if not set as env var)
set -euo pipefail
NAMESPACE="sso"
REALM_NAME="net-kingdom"
while [[ $# -gt 0 ]]; do
case "$1" in
--realm-name) REALM_NAME="$2"; shift 2 ;;
*) echo "Unknown option: $1" >&2; exit 1 ;;
esac
done
# ── Find the running Keycloak pod ─────────────────────────────────────────────
KC_POD=$(kubectl get pod -n "$NAMESPACE" \
-l app.kubernetes.io/name=keycloak \
--field-selector=status.phase=Running \
-o jsonpath='{.items[0].metadata.name}' 2>/dev/null || echo "")
if [[ -z "$KC_POD" ]]; then
echo "ERROR: No running Keycloak pod found in namespace $NAMESPACE." >&2
echo "Run verify-t05.sh to diagnose." >&2
exit 1
fi
echo "Using pod: $KC_POD"
# ── Admin password ────────────────────────────────────────────────────────────
if [[ -z "${KC_ADMIN_PASSWORD:-}" ]]; then
echo -n "Keycloak admin password (KC_ADMIN_PASSWORD): "
read -rs KC_ADMIN_PASSWORD
echo ""
fi
if [[ -z "$KC_ADMIN_PASSWORD" ]]; then
echo "ERROR: KC_ADMIN_PASSWORD is required." >&2
exit 1
fi
# ── Helper: run kcadm.sh inside the pod ──────────────────────────────────────
kcadm() {
kubectl exec -n "$NAMESPACE" "$KC_POD" -- \
/opt/keycloak/bin/kcadm.sh "$@"
}
# ── 1. Authenticate ───────────────────────────────────────────────────────────
echo ""
echo "── Authenticating ───────────────────────────────────────────────────────"
kcadm config credentials \
--server http://localhost:8080 \
--realm master \
--user admin \
--password "$KC_ADMIN_PASSWORD"
echo " Authenticated as admin@master"
# ── 2. Harden master realm ────────────────────────────────────────────────────
echo ""
echo "── Hardening master realm ───────────────────────────────────────────────"
# Require SSL for all connections to master realm (external access requires HTTPS).
kcadm update realms/master \
--set 'sslRequired=external'
echo " sslRequired=external (master)"
# Brute-force protection: lock after 5 failures for 5 minutes.
kcadm update realms/master \
--set 'bruteForceProtected=true' \
--set 'failureFactor=5' \
--set 'waitIncrementSeconds=60' \
--set 'maxFailureWaitSeconds=900' \
--set 'minimumQuickLoginWaitSeconds=60'
echo " Brute-force protection enabled (master)"
# Shorten access token lifetime for security.
kcadm update realms/master \
--set 'accessTokenLifespan=300' # 5 min
echo " Access token lifetime: 300s (master)"
# ── 3. Create the net-kingdom application realm ───────────────────────────────
echo ""
echo "── Creating realm: $REALM_NAME ─────────────────────────────────────────"
if kcadm get realms/"$REALM_NAME" &>/dev/null; then
echo " Realm $REALM_NAME already exists — skipping creation."
else
kcadm create realms \
--set "realm=$REALM_NAME" \
--set 'enabled=true' \
--set 'displayName=net-kingdom' \
--set 'sslRequired=external' \
--set 'registrationAllowed=false' \
--set 'bruteForceProtected=true' \
--set 'failureFactor=5' \
--set 'waitIncrementSeconds=60' \
--set 'maxFailureWaitSeconds=900' \
--set 'minimumQuickLoginWaitSeconds=60' \
--set 'accessTokenLifespan=300' \
--set 'refreshTokenMaxReuse=0' \
--set 'revokeRefreshToken=true'
echo " Realm $REALM_NAME created."
fi
# ── 4. Summary ────────────────────────────────────────────────────────────────
echo ""
echo "════════════════════════════════════════════════════════════"
echo " T05 realm bootstrap complete."
echo "════════════════════════════════════════════════════════════"
echo ""
echo "What was done:"
echo " - master realm: SSL required, brute-force protection, short token lifetimes"
echo " - realm '$REALM_NAME' created with equivalent hardening"
echo ""
echo "Next steps (T06):"
echo " 1. Log in to https://kc.coulomb.social/admin with the bootstrap admin."
echo " Immediately create a permanent admin account, then delete/disable"
echo " the bootstrap 'admin' account (or rotate KC_BOOTSTRAP_ADMIN_PASSWORD)."
echo " 2. In realm '$REALM_NAME':"
echo " - Configure the privacyIDEA authentication flow (see T06 README)."
echo " - Set privacyIDEA base URL: https://pink.coulomb.social"
echo " - Set trigger-admin credentials from the privacyidea-trigger-admin Secret."
echo " 3. Run verify-t05.sh to confirm all T05 done-criteria."