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-configAudienceResolveProtocolMapper
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-configFullNameProtocolMapper
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-configHardcodedClaimProtocolMapper
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-configHardcodedRoleProtocolMapper
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-configSubProtocolMapper
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-configUserAttributeProtocolMapper
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-configUserClientRoleProtocolMapper
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-configUserPropertyProtocolMapper
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-configUserRealmRoleProtocolMapper
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-configUserSessionNoteProtocolMapper
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-config2. 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-configGroupIdentityProviderMapper
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-configImporterIdentityProviderMapper
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-configRoleIdentityProviderMapper
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-configTemplateImporterIdentityProviderMapper
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-configToRoleIdentityProviderMapper
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-config3. 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-configGenericClientRoleMapper
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-config4. 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-configSamlUserPropertyProtocolMapper
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-config5. 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-configBug Fixes
- fix:
valid_redirect_urisandweb_originsadded toLateInitializer.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
realmIdandroleused in basicClientServiceAccountRolee2e test to avoid flaky reference resolution - fix: Removed invalid
deletionPolicyfield 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.txtentries 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.