Identity Domain
The Identity domain manages identity and access management for the Control Plane through Keycloak integration. It provisions identity providers, realms, and service-account clients in a declarative, Kubernetes-native way.
Custom Resources
Client
Client is the Schema for the clients API
Group: identity.cp.ei.telekom.de · Version: v1 · Scope: Namespaced
ClientSpec
Appears in: Client
ClientSpec defines the desired state of Client
| Field | Type | Default | Validation |
|---|---|---|---|
clientId | string | — | Required |
clientSecret | string | — | Required |
realm | ObjectRef | — | Required |
ObjectRef
Appears in: ClientSpec, RealmSpec
ObjectRef is a reference to a Kubernetes object It is similar to types.NamespacedName but has the required json tags for serialization
| Field | Type | Default | Validation |
|---|---|---|---|
name | string | — | Required |
namespace | string | — | Required |
uid | string | — | Optional |
ClientStatus
Appears in: Client
ClientStatus defines the observed state of Client
| Field | Type | Default | Validation |
|---|---|---|---|
allowedOrigins | string[] | — | Optional |
clientUid | string | — | Optional |
conditions | Condition[] | — | Optional |
issuerUrl | string | — | Required |
rotatedClientSecret | string | — | Optional |
rotatedSecretExpiresAt | string | — | Optional, Format: date-time |
secretExpiresAt | string | — | Optional, Format: date-time |
Condition
Appears in: ClientStatus, IdentityProviderStatus, RealmStatus
| Field | Type | Default | Validation |
|---|---|---|---|
lastTransitionTime | string | — | Required, Format: date-time |
message | string | — | Required, maxLength: 32768 |
observedGeneration | integer | — | Optional, Format: int64, minimum: 0 |
reason | string | — | Required, minLength: 1, maxLength: 1024, pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ |
status | string | — | Required, Enum: True \| False \| Unknown |
type | string | — | Required, maxLength: 316, pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ |
IdentityProvider
IdentityProvider is the Schema for the identityproviders API
Group: identity.cp.ei.telekom.de · Version: v1 · Scope: Namespaced
IdentityProviderSpec
Appears in: IdentityProvider
IdentityProviderSpec defines the desired state of IdentityProvider
| Field | Type | Default | Validation |
|---|---|---|---|
adminClientId | string | — | Required |
adminPassword | string | — | Required |
adminUrl | string | — | Required |
adminUserName | string | — | Required |
IdentityProviderStatus
Appears in: IdentityProvider
IdentityProviderStatus defines the observed state of IdentityProvider
| Field | Type | Default | Validation |
|---|---|---|---|
adminConsoleUrl | string | — | Optional |
adminTokenUrl | string | — | Required |
adminUrl | string | — | Required |
conditions | Condition[] | — | Optional |
Realm
Realm is the Schema for the realms API
Group: identity.cp.ei.telekom.de · Version: v1 · Scope: Namespaced
RealmSpec
Appears in: Realm
RealmSpec defines the desired state of Realm
| Field | Type | Default | Validation |
|---|---|---|---|
allowedOrigins | string[] | — | Optional |
attributes | map<string, string> | — | Optional |
claims | Claims[] | — | Optional |
identityProvider | ObjectRef | — | Required |
secretRotation | SecretRotation | — | Optional |
Claims
Appears in: RealmSpec
Claims defines claims that are added to all tokens issued for clients in this realm. Each claim can be a static value (HardcodedClaim) or derived from a Keycloak session note (SessionNote). The controller manages a dedicated Keycloak client scope with protocol mappers for each claim.
| Field | Type | Default | Validation |
|---|---|---|---|
name | string | — | Required, minLength: 1 |
type | string | HardcodedClaim | Optional, Enum: HardcodedClaim \| SessionNote |
value | string | — | Optional |
SecretRotation
Appears in: RealmSpec
SecretRotation configures the Keycloak client-secret rotation policy for this realm. When set, the controller ensures a client-policy profile + policy with the given grace period exists in Keycloak. When nil, the controller does not manage rotation policy.
| Field | Type | Default | Validation |
|---|---|---|---|
expirationPeriod | string | — | Required |
gracePeriod | string | — | Required |
remainingRotationPeriod | string | — | Required |
RealmStatus
Appears in: Realm
RealmStatus defines the observed state of Realm
| Field | Type | Default | Validation |
|---|---|---|---|
adminClientId | string | — | Required |
adminPassword | string | — | Required |
adminTokenUrl | string | — | Required |
adminUrl | string | — | Required |
adminUserName | string | — | Required |
conditions | Condition[] | — | Optional |
issuerUrl | string | — | Required |
managedAttributes | string[] | — | Optional |
Secret Rotation Support
When a Realm is configured with a secretRotation policy, the Identity domain provisions a Keycloak client-policy that enables graceful secret rotation for opted-in clients. During rotation:
- The current secret is moved to a "rotated" slot in Keycloak
- A new secret is set as the primary credential
- Both secrets are accepted until the grace period expires
Individual clients can opt out via the identity.cp.ei.telekom.de/disable-secret-rotation: "true" annotation.
Realm Attributes
spec.attributes sets Keycloak realm attributes. Keys and values are passed to Keycloak as strings:
apiVersion: identity.cp.ei.telekom.de/v1
kind: Realm
metadata:
name: default
spec:
identityProvider:
name: my-idp
namespace: my-env--my-zone
attributes:
frontendUrl: https://iam.example.com/auth
displayName: Default realm
The controller only manages keys that it has applied itself. They are recorded in status.managedAttributes:
- Attributes that were never listed in
spec.attributes, for example attributes set manually in Keycloak, are left unchanged. This also applies to existing realms after an upgrade. - Removing a key from
spec.attributesremoves the attribute from Keycloak, but only if it is listed instatus.managedAttributes. Setting a value to""keeps the attribute with an empty value. - If the status cannot be written after Keycloak was updated (for example after a conflict), the ownership of newly added keys is lost. Such keys then stay in Keycloak when they are later removed from the spec and have to be removed manually.
Keys must not be empty. Do not store credentials or other secrets in attributes: they are stored in plain text in the Realm resource and in Keycloak.
Frontend URL and Issuer
The frontendUrl attribute is the public base URL of Keycloak, not the issuer. Use an absolute http or https URL with a host and without credentials, query or fragment, for example https://iam.example.com/auth. A context path such as /auth is allowed and a trailing slash is ignored. An empty value means the frontend URL is not set. The value is not validated: it is passed to Keycloak as configured, and a misconfigured value is the responsibility of whoever set it.
status.issuerUrl is determined after every successful realm sync:
- If the realm has a valid
frontendUrl(set by the spec or manually in Keycloak), the issuer is<frontendUrl>/realms/<realm>, for examplehttps://iam.example.com/auth/realms/default. - Otherwise (no or an invalid
frontendUrl), the issuer is read from the realm's OIDC discovery document (/.well-known/openid-configuration). The document is fetched through the identity provider's admin URL, without admin credentials, using the same TLS settings as the admin API. The admin URL itself is never used as the issuer. The discovered issuer must be anhttp(s)URL without credentials, query or fragment ending with/realms/<realm>; otherwise the Realm is blocked.
If the issuer cannot be determined, for example because the discovery request fails, the controller clears status.issuerUrl, marks the Realm as not ready and retries. Clients of the realm are not provisioned until a confirmed issuer is available.
Without a frontendUrl, Keycloak derives the issuer from the request it receives (depending on its hostname configuration). The issuer discovered through the internal admin URL may then differ from the issuer seen by external clients. Set frontendUrl, or configure a fixed Keycloak hostname, to get a stable public issuer.
Domain Interactions
- Admin domain — Zones define which identity provider to use.
- Organization domain — Team creation provisions identity clients.
- Application domain — Application creation provisions identity clients.
- Event domain — EventConfig provisioning creates identity clients for OAuth2 token exchange.
- Secret Manager — Resolves secret references before provisioning clients in Keycloak.