---
# === IDENTITY ===
id: software/devops/k8s-rbac/2026
canonical_question: "How do I configure Kubernetes RBAC (Role-Based Access Control)?"
aliases:
  - "Kubernetes RBAC configuration"
  - "k8s Role ClusterRole RoleBinding ClusterRoleBinding"
  - "Kubernetes RBAC least privilege best practices"
  - "kubectl RBAC setup ServiceAccount permissions"
  - "Kubernetes role-based access control YAML"
  - "k8s RBAC security hardening"
  - "Kubernetes RBAC aggregated ClusterRoles"
  - "Kubernetes ServiceAccount RBAC binding"
entity_type: software_reference
domain: software > devops > Kubernetes RBAC Configuration
region: global
jurisdiction: global
temporal_scope: 2017-2026

# === VERIFICATION ===
last_verified: 2026-02-27
confidence: 0.94
version: 1.0
first_published: 2026-02-27

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: stable
  last_breaking_change: "K8s 1.22 removed beta RBAC APIs (rbac.authorization.k8s.io/v1beta1); v1 GA since K8s 1.8"
  next_review: 2026-08-26
  change_sensitivity: low

# === CONSTRAINTS ===
constraints:
  - "RBAC is additive-only -- there are NO deny rules; every rule grants access, and access not explicitly granted is denied by default"
  - "roleRef in RoleBinding/ClusterRoleBinding is IMMUTABLE after creation -- you must delete and recreate the binding to change the referenced role"
  - "Never add users to the system:masters group -- it bypasses ALL RBAC authorization checks and cannot be restricted"
  - "The escalate and bind verbs allow privilege escalation -- restrict these to cluster administrators only"
  - "Granting create on pods/deployments implicitly grants access to any Secret, ConfigMap, or ServiceAccount mountable in that namespace"
  - "ClusterRoleBindings grant permissions cluster-wide -- prefer RoleBindings scoped to a namespace unless cluster-wide access is genuinely required"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "Need to configure Kubernetes NetworkPolicy (network-level access control, not API-level)"
    use_instead: "software/devops/k8s-network-policy/2026"
  - condition: "Need to configure Pod Security Admission (pod-level security constraints)"
    use_instead: "software/devops/k8s-pod-security-admission/2026"
  - condition: "Need OPA/Gatekeeper policy engine for custom admission control beyond RBAC"
    use_instead: "software/devops/k8s-opa-gatekeeper/2026"

# === AGENT HINTS ===
inputs_needed:
  - key: scope
    question: "Do you need namespace-scoped or cluster-wide permissions?"
    type: choice
    options: ["Namespace-scoped (single namespace)", "Cluster-wide (all namespaces)", "Not sure"]
  - key: subject_type
    question: "What type of subject needs permissions?"
    type: choice
    options: ["User", "Group", "ServiceAccount (for pods/workloads)", "Not sure"]
  - key: permission_level
    question: "What level of access is needed?"
    type: choice
    options: ["Read-only (get/list/watch)", "Read-write (create/update/delete)", "Admin (full namespace control)", "Custom (specific verbs/resources)"]

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/software/devops/k8s-rbac/2026"
suggested_citation: "Source: knowledgelib.io -- AI Knowledge Library (verified 2026-02-27)"

# === RELATED UNITS ===
related_kos:
  depends_on: []
  related_to:
    - id: "software/devops/k8s-deployment-service-ingress/2026"
      label: "Kubernetes Deployment + Service + Ingress"
    - id: "software/debugging/kubernetes-crashloopbackoff/2026"
      label: "Kubernetes CrashLoopBackOff Debugging"
  solves: []
  alternative_to: []
  often_confused_with:
    - id: "software/devops/k8s-network-policy/2026"
      label: "Kubernetes NetworkPolicy (network-level, not API-level access control)"

# === SOURCES (7 authoritative sources) ===
sources:
  - id: src1
    title: "Using RBAC Authorization"
    author: Kubernetes Project
    url: https://kubernetes.io/docs/reference/access-authn-authz/rbac/
    type: official_docs
    published: 2024-12-01
    reliability: authoritative
  - id: src2
    title: "Role Based Access Control Good Practices"
    author: Kubernetes Project
    url: https://kubernetes.io/docs/concepts/security/rbac-good-practices/
    type: official_docs
    published: 2024-06-01
    reliability: authoritative
  - id: src3
    title: "Best practices for GKE RBAC"
    author: Google Cloud
    url: https://docs.cloud.google.com/kubernetes-engine/docs/best-practices/rbac
    type: official_docs
    published: 2025-01-15
    reliability: high
  - id: src4
    title: "Kubernetes RBAC Best Practices -- From Basic to Advanced"
    author: Wiz
    url: https://www.wiz.io/academy/container-security/kubernetes-rbac-best-practices
    type: technical_blog
    published: 2025-03-01
    reliability: high
  - id: src5
    title: "Privilege Escalation with Kubernetes RBAC Misconfigurations"
    author: Esra Kayhan
    url: https://medium.com/@esrakyhn/privilege-escalation-with-kubernetes-rbac-misconfigurations-8add491d99f7
    type: technical_blog
    published: 2025-10-01
    reliability: moderate_high
  - id: src6
    title: "Using RBAC, Generally Available in Kubernetes v1.8"
    author: Kubernetes Project
    url: https://kubernetes.io/blog/2017/10/using-rbac-generally-available-18/
    type: official_docs
    published: 2017-10-12
    reliability: authoritative
  - id: src7
    title: "Kubernetes RBAC: A Step-by-Step Guide for Securing Your Cluster"
    author: Trilio
    url: https://trilio.io/kubernetes-best-practices/kubernetes-rbac/
    type: technical_blog
    published: 2025-06-01
    reliability: moderate_high
---

# Kubernetes RBAC Configuration

## TL;DR

- **Bottom line**: Kubernetes RBAC controls API access through four objects -- Role, ClusterRole, RoleBinding, and ClusterRoleBinding -- using additive-only allow rules with no deny capability. [src1]
- **Key tool/command**: `kubectl auth can-i <verb> <resource> --as=<user> [--namespace=<ns>]`
- **Watch out for**: Wildcard permissions (`*`) in verbs or resources grant access to all current AND future resources, including secrets and admission webhooks. [src2]
- **Works with**: Kubernetes 1.8+ (RBAC GA since v1.8; `rbac.authorization.k8s.io/v1` is the only supported API version in modern clusters).

## Constraints
<!-- Agents: read this section before recommending any action from this unit.
     These are hard constraints that must not be violated. -->

- RBAC is additive-only -- there are NO deny rules; all rules grant access, and access not explicitly granted is denied by default [src1]
- `roleRef` in RoleBinding/ClusterRoleBinding is IMMUTABLE after creation -- delete and recreate the binding to change the referenced role [src1]
- Never add users to the `system:masters` group -- it bypasses ALL RBAC authorization checks and cannot be restricted by any RBAC policy [src2]
- The `escalate` and `bind` verbs allow privilege escalation -- restrict these to cluster administrators only [src2]
- Granting `create` on pods/deployments implicitly grants access to any Secret, ConfigMap, or ServiceAccount mountable in that namespace [src2]
- ClusterRoleBindings grant permissions cluster-wide -- prefer namespace-scoped RoleBindings unless cluster-wide access is genuinely required [src3]

## Quick Reference

| Resource | Scope | Purpose | API Group | Key Fields |
|---|---|---|---|---|
| `Role` | Namespace | Define permissions within a single namespace | `rbac.authorization.k8s.io/v1` | `rules[].apiGroups`, `resources`, `verbs` |
| `ClusterRole` | Cluster | Define cluster-wide or cross-namespace permissions | `rbac.authorization.k8s.io/v1` | `rules[]`, `aggregationRule` |
| `RoleBinding` | Namespace | Bind Role or ClusterRole to subjects in one namespace | `rbac.authorization.k8s.io/v1` | `subjects[]`, `roleRef` (immutable) |
| `ClusterRoleBinding` | Cluster | Bind ClusterRole to subjects cluster-wide | `rbac.authorization.k8s.io/v1` | `subjects[]`, `roleRef` (immutable) |
| `ServiceAccount` | Namespace | Identity for pods; bound to Roles via RoleBinding | `v1` | `automountServiceAccountToken` |

| Verb | Type | Description |
|---|---|---|
| `get` | Read | Retrieve a single resource by name |
| `list` | Read | List all resources of a type (exposes secret values!) |
| `watch` | Read | Stream changes to resources (exposes secret values!) |
| `create` | Write | Create a new resource |
| `update` | Write | Replace an entire resource |
| `patch` | Write | Modify specific fields of a resource |
| `delete` | Write | Delete a single resource |
| `deletecollection` | Write | Delete all resources of a type |
| `escalate` | Dangerous | Modify RBAC rules beyond your own permissions |
| `bind` | Dangerous | Create bindings to roles with higher permissions |
| `impersonate` | Dangerous | Act as another user, group, or service account |

| Default ClusterRole | Permissions | Use Case |
|---|---|---|
| `cluster-admin` | Full access to ALL resources | Emergency break-glass only [src2] |
| `admin` | Full access within a namespace (no ResourceQuota/Namespace) | Namespace administrators |
| `edit` | Read/write most resources (no Roles/RoleBindings) | Developers deploying workloads |
| `view` | Read-only most resources (no Secrets) | Auditors, read-only dashboards |

## Decision Tree

```
START
├── Need cluster-wide access to non-namespaced resources (nodes, namespaces, PVs)?
│   ├── YES → Use ClusterRole + ClusterRoleBinding
│   └── NO ↓
├── Need the same permissions across multiple namespaces?
│   ├── YES → Define a ClusterRole + RoleBinding per namespace
│   └── NO ↓
├── Need permissions in a single namespace only?
│   ├── YES → Use Role + RoleBinding (most secure, preferred)
│   └── NO ↓
├── Need to extend a built-in role (admin/edit/view)?
│   ├── YES → Use aggregated ClusterRole with matching labels
│   └── NO ↓
├── Subject is a pod/workload?
│   ├── YES → Create dedicated ServiceAccount + Role + RoleBinding
│   │         Set automountServiceAccountToken: false on SA
│   └── NO ↓
├── Subject is a human user?
│   ├── YES → Bind to Group (not individual User) for manageability
│   └── NO ↓
└── DEFAULT → Start with the built-in "view" ClusterRole; add permissions incrementally
```

## Step-by-Step Guide

### 1. Create a ServiceAccount for your workload

Every application should have its own ServiceAccount rather than using the `default` ServiceAccount. Disable automatic token mounting unless the pod needs Kubernetes API access. [src2] [src3]

```yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: myapp-sa
  namespace: production
automountServiceAccountToken: false
```

**Verify**: `kubectl get sa myapp-sa -n production` --> should show the ServiceAccount

### 2. Define a Role with minimum required permissions

Specify exact `apiGroups`, `resources`, and `verbs`. Use `resourceNames` to restrict access to specific objects when possible. Never use wildcards. [src1] [src2]

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: myapp-role
  namespace: production
rules:
# Read only the specific ConfigMap this app needs
- apiGroups: [""]
  resources: ["configmaps"]
  resourceNames: ["myapp-config"]
  verbs: ["get", "watch"]
# Read pods for health monitoring
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "list"]
```

**Verify**: `kubectl describe role myapp-role -n production` --> should show the rules

### 3. Bind the Role to the ServiceAccount

Create a RoleBinding that connects the ServiceAccount to the Role. The `roleRef` is immutable -- to change the role reference, delete and recreate the binding. [src1]

```yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: myapp-binding
  namespace: production
subjects:
- kind: ServiceAccount
  name: myapp-sa
  namespace: production
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: myapp-role
```

**Verify**: `kubectl auth can-i get configmaps --as=system:serviceaccount:production:myapp-sa -n production` --> `yes`

### 4. Assign the ServiceAccount to your Pod/Deployment

Reference the ServiceAccount in your pod spec. If the pod does need API access, set `automountServiceAccountToken: true` in the pod spec (overrides the SA-level setting). [src3]

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
  namespace: production
spec:
  replicas: 2
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      serviceAccountName: myapp-sa
      automountServiceAccountToken: true
      containers:
      - name: myapp
        image: myapp:1.2.3
        resources:
          requests:
            memory: "128Mi"
            cpu: "100m"
          limits:
            memory: "256Mi"
            cpu: "200m"
```

**Verify**: `kubectl get pods -n production -o jsonpath='{.items[0].spec.serviceAccountName}'` --> `myapp-sa`

### 5. Test permissions with kubectl auth can-i

Always verify both positive (allowed) and negative (denied) access after configuring RBAC. [src1]

```bash
# Should succeed (allowed by the Role)
kubectl auth can-i get configmaps --as=system:serviceaccount:production:myapp-sa -n production
# yes

# Should fail (not granted)
kubectl auth can-i create deployments --as=system:serviceaccount:production:myapp-sa -n production
# no

# Check all permissions for a subject
kubectl auth can-i --list --as=system:serviceaccount:production:myapp-sa -n production
```

**Verify**: Positive tests return `yes`, negative tests return `no`

### 6. Apply all manifests with kubectl auth reconcile

Use `kubectl auth reconcile` for idempotent RBAC application, especially in CI/CD pipelines. It handles create-or-update safely. [src1]

```bash
kubectl auth reconcile -f rbac-manifests/ --dry-run=server
kubectl auth reconcile -f rbac-manifests/
```

**Verify**: `kubectl get role,rolebinding -n production` --> should list all created objects

## Code Examples
<!-- Keep inline examples <=15 lines. For longer scripts, extract to scripts/ subdirectory
     and link: "Full script: [name.ext](scripts/name.ext) (N lines)" -->

### YAML: Namespace-scoped developer Role + RoleBinding

> Full script: [yaml-namespace-scoped-developer-role-rolebinding.yml](scripts/yaml-namespace-scoped-developer-role-rolebinding.yml) (31 lines)

```yaml
# Input:  A developer group needing read/write access in "development" namespace
# Output: Role + RoleBinding granting deployment and service management
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
# ... (see full script)
```

### YAML: ClusterRole with aggregation for monitoring

```yaml
# Input:  Need to extend the built-in "view" role with metrics access
# Output: Aggregated ClusterRole that merges into "view" automatically

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: metrics-reader
  labels:
    # This label causes automatic aggregation into the "view" ClusterRole
    rbac.authorization.k8s.io/aggregate-to-view: "true"
rules:
- apiGroups: ["metrics.k8s.io"]
  resources: ["pods", "nodes"]
  verbs: ["get", "list"]
```

### YAML: CI/CD ServiceAccount with scoped deployment permissions

> Full script: [yaml-ci-cd-serviceaccount-with-scoped-deployment-p.yml](scripts/yaml-ci-cd-serviceaccount-with-scoped-deployment-p.yml) (38 lines)

```yaml
# Input:  CI/CD pipeline needs to deploy to "staging" namespace only
# Output: ServiceAccount + Role granting only deployment rollout capabilities
apiVersion: v1
kind: ServiceAccount
metadata:
# ... (see full script)
```

### YAML: Read-only ClusterRole for auditors across all namespaces

> Full script: [yaml-read-only-clusterrole-for-auditors-across-all.yml](scripts/yaml-read-only-clusterrole-for-auditors-across-all.yml) (25 lines)

```yaml
# Input:  Auditor group needs read-only access to all namespaces
# Output: ClusterRole + ClusterRoleBinding granting cluster-wide read access
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
# ... (see full script)
```

## Anti-Patterns

### Wrong: Using wildcards for verbs and resources

```yaml
# BAD -- grants ALL permissions on ALL resources, including secrets,
# admission webhooks, and any future resources added to the cluster [src2]
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: super-user
rules:
- apiGroups: ["*"]
  resources: ["*"]
  verbs: ["*"]
```

### Correct: Explicit verbs and resources

```yaml
# GOOD -- grants only the specific permissions needed [src2]
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: app-manager
  namespace: production
rules:
- apiGroups: ["apps"]
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "update", "patch"]
- apiGroups: [""]
  resources: ["services"]
  verbs: ["get", "list"]
```

### Wrong: Binding cluster-admin to a ServiceAccount

```yaml
# BAD -- if any pod using this SA is compromised, the attacker has
# full cluster-admin access to the entire cluster [src5]
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: app-admin
subjects:
- kind: ServiceAccount
  name: default
  namespace: production
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
```

### Correct: Dedicated ServiceAccount with scoped Role

```yaml
# GOOD -- dedicated SA with minimum permissions, namespace-scoped [src2] [src3]
apiVersion: v1
kind: ServiceAccount
metadata:
  name: myapp-sa
  namespace: production
automountServiceAccountToken: false
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: myapp-binding
  namespace: production
subjects:
- kind: ServiceAccount
  name: myapp-sa
  namespace: production
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: myapp-role
```

### Wrong: Using the default ServiceAccount

```yaml
# BAD -- the default SA is shared by all pods in the namespace;
# any RBAC granted to it applies to every pod [src3]
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  template:
    spec:
      # No serviceAccountName specified = uses "default"
      containers:
      - name: myapp
        image: myapp:latest
```

### Correct: Dedicated ServiceAccount per workload

```yaml
# GOOD -- each workload has its own SA with tailored permissions [src3]
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp
spec:
  template:
    spec:
      serviceAccountName: myapp-sa
      automountServiceAccountToken: true
      containers:
      - name: myapp
        image: myapp:1.2.3
```

### Wrong: Granting list/watch on secrets cluster-wide

```yaml
# BAD -- list and watch on secrets exposes ALL secret values
# in plaintext, not just metadata [src2]
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: secret-viewer
rules:
- apiGroups: [""]
  resources: ["secrets"]
  verbs: ["get", "list", "watch"]
```

### Correct: Scope secret access to specific names and namespaces

```yaml
# GOOD -- access only specific secrets in one namespace [src2]
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: app-secret-reader
  namespace: production
rules:
- apiGroups: [""]
  resources: ["secrets"]
  resourceNames: ["myapp-tls", "myapp-db-credentials"]
  verbs: ["get"]
```

### Wrong: Granting escalate or bind verbs to non-admins

```yaml
# BAD -- allows the subject to grant themselves any permission,
# effectively making them a cluster-admin [src5]
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: rbac-manager
rules:
- apiGroups: ["rbac.authorization.k8s.io"]
  resources: ["roles", "clusterroles"]
  verbs: ["get", "list", "create", "update", "patch", "escalate"]
- apiGroups: ["rbac.authorization.k8s.io"]
  resources: ["rolebindings", "clusterrolebindings"]
  verbs: ["get", "list", "create", "update", "patch", "bind"]
```

### Correct: Restrict RBAC management to cluster admins

```yaml
# GOOD -- only cluster-admin (via break-glass) should modify RBAC objects
# Regular users should request RBAC changes through GitOps/PR workflow [src2]
# Do NOT create custom roles with escalate/bind verbs
```

## Common Pitfalls

- **RoleBinding vs ClusterRoleBinding confusion**: A ClusterRole bound via RoleBinding is scoped to the RoleBinding's namespace. A ClusterRole bound via ClusterRoleBinding grants cluster-wide access. This distinction is critical -- the same ClusterRole behaves differently depending on the binding type. Fix: Always use RoleBinding unless cluster-wide access is explicitly needed. [src1]
- **list/watch exposes secret values**: Many assume `list` and `watch` on secrets only show metadata. In reality, they return full secret data in plaintext. Fix: Never grant `list`/`watch` on secrets; use `get` with `resourceNames` for specific secrets only. [src2]
- **Forgetting automountServiceAccountToken**: By default, Kubernetes mounts a service account token into every pod, even if the pod never calls the API. Fix: Set `automountServiceAccountToken: false` on the ServiceAccount and only enable it in the pod spec for pods that need it. [src3]
- **Token reuse after RBAC changes**: Kubernetes API tokens are validated at request time, not issuance time. However, TokenReview results may be cached by webhook authenticators. Fix: After revoking RBAC, also delete the ServiceAccount or its token secrets to immediately invalidate access. [src1]
- **system:authenticated includes everyone with a Google/OIDC account**: On managed clusters (GKE, EKS), binding to `system:authenticated` grants access to anyone with a valid identity token, including external users. Fix: Never bind roles to `system:authenticated` or `system:unauthenticated`. [src3]
- **Aggregated ClusterRole unintended expansion**: Adding a label like `rbac.authorization.k8s.io/aggregate-to-admin: "true"` to a ClusterRole automatically merges its rules into the built-in `admin` role for all namespace admins. Fix: Audit aggregation labels carefully and test with `kubectl auth can-i`. [src1]

## Diagnostic Commands

```bash
# Check if a specific user/SA can perform an action
kubectl auth can-i get pods --as=jane -n production

# Check if a ServiceAccount can perform an action
kubectl auth can-i create deployments --as=system:serviceaccount:staging:cicd-deployer -n staging

# List all permissions for a subject in a namespace
kubectl auth can-i --list --as=system:serviceaccount:production:myapp-sa -n production

# List all Roles and RoleBindings in a namespace
kubectl get roles,rolebindings -n production

# List all ClusterRoles and ClusterRoleBindings
kubectl get clusterroles,clusterrolebindings

# Describe a specific Role to see its rules
kubectl describe role myapp-role -n production

# Describe a binding to see subjects and roleRef
kubectl describe rolebinding myapp-binding -n production

# Find all bindings referencing a specific ClusterRole
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin") | .metadata.name'

# Audit: find all subjects with cluster-admin access
kubectl get clusterrolebindings -o json | jq '.items[] | select(.roleRef.name=="cluster-admin") | {name: .metadata.name, subjects: .subjects}'

# Dry-run RBAC reconciliation (safe for CI/CD)
kubectl auth reconcile -f rbac-manifests/ --dry-run=server

# Check which API groups/resources are available
kubectl api-resources --verbs=list -o wide
```

## Version History & Compatibility

| Version | Status | Breaking Changes | Migration Notes |
|---|---|---|---|
| K8s 1.32+ | Current | KubeletCrashLoopBackOffMax alpha feature; no RBAC-specific changes | -- |
| K8s 1.30 | Current | ValidatingAdmissionPolicy GA -- can supplement RBAC with CEL-based policies | Use VAP for complex admission rules that RBAC alone cannot express |
| K8s 1.24 | Supported | BoundServiceAccountTokenVolume GA; automatic secret-based tokens removed | Tokens now auto-rotated via TokenRequest API; no manual Secret needed |
| K8s 1.22 | Minimum recommended | `rbac.authorization.k8s.io/v1beta1` REMOVED | Update all manifests to `rbac.authorization.k8s.io/v1` |
| K8s 1.8 | Historical | RBAC promoted to GA (`rbac.authorization.k8s.io/v1`) | -- |
| K8s 1.6 | Historical (EOL) | RBAC introduced as beta (`rbac.authorization.k8s.io/v1beta1`) | -- |

## When to Use / When Not to Use

| Use When | Don't Use When | Use Instead |
|---|---|---|
| Controlling who can access which Kubernetes API resources | Need network-level traffic control between pods | NetworkPolicy |
| Restricting ServiceAccount permissions for workloads | Need to enforce pod security constraints (no privileged, no hostPath) | Pod Security Admission / Pod Security Standards |
| Granting namespace-scoped developer access | Need complex conditional policies (e.g., "allow only images from approved registries") | OPA/Gatekeeper or ValidatingAdmissionPolicy |
| Setting up CI/CD pipeline access to deploy | Need to restrict API access based on source IP or time of day | Admission webhooks or API server audit policies |
| Auditor read-only access across namespaces | Need data-level encryption or secret management | External secrets management (Vault, AWS Secrets Manager) |

## Important Caveats

- RBAC permissions are additive-only -- you cannot write a "deny" rule. To revoke access, you must remove the granting RoleBinding/ClusterRoleBinding. [src1]
- On managed Kubernetes (GKE, EKS, AKS), the cloud provider may inject additional ClusterRoleBindings. Review these regularly and do not assume the only RBAC in your cluster is what you defined. [src3]
- The `system:masters` group is hardcoded in the Kubernetes API server and bypasses all RBAC checks. There is no way to restrict a user in this group through RBAC. [src2]
- Secret-based ServiceAccount tokens (pre-1.24) are long-lived and never expire. On clusters upgraded from older versions, audit for and remove legacy token secrets. [src1]
- Kubernetes RBAC does not support field-level access control -- you cannot grant access to only specific fields of a resource (e.g., allowing read of a Deployment's status but not its spec). [src1]

## Related Units
<!-- Generated from related_kos frontmatter -->

- [Kubernetes Deployment + Service + Ingress](/software/devops/k8s-deployment-service-ingress/2026)
- [Kubernetes CrashLoopBackOff Debugging](/software/debugging/kubernetes-crashloopbackoff/2026)
