{
  "id": "manage-bindings",
  "title": "Manage role bindings",
  "url": "https://redis.io/docs/latest/operate/kubernetes/security/access-control/manage-bindings/",
  "summary": "Assign roles to users with RedisEnterpriseRoleBinding and RedisEnterpriseClusterRoleBinding resources.",
  "tags": [
    "docs",
    "operate",
    "kubernetes"
  ],
  "last_updated": "2026-07-24T10:52:10-07:00",
  "page_type": "content",
  "content_hash": "d6a290f5d11664da68aef94e0d04c0116063c7dab9395147aa150e1fb133a190",
  "sections": [
    {
      "id": "overview",
      "title": "Overview",
      "role": "overview",
      "text": "A role binding assigns a role to one or more users. Redis Software for Kubernetes supports two binding kinds, one for database-scoped roles and one for cluster-scoped roles:\n\n- `RedisEnterpriseRoleBinding` — binds a `RedisEnterpriseRole` (database-scoped) to users.\n- `RedisEnterpriseClusterRoleBinding` — binds a `RedisEnterpriseClusterRole` (cluster-scoped) to users.\n\nBoth have the same two spec fields: `roleRef` points at a single role, and `subjects` lists the users who receive it. A user holds the permissions defined by every role bound to it across all bindings.\n\nFor the conceptual model and a complete end-to-end example, see [Roles and bindings](https://redis.io/docs/latest/operate/kubernetes/security/access-control/_index#roles-and-bindings)."
    },
    {
      "id": "common-patterns",
      "title": "Common patterns",
      "role": "content",
      "text": "Each binding references exactly one role through `roleRef` and lists up to 100 subjects. A user can be the subject of many bindings, so you grant a user multiple roles by creating multiple bindings. Beyond that, the CRD model doesn't enforce a granularity — pick one of these patterns and stick with it across the namespace to make audits and reviews predictable:\n\n- **One binding per role, many subjects** — every user with the role lives in one resource. A single apply changes access for every user at once, which can be either a feature or a hazard depending on the change.\n- **One binding per user-role pair** — most verbose, but each grant is a discrete resource. Useful for attributing changes in GitOps and for scoping Kubernetes RBAC permissions on individual 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 binding resource, the role it references, and any `RedisEnterpriseUser` subjects must all live in the operator namespace.\n- Create the role before the binding when possible. The operator still admits a binding that references a missing role — the binding stays unresolved until the role lands."
    },
    {
      "id": "create-a-database-role-binding",
      "title": "Create a database role binding",
      "role": "content",
      "text": "`RedisEnterpriseRoleBinding` references a `RedisEnterpriseRole` and a list of subjects:\n\n[code example]\n\n`kind` on `roleRef` defaults to `RedisEnterpriseRole` and can be omitted. Subjects default to `RedisEnterpriseUser` the same way.\n\nTo grant the same role to several users, list them as separate subjects:\n\n[code example]"
    },
    {
      "id": "apply-order-doesn-t-matter",
      "title": "Apply order doesn't matter",
      "role": "content",
      "text": "The operator admits a binding even when the role it references doesn't exist yet. The binding stays unresolved until the role lands, and the user picks up the role on the next reconcile. This lets `kubectl apply -f manifests/` work regardless of file order.\n\nWhile the role is missing, the affected user's `RolesBound` condition is `False` with reason `RoleNotFound`:\n\n[code example]\n\nThe condition flips to `True` after the missing role exists and reconciles."
    },
    {
      "id": "create-a-cluster-role-binding",
      "title": "Create a cluster role binding",
      "role": "content",
      "text": "`RedisEnterpriseClusterRoleBinding` has the same shape but references a `RedisEnterpriseClusterRole`:\n\n[code example]\n\nA cluster role binding grants the role across every REDB in the cluster, including REDBs represented by resources in other namespaces. Reserve cluster role bindings for administrators who need cluster-wide access."
    },
    {
      "id": "subjects",
      "title": "Subjects",
      "role": "content",
      "text": "Each entry in `spec.subjects` references a `RedisEnterpriseUser` in the operator namespace. `spec.subjects[].kind` can be left empty or set to `RedisEnterpriseUser`, and `name` is the resource's `metadata.name`:\n\n[code example]\n\nA binding can list up to 100 subjects. To grant the role to more users, create additional bindings that reference the same role."
    },
    {
      "id": "update-a-binding",
      "title": "Update a binding",
      "role": "content",
      "text": "Edit `spec.subjects` to add or remove users from the role, or change `roleRef` to point at a different role.\n\n- **Add a user** — append a new entry to `subjects` and apply. The user picks up the role on the next reconcile.\n- **Remove a user** — delete the entry from `subjects`. The user loses the role; other subjects in the binding keep their access.\n- **Replace the role** — change `roleRef.name`. Subjects lose the old role and gain the new one. Consider creating a new binding instead if you need a staged rollout.\n\nA user's effective roles appear in `status.roles` on the `RedisEnterpriseUser`."
    },
    {
      "id": "find-bindings-that-reference-a-role-or-user",
      "title": "Find bindings that reference a role or user",
      "role": "content",
      "text": "Before renaming or deleting a role, find every binding that points at it:\n\n[code example]\n\nTo find every binding that grants a role to a specific user:\n\n[code example]"
    },
    {
      "id": "inspect-binding-status",
      "title": "Inspect binding status",
      "role": "content",
      "text": "The binding's own `status` block is empty. To see whether a binding has actually granted permissions, check the referenced user instead:\n\n[code example]"
    },
    {
      "id": "delete-a-binding",
      "title": "Delete a binding",
      "role": "content",
      "text": "[code example]\n\nRemoving the binding revokes the role from every subject listed in it. If you delete the only binding that granted a user any role, the operator falls back to assigning the `none` role so the user is never roleless."
    },
    {
      "id": "troubleshoot",
      "title": "Troubleshoot",
      "role": "errors",
      "text": "Watch reconciliation events with `kubectl describe redisenterpriserolebinding <name>` (or `redisenterpriseclusterrolebinding`). Since bindings are observed by the user controller, the most useful diagnostic signals appear on the user resource:\n\n- **The user's `RolesBound` condition is `False` with reason `RoleNotFound`** — A binding references this user but points at a role that doesn't exist. Either create the missing role or fix `roleRef.name`. See [Apply order doesn't matter](#apply-order-doesnt-matter).\n- **User has permissions you didn't expect** — Multiple bindings may be granting the same user different roles. Use the recipes in [Find bindings that reference a role or user](#find-bindings-that-reference-a-role-or-user) to list everything that targets the user.\n- **`MissingRoleUIDs` event on a user** — Redis Software has role UIDs assigned to the user that the operator can't trace back to any Kubernetes role resource. This typically means roles were granted directly through the Redis Software REST API or Cluster Manager UI, bypassing the CRD model. Recreate the assignment as a `RedisEnterpriseRoleBinding` (or `RedisEnterpriseClusterRoleBinding`) so the CRD model is the source of truth, then revoke the direct assignment.\n\nFor full field details, see the [`RedisEnterpriseRoleBinding`](https://redis.io/docs/latest/operate/kubernetes/reference/api/redis_enterprise_role_binding_api) and [`RedisEnterpriseClusterRoleBinding`](https://redis.io/docs/latest/operate/kubernetes/reference/api/redis_enterprise_cluster_role_binding_api) API reference."
    },
    {
      "id": "related-topics",
      "title": "Related topics",
      "role": "related",
      "text": "- [Roles and bindings](https://redis.io/docs/latest/operate/kubernetes/security/access-control/_index#roles-and-bindings) — the conceptual model and an end-to-end example.\n- [Manage roles](https://redis.io/docs/latest/operate/kubernetes/security/access-control/manage-roles) — create the roles that a binding references.\n- [Manage users](https://redis.io/docs/latest/operate/kubernetes/security/access-control/manage-users) — create the users that a binding lists as subjects."
    }
  ],
  "examples": [
    {
      "id": "create-a-database-role-binding-ex0",
      "language": "yaml",
      "code": "apiVersion: app.redislabs.com/v1alpha1\nkind: RedisEnterpriseRoleBinding\nmetadata:\n  name: alice-orders-viewer\nspec:\n  roleRef:\n    kind: RedisEnterpriseRole\n    name: orders-viewer\n  subjects:\n  - kind: RedisEnterpriseUser\n    name: alice",
      "section_id": "create-a-database-role-binding"
    },
    {
      "id": "create-a-database-role-binding-ex1",
      "language": "yaml",
      "code": "spec:\n  roleRef:\n    name: orders-viewer\n  subjects:\n  - name: alice\n  - name: bob\n  - name: carol",
      "section_id": "create-a-database-role-binding"
    },
    {
      "id": "apply-order-doesn-t-matter-ex0",
      "language": "sh",
      "code": "kubectl get redisenterpriseuser alice -o jsonpath='{.status.conditions[?(@.type==\"RolesBound\")]}'",
      "section_id": "apply-order-doesn-t-matter"
    },
    {
      "id": "create-a-cluster-role-binding-ex0",
      "language": "yaml",
      "code": "apiVersion: app.redislabs.com/v1alpha1\nkind: RedisEnterpriseClusterRoleBinding\nmetadata:\n  name: ops-admins\nspec:\n  roleRef:\n    kind: RedisEnterpriseClusterRole\n    name: cluster-admin\n  subjects:\n  - name: alice\n  - name: bob",
      "section_id": "create-a-cluster-role-binding"
    },
    {
      "id": "subjects-ex0",
      "language": "yaml",
      "code": "spec:\n  subjects:\n  - kind: RedisEnterpriseUser\n    name: alice\n  - name: bob    # kind defaults to RedisEnterpriseUser",
      "section_id": "subjects"
    },
    {
      "id": "find-bindings-that-reference-a-role-or-user-ex0",
      "language": "sh",
      "code": "kubectl get redisenterpriserolebinding -o json | \\\n  jq '.items[] | select(.spec.roleRef.name == \"orders-viewer\") | .metadata.name'\nkubectl get redisenterpriseclusterrolebinding -o json | \\\n  jq '.items[] | select(.spec.roleRef.name == \"orders-viewer\") | .metadata.name'",
      "section_id": "find-bindings-that-reference-a-role-or-user"
    },
    {
      "id": "find-bindings-that-reference-a-role-or-user-ex1",
      "language": "sh",
      "code": "kubectl get redisenterpriserolebinding -o json | \\\n  jq '.items[] | select(.spec.subjects[]?.name == \"alice\") | .metadata.name'\nkubectl get redisenterpriseclusterrolebinding -o json | \\\n  jq '.items[] | select(.spec.subjects[]?.name == \"alice\") | .metadata.name'",
      "section_id": "find-bindings-that-reference-a-role-or-user"
    },
    {
      "id": "inspect-binding-status-ex0",
      "language": "sh",
      "code": "kubectl get redisenterpriseuser alice -o jsonpath='{.status.roles}'",
      "section_id": "inspect-binding-status"
    },
    {
      "id": "delete-a-binding-ex0",
      "language": "sh",
      "code": "kubectl delete redisenterpriserolebinding alice-orders-viewer",
      "section_id": "delete-a-binding"
    }
  ]
}
