Custom Resource Definitions
The Keycloak Operator provides several Custom Resource Definitions (CRDs) to manage Keycloak resources declaratively.
Resource Hierarchy
KeycloakInstance / ClusterKeycloakInstance
└── KeycloakRealm / ClusterKeycloakRealm
├── KeycloakClient
│ ├── KeycloakUser (service account, via clientRef)
│ ├── KeycloakRole (client role)
│ └── KeycloakProtocolMapper
├── KeycloakUser (regular users, via realmRef)
│ └── KeycloakUserCredential
├── KeycloakGroup
├── KeycloakClientScope
│ └── KeycloakProtocolMapper
├── KeycloakRole (realm role)
├── KeycloakRoleMapping (maps roles to Users/Groups)
├── KeycloakComponent (LDAP, key providers, etc.)
├── KeycloakIdentityProvider
│ └── KeycloakIdentityProviderMapper
├── KeycloakAuthenticationFlow
├── KeycloakRequiredAction
└── KeycloakOrganization (requires Keycloak 26+)
Overview
Instance Resources
| CRD | Description | Scope |
|---|---|---|
| KeycloakInstance | Connection to a Keycloak server | Namespaced |
| ClusterKeycloakInstance | Cluster-scoped Keycloak connection | Cluster |
Realm Resources
| CRD | Description | Parent |
|---|---|---|
| KeycloakRealm | Realm configuration | KeycloakInstance |
| ClusterKeycloakRealm | Cluster-scoped realm | ClusterKeycloakInstance |
OAuth & Client Resources
| CRD | Description | Parent |
|---|---|---|
| KeycloakClient | OAuth2/OIDC client | KeycloakRealm |
| KeycloakClientScope | Client scope configuration | KeycloakRealm |
| KeycloakProtocolMapper | Token claim mappers | KeycloakClient or KeycloakClientScope |
Identity Resources
| CRD | Description | Parent |
|---|---|---|
| KeycloakUser | User management | KeycloakRealm or KeycloakClient¹ |
| KeycloakUserCredential | User password management | KeycloakUser |
| KeycloakGroup | Group management | KeycloakRealm |
Role & Access Control
| CRD | Description | Parent |
|---|---|---|
| KeycloakRole | Realm and client roles | KeycloakRealm or KeycloakClient |
| KeycloakRoleMapping | Role-to-subject mappings | KeycloakUser or KeycloakGroup |
Federation & Infrastructure
| CRD | Description | Parent |
|---|---|---|
| KeycloakComponent | LDAP federation, key providers | KeycloakRealm |
| KeycloakIdentityProvider | External identity providers | KeycloakRealm |
| KeycloakIdentityProviderMapper | Identity provider claim/role/attribute mappers | KeycloakIdentityProvider |
| KeycloakAuthenticationFlow | Custom authentication / registration flows | KeycloakRealm |
| KeycloakRequiredAction | Required action providers (e.g. update password, verify email) | KeycloakRealm |
| KeycloakOrganization | Organization management² | KeycloakRealm |
¹ KeycloakUser supports clientRef for managing service account users associated with a client
² KeycloakOrganization requires Keycloak 26.0.0 or later
Common Patterns
Spec Layout
Every CRD that mirrors a Keycloak representation is built from the same four layers:
- Placement refs — typed references that anchor the resource in the hierarchy:
realmRef,clusterRealmRef,clientRef,clientScopeRef,parentGroupRef,identityProviderRef, … - Identity — one typed, required, immutable field naming the object in Keycloak:
realmName,clientId,username,alias, orname. It is mirrored to status and shown as a printer column. - Kubernetes integration — typed fields for anything that touches cluster objects or other CRs: Secret references (
clientSecretRef,smtpSecretRef,configSecretRef),initialPassword,tokenExchange. The operator injects these into the payload or applies them through separate Keycloak API calls. - Payload —
spec.definition, the verbatim Keycloak API representation. The operator writes into it (identifier, secret merges) but never reads configuration out of it; everything else passes through unchanged. This is what lets you configure any Keycloak property, even ones the CRD does not model.
spec:
instanceRef: # 1. placement
name: my-keycloak
realmName: my-realm # 2. identity
smtpSecretRef: # 3. Kubernetes integration
name: smtp-credentials
definition: # 4. payload — full Keycloak API object
enabled: true
displayName: My Realm
Every datum has exactly one home. A value that belongs to a typed layer must not also be configured inside definition: an identifier in the definition is tolerated only when it matches the spec field, and a conflicting value sets Ready=False.
Fully typed CRDs without a definition (KeycloakInstance, KeycloakRoleMapping, KeycloakUserCredential) are operator constructs rather than representation mirrors, so they have no payload layer.
For contributors, the layer of a new field follows mechanically:
- References a Kubernetes object or another CR? → typed spec field (layer 3).
- Managed through a separate Keycloak API endpoint rather than the representation
PUT? → its own CRD (like KeycloakRoleMapping) or a typed spec section — never keys insidedefinition. - Part of the Keycloak representation itself? → stays in
definition, untyped.
Status Tracking
All resources expose status information:
status:
ready: true
message: "Resource synchronized successfully"
conditions:
- type: Ready
status: "True"
lastTransitionTime: "2024-01-01T00:00:00Z"
reason: Synchronized
message: "Resource is in sync with Keycloak"
Finalizers
Resources use finalizers to ensure proper cleanup when deleted:
metadata:
finalizers:
- keycloak.hostzero.com/finalizer
Preserving Resources on Deletion
By default, when you delete a Custom Resource, the operator also deletes the corresponding resource in Keycloak. If you want to keep the resource in Keycloak while removing the CR from Kubernetes, use the keycloak.hostzero.com/preserve-resource annotation:
apiVersion: keycloak.hostzero.com/v1beta1
kind: KeycloakRealm
metadata:
name: my-realm
annotations:
keycloak.hostzero.com/preserve-resource: "true"
spec:
# ...
When this annotation is set to "true", deleting the CR will:
- Remove the CR from Kubernetes
- Keep the resource in Keycloak untouched
This is useful for scenarios like:
- Migrating management of a resource to a different system
- Temporarily removing operator control without losing data
- Testing or debugging without affecting production resources
Note: The annotation value must be exactly
"true"(as a string) to preserve the resource. Any other value (or absence of the annotation) will result in normal deletion behavior.
Supported Resources: This annotation works with all resource types except KeycloakInstance and ClusterKeycloakInstance (which don’t manage Keycloak resources directly).
API Version
All CRDs use the keycloak.hostzero.com/v1beta1 API version:
apiVersion: keycloak.hostzero.com/v1beta1
kind: KeycloakRealm