7.2 KiB
Keycloak
Identity and Access Management (IAM) solution for Kubernetes:
- Keycloak Operator: Manages Keycloak instances via CRDs
- Keycloak: Open Source Identity and Access Management
- PostgreSQL Integration: Uses CloudNativePG cluster for persistence
- OIDC Provider: Centralized authentication for all services
Prerequisites
- Kubernetes cluster (k3s)
- PostgreSQL (CloudNativePG)
- External Secrets Operator (optional, for Vault integration)
- Vault (optional, for credential storage)
Installation
just keycloak::install
You will be prompted for:
- Keycloak admin username: Default is
admin - Keycloak admin password: Auto-generated if not provided
- Keycloak host (FQDN): e.g.,
auth.example.com
What Gets Installed
- Keycloak Operator and CRDs
- Keycloak instance with PostgreSQL backend
- Ingress for external access
- Admin credentials stored in Kubernetes Secret (and optionally Vault)
The stack uses the official Keycloak Operator.
Pod Security Standards
The keycloak namespace uses baseline Pod Security Standard enforcement.
pod-security.kubernetes.io/enforce=baseline
Why Baseline Instead of Restricted?
The Keycloak Operator (provided by upstream) does not meet the restricted Pod Security Standard requirements:
- Missing
allowPrivilegeEscalation: false - Missing
securityContext.capabilities.drop: [ALL] - Missing
runAsNonRoot: true - Missing
seccompProfile
Since the Operator is deployed via official manifests from GitHub, we cannot modify its security context without maintaining a custom fork.
Security Measures
While using baseline enforcement at the namespace level, the Keycloak application Pod applies restricted-level security contexts via unsupported.podTemplate:
Pod Security Context:
runAsNonRoot: truerunAsUser: 1000runAsGroup: 1000fsGroup: 1000seccompProfile.type: RuntimeDefault
Container Security Context:
allowPrivilegeEscalation: falsecapabilities.drop: [ALL]runAsNonRoot: trueseccompProfile.type: RuntimeDefault
Note: readOnlyRootFilesystem: false is required because Keycloak needs to write configuration files and cache data.
Baseline vs Restricted
Baseline still provides strong security:
- Prohibits privileged containers
- Prohibits
hostNetwork,hostPID,hostIPC - Prohibits
hostPathvolumes - Restricts dangerous capabilities
The primary difference is that baseline does not enforce seccomp profiles and capability drops, which the Operator lacks but the Keycloak Pod implements.
Access
Access Keycloak at https://your-keycloak-host/
Admin Credentials:
- Username: Retrieved via
just keycloak::admin-username - Password: Retrieved via
just keycloak::admin-password
Configuration
Environment variables (set in .env.local or override):
KEYCLOAK_NAMESPACE=keycloak # Kubernetes namespace
KEYCLOAK_OPERATOR_VERSION=26.4.5 # Keycloak Operator version
KEYCLOAK_REALM= # Default realm name
KEYCLOAK_HOST= # Keycloak FQDN
KEYCLOAK_ADMIN_USER= # Admin username
KEYCLOAK_ADMIN_PASSWORD= # Admin password
Realm Management
Create Realm
just keycloak::create-realm
You will be prompted for the realm name. This creates a new realm for your applications.
Delete Realm
just keycloak::delete-realm <realm-name>
User Management
Create User
just keycloak::create-user
Interactive prompts for:
- Username
- First name
- Last name
- Password
- Realm
Delete User
just keycloak::delete-user <username>
Add User to Group
just keycloak::add-user-to-group <username> <group>
List Users
just keycloak::list-users
Client Management
Create OIDC Client
just keycloak::create-client realm=<realm> client_id=<client-id> redirect_url=<url> client_secret=<secret>
This creates a confidential OIDC client with the specified settings.
For public clients (e.g., browser-based apps):
just keycloak::create-public-client realm=<realm> client_id=<client-id> redirect_url=<url>
Delete Client
just keycloak::delete-client <realm> <client-id>
List Clients
just keycloak::list-clients
Group Management
Create Group
just keycloak::create-group <group-name>
Delete Group
just keycloak::delete-group <group-name>
List Groups
just keycloak::list-groups
Common Integration Patterns
OIDC Authentication for Web Applications
-
Create OIDC client:
just keycloak::create-client \ realm=myrealm \ client_id=myapp \ redirect_url=https://myapp.example.com/callback \ client_secret=$(just utils::random-password) -
Configure your application:
- OIDC Discovery URL:
https://your-keycloak-host/realms/myrealm - Client ID:
myapp - Client Secret: (from step 1)
- Redirect URI:
https://myapp.example.com/callback
- OIDC Discovery URL:
-
Create user groups for authorization:
just keycloak::create-group myapp-admins just keycloak::create-group myapp-users -
Add users to groups:
just keycloak::add-user-to-group alice myapp-admins just keycloak::add-user-to-group bob myapp-users
JWT Token Validation
Applications can validate JWT tokens issued by Keycloak using the public keys from:
https://your-keycloak-host/realms/myrealm/protocol/openid-connect/certs
Kubernetes OIDC Authentication
To enable OIDC authentication for Kubernetes API:
just k8s::setup-oidc-auth
This configures k3s to use Keycloak for user authentication.
Monitoring
Enable Prometheus monitoring for Keycloak:
just keycloak::enable-monitoring
This creates a ServiceMonitor that scrapes metrics from Keycloak's management port (9000).
Metrics are automatically renamed from vendor_* to keycloak_* for better discoverability.
Troubleshooting
Check Keycloak Pod Status
kubectl get pods -n keycloak
View Keycloak Logs
kubectl logs -n keycloak keycloak-0
Check Database Connection
Verify PostgreSQL connection:
kubectl get secret database-config -n keycloak -o yaml
Reset Admin Password
# Delete existing credentials
kubectl delete secret keycloak-credentials -n keycloak
kubectl delete secret keycloak-bootstrap-admin -n keycloak
# Recreate with new password
just keycloak::create-credentials
Management
Uninstall Keycloak Instance
just keycloak::uninstall
This removes the Keycloak instance but keeps the Operator installed.
To keep the database:
just keycloak::uninstall delete-db=false
Uninstall Keycloak Operator
just keycloak::uninstall-operator
This removes the Operator and all CRDs.