identity-service
Purpose
identity-service is the Keycloak-backed IAM for OpenBox. Issues OIDC tokens, manages user accounts + realms + clients, and enforces MFA / SSO federation if configured. The openbox-backend and openbox-fe are both OIDC clients of this service.
Plane: Control plane.
Ports & endpoints
| Port | Protocol | Purpose | Exposed via |
|---|---|---|---|
8080 | HTTPS | Keycloak admin + realm endpoints | Istio Gateway (public) |
8080/realms/openbox/protocol/openid-connect/* | OIDC | Token endpoints for openbox-backend + openbox-fe | Public via ingress |
8080/admin/master/console/ | HTML | Admin console (accessed by ops) | Public via ingress; consider ZTNA gate |
9000/health | HTTP | Keycloak health probes | K8s kubelet |
9000/metrics | HTTP | Prometheus scrape | Cluster-internal |
Realms shipped by chart:
master— admin realm (bootstrap creds provisioned by chart)openbox— application realm (users + clients live here)
Runtime
| Property | Value |
|---|---|
| Container count per pod | 1 (Keycloak on JVM) |
| Resource requests | 200m CPU / 1700 Mi RAM |
| Resource limits | 500m CPU / 2 Gi RAM |
| HPA min → max replicas | 3 → 5 (Keycloak HA requires ≥ 3) |
| HPA target | CPU 60% |
| Node placement | General CPU pool |
| Startup time | ~2-3 min (JVM warmup + DB schema migration) |
JVM footprint is the reason for the high RAM request. Set -Xms / -Xmx via KEYCLOAK_JAVA_OPTS env if you need to bound heap tighter.
Configuration
Chart values keys (top-level identity-service.*)
| Key | Purpose |
|---|---|
enabled | Toggle whole service (rarely disabled) |
replicaCount | Static; ignored when HPA on. Chart default 3 for HA |
image.repository / image.tag | Container image (quay.io/keycloak/keycloak:XX.X default) |
secret.stringData.KC_DB_PASSWORD | Required — Keycloak DB password |
secret.stringData.KC_BOOTSTRAP_ADMIN_PASSWORD | Required — bootstrap admin password. Rotate immediately after first login. |
db.host / .port / .name | External DB (else uses in-cluster PG) |
db.userSecretRef | K8s Secret with username + password for DB user |
Runtime env vars
KC_DB_URL— JDBC URL for identity PostgresKC_DB_USERNAME,KC_DB_PASSWORD— from secret refsKC_HOSTNAME— public URL (used in tokenissclaim)KC_PROXY_HEADERS—xforwardedif behind ALB/NGINXKEYCLOAK_ADMIN—adminbootstrap userKEYCLOAK_ADMIN_PASSWORD— from bootstrap secret (rotate!)
IAM permissions
None required — Keycloak does not call AWS APIs.
Dependencies
Downstream
| Target | Protocol | Purpose |
|---|---|---|
openbox-identity-postgresql | JDBC :5432 | Realm + user + token storage |
Upstream
openbox-backend— OIDC verification, token endpointopenbox-fe— browser-side OIDC redirects- End users (via browser) — login flow
Deployment guidelines
Prod
- Keep
replicaCount: 3+— Keycloak requires ≥ 3 for its Infinispan cluster consensus - Use external RDS — do not run in-cluster Postgres for identity data in prod
- Set
KC_HOSTNAMEto your public FE URL (tokenissclaim must match) - Enable session sticky affinity on ingress (Keycloak sessions are node-local unless clustered — Infinispan handles this once ≥ 3 replicas)
- Rotate bootstrap admin password immediately after first login. Chart provisions a random one, but you should replace + document it
- Configure SSO federation (SAML / OIDC) if your org has existing IdP — Keycloak Admin Console → Identity Providers
Local PoC
replicaCount: 1— HA irrelevant on laptop- In-cluster PG (Bitnami) is fine
- Skip session affinity
Troubleshooting
Pod Running but backend logs "Cannot connect to identity service"
→ Keycloak still bootstrapping (JVM + DB migration). Takes ~2-3 min on cold start. kubectl logs deploy/identity-service — look for Keycloak … started. Backend retries auto-fix once ready.
Login page loads, but submit returns 500
→ Realm openbox not created OR bootstrap admin password wrong. Log into /admin with bootstrap creds; verify realm exists + import if missing.
Token returned but backend rejects it (invalid_issuer)
→ KC_HOSTNAME mismatch. Token iss claim = https://<KC_HOSTNAME>/realms/openbox, but backend expects a different value. Fix env.KC_HOSTNAME in values, helm upgrade, restart.
Keycloak Infinispan cluster split-brain (3 pods but session errors) → Pods can't reach each other for cluster sync. Check NetworkPolicy — Keycloak needs peer-to-peer port 7800 (JGroups) between its own pods. Chart's default NetworkPolicy allows this; if you've added a custom one, allow ingress from same-app pods.
High RAM usage / OOMKilled
→ JVM heap unbounded. Set KEYCLOAK_JAVA_OPTS="-Xms512m -Xmx1500m" and bump resources.limits.memory to 2 Gi (chart default).
Bootstrap password lost
→ Cannot recover from Keycloak (bcrypt hashed). Recovery: kubectl exec into a pod, run /opt/keycloak/bin/kc.sh in admin mode to re-add an admin user, or destroy + reinstall the realm (lose users too). Rotate immediately after install to avoid this trap.