https://github.com/vriesdemichael/keycloak-operator
A keycloak operator that enables gitops deployment
https://github.com/vriesdemichael/keycloak-operator
authorization gitops idp keycloak kopf kubernetes oauth2 operator realm
Last synced: 13 days ago
JSON representation
A keycloak operator that enables gitops deployment
- Host: GitHub
- URL: https://github.com/vriesdemichael/keycloak-operator
- Owner: vriesdemichael
- License: mit
- Created: 2025-09-25T09:50:09.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2026-06-11T04:45:31.000Z (18 days ago)
- Last Synced: 2026-06-11T06:23:57.187Z (18 days ago)
- Topics: authorization, gitops, idp, keycloak, kopf, kubernetes, oauth2, operator, realm
- Language: Python
- Homepage: https://vriesdemichael.github.io/keycloak-operator/
- Size: 73.2 MB
- Stars: 4
- Watchers: 0
- Forks: 1
- Open Issues: 15
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
- Codeowners: .github/CODEOWNERS
- Security: docs/security/threat-model.md
- Agents: AGENTS.md
Awesome Lists containing this project
README
# Keycloak Operator
[](https://github.com/vriesdemichael/keycloak-operator/actions/workflows/ci-cd-unified.yml)
[](https://codecov.io/gh/vriesdemichael/keycloak-operator)
[](https://github.com/vriesdemichael/keycloak-operator/pkgs/container/charts%2Fkeycloak-operator)
[](LICENSE)
[](https://www.python.org/downloads/)
A Kubernetes operator for managing Keycloak instances, realms, and OAuth2/OIDC clients declaratively with full GitOps compatibility.
## 🚀 Quick Start
Get a complete Keycloak setup running in under 10 minutes.
Helm charts are the recommended deployment path. Direct CR manifests are supported for advanced/manual workflows where you want to manage RBAC, secret access, and lifecycle wiring yourself.
```bash
# 1. Install the operator and a managed Keycloak instance
# Note: The chart creates the namespace by default, don't use --create-namespace
helm install keycloak-operator \
oci://ghcr.io/vriesdemichael/charts/keycloak-operator \
--namespace keycloak-system \
--set keycloak.managed=true \
--set keycloak.database.cnpg.enabled=true
# Or install from local charts:
# helm install keycloak-operator ./charts/keycloak-operator \
# --namespace keycloak-system
# 2. Create an identity realm
helm install my-app-realm \
oci://ghcr.io/vriesdemichael/charts/keycloak-realm \
--namespace my-app \
--create-namespace \
--set realmName=my-app \
--set operatorRef.namespace=keycloak-system \
--set 'clientAuthorizationGrants={my-app}'
# 3. Create an OAuth2 client
helm install my-app-client \
oci://ghcr.io/vriesdemichael/charts/keycloak-client \
--namespace my-app \
--set clientId=my-app \
--set realmRef.name=my-app-realm \
--set realmRef.namespace=my-app \
--set 'redirectUris={https://my-app.example.com/callback}'
```
**📖 [Full Quick Start Guide →](https://vriesdemichael.github.io/keycloak-operator/latest/quickstart/)**
**Advanced:** If you want to work directly with CR manifests instead of Helm releases, see [Helm vs Direct CR Deployments](https://vriesdemichael.github.io/keycloak-operator/latest/how-to/helm-vs-cr-deployments/).
## ✨ Features
- **Declarative Configuration** - Manage Keycloak entirely through Kubernetes resources
- **Admission Webhooks** - Immediate validation feedback with clear error messages ([docs](https://vriesdemichael.github.io/keycloak-operator/latest/admission-webhooks/))
- **GitOps Ready** - Full observability with status conditions and `observedGeneration` tracking
- **Drift Detection** - Automatic detection of orphaned resources and configuration drift ([docs](https://vriesdemichael.github.io/keycloak-operator/latest/guides/drift-detection/))
- **Cross-Namespace Support** - Secure delegation model for multi-tenant environments
- **Production Ready** - Rate limiting, exponential backoff, and comprehensive monitoring
- **Comprehensive Test Coverage** - Unit and integration tests with coverage tracking
- **Resource Quotas** - Namespace-level limits on realms and clients via admission webhooks
- **Rate Limiting** - Two-level throttling (global + per-namespace) protects Keycloak from overload
- **High Availability** - Multi-replica Keycloak with PostgreSQL clustering via CloudNativePG
- **OAuth2/OIDC Clients** - Automated client provisioning with credential management
- **Service Accounts** - Declarative role assignment for machine-to-machine authentication
- **OIDC Endpoint Discovery** - Automatic population of all OIDC/OAuth2 endpoints in realm status
- **Multi-Version Support** - Supports Keycloak 24.x, 25.x, and 26.x via compatibility adapters
## 📚 Documentation
**🌐 [Full Documentation](https://vriesdemichael.github.io/keycloak-operator/)** - Versioned documentation with version selector
### Quick Links
- **[Quick Start Guide](https://vriesdemichael.github.io/keycloak-operator/latest/quickstart/)** - Get started in 10 minutes
- **[Helm vs Direct CR Deployments](https://vriesdemichael.github.io/keycloak-operator/latest/how-to/helm-vs-cr-deployments/)** - Recommended workflow versus advanced manual path
- **[Architecture](https://vriesdemichael.github.io/keycloak-operator/latest/concepts/architecture/)** - How the operator works
- **[Admission Webhooks](https://vriesdemichael.github.io/keycloak-operator/latest/admission-webhooks/)** - Resource validation and quotas
- **[Security Model](https://vriesdemichael.github.io/keycloak-operator/latest/concepts/security/)** - Secret-based authorization explained
- **[Drift Detection](https://vriesdemichael.github.io/keycloak-operator/latest/guides/drift-detection/)** - Orphan detection and auto-remediation
- **[Observability](https://vriesdemichael.github.io/keycloak-operator/latest/guides/observability/)** - Metrics, logs, and status conditions
- **[Versioning](https://vriesdemichael.github.io/keycloak-operator/latest/versioning/)** - How to access older documentation and chart versions
- **[Development Guide](https://vriesdemichael.github.io/keycloak-operator/latest/development/)** - Contributing to the project
> **Note: Version-Specific Documentation**
> Use the version selector in the documentation to view docs for your installed version.
> See the [Versioning Guide](https://vriesdemichael.github.io/keycloak-operator/latest/versioning/) for details.
## 🏗️ Architecture
The operator manages three custom resources:
```mermaid
flowchart LR
kc[Keycloak\nInstance]
realm[KeycloakRealm\nIdentity Boundary]
client[KeycloakClient\nOAuth2/OIDC Boundary]
kc --> realm --> client
```
- **Keycloak**: The identity server instance with database and networking
- **KeycloakRealm**: Identity domain with users, roles, and authentication settings
- **KeycloakClient**: OAuth2/OIDC applications with automated credential management
## 🌐 External Keycloak Mode
The operator can manage resources (realms, clients) in an existing, external Keycloak instance instead of deploying its own.
### Configuration
In your `values.yaml`:
```yaml
keycloak:
managed: false
url: "https://keycloak.example.com"
adminUsername: "admin"
adminSecret: "my-external-secret" # Secret in the operator namespace
adminPasswordKey: "password"
```
This is the actual chart contract for external mode:
- `keycloak.managed=false` disables templating of the managed `Keycloak` CR
- `keycloak.url` tells the operator where the existing Keycloak instance lives
- `keycloak.adminSecret` tells the operator which Secret to read for the admin password
- `keycloak.adminPasswordKey` defaults to `password`, but can be overridden when your Secret uses a different key
Do not confuse this with `keycloak.admin.existingSecret`, which is only used for managed mode when `keycloak.managed=true`.
#### Creating the Admin Secret
The admin secret must exist in the operator's namespace. It only needs to contain the password value the operator will use together with `keycloak.adminUsername`.
```bash
kubectl create secret generic my-external-secret \
--from-literal=password='your-admin-password' \
--namespace keycloak-system
```
**Note:** In external mode, the operator connects directly to the existing Keycloak instance using `keycloak.url` and the configured admin Secret. You typically do not deploy a managed `Keycloak` CR from this chart in that setup.
## 📊 Example
Create a complete OAuth2 setup:
```yaml
# yaml-language-server: $schema=https://vriesdemichael.github.io/keycloak-operator/schemas/v1/Keycloak.json
# Keycloak instance with PostgreSQL database
apiVersion: vriesdemichael.github.io/v1
kind: Keycloak
metadata:
name: keycloak
namespace: keycloak-system
spec:
replicas: 3
image: quay.io/keycloak/keycloak:26.0.0
database:
type: postgresql
host: keycloak-postgres-rw
port: 5432
database: app
username: app
passwordSecret:
name: keycloak-postgres-app
key: password
---
# yaml-language-server: $schema=https://vriesdemichael.github.io/keycloak-operator/schemas/v1/KeycloakRealm.json
# Identity realm with client authorization grants
apiVersion: vriesdemichael.github.io/v1
kind: KeycloakRealm
metadata:
name: my-app-realm
namespace: my-app
spec:
realmName: my-app
operatorRef:
namespace: keycloak-system
# Namespaces authorized to create clients in this realm
clientAuthorizationGrants:
- my-app
---
# yaml-language-server: $schema=https://vriesdemichael.github.io/keycloak-operator/schemas/v1/KeycloakClient.json
# OAuth2 client (namespace must be in realm's clientAuthorizationGrants)
apiVersion: vriesdemichael.github.io/v1
kind: KeycloakClient
metadata:
name: my-app-client
namespace: my-app
spec:
clientId: my-app
realmRef:
name: my-app-realm
namespace: my-app
publicClient: false
redirectUris:
- "https://my-app.example.com/callback"
```
See [examples/](examples/) for advanced raw-manifest examples. For normal installs, prefer the Helm charts and the quick start flow above.
## 🎯 IDE Integration
Get autocompletion, validation, and inline documentation in your IDE using published JSON schemas:
```yaml
# yaml-language-server: $schema=https://vriesdemichael.github.io/keycloak-operator/schemas/v1/KeycloakRealm.json
apiVersion: vriesdemichael.github.io/v1
kind: KeycloakRealm
# ... IDE will autocomplete fields with descriptions!
```
**Features:**
- ✅ Autocomplete for all CRD fields
- ✅ Inline validation with error messages
- ✅ Field descriptions from CRD schema
- ✅ Enum value suggestions
**Supported IDEs:**
- VS Code (with [YAML extension](https://marketplace.visualstudio.com/items?itemName=redhat.vscode-yaml))
- IntelliJ IDEA / PyCharm (built-in)
- Neovim (with yaml-language-server)
**Available schemas:**
- `https://vriesdemichael.github.io/keycloak-operator/schemas/v1/Keycloak.json`
- `https://vriesdemichael.github.io/keycloak-operator/schemas/v1/KeycloakRealm.json`
- `https://vriesdemichael.github.io/keycloak-operator/schemas/v1/KeycloakClient.json`
Add the schema annotation as the first line of your YAML files to enable IDE features.
## 🔐 Security
The operator uses a **namespace grant authorization model** combining Kubernetes RBAC with declarative access control:
- **Realm Creation**: Controlled by standard Kubernetes RBAC (who can create `KeycloakRealm` resources)
- **Client Creation**: Controlled by realm's `clientAuthorizationGrants` list (which namespaces can create clients)
- **Self-service**: Teams can create realms and clients without platform team intervention
- **GitOps Native**: All authorization is declarative and stored in Git
- **Auditability**: All access changes tracked in Git history and Kubernetes audit logs
Read the [Security Model](https://vriesdemichael.github.io/keycloak-operator/latest/concepts/security/) documentation for detailed authorization architecture.
## 📈 Monitoring
The operator exposes Prometheus metrics and includes a Grafana dashboard:
```bash
# Enable monitoring in Helm chart
helm install keycloak-operator ./charts/keycloak-operator \
--set monitoring.enabled=true \
--set monitoring.prometheusRules.enabled=true \
--set monitoring.grafanaDashboard.enabled=true
```
Key metrics:
- Reconciliation success/failure rates
- Rate limiting wait times and timeouts
- Reconciliation duration (p50/p95/p99)
- Resource counts by phase
See [Observability](https://vriesdemichael.github.io/keycloak-operator/latest/guides/observability/) for full details.
## 🚦 Rate Limiting
The operator implements two-level rate limiting to protect Keycloak from API overload:
### Configuration
```yaml
env:
# Global rate limit (all namespaces combined)
- name: KEYCLOAK_API_GLOBAL_RATE_LIMIT_TPS
value: "50" # requests per second
- name: KEYCLOAK_API_GLOBAL_BURST
value: "100" # burst capacity
# Per-namespace rate limit (fair sharing)
- name: KEYCLOAK_API_NAMESPACE_RATE_LIMIT_TPS
value: "5" # requests per second
- name: KEYCLOAK_API_NAMESPACE_BURST
value: "10" # burst capacity
# Jitter to prevent thundering herd
- name: RECONCILE_JITTER_MAX_SECONDS
value: "5.0" # 0-5 second random delay
```
### Protection Scenarios
| Scenario | Protection |
|----------|-----------|
| Spam 1000 realms in one namespace | Limited to 5 req/s = 200s minimum |
| Multiple teams overwhelming Keycloak | Global 50 req/s enforced |
| Operator restart (50+ resources) | Jitter + rate limiting prevents flood |
### Monitoring
Prometheus metrics available at `:8081/metrics`:
- `keycloak_operator_api_rate_limit_wait_seconds` - Time waiting for tokens
- `keycloak_operator_api_rate_limit_acquired_total` - Successful token acquisitions
- `keycloak_operator_api_rate_limit_timeouts_total` - Rate limit timeout errors
- `keycloak_operator_api_rate_limit_budget_available` - Current available tokens per namespace
## 🤝 Contributing
Contributions welcome!
To set up a development environment:
```bash
# Clone the repository
git clone https://github.com/vriesdemichael/keycloak-operator.git
cd keycloak-operator
# Check required tools and install pre-commit hooks
task dev:setup
# Run quality checks
task quality:check
# Run unit tests
task test:unit
```
See [Development Guide](https://vriesdemichael.github.io/keycloak-operator/latest/development/) and [AGENTS.md](AGENTS.md) for more details.
## 📝 License
MIT License - see [LICENSE](LICENSE) for details.
## 🔗 Links
- [GitHub Repository](https://github.com/vriesdemichael/keycloak-operator)
- [Issue Tracker](https://github.com/vriesdemichael/keycloak-operator/issues)
- [Documentation](https://vriesdemichael.github.io/keycloak-operator/latest/)