generated from coulomb/repo-seed
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>
151 lines
6.5 KiB
Bash
Executable File
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."
|