{
  "id": "manage-users",
  "title": "Manage users",
  "url": "https://redis.io/docs/latest/operate/kubernetes/security/access-control/manage-users/",
  "summary": "Create and update Redis Software users on Kubernetes with the RedisEnterpriseUser custom resource.",
  "tags": [
    "docs",
    "operate",
    "kubernetes"
  ],
  "last_updated": "2026-07-24T10:52:10-07:00",
  "page_type": "content",
  "content_hash": "d4c989500f3a081dae04a0418e216989a28047d9ff25dab9eadbda80fef234d9",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "A `RedisEnterpriseUser` resource defines a Redis Software user. The operator creates the user in Redis Software and keeps it in sync with the resource. Passwords live in Kubernetes Secrets that the resource references by name.\n\nThis page covers creating users, changing passwords, and recovering locked accounts. To grant a user permissions, see [Manage role bindings](https://redis.io/docs/latest/operate/kubernetes/security/access-control/manage-bindings)."
    },
    {
      "id": "before-you-start",
      "title": "Before you start",
      "role": "content",
      "text": "- Requires Redis Software for Kubernetes operator 8.2.0-12 or later.\n- The `RedisEnterpriseUser` resource and every referenced password Secret must live in the operator namespace.\n- Passwords must satisfy the cluster's [password complexity rules](https://redis.io/docs/latest/operate/rs/security/access-control/manage-passwords/password-complexity-rules)."
    },
    {
      "id": "create-a-user",
      "title": "Create a user",
      "role": "content",
      "text": "1. Create a Secret with the password under the key `password`:\n\n    [code example]\n\n2. Create the `RedisEnterpriseUser` resource:\n\n    [code example]\n\n3. Apply the resource and confirm the operator created the user:\n\n    [code example]\n\n    `status.uid` holds the Redis Software user ID once reconciliation succeeds. `status.signinStatus` reports the user's current sign-in state.\n\nThe new user has no permissions until you create a role binding. The operator assigns the Redis Software `none` role so the user is never roleless."
    },
    {
      "id": "required-and-optional-fields",
      "title": "Required and optional fields",
      "role": "content",
      "text": "| Field | Required | Notes |\n| --- | --- | --- |\n| `spec.email` | Yes | Must be unique in the cluster. |\n| `spec.username` | No | Defaults to a generated value. ASCII only, excluding `&`, `<`, `>`, `\"`. The effective value appears in `status.username`. |\n| `spec.passwordSecrets` | Yes | At least one Secret. Each Secret must have a `password` key. |\n| `spec.passwordMode` | No | `Single` (default) or `Rotatable`. See [Choose a password mode](#choose-a-password-mode). |\n| `spec.alerts` | No | Email alert settings. Effective only when [cluster alerts](https://redis.io/docs/latest/operate/rs/clusters/configure/cluster-settings#alert-settings) are configured. |\n\nFor the full schema, see [`RedisEnterpriseUser`](https://redis.io/docs/latest/operate/kubernetes/reference/api/redis_enterprise_user_api)."
    },
    {
      "id": "use-a-generated-username",
      "title": "Use a generated username",
      "role": "content",
      "text": "If you omit `spec.username`, the operator assigns one and reports it in `status.username`. Read it with:\n\n[code example]\n\nUse that value when you sign in to Redis Software. To reference the user from a binding's `subjects` list, use the resource name (`metadata.name`) instead — not the generated username."
    },
    {
      "id": "choose-a-password-mode",
      "title": "Choose a password mode",
      "role": "content",
      "text": "`spec.passwordMode` controls how passwords change.\n\n- **`Single`** (default) — Exactly one entry in `passwordSecrets`. To change the password, update the value in the Secret or point the resource at a different Secret. Suitable for interactive users.\n- **`Rotatable`** — One or two entries in `passwordSecrets`. The operator marks each referenced Kubernetes Secret immutable so the password can't be edited in place. Suitable for service accounts that need zero-downtime credential rotation. Vault-backed secrets are treated as immutable but aren't modified by the operator.\n\nYou can't switch modes while the user has two password secrets. Reduce to one secret first."
    },
    {
      "id": "change-a-password",
      "title": "Change a password",
      "role": "content",
      "text": ""
    },
    {
      "id": "single-mode",
      "title": "Single mode",
      "role": "content",
      "text": "Edit the Secret value, then re-apply it. The operator detects the new version and updates the user's password.\n\n[code example]\n\nAlternatively, create a new Secret and update `spec.passwordSecrets[0].name` to point at it."
    },
    {
      "id": "rotatable-mode-zero-downtime-rotation",
      "title": "Rotatable mode (zero-downtime rotation)",
      "role": "content",
      "text": "In Rotatable mode the operator makes referenced Kubernetes Secrets immutable, so you rotate by adding a new Secret alongside the old one.\n\n1. Create a new Secret with the next password.\n2. Add it to `spec.passwordSecrets`. Both passwords now authenticate.\n3. Update clients to use the new password.\n4. Remove the old Secret from `spec.passwordSecrets`. Only the new password authenticates.\n5. Delete the old Secret when nothing else references it.\n\n`status.passwordSecrets` lists each active Secret with its resolved version."
    },
    {
      "id": "update-the-email-address",
      "title": "Update the email address",
      "role": "content",
      "text": "You can change `spec.email` only while `passwordSecrets` contains exactly one entry. If a Rotatable rotation is in progress, reduce to a single secret first, change the email, then add the second secret back."
    },
    {
      "id": "configure-email-alerts",
      "title": "Configure email alerts",
      "role": "configuration",
      "text": "Email alerts deliver only when the cluster has alert email settings configured. The user's alerts have two layers: a master `enabled` toggle for the whole user, and a per-category toggle for cluster alerts. Database alerts are configured by listing the databases the user should receive alerts for:\n\n[code example]\n\nOmit `databaseAlerts.databases` to receive alerts for every database."
    },
    {
      "id": "inspect-user-status",
      "title": "Inspect user status",
      "role": "content",
      "text": "The `status` block reports observed state from Redis Software:\n\n| Field | Meaning |\n| --- | --- |\n| `uid` | Internal Redis Software user ID. Appears once the user is reconciled. |\n| `username` | Effective username, including any default the operator assigned. |\n| `roles` / `rolesDisplay` | Roles currently bound to the user. |\n| `signinStatus` | `Unknown`, `Active`, `Locked`, or `PasswordExpired`. |\n| `passwordIssueDate` | When Redis Software last accepted the user's password. |\n| `passwordSecrets` | Each referenced Secret with the resolved version the operator reconciled. |\n| `observedGeneration` | The `metadata.generation` the operator last acted on. Compare with `metadata.generation` to confirm reconciliation has caught up. |\n| `conditions` | The `RolesBound` condition reports whether every bound role resolves. |"
    },
    {
      "id": "recover-a-locked-user",
      "title": "Recover a locked user",
      "role": "content",
      "text": "`status.signinStatus: Locked` means the user failed too many sign-in attempts. The operator skips password changes while the user is locked, so you must update the resource before unlocking — otherwise the operator can later reconcile the old desired password back onto the user.\n\n1. Update the password in the `RedisEnterpriseUser` source of truth: change the referenced Secret value (Single mode) or add a new Secret reference (Rotatable mode).\n2. Follow the [Redis Software unlock procedure](https://redis.io/docs/latest/operate/rs/security/access-control/manage-users/login-lockout#unlock-locked-user-accounts) to reset and unlock the account in the cluster.\n\n`status.signinStatus: PasswordExpired` clears once you set a new password through the resource."
    },
    {
      "id": "delete-a-user",
      "title": "Delete a user",
      "role": "content",
      "text": "Delete every binding that references the user before deleting the user itself. Use the recipes in [Find bindings that reference a role or user](https://redis.io/docs/latest/operate/kubernetes/security/access-control/manage-bindings#find-bindings-that-reference-a-role-or-user) to list them, delete each by name, then delete the user:\n\n[code example]\n\nThe operator removes the user from Redis Software. A finalizer keeps the Kubernetes resource until the Redis Software user and any related Secret finalizers are cleaned up; deletion may take longer or stall if the Redis Software API is unavailable.\n\nPassword Secrets aren't deleted — remove them separately when nothing else references them."
    },
    {
      "id": "troubleshoot",
      "title": "Troubleshoot",
      "role": "errors",
      "text": "Watch reconciliation events with `kubectl describe redisenterpriseuser <name>`. Common events:\n\n| Event | Meaning |\n| --- | --- |\n| `PasswordSecretMissing` | A name in `passwordSecrets` doesn't exist in the operator namespace. |\n| `PasswordSecretInvalid` | The Secret exists but has no `password` key, or the value is empty. |\n| `UserPasswordAdded` / `UserPasswordReplaced` / `UserPasswordDeleted` | Normal reconciliation actions. Useful for confirming a rotation step. |\n| `UserLocked` | Password operations are skipped because the user is locked. See [Recover a locked user](#recover-a-locked-user). |\n| `MissingRoleUIDs` | The user has Redis Software role UIDs that no longer map back to a Kubernetes role resource. |\n| `RSObjectNotFound` | A Redis Software object the user previously resolved against is gone. |\n| `RSOperationFailed` | A Redis Software API call failed; check the message for details. |\n\nOther things to check:\n\n- **`status.signinStatus: Unknown`** — The operator hasn't reconciled the user yet, or it can't read the referenced Secret. Check `PasswordSecretMissing` and `PasswordSecretInvalid` events.\n- **`RolesBound` condition is `False` with reason `RoleNotFound`** — A binding references this user but points at a role that doesn't exist. Create the role or fix the binding.\n- **Secret edit rejected** — In Rotatable mode the operator sets `immutable: true` on the Secret. Create a new Secret instead of editing an existing one.\n- **Cluster Manager UI shows a different role than expected** — Roles come from `RedisEnterpriseRoleBinding` and `RedisEnterpriseClusterRoleBinding` resources, not from the user spec. Check the bindings, not the user."
    },
    {
      "id": "related-topics",
      "title": "Related topics",
      "role": "related",
      "text": "- [Manage role bindings](https://redis.io/docs/latest/operate/kubernetes/security/access-control/manage-bindings) — assign roles to this user.\n- [Default user](https://redis.io/docs/latest/operate/rs/security/access-control/manage-users/default-user) — the built-in cluster admin account, managed outside the CRD model.\n- [Password complexity rules](https://redis.io/docs/latest/operate/rs/security/access-control/manage-passwords/password-complexity-rules) and [password expiration](https://redis.io/docs/latest/operate/rs/security/access-control/manage-passwords/password-expiration).\n- [`RedisEnterpriseUser` API reference](https://redis.io/docs/latest/operate/kubernetes/reference/api/redis_enterprise_user_api)."
    }
  ],
  "examples": [
    {
      "id": "create-a-user-ex0",
      "language": "sh",
      "code": "kubectl create secret generic alice-password \\\n      --from-literal=password='S0me-Str0ng-Passw0rd!'",
      "section_id": "create-a-user"
    },
    {
      "id": "create-a-user-ex1",
      "language": "yaml",
      "code": "apiVersion: app.redislabs.com/v1alpha1\n    kind: RedisEnterpriseUser\n    metadata:\n      name: alice\n    spec:\n      email: alice@example.com\n      username: alice\n      passwordSecrets:\n      - name: alice-password",
      "section_id": "create-a-user"
    },
    {
      "id": "create-a-user-ex2",
      "language": "sh",
      "code": "kubectl apply -f alice.yaml\n    kubectl get redisenterpriseuser alice -o yaml",
      "section_id": "create-a-user"
    },
    {
      "id": "use-a-generated-username-ex0",
      "language": "sh",
      "code": "kubectl get redisenterpriseuser alice -o jsonpath='{.status.username}'",
      "section_id": "use-a-generated-username"
    },
    {
      "id": "single-mode-ex0",
      "language": "sh",
      "code": "kubectl create secret generic alice-password \\\n  --from-literal=password='N3w-Str0ng-Passw0rd!' \\\n  --dry-run=client -o yaml | kubectl apply -f -",
      "section_id": "single-mode"
    },
    {
      "id": "configure-email-alerts-ex0",
      "language": "yaml",
      "code": "spec:\n  alerts:\n    enabled: true            # master toggle; required for any alert to deliver\n    clusterAlerts:\n      enabled: true          # opt in to cluster-level alerts\n    databaseAlerts:\n      databases:             # list specific databases, or omit to receive all\n      - name: my-database",
      "section_id": "configure-email-alerts"
    },
    {
      "id": "delete-a-user-ex0",
      "language": "sh",
      "code": "kubectl delete redisenterpriserolebinding alice-orders-viewer\nkubectl delete redisenterpriseuser alice",
      "section_id": "delete-a-user"
    }
  ]
}
