generated from coulomb/repo-seed
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>
This commit is contained in:
150
sso-mfa/k8s/keycloak/bootstrap-realm.sh
Executable file
150
sso-mfa/k8s/keycloak/bootstrap-realm.sh
Executable file
@@ -0,0 +1,150 @@
|
||||
#!/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."
|
||||
Reference in New Issue
Block a user