This commit is contained in:
2026-09-28 16:28:35 +01:00
parent 666b1ff877
commit e27aa106fd
76 changed files with 5634 additions and 906 deletions
@@ -21,10 +21,6 @@
"name": {
"description": "Name of the resource",
"type": "string"
},
"namespace": {
"description": "Namespace of the resource (optional, defaults to the same namespace)",
"type": "string"
}
},
"required": [
@@ -33,6 +29,16 @@
"type": "object",
"additionalProperties": false
},
"clientRoles": {
"additionalProperties": {
"items": {
"type": "string"
},
"type": "array"
},
"description": "ClientRoles maps a client's clientId to the authoritative set of\nclient-level role names for this user. When omitted, client roles are not\nmanaged; when set, roles on clients absent from the map are removed.\nDo not combine with KeycloakRoleMapping resources targeting the same user.",
"type": "object"
},
"clusterRealmRef": {
"description": "ClusterRealmRef is a reference to a ClusterKeycloakRealm\nOne of realmRef, clusterRealmRef, or clientRef must be specified\nUse this for regular realm users with cluster-scoped realms",
"properties": {
@@ -48,12 +54,19 @@
"additionalProperties": false
},
"definition": {
"description": "Definition contains the Keycloak UserRepresentation",
"description": "Definition contains the Keycloak UserRepresentation. Set the username via\nspec.username; role and group assignments go in spec.realmRoles,\nspec.clientRoles, and spec.groups.",
"type": "object",
"x-kubernetes-preserve-unknown-fields": true
},
"groups": {
"description": "Groups is the authoritative set of group names this user belongs to,\nreconciled via the Keycloak group-membership endpoints. When omitted,\ngroup memberships are not managed; an empty list removes all memberships.",
"items": {
"type": "string"
},
"type": "array"
},
"initialPassword": {
"description": "InitialPassword sets the initial password for the user (only on creation)",
"description": "InitialPassword sets the initial password for the user (only on creation).\nFor managed credentials stored in a Kubernetes secret, use KeycloakUserCredential.",
"properties": {
"temporary": {
"description": "Temporary indicates if the user must change password on first login",
@@ -76,10 +89,6 @@
"name": {
"description": "Name of the resource",
"type": "string"
},
"namespace": {
"description": "Namespace of the resource (optional, defaults to the same namespace)",
"type": "string"
}
},
"required": [
@@ -88,34 +97,34 @@
"type": "object",
"additionalProperties": false
},
"userSecret": {
"description": "UserSecret configures where to store user credentials",
"properties": {
"generatePassword": {
"description": "GeneratePassword indicates whether to generate a password",
"type": "boolean"
},
"passwordKey": {
"description": "PasswordKey is the key for the password (defaults to \"password\")",
"type": "string"
},
"secretName": {
"description": "SecretName is the name of the Kubernetes secret to create",
"type": "string"
},
"usernameKey": {
"description": "UsernameKey is the key for the username in the secret (defaults to \"username\")",
"type": "string"
}
"realmRoles": {
"description": "RealmRoles is the authoritative set of realm-level role names for this\nuser, reconciled via the Keycloak role-mapping endpoints. When omitted,\nrealm roles are not managed; an empty list removes all realm roles.\nPointer types so an explicit empty value survives JSON round-trips.\nDo not combine with KeycloakRoleMapping resources targeting the same user.",
"items": {
"type": "string"
},
"required": [
"secretName"
],
"type": "object",
"additionalProperties": false
"type": "array"
},
"username": {
"description": "Username is the username in Keycloak. Required for regular realm users;\nomit it for service account users, which are identified by clientRef and\nwhose username is derived by Keycloak. Immutable once set.",
"minLength": 1,
"type": "string"
}
},
"type": "object",
"x-kubernetes-validations": [
{
"message": "exactly one of realmRef, clusterRealmRef, or clientRef must be set",
"rule": "(has(self.realmRef) ? 1 : 0) + (has(self.clusterRealmRef) ? 1 : 0) + (has(self.clientRef) ? 1 : 0) == 1"
},
{
"message": "spec.username is required unless spec.clientRef is set (service account user)",
"rule": "has(self.clientRef) || (has(self.username) && size(self.username) > 0)"
},
{
"message": "spec.username is immutable once set",
"rule": "!has(oldSelf.username) || (has(self.username) && self.username == oldSelf.username)"
}
],
"additionalProperties": false
},
"status": {
@@ -239,6 +248,10 @@
"userID": {
"description": "UserID is the Keycloak internal user ID",
"type": "string"
},
"username": {
"description": "Username is the resolved username in Keycloak",
"type": "string"
}
},
"required": [