github crossplane-contrib/provider-keycloak v2.24.0

one day ago

This release adds 22 new managed resource CRDs covering protocol mappers for OpenID Connect clients, SAML clients, and identity providers, as well as generic client mappers and an LDAP hardcoded attribute mapper. Several bug fixes improve reconciliation stability.


New Resources

1. OpenID Protocol Mappers (11 new CRDs)

All OpenID protocol mapper resources live in the openidgroup.keycloak.crossplane.io/v1alpha1 API group and attach to an openidclient.keycloak.crossplane.io/v1alpha1 Client.

AudienceProtocolMapper

Adds a static custom audience to the token.

apiVersion: openidgroup.keycloak.crossplane.io/v1alpha1
kind: AudienceProtocolMapper
metadata:
  name: audience-mapper
spec:
  forProvider:
    name: audience-mapper
    includedCustomAudience: foo
    clientIdSelector:
      matchLabels:
        testing.upbound.io/example-name: openid_client
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config
---
apiVersion: openidclient.keycloak.crossplane.io/v1alpha1
kind: Client
metadata:
  name: openid-client
  labels:
    testing.upbound.io/example-name: openid_client
spec:
  forProvider:
    clientId: client
    name: client
    accessType: CONFIDENTIAL
    enabled: true
    validRedirectUris:
      - http://localhost:8080/openid-callback
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config
---
apiVersion: realm.keycloak.crossplane.io/v1alpha1
kind: Realm
metadata:
  name: realm
  labels:
    testing.upbound.io/example-name: realm
spec:
  forProvider:
    realm: my-realm
    enabled: true
  providerConfigRef:
    name: keycloak-provider-config

AudienceResolveProtocolMapper

Automatically resolves and adds all client audiences to the token.

apiVersion: openidgroup.keycloak.crossplane.io/v1alpha1
kind: AudienceResolveProtocolMapper
metadata:
  name: audience-resolve-mapper
spec:
  forProvider:
    name: my-audience-resolve-mapper
    clientIdSelector:
      matchLabels:
        testing.upbound.io/example-name: openid_client
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

FullNameProtocolMapper

Maps the user's full name (firstName lastName) into the token.

apiVersion: openidgroup.keycloak.crossplane.io/v1alpha1
kind: FullNameProtocolMapper
metadata:
  name: full-name-mapper
spec:
  forProvider:
    name: full-name-mapper
    clientIdSelector:
      matchLabels:
        testing.upbound.io/example-name: openid_client
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

HardcodedClaimProtocolMapper

Adds a static claim with a fixed value to the token.

apiVersion: openidgroup.keycloak.crossplane.io/v1alpha1
kind: HardcodedClaimProtocolMapper
metadata:
  name: hardcoded-claim-mapper
spec:
  forProvider:
    name: hardcoded-claim-mapper
    claimName: foo
    claimValue: bar
    clientIdSelector:
      matchLabels:
        testing.upbound.io/example-name: openid_client
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

HardcodedRoleProtocolMapper

Adds a hardcoded realm role to every token issued for this client.

apiVersion: openidgroup.keycloak.crossplane.io/v1alpha1
kind: HardcodedRoleProtocolMapper
metadata:
  name: hardcoded-role-mapper
spec:
  forProvider:
    name: hardcoded-role-mapper
    roleIdSelector:
      matchLabels:
        testing.upbound.io/example-name: role
    clientIdSelector:
      matchLabels:
        testing.upbound.io/example-name: openid_client
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config
---
apiVersion: role.keycloak.crossplane.io/v1alpha1
kind: Role
metadata:
  name: role
  labels:
    testing.upbound.io/example-name: role
spec:
  forProvider:
    name: my-role
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

SubProtocolMapper

Maps the Keycloak user ID into the sub claim of the token.

apiVersion: openidgroup.keycloak.crossplane.io/v1alpha1
kind: SubProtocolMapper
metadata:
  name: sub-mapper
spec:
  forProvider:
    name: sub-mapper
    clientIdSelector:
      matchLabels:
        testing.upbound.io/example-name: openid_client
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

UserAttributeProtocolMapper

Maps a custom user attribute into a token claim.

apiVersion: openidgroup.keycloak.crossplane.io/v1alpha1
kind: UserAttributeProtocolMapper
metadata:
  name: user-attribute-mapper
spec:
  forProvider:
    name: user-attribute-mapper
    userAttribute: foo
    claimName: bar
    clientIdSelector:
      matchLabels:
        testing.upbound.io/example-name: openid_client
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

UserClientRoleProtocolMapper

Includes the user's client roles in a token claim.

apiVersion: openidgroup.keycloak.crossplane.io/v1alpha1
kind: UserClientRoleProtocolMapper
metadata:
  name: user-client-role-mapper
spec:
  forProvider:
    name: user-client-role-mapper
    claimName: foo
    clientIdSelector:
      matchLabels:
        testing.upbound.io/example-name: openid_client
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

UserPropertyProtocolMapper

Maps a built-in Keycloak user property (e.g. email, username) into a token claim.

apiVersion: openidgroup.keycloak.crossplane.io/v1alpha1
kind: UserPropertyProtocolMapper
metadata:
  name: user-property-mapper
spec:
  forProvider:
    name: user-property-mapper
    userProperty: email
    claimName: email
    clientIdSelector:
      matchLabels:
        testing.upbound.io/example-name: openid_client
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

UserRealmRoleProtocolMapper

Includes the user's realm roles in a token claim.

apiVersion: openidgroup.keycloak.crossplane.io/v1alpha1
kind: UserRealmRoleProtocolMapper
metadata:
  name: user-realm-role-mapper
spec:
  forProvider:
    name: user-realm-role-mapper
    claimName: foo
    clientIdSelector:
      matchLabels:
        testing.upbound.io/example-name: openid_client
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

UserSessionNoteProtocolMapper

Maps a user session note (set at login time) into a token claim.

apiVersion: openidgroup.keycloak.crossplane.io/v1alpha1
kind: UserSessionNoteProtocolMapper
metadata:
  name: user-session-note-mapper
spec:
  forProvider:
    name: user-session-note-mapper
    sessionNote: bar
    claimName: foo
    claimValueType: String
    clientIdSelector:
      matchLabels:
        testing.upbound.io/example-name: openid_client
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

2. Identity Provider Mappers (6 new CRDs)

All identity provider mapper resources live in the identityprovider.keycloak.crossplane.io/v1alpha1 API group.

AttributeIdentityProviderMapper

Hardcodes a user session attribute for all users that authenticate via a specific identity provider.

apiVersion: identityprovider.keycloak.crossplane.io/v1alpha1
kind: AttributeIdentityProviderMapper
metadata:
  name: idp-attribute-mapper
spec:
  forProvider:
    name: hardcodedUserSessionAttribute
    identityProviderAlias: my-idp
    attributeName: attribute
    attributeValue: value
    userSession: true
    extraConfig:
      syncMode: INHERIT
    realmSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

GroupIdentityProviderMapper

Assigns users who authenticate via an identity provider to a specific Keycloak group.

apiVersion: identityprovider.keycloak.crossplane.io/v1alpha1
kind: GroupIdentityProviderMapper
metadata:
  name: idp-group-mapper
spec:
  forProvider:
    name: hardcodedGroup
    identityProviderAlias: my-idp
    group: my-realm-group
    extraConfig:
      syncMode: INHERIT
    realmSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config
---
apiVersion: group.keycloak.crossplane.io/v1alpha1
kind: Group
metadata:
  name: realm-group
spec:
  forProvider:
    name: my-realm-group
    description: My Realm Group
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

ImporterIdentityProviderMapper

Imports a specific IDP claim value into a Keycloak user attribute at login.

apiVersion: identityprovider.keycloak.crossplane.io/v1alpha1
kind: ImporterIdentityProviderMapper
metadata:
  name: idp-importer-mapper
spec:
  forProvider:
    name: email-attribute-importer
    identityProviderAlias: my-idp
    claimName: my-email-claim
    userAttribute: email
    extraConfig:
      syncMode: INHERIT
    realmSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config
---
apiVersion: oidc.keycloak.crossplane.io/v1alpha1
kind: IdentityProvider
metadata:
  name: my-idp
spec:
  forProvider:
    alias: my-idp
    authorizationUrl: https://example.com/auth
    tokenUrl: https://example.com/token
    defaultScopes: openid profile email
    clientIdSecretRef:
      key: client-id
      name: idp-credentials
      namespace: crossplane-system
    clientSecretSecretRef:
      key: client-secret
      name: idp-credentials
      namespace: crossplane-system
    realmSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

RoleIdentityProviderMapper

Grants a hardcoded realm role to all users that authenticate via a specific identity provider.

apiVersion: identityprovider.keycloak.crossplane.io/v1alpha1
kind: RoleIdentityProviderMapper
metadata:
  name: idp-role-mapper
spec:
  forProvider:
    name: hardcodedRole
    identityProviderAlias: my-idp
    role: my-realm-role
    extraConfig:
      syncMode: INHERIT
    realmSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config
---
apiVersion: role.keycloak.crossplane.io/v1alpha1
kind: Role
metadata:
  name: realm-role
spec:
  forProvider:
    name: my-realm-role
    description: My Realm Role
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

TemplateImporterIdentityProviderMapper

Derives the Keycloak username from an IDP token using a template expression.

apiVersion: identityprovider.keycloak.crossplane.io/v1alpha1
kind: TemplateImporterIdentityProviderMapper
metadata:
  name: username-importer
spec:
  forProvider:
    name: username-template-importer
    identityProviderAlias: my-idp
    template: "${ALIAS}.${CLAIM.email}"
    extraConfig:
      syncMode: INHERIT
    realmSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

ToRoleIdentityProviderMapper

Grants a realm role to users whose IDP token contains a specific claim value.

apiVersion: identityprovider.keycloak.crossplane.io/v1alpha1
kind: ToRoleIdentityProviderMapper
metadata:
  name: idp-to-role-mapper
spec:
  forProvider:
    name: role-attribute
    identityProviderAlias: my-idp
    claimName: my-claim
    claimValue: my-value
    role: my-realm-role
    extraConfig:
      syncMode: INHERIT
    realmSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

3. Generic Client Mappers (2 new CRDs)

These resources live in the client.keycloak.crossplane.io/v1alpha1 API group.

GenericClientProtocolMapper

Attaches a fully custom protocol mapper (any protocolMapper type supported by Keycloak) to any client using free-form config key/value pairs. This is the escape hatch for mapper types not yet covered by a dedicated CRD.

apiVersion: client.keycloak.crossplane.io/v1alpha1
kind: GenericClientProtocolMapper
metadata:
  name: saml-hardcode-attribute-mapper
spec:
  forProvider:
    name: test-mapper
    protocol: saml
    protocolMapper: saml-hardcode-attribute-mapper
    config:
      attribute.name: name
      attribute.nameformat: Basic
      attribute.value: value
      friendly.name: display name
    clientIdSelector:
      matchLabels:
        testing.upbound.io/example-name: saml_client
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config
---
apiVersion: samlclient.keycloak.crossplane.io/v1alpha1
kind: Client
metadata:
  name: saml-client
  labels:
    testing.upbound.io/example-name: saml_client
spec:
  forProvider:
    clientId: test-client
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

GenericClientRoleMapper

Assigns a realm role (or composite) directly into a client's scope, making the role available in tokens for that client.

apiVersion: client.keycloak.crossplane.io/v1alpha1
kind: GenericClientRoleMapper
metadata:
  name: client-role-mapper
spec:
  forProvider:
    clientIdSelector:
      matchLabels:
        testing.upbound.io/example-name: client
    roleIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm_role
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config
---
apiVersion: openidclient.keycloak.crossplane.io/v1alpha1
kind: Client
metadata:
  name: client
  labels:
    testing.upbound.io/example-name: client
spec:
  forProvider:
    clientId: client
    name: client
    accessType: BEARER-ONLY
    enabled: true
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config
---
apiVersion: role.keycloak.crossplane.io/v1alpha1
kind: Role
metadata:
  name: realm-role
  labels:
    testing.upbound.io/example-name: realm_role
spec:
  forProvider:
    name: my-realm-role
    description: My Realm Role
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

4. SAML Client Protocol Mappers (2 new CRDs)

These resources live in the samlclient.keycloak.crossplane.io/v1alpha1 API group.

SamlUserAttributeProtocolMapper

Maps a custom user attribute into a SAML assertion attribute.

apiVersion: samlclient.keycloak.crossplane.io/v1alpha1
kind: SamlUserAttributeProtocolMapper
metadata:
  name: saml-user-attribute-mapper
spec:
  forProvider:
    name: displayname-user-attribute-mapper
    userAttribute: displayName
    samlAttributeName: displayName
    samlAttributeNameFormat: Unspecified
    clientIdSelector:
      matchLabels:
        testing.upbound.io/example-name: saml_client
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config
---
apiVersion: samlclient.keycloak.crossplane.io/v1alpha1
kind: Client
metadata:
  name: saml-client
  labels:
    testing.upbound.io/example-name: saml_client
spec:
  forProvider:
    clientId: saml-client
    name: saml-client
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

SamlUserPropertyProtocolMapper

Maps a built-in Keycloak user property (e.g. email) into a SAML assertion attribute.

apiVersion: samlclient.keycloak.crossplane.io/v1alpha1
kind: SamlUserPropertyProtocolMapper
metadata:
  name: saml-user-property-mapper
spec:
  forProvider:
    name: email-user-property-mapper
    userProperty: email
    samlAttributeName: email
    samlAttributeNameFormat: Unspecified
    clientIdSelector:
      matchLabels:
        testing.upbound.io/example-name: saml_client
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

5. LDAP Mapper (1 new CRD)

UserModelHardcodedAttributeMapper

Sets a hardcoded value for a Keycloak user model attribute on every user imported from LDAP — useful for bootstrapping attributes that LDAP does not provide (e.g. email_verified).

apiVersion: ldap.keycloak.crossplane.io/v1alpha1
kind: UserModelHardcodedAttributeMapper
metadata:
  name: email-verified
spec:
  forProvider:
    name: email_verified
    attributeName: email_verified
    attributeValue: "true"
    ldapUserFederationIdSelector:
      matchLabels:
        testing.upbound.io/example-name: ldap_user_federation
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config
---
apiVersion: ldap.keycloak.crossplane.io/v1alpha1
kind: UserFederation
metadata:
  name: ldap-user-federation
  labels:
    testing.upbound.io/example-name: ldap_user_federation
spec:
  forProvider:
    name: openldap
    connectionUrl: ldap://openldap
    bindDn: cn=admin,dc=example,dc=org
    bindCredentialSecretRef:
      key: password
      name: ldap-credentials
      namespace: crossplane-system
    usersDn: dc=example,dc=org
    usernameLdapAttribute: cn
    rdnLdapAttribute: cn
    uuidLdapAttribute: entryDN
    userObjectClasses:
      - simpleSecurityObject
      - organizationalRole
    syncRegistrations: true
    realmIdSelector:
      matchLabels:
        testing.upbound.io/example-name: realm
  providerConfigRef:
    name: keycloak-provider-config

Bug Fixes

  • fix: valid_redirect_uris and web_origins added to LateInitializer.IgnoredFields — prevents spurious update loops when Keycloak returns normalised redirect URI lists that differ from the desired state
  • fix: Nil panics in mapper lookup resolved when realm ref is absent in namespaced demo manifests
  • fix: Hardcoded realmId and role used in basic ClientServiceAccountRole e2e test to avoid flaky reference resolution
  • fix: Removed invalid deletionPolicy field from namespaced client e2e test manifest
  • fix: Corrected API groups, kind names, and field names in SAML and OpenID protocol mapper e2e demo files

E2E / CI Improvements

  • ci: Added Keycloak 26.7.0 to the e2e test matrix
  • test: Added comprehensive e2e demo manifests and cases.txt entries for all new mapper resource groups — identity provider mappers (058), OpenID protocol mappers (059), and SAML/generic mappers (065)

New CRD Summary

Group Kind API Version
openidgroup.keycloak.crossplane.io AudienceProtocolMapper v1alpha1
openidgroup.keycloak.crossplane.io AudienceResolveProtocolMapper v1alpha1
openidgroup.keycloak.crossplane.io FullNameProtocolMapper v1alpha1
openidgroup.keycloak.crossplane.io HardcodedClaimProtocolMapper v1alpha1
openidgroup.keycloak.crossplane.io HardcodedRoleProtocolMapper v1alpha1
openidgroup.keycloak.crossplane.io SubProtocolMapper v1alpha1
openidgroup.keycloak.crossplane.io UserAttributeProtocolMapper v1alpha1
openidgroup.keycloak.crossplane.io UserClientRoleProtocolMapper v1alpha1
openidgroup.keycloak.crossplane.io UserPropertyProtocolMapper v1alpha1
openidgroup.keycloak.crossplane.io UserRealmRoleProtocolMapper v1alpha1
openidgroup.keycloak.crossplane.io UserSessionNoteProtocolMapper v1alpha1
identityprovider.keycloak.crossplane.io AttributeIdentityProviderMapper v1alpha1
identityprovider.keycloak.crossplane.io GroupIdentityProviderMapper v1alpha1
identityprovider.keycloak.crossplane.io ImporterIdentityProviderMapper v1alpha1
identityprovider.keycloak.crossplane.io RoleIdentityProviderMapper v1alpha1
identityprovider.keycloak.crossplane.io TemplateImporterIdentityProviderMapper v1alpha1
identityprovider.keycloak.crossplane.io ToRoleIdentityProviderMapper v1alpha1
client.keycloak.crossplane.io GenericClientProtocolMapper v1alpha1
client.keycloak.crossplane.io GenericClientRoleMapper v1alpha1
samlclient.keycloak.crossplane.io SamlUserAttributeProtocolMapper v1alpha1
samlclient.keycloak.crossplane.io SamlUserPropertyProtocolMapper v1alpha1
ldap.keycloak.crossplane.io UserModelHardcodedAttributeMapper v1alpha1

Upgrade Notes

No breaking changes. All new CRDs are purely additive. After upgrading the provider package the new kinds will be available immediately — no migration of existing resources is required.

All new resources support both the cluster-scoped (*.keycloak.crossplane.io) and namespace-scoped (*.keycloak.m.crossplane.io) API groups.

Don't miss a new provider-keycloak release

NewReleases is sending notifications on new releases.