Skip to content

This release includes 4 breaking changes for platform teams planning a safe upgrade.

Published 21h Secrets & Credentials
✓ No known CVEs patched
Read the diff → Tool health → What is this tool? →

✓ No known CVEs patched in this version

Topics

keycloak kubernetes sso sso-authentication

Affected surfaces

auth rbac

Summary

AI summary

Broad release touches Upgrade Guide, Breaking changes, deps, and Highlights.

Full changelog

This release unifies resource identity across all CRDs: every resource now declares its Keycloak identifier in a dedicated, immutable spec field instead of inside the raw definition blob. It also scopes namespaced references to their own namespace, adds declarative role and group assignment on KeycloakUser (including client service accounts), and fixes duplicate user-profile components and an organization reconcile loop.

Breaking changes

Typed identifier fields on all resource CRDs (#101)

Every resource CRD now identifies its Keycloak object through a dedicated spec field. The field is required, is validated at admission, and is immutable once set (changing an identifier previously orphaned the old Keycloak object silently).

| CRD | Identifier field |
|-----|------------------|
| KeycloakRealm, ClusterKeycloakRealm | spec.realmName |
| KeycloakClient | spec.clientId |
| KeycloakUser | spec.username (omit for service accounts via clientRef) |
| KeycloakGroup, KeycloakRole, KeycloakClientScope, KeycloakComponent, KeycloakOrganization, KeycloakProtocolMapper, KeycloakIdentityProviderMapper | spec.name |
| KeycloakIdentityProvider, KeycloakRequiredAction | spec.alias |

Migration

Add the spec field carrying the same value the definition uses. An identifier inside spec.definition is tolerated only when it matches the spec field, so existing definitions do not need to be rewritten; a conflicting value is rejected.

# Before
spec:
  definition:
    realm: production
    enabled: true

# After
spec:
  realmName: production    # new: required, immutable
  definition:
    realm: production      # optional; must match spec.realmName if present
    enabled: true

Unmigrated resources report InvalidIdentifier in their status and pause reconciliation until the spec field is added — nothing is deleted. The resolved identifier is surfaced in each resource's status (e.g. status.realmName) and is what dependent resources consume.

Also note: the KeycloakClient status field status.clientID was renamed to status.clientId.

Namespaced references no longer cross namespaces (#90)

The namespace property is removed from all namespaced refs (realmRef, instanceRef, clientRef, clientScopeRef, userRef, roleRef, groupRef, parentGroupRef, identityProviderRef); they now always resolve in the referring resource's own namespace. The field is silently pruned by the API server, not rejected — audit your manifests before upgrading.

Cross-namespace sharing remains fully supported through the cluster-scoped kinds: point resources in any namespace at a shared ClusterKeycloakRealm (clusterRealmRef) or ClusterKeycloakInstance (clusterInstanceRef), or co-locate the resources in one namespace.

Role and group assignments move out of the KeycloakUser definition (#94)

realmRoles, clientRoles, and groups keys inside spec.definition are now rejected with InvalidDefinition. They were previously ignored (Keycloak's user endpoint does not apply them), which commonly bit users pasting exported user representations. They are now typed spec fields that are actually reconciled — see Highlights below.

# Before (keys were silently ignored)
spec:
  username: jdoe
  definition:
    enabled: true
    realmRoles: ["offline_access"]
    groups: ["developers"]

# After (authoritatively reconciled)
spec:
  username: jdoe
  definition:
    enabled: true
  realmRoles:
    - offline_access
  groups:
    - developers

Stricter admission validation for references (#105)

CRD schemas now enforce what the API documentation always required: exactly one of realmRef/clusterRealmRef (or clientRef on users), at most one of role/roleRef, exactly one role-mapping subject, and so on. Manifests that were previously accepted with ambiguous or missing references are now rejected at admission time.

Highlights

  • Identifier unification — uniform identity handling across all resource CRDs: typed, immutable identifier fields with CEL validation, resolved identifiers surfaced in status for dependent controllers, and deletion paths that no longer issue Keycloak calls with empty identifiers. See the new Spec Layout section for the architecture behind this. (#101)
  • Declarative user roles and groupsspec.realmRoles, spec.clientRoles, and spec.groups on KeycloakUser are reconciled through Keycloak's dedicated role-mapping and group-membership endpoints, for regular users and service accounts alike. Each field is authoritative when set (an empty list removes everything) and unmanaged when omitted. Do not combine them with KeycloakRoleMapping resources for the same user. (#94)
  • Role mappings for service accountsKeycloakRoleMapping gains subject.serviceAccountRef to assign roles to a client's service account without an intermediate KeycloakUser. (#94)
  • User-profile component adoptionKeycloakComponent now adopts the unnamed declarative-user-profile component Keycloak creates when the user profile is saved through the Admin UI or /users/profile API, instead of creating a duplicate. (#104)
  • Organization drift detectionKeycloakOrganization compares desired and current state before updating, ending the continuous PUT loop that flooded logs and Keycloak. (#96)
  • Nightly container builds (#102) and GitHub Actions pinned to immutable SHAs (#103).

Upgrade Guide

1. Upgrade the operator first

The new identifier fields do not exist in the v0.9.0 CRD schemas and would be pruned if you applied migrated manifests before upgrading. Upgrade the operator (which updates the CRDs), then migrate manifests. Existing resources keep running; unmigrated ones pause reconciliation with InvalidIdentifier until step 2 — nothing is deleted.

helm upgrade keycloak-operator oci://ghcr.io/hostzero-gmbh/charts/keycloak-operator \
  --namespace keycloak-operator \
  --version 0.10.0

2. Migrate manifests

For every resource:

  1. Add the typed identifier field (see the table above) with the value currently used inside spec.definition.
  2. Remove namespace from any refs; switch cross-namespace setups to clusterRealmRef / clusterInstanceRef.
  3. On KeycloakUser, move realmRoles / clientRoles / groups out of spec.definition into the spec fields.
  4. Ensure exactly one realm/instance/subject reference is set per resource.

What's Changed

  • Feat/same namespace refs by @fkold in https://github.com/Hostzero-GmbH/keycloak-operator/pull/90
  • fix: prevent continious update organization loop by @nejec in https://github.com/Hostzero-GmbH/keycloak-operator/pull/96
  • chore: add nightly container builds by @nejec in https://github.com/Hostzero-GmbH/keycloak-operator/pull/102
  • ci: pin GitHub Actions to immutable SHAs by @luxass in https://github.com/Hostzero-GmbH/keycloak-operator/pull/103
  • fix(crd): enforce mutually exclusive references by @luxass in https://github.com/Hostzero-GmbH/keycloak-operator/pull/105
  • chore(deps): bump softprops/action-gh-release from 3.0.0 to 3.0.1 by @dependabot[bot] in https://github.com/Hostzero-GmbH/keycloak-operator/pull/108
  • chore(deps): bump actions/checkout from 6.0.3 to 7.0.0 by @dependabot[bot] in https://github.com/Hostzero-GmbH/keycloak-operator/pull/107
  • chore(deps): bump the kubernetes group with 3 updates by @dependabot[bot] in https://github.com/Hostzero-GmbH/keycloak-operator/pull/114
  • chore(deps): bump the github-actions group with 9 updates by @dependabot[bot] in https://github.com/Hostzero-GmbH/keycloak-operator/pull/115
  • chore(deps): bump the github-actions group with 2 updates by @dependabot[bot] in https://github.com/Hostzero-GmbH/keycloak-operator/pull/119
  • chore(deps): bump github.com/prometheus/client_golang from 1.23.2 to 1.24.1 by @dependabot[bot] in https://github.com/Hostzero-GmbH/keycloak-operator/pull/118
  • chore(deps): bump github.com/go-logr/logr from 1.4.3 to 1.4.4 by @dependabot[bot] in https://github.com/Hostzero-GmbH/keycloak-operator/pull/117
  • chore(deps): bump the kubernetes group with 3 updates by @dependabot[bot] in https://github.com/Hostzero-GmbH/keycloak-operator/pull/116
  • Feat: identifier unification by @fkold in https://github.com/Hostzero-GmbH/keycloak-operator/pull/101
  • feat: reconcile realm roles, client roles, and groups on KeycloakUser by @mohamedhabas11 in https://github.com/Hostzero-GmbH/keycloak-operator/pull/94
  • fix: adopt existing user profile components by @luxass in https://github.com/Hostzero-GmbH/keycloak-operator/pull/104

New Contributors

  • @fkold made their first contribution in https://github.com/Hostzero-GmbH/keycloak-operator/pull/90
  • @nejec made their first contribution in https://github.com/Hostzero-GmbH/keycloak-operator/pull/96
  • @mohamedhabas11 made their first contribution in https://github.com/Hostzero-GmbH/keycloak-operator/pull/94

Full Changelog: https://github.com/Hostzero-GmbH/keycloak-operator/compare/v0.9.0...v0.10.0

Breaking Changes

  • Typed immutable identifier fields added to all resource CRDs (e.g., spec.realmName, spec.clientId) and required for reconciliation; definition‑based identifiers are deprecated.
  • Namespaced reference `namespace` field removed; refs now resolve only within the referring resource's own namespace. Cross‑namespace use must employ cluster‑scoped kinds like ClusterKeycloakRealm.
  • `KeycloakUser` role and group keys (`realmRoles`, `clientRoles`, `groups`) inside `spec.definition` are rejected; they must be moved to typed spec fields for reconciliation.
  • Stricter admission validation enforces mutually exclusive reference fields (e.g., exactly one of realmRef/clusterRealmRef) across all CRDs.

Weekly OSS security release digest.

The CVE patches and breaking changes that affected production tools this week. One email, every Sunday.

No spam, unsubscribe anytime.

Share this release

Track Hostzero-GmbH/keycloak-operator

Get notified when new releases ship.

Sign up free

About Hostzero-GmbH/keycloak-operator

All releases →

Related context

Earlier breaking changes

  • v0.9.0 Removes `spec.credentials` and `spec.client`; requires migration to new `spec.auth` block.

Beta — feedback welcome: [email protected]