RBAC Best Practices

A comprehensive guide to Kubernetes RBAC best practices covering roles, clusterroles, bindings, service accounts, least privilege, and practical implementation strategies for securing cluster access.

Roles Bindings Service Accounts Least Privilege
Understanding Kubernetes RBAC

Role-Based Access Control (RBAC) is the primary authorization mechanism in Kubernetes. It controls who can access the cluster API and what they can do with resources. RBAC is essential for security, compliance, and operational governance.

RBAC consists of four key components:

  • Roles/ClusterRoles: Define what permissions are granted
  • Subjects: Users, groups, or service accounts
  • Bindings: Connect subjects to roles
  • Service Accounts: Special identities for pods
Core RBAC Principle: Always apply the principle of least privilege. Grant only the minimum permissions necessary for a user, group, or service account to perform its required functions. This limits the blast radius of security incidents and reduces insider threats.
RBAC Components Overview

Role

Namespace-scoped permissions
A Role defines permissions within a specific namespace. It's used for granting access to resources in a single namespace. Example: "read pods in default namespace".
Namespace-specific permissions

ClusterRole

Cluster-scoped permissions
A ClusterRole grants permissions at the cluster level. It can be used for cluster-wide resources (nodes, persistent volumes) or can be bound to namespaced resources across all namespaces.
Cluster-wide permissions

RoleBinding

Bind Role to subjects
RoleBinding grants the permissions defined in a Role to a user, group, or service account within a specific namespace. It's used for namespace-specific authorization.
Namespace-specific authorization

ClusterRoleBinding

Bind ClusterRole to subjects
ClusterRoleBinding grants permissions from a ClusterRole to subjects across the entire cluster. Used for cluster-wide authorization and for binding clusterroles to namespaced resources.
Cluster-wide authorization

ServiceAccount

Identity for pods
ServiceAccounts are Kubernetes identities for pods. They are used to authenticate pods to the Kubernetes API and to external services. Each namespace has a default ServiceAccount.
Pod identity, API access

Subject

User, Group, or SA
Subjects are entities that are granted permissions. They can be individual users, groups (for managing multiple users), or ServiceAccounts. Bindings connect subjects to Roles/ClusterRoles.
Permission assignment
Roles and ClusterRoles: Defining Permissions
# Basic Role - Read-only pods in namespace apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: pod-reader namespace: default rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"] # Role with multiple resources apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: deployment-manager namespace: default rules: - apiGroups: ["apps"] resources: ["deployments", "statefulsets", "daemonsets"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # Role with subresources apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: pod-log-reader namespace: default rules: - apiGroups: [""] resources: ["pods/log"] verbs: ["get", "list"] # ClusterRole - Read-only cluster-wide apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: cluster-readonly rules: - apiGroups: ["*"] resources: ["*"] verbs: ["get", "list", "watch"] - nonResourceURLs: ["/healthz", "/readyz"] verbs: ["get"] # ClusterRole - Admin (full permissions) apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: cluster-admin rules: - apiGroups: ["*"] resources: ["*"] verbs: ["*"] - nonResourceURLs: ["*"] verbs: ["*"] # Role for managing secrets (limited) apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: secret-manager namespace: production rules: - apiGroups: [""] resources: ["secrets"] verbs: ["get", "list", "create", "update", "delete"] resourceNames: ["db-credentials", "tls-cert"] # Limit to specific secrets
Role Design Best Practices:
  • Use Roles (namespace-scoped) over ClusterRoles when possible
  • Be specific with resources and verbs
  • Use resourceNames to limit access to specific instances
  • Create reusable roles for common patterns (read-only, write, admin)
  • Avoid using "*" for apiGroups, resources, or verbs unless absolutely necessary
Bindings: Connecting Subjects to Roles

Bindings attach roles to subjects (users, groups, or service accounts). RoleBindings are namespace-scoped, while ClusterRoleBindings are cluster-scoped.

# RoleBinding - Bind Role to User apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: developer-access namespace: default subjects: - kind: User name: developer@example.com apiGroup: rbac.authorization.k8s.io - kind: User name: jane@example.com apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io # RoleBinding - Bind Role to Group apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: team-access namespace: default subjects: - kind: Group name: development-team apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: deployment-manager apiGroup: rbac.authorization.k8s.io # RoleBinding - Bind ClusterRole within Namespace apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: admin-within-namespace namespace: production subjects: - kind: User name: ops-user apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: cluster-admin # ClusterRole bound to specific namespace apiGroup: rbac.authorization.k8s.io # ClusterRoleBinding - Bind ClusterRole Cluster-wide apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: cluster-admin-binding subjects: - kind: User name: cluster-admin@example.com apiGroup: rbac.authorization.k8s.io - kind: Group name: platform-engineering apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: cluster-admin apiGroup: rbac.authorization.k8s.io # RoleBinding - Bind to ServiceAccount apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: app-reader namespace: default subjects: - kind: ServiceAccount name: my-app-sa namespace: default roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io
Binding Best Practices:
  • Use groups instead of individual users when possible (manage permissions at group level)
  • Prefer RoleBindings over ClusterRoleBindings for namespace-specific access
  • Create separate bindings for different teams or roles
  • Use namespaces to isolate permissions
  • Regularly audit bindings to remove unnecessary permissions
Service Accounts: Pod Identity

ServiceAccounts are Kubernetes identities for pods. They allow pods to authenticate to the Kubernetes API and external services. Each namespace has a default ServiceAccount, but you should create specific ServiceAccounts for different workloads.

# Create a ServiceAccount kubectl create serviceaccount my-app-sa -n default # ServiceAccount YAML apiVersion: v1 kind: ServiceAccount metadata: name: my-app-sa namespace: default labels: app: my-app secrets: - name: my-app-sa-token-xxxxx # Mounted token secret # Use ServiceAccount in Pod apiVersion: v1 kind: Pod metadata: name: my-app spec: serviceAccountName: my-app-sa # Use specific SA instead of default containers: - name: app image: myapp:latest # Automount ServiceAccount token (disable if not needed) apiVersion: v1 kind: ServiceAccount metadata: name: my-app-sa automountServiceAccountToken: false # Pod with no ServiceAccount token apiVersion: v1 kind: Pod metadata: name: no-sa-pod spec: automountServiceAccountToken: false # Don't mount token containers: - name: app image: myapp:latest # Grant ServiceAccount permissions apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: app-sa-binding namespace: default subjects: - kind: ServiceAccount name: my-app-sa namespace: default roleRef: kind: Role name: pod-reader apiGroup: rbac.authorization.k8s.io # Get ServiceAccount token (for external authentication) kubectl get secret my-app-sa-token-xxxxx -o jsonpath="{.data.token}" | base64 -d
ServiceAccount Best Practices:
  • Create specific ServiceAccounts for different applications
  • Bind ServiceAccounts to roles with least privilege
  • Disable automounting of tokens (automountServiceAccountToken: false) if not needed
  • Use separate ServiceAccounts for different environments (dev, staging, prod)
  • Rotate ServiceAccount tokens regularly
  • Use AWS IAM Roles for Service Accounts (IRSA) or GCP Workload Identity for cloud integration
Least Privilege Patterns

Implementing least privilege is the most critical RBAC best practice. Here are common patterns for different scenarios:

Developer Access

Read-only access to pods and logs in development namespaces. Limited ability to restart deployments.
Development teams

Operations Access

Full access to manage workloads in production, but limited access to secrets and nodes. Read-only for cluster-wide resources.
Site reliability engineers

Application Access

ServiceAccounts with minimal permissions. Read configmaps/secrets they need, no access to other resources.
Pod-to-API communication

Admin Access

Limited to specific administrators. Full cluster access with audit logging. Used only for emergency or infrastructure changes.
Cluster administrators
# Developer Role (read-only + logs) apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: developer namespace: dev rules: - apiGroups: [""] resources: ["pods", "pods/log"] verbs: ["get", "list", "watch"] - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", "list", "watch"] # Operations Role (manage workloads) apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: operator namespace: production rules: - apiGroups: ["*"] resources: ["deployments", "statefulsets", "daemonsets", "services", "configmaps"] verbs: ["*"] - apiGroups: [""] resources: ["secrets"] verbs: ["get", "list"] # Read-only for secrets # Application ServiceAccount apiVersion: v1 kind: ServiceAccount metadata: name: app-sa namespace: default automountServiceAccountToken: false # Disable API access # If API access needed, grant minimal apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: app-sa-binding namespace: default subjects: - kind: ServiceAccount name: app-sa namespace: default roleRef: kind: Role name: app-reader apiGroup: rbac.authorization.k8s.io
RBAC Auditing and Troubleshooting

Regular RBAC audits are essential for maintaining security. Here are commands and tools for auditing and troubleshooting RBAC.

# Check permissions for current user kubectl auth can-i get pods kubectl auth can-i create deployments --namespace production kubectl auth can-i delete secrets --namespace default # Check permissions for specific user kubectl auth can-i get pods --as=developer@example.com kubectl auth can-i create deployments --as=developer@example.com --namespace dev # Check permissions for ServiceAccount kubectl auth can-i get pods --as=system:serviceaccount:default:my-app-sa # View RBAC resources kubectl get roles --all-namespaces kubectl get clusterroles kubectl get rolebindings --all-namespaces kubectl get clusterrolebindings # Describe specific role kubectl describe role developer -n dev kubectl describe clusterrole cluster-admin # Check who has access to a specific resource kubectl get rolebindings -n default -o yaml | grep -A 5 subjects # Using kubectl-rbac-tool # Install: kubectl krew install rbac-tool kubectl rbac-tool who-can get pods -n default kubectl rbac-tool audit # Using rbac-view kubectl rbac-tool view --output dot | dot -Tpng > rbac.png # Check aggregated ClusterRoles kubectl get clusterroles -o yaml | grep -A 5 aggregationRule # Validate RBAC with OPA/Gatekeeper # Create constraint to enforce RBAC best practices
Audit Frequency: Perform RBAC audits at least quarterly. Review permissions after team changes, application changes, or security incidents. Use automated tools to detect over-permissioned roles and stale permissions.
RBAC Components Comparison
Component Scope Purpose Example Use
Role Namespace Define permissions within a namespace Read pods in 'default'
ClusterRole Cluster Define permissions cluster-wide Manage nodes, persistent volumes
RoleBinding Namespace Grant Role permissions to subjects in a namespace Give developer read access in 'dev'
ClusterRoleBinding Cluster Grant ClusterRole permissions to subjects cluster-wide Give admin full cluster access
ServiceAccount Namespace Identity for pods App authentication to API
User External Human identity Developer, operator login
Group External Manage multiple users Development team permissions
Frequently Asked Questions
What is the difference between Role and ClusterRole?
A Role grants permissions within a specific namespace. A ClusterRole grants permissions at the cluster level. However, a ClusterRole can also be used within a specific namespace when bound via a RoleBinding, providing flexibility.
How do I grant permissions to a specific user?
Create a Role or ClusterRole, then create a RoleBinding or ClusterRoleBinding that references the user as a subject. For example: subjects: - kind: User name: user@example.com.
What is a ServiceAccount and when should I use it?
A ServiceAccount is a Kubernetes identity for pods. Use it when your pod needs to authenticate to the Kubernetes API or external services. Create specific ServiceAccounts for different applications and bind them to roles with least privilege.
How do I check if a user has a specific permission?
Use kubectl auth can-i. For example: kubectl auth can-i get pods --as=developer@example.com. This checks if the user has permission to get pods.
What is the default ServiceAccount and why is it a security concern?
The default ServiceAccount is automatically created in each namespace and is used by pods that don't specify a ServiceAccount. It often has minimal permissions but may be over-permissioned. Always create specific ServiceAccounts for pods that need API access.
How do I aggregate multiple ClusterRoles?
Use the aggregationRule field in a ClusterRole. It allows you to combine multiple ClusterRoles into a single role. This is useful for creating composite roles like 'view' and 'edit' that aggregate other roles.
How do I audit RBAC permissions?
Use kubectl commands to list roles and bindings. Use tools like kubectl-rbac-tool or rbac-view for visualization. Regular audits should be scheduled to review and remove unnecessary permissions.
Can I use RBAC with external identity providers?
Yes! Kubernetes supports integration with external identity providers via OIDC. Users authenticate through the provider, and RBAC uses their identity for authorization. This allows integration with Azure AD, Google IAM, Okta, etc.
Previous: Kubernetes Security Next: OPA & Gatekeeper

RBAC is the foundation of Kubernetes security. Implement least privilege, audit regularly, and use ServiceAccounts for pod identities to maintain a secure cluster environment.