Secret Management¶
This guide covers generated client credentials, manual client secret binding, automated rotation, and GitOps-friendly secret provisioning.
Use the Helm charts as the primary configuration path. Direct CR edits still work, but they are the advanced path.
What The Operator Manages¶
For confidential KeycloakClient resources, the operator can create and maintain a Kubernetes Secret named:
<client-name>-credentialsby defaultsecretNameif you set one explicitly
The managed client credentials secret contains:
client-idclient-secretfor confidential clientskeycloak-urlrealmtoken-endpointuserinfo-endpointjwks-endpointissuer
Applications should consume that Secret directly from the cluster instead of copying values into Git-managed manifests.
Helm-First Configuration¶
The keycloak-client chart is the primary entry point.
Generated Client Credentials¶
manageSecret: true
secretName: my-app-oidc
secretRotation:
enabled: true
rotationPeriod: 90d
rotationTime: "03:00"
timezone: UTC
This renders a KeycloakClient that lets the operator generate the secret and rotate it on schedule.
Manual Existing Secret Binding¶
If the client secret already exists outside the operator, bind it explicitly:
Important constraints:
clientSecretandsecretRotation.enabled=truecannot be used togetherclientSecretcannot be used for public clients- the referenced secret must live in the same namespace as the
KeycloakClient
The chart already enforces the first rule by omitting the rendered secretRotation block when clientSecret.name is set.
Automated Rotation¶
Automated client secret rotation is atomic.
When Keycloak rotates a standard client secret, the previous secret becomes invalid immediately. There is no built-in secret history or overlap window.
Rotation is configured on the client resource:
Field semantics:
rotationPeriodacceptss,m,h, anddunitsrotationTimeis optional and usesHH:MMformattimezoneuses IANA timezone names such asUTCorEurope/Amsterdam
The operator stores the last successful rotation timestamp in two places:
- Secret annotation
keycloak-operator/rotated-at KeycloakClient.status.lastSecretRotation
The rotation daemon recalculates the next run from that timestamp, so pod restarts do not lose schedule state.
Rotation Failure Behavior¶
If rotation fails, the daemon retries with backoff and records rotation error metrics.
Rotation only runs while the client remains operational. If client reconciliation is paused at the operator level, the rotation daemon pauses too.
Restart Coordination¶
Because rotation is atomic, workloads that use the secret must reload it quickly.
Stakater Reloader¶
This is the simplest pattern for most clusters.
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
annotations:
reloader.stakater.com/auto: "true"
spec:
template:
spec:
containers:
- name: my-app
env:
- name: CLIENT_ID
valueFrom:
secretKeyRef:
name: my-app-oidc
key: client-id
- name: CLIENT_SECRET
valueFrom:
secretKeyRef:
name: my-app-oidc
key: client-secret
Kyverno Restart Policy¶
If you standardize on Kyverno, mutate workloads when the managed credentials secret changes.
Target the actual operator-managed secret label contract.
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
name: restart-on-keycloak-client-secret-change
spec:
rules:
- name: restart-deployments-using-rotated-client-secret
match:
any:
- resources:
kinds:
- Secret
selector:
matchLabels:
vriesdemichael.github.io/keycloak-component: client-credentials
mutate:
targets:
- apiVersion: apps/v1
kind: Deployment
context:
- name: deployments
apiCall:
urlPath: "/apis/apps/v1/namespaces/{{request.object.metadata.namespace}}/deployments"
jmesPath: "items[?spec.template.spec.containers[].env[].valueFrom.secretKeyRef.name.contains(@, '{{request.object.metadata.name}}')]"
foreach:
- list: "deployments"
patchStrategicMerge:
spec:
template:
metadata:
annotations:
ops.keycloak.io/restartedAt: "{{ time_now_utc() }}"
Provisioning Secrets With GitOps Tools¶
External Secrets Operator¶
Use ESO when the source of truth for a secret lives in Vault, AWS Secrets Manager, 1Password, or another external backend.
Typical pattern:
- ESO materializes the secret into the application namespace.
- The
KeycloakClientreferences that secret throughclientSecretfor manual binding, or the application references the operator-managed credentials secret. - The application deployment reloads when the effective secret changes.
Sealed Secrets¶
Use Sealed Secrets when you want Git-stored encrypted manifests that are decrypted in-cluster.
This works well for:
- pre-created
clientSecretvalues - application-side credentials or sidecar configuration
- admin/bootstrap secrets for managed
Keycloakinstances
Operator Read-Access Label¶
Some secret references across the operator require explicit opt-in so the operator may read them safely. Where that applies, label the secret with:
That label is especially relevant for secret references used by realm features such as SMTP, identity providers, and user federation.
Operational Notes¶
- secret rotation is only meaningful for confidential clients
- manual
clientSecretbinding is the right choice when another secret system owns the credential lifecycle - generated credentials plus rotation are the right choice when the operator owns the client lifecycle end to end
- application restart automation is mandatory if you enable rotation
- if you use Kyverno or another policy engine, match the real client-credentials secret labels instead of inventing a separate secret type label
See Also¶
- Day Two Operations
- Backup & Restore
- the
charts/keycloak-clientREADME for chart-specific values details