Skip to main content

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

FieldTypeDefaultValidation
clientIdstring—Required
clientSecretstring—Required
realmObjectRef—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

FieldTypeDefaultValidation
namestring—Required
namespacestring—Required
uidstring—Optional

ClientStatus​

Appears in: Client

ClientStatus defines the observed state of Client

FieldTypeDefaultValidation
allowedOriginsstring[]—Optional
clientUidstring—Optional
conditionsCondition[]—Optional
issuerUrlstring—Required
rotatedClientSecretstring—Optional
rotatedSecretExpiresAtstring—Optional, Format: date-time
secretExpiresAtstring—Optional, Format: date-time

Condition​

Appears in: ClientStatus, IdentityProviderStatus, RealmStatus

FieldTypeDefaultValidation
lastTransitionTimestring—Required, Format: date-time
messagestring—Required, maxLength: 32768
observedGenerationinteger—Optional, Format: int64, minimum: 0
reasonstring—Required, minLength: 1, maxLength: 1024, pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
statusstring—Required, Enum: True \| False \| Unknown
typestring—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

FieldTypeDefaultValidation
adminClientIdstring—Required
adminPasswordstring—Required
adminUrlstring—Required
adminUserNamestring—Required

IdentityProviderStatus​

Appears in: IdentityProvider

IdentityProviderStatus defines the observed state of IdentityProvider

FieldTypeDefaultValidation
adminConsoleUrlstring—Optional
adminTokenUrlstring—Required
adminUrlstring—Required
conditionsCondition[]—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

FieldTypeDefaultValidation
allowedOriginsstring[]—Optional
attributesmap<string, string>—Optional
claimsClaims[]—Optional
identityProviderObjectRef—Required
secretRotationSecretRotation—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.

FieldTypeDefaultValidation
namestring—Required, minLength: 1
typestringHardcodedClaimOptional, Enum: HardcodedClaim \| SessionNote
valuestring—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.

FieldTypeDefaultValidation
expirationPeriodstring—Required
gracePeriodstring—Required
remainingRotationPeriodstring—Required

RealmStatus​

Appears in: Realm

RealmStatus defines the observed state of Realm

FieldTypeDefaultValidation
adminClientIdstring—Required
adminPasswordstring—Required
adminTokenUrlstring—Required
adminUrlstring—Required
adminUserNamestring—Required
conditionsCondition[]—Optional
issuerUrlstring—Required
managedAttributesstring[]—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:

  1. The current secret is moved to a "rotated" slot in Keycloak
  2. A new secret is set as the primary credential
  3. 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.attributes removes the attribute from Keycloak, but only if it is listed in status.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:

  1. If the realm has a valid frontendUrl (set by the spec or manually in Keycloak), the issuer is <frontendUrl>/realms/<realm>, for example https://iam.example.com/auth/realms/default.
  2. 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 an http(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.

caution

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.