Keycloak - Identity and Access Management
Table of Contents
Overview
Keycloak is an open-source Identity and Access Management (IAM) solution deployed in the Fako cluster. It provides single sign-on (SSO), user federation, identity brokering, and social login capabilities. This deployment uses Keycloak 26.x with PostgreSQL backend and is configured for high availability with clustering.
Key Features
- Single Sign-On (SSO): One login for multiple applications
- Identity Brokering: Connect to external identity providers
- User Federation: Sync users from LDAP or Active Directory
- Social Login: Support for Google, GitHub, Facebook, etc.
- Multi-Factor Authentication: Enhanced security with MFA
- High Availability: Clustered deployment with 2 replicas
- Secure Credential Management: Integration with AWS Secrets Manager
Architecture
Components
- Deployment: 2-replica deployment with pod anti-affinity
- Services:
- Main service on port 8080
- Headless service for JGroups clustering
- Storage: PostgreSQL database (postgres-cluster)
- ConfigMap: Environment configuration
- External Secrets:
- Admin credentials from AWS Secrets Manager
- Database credentials from AWS Secrets Manager
- Init Container: Database initialization and user setup
Resource Requirements
- Memory: 1Gi (request), 2Gi (limit) per pod
- CPU: 500m (request), 1000m (limit) per pod
- Database: PostgreSQL with dedicated database and user
Configuration
Environment Settings
| Parameter | Value | Description |
|---|---|---|
KC_HOSTNAME | https://auth.landryzetam.net | External hostname |
KC_HOSTNAME_STRICT | false | Allow backend access |
KC_HTTP_ENABLED | true | Enable HTTP (behind proxy) |
KC_PROXY | edge | Running behind edge proxy |
KC_PROXY_HEADERS | xforwarded | Use X-Forwarded headers |
KC_HEALTH_ENABLED | true | Enable health endpoints |
KC_METRICS_ENABLED | true | Enable metrics |
KC_CACHE_STACK | kubernetes | Use Kubernetes discovery |
Database Configuration
- Type: PostgreSQL
- Host:
postgres-cluster-rw.postgres.svc.cluster.local - Port: 5432
- Database:
keycloak - Credentials: Managed via AWS Secrets Manager
Clustering Configuration
JGroups clustering is configured for session replication:
- Discovery: DNS-based using headless service
- Query:
keycloak-headless.keycloak.svc.cluster.local - Port: 7800
Usage
Accessing Keycloak
External access:
https://auth.landryzetam.net
Internal access:
http://keycloak.keycloak.svc.cluster.local:8080
Admin Console
- Navigate to
https://auth.landryzetam.net/admin - Login with admin credentials from AWS Secrets Manager
Creating a Realm
- Login to admin console
- Click on the realm dropdown (top-left)
- Click “Create Realm”
- Configure realm settings:
- Name
- Display name
- Login settings
- Token settings
Adding Applications
# Example: Register an application
1. Select your realm
2. Navigate to Clients → Create
3. Configure:
- Client ID: your-app-id
- Client Protocol: openid-connect
- Root URL: https://your-app.example.com
User Management
Create User
# Via Admin Console
1. Select realm
2. Navigate to Users → Add user
3. Fill in user details
4. Set temporary password
Import Users from LDAP
# Configure User Federation
1. Navigate to User Federation
2. Add provider → LDAP
3. Configure connection settings
4. Set up attribute mappings
Operations
Checking Service Status
# Check pods
kubectl get pods -n keycloak
# View logs
kubectl logs -n keycloak -l app=keycloak
# Check cluster status
kubectl exec -n keycloak deployment/keycloak -- \
curl -s http://localhost:9000/health/ready
Database Management
Check Database Connection
kubectl exec -n keycloak deployment/keycloak -- \
env | grep KC_DB
Database Maintenance
# Connect to PostgreSQL
kubectl exec -it -n postgres postgres-cluster-rw-0 -- psql -U postgres -d keycloak
# Check Keycloak tables
\dt realm*
Backup and Restore
Export Realm
# Export specific realm
kubectl exec -n keycloak deployment/keycloak -- \
/opt/keycloak/bin/kc.sh export \
--file /tmp/realm-export.json \
--realm your-realm
# Copy export locally
kubectl cp keycloak/keycloak-pod:/tmp/realm-export.json ./realm-backup.json
Import Realm
# Copy file to pod
kubectl cp ./realm-backup.json keycloak/keycloak-pod:/tmp/realm-import.json
# Import realm
kubectl exec -n keycloak deployment/keycloak -- \
/opt/keycloak/bin/kc.sh import \
--file /tmp/realm-import.json
Troubleshooting
Pod Not Starting
- Check init container logs:
kubectl logs -n keycloak -l app=keycloak -c database-init
- Verify AWS credentials:
kubectl get secret -n keycloak aws-credentials-env
- Check external secrets:
kubectl get externalsecret -n keycloak
kubectl describe externalsecret -n keycloak keycloak-admin-credentials
Authentication Issues
- Check admin credentials:
kubectl get secret -n keycloak keycloak-admin-credentials -o yaml
- Reset admin password:
# Connect to pod
kubectl exec -it -n keycloak deployment/keycloak -- bash
# Reset password
/opt/keycloak/bin/kc.sh start-dev \
--bootstrap-admin-username=admin \
--bootstrap-admin-password=newpassword
Clustering Issues
- Check JGroups discovery:
# View cluster members
kubectl exec -n keycloak deployment/keycloak -- \
nslookup keycloak-headless.keycloak.svc.cluster.local
- Check JGroups logs:
kubectl logs -n keycloak -l app=keycloak | grep -i jgroups
Performance Issues
- Monitor resource usage:
kubectl top pods -n keycloak
- Check database performance:
# Long-running queries
kubectl exec -n postgres postgres-cluster-rw-0 -- \
psql -U postgres -d keycloak -c \
"SELECT pid, now() - pg_stat_activity.query_start AS duration, query
FROM pg_stat_activity
WHERE (now() - pg_stat_activity.query_start) > interval '5 minutes';"
Security Considerations
Credential Management
- Admin credentials stored in AWS Secrets Manager
- Database credentials managed via External Secrets Operator
- No hardcoded passwords in configurations
Network Security
- TLS termination at ingress
- Internal communication over HTTP (secure network)
- Consider implementing network policies
Best Practices
- Regular Updates: Keep Keycloak version updated
- Audit Logging: Enable and monitor audit logs
- Token Rotation: Configure appropriate token lifetimes
- Password Policies: Enforce strong password requirements
- MFA: Enable multi-factor authentication for admin accounts
Integration Examples
OAuth2/OIDC Client Configuration
Spring Boot Application
spring:
security:
oauth2:
client:
registration:
keycloak:
client-id: your-app
client-secret: ${CLIENT_SECRET}
scope: openid,profile,email
authorization-grant-type: authorization_code
provider:
keycloak:
issuer-uri: https://auth.landryzetam.net/realms/your-realm
Node.js Application
const Keycloak = require('keycloak-connect');
const keycloak = new Keycloak({
realm: 'your-realm',
'auth-server-url': 'https://auth.landryzetam.net/',
'ssl-required': 'external',
clientId: 'your-app',
credentials: {
secret: process.env.CLIENT_SECRET
}
});
Service Account Setup
# Create service account
1. Create client with:
- Access Type: confidential
- Service Accounts Enabled: true
2. Note the client secret
3. Assign roles to service account
Monitoring
Key Metrics
- Login success/failure rates
- Token issuance rate
- Database connection pool usage
- Memory and CPU utilization
- Response times
Health Endpoints
- Readiness:
http://keycloak:9000/health/ready - Liveness:
http://keycloak:9000/health/live - Metrics:
http://keycloak:9000/metrics
Prometheus Integration
# ServiceMonitor for Prometheus
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: keycloak
namespace: keycloak
spec:
selector:
matchLabels:
app: keycloak
endpoints:
- port: management
path: /metrics
Maintenance
Version Upgrades
Backup current state:
- Export all realms
- Backup database
Test upgrade:
- Deploy new version in staging
- Verify functionality
Rolling upgrade:
- Update image version
- Monitor pod rollout
Database Maintenance
# Vacuum database
kubectl exec -n postgres postgres-cluster-rw-0 -- \
psql -U postgres -d keycloak -c "VACUUM ANALYZE;"
# Check table sizes
kubectl exec -n postgres postgres-cluster-rw-0 -- \
psql -U postgres -d keycloak -c \
"SELECT schemaname,tablename,pg_size_pretty(pg_relation_size(schemaname||'.'||tablename)) AS size
FROM pg_tables WHERE schemaname='public' ORDER BY pg_relation_size(schemaname||'.'||tablename) DESC;"
Future Improvements
- Implement automated backup strategy
- Add Grafana dashboards for monitoring
- Configure audit logging to external system
- Implement custom themes
- Add support for WebAuthn/FIDO2
- Configure user self-registration workflows
- Implement automated realm provisioning
- Add integration with external identity providers