Kubernetes role-based access control (RBAC) is a security mechanism that can differentiate between a robust, secure cluster and one vulnerable to internal threats and misconfigurations. At its core, RBAC determines who can do what, where, and when within a Kubernetes cluster. However, RBAC goes beyond simple authentication.
RBAC acts as a primary gatekeeper for all actions within a Kubernetes cluster, ensuring that users and services have only the permissions they need and nothing more. It provides fine-grained authorization policies that determine what actions users, groups, or service accounts can perform on which resources. This granularity is essential in multi-tenant clusters or in environments with strict compliance requirements.
Consider a scenario where your development team needs access to deploy applications but shouldn’t be able to view sensitive data in production namespaces. Or perhaps you’re integrating a third-party monitoring tool that requires read-only access across the cluster. Without proper RBAC configuration, you might find yourself granting overly broad permissions, violating the principle of least privilege and potentially exposing your cluster to unnecessary risks.
In this article, we explain what RBAC is, how it works, and how to implement advanced RBAC techniques. We also tackle common challenges in real-world scenarios and provide practical strategies for maintaining a secure Kubernetes environment.
Summary of key Kubernetes RBAC aspects
Aspect | Summary |
Core RBAC components | Roles and ClusterRoles define sets of permissions. RoleBindings and ClusterRoleBindings link these roles to subjects like users, groups, or service accounts. |
Basic RBAC implementation | Create roles and ClusterRoles to specify the allowed actions on resources. Use RoleBindings and ClusterRoleBindings to assign these permissions to specific subjects. |
Implications for backup/restore | Backup and restore operations require broad permissions, which can pose security risks. Backup tools often need complex RBAC configurations. Balancing comprehensive access with the least privilege principle is challenging. |
RBAC in OpenShift | OpenShift uses a more granular RBAC model than standard Kubernetes. It includes additional default roles and integrates with OpenShift’s project-based structure. |
Advanced RBAC implementation techniques | Utilize groups for streamlined permission management. Integrate Open Policy Agent (OPA) for automated policy enforcement. Connect RBAC with external identity providers for centralized access control. |
Understanding Kubernetes RBAC components
Kubernetes RBAC defines permissions through three main components: roles, bindings, and subjects. These components work together to control access to Kubernetes resources.
The Kubernetes API server validates requests using both authentication (who you are) and authorization (what you can do). When a request hits the API server, it first authenticates the user through configured authentication plugins (like client certificates, bearer tokens, or OpenID Connect) and then checks RBAC rules to determine if the authenticated user has sufficient permissions.
fig. Kubernetes API Access Control
Automated Kubernetes Data Protection & Intelligent Recovery
Perform secure application-centric backups of containers, VMs, helm & operators
Use pre-staged snapshots to instantly test, transform, and restore during recovery
Scale with fully automated policy-driven backup-and-restore workflows
Roles and ClusterRoles
Roles and ClusterRoles are Kubernetes objects that define sets of permissions.
A role defines permissions within a specific namespace, controlling access to resources like pods, services, or configmaps within that namespace’s boundaries.
Here’s a basic role example:
# Role for pod viewing in development namespace apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: development name: pod-viewer rules: - apiGroups: [""] resources: ["pods"] verbs: ["get", "list", "watch"]
ClusterRoles expand this scope to cluster-wide permissions, enabling access across all namespaces and to cluster-level resources such as nodes or persistent volumes:
# ClusterRole for monitoring across all namespaces apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: metrics-collector rules: - apiGroups: [""] resources: ["pods", "nodes"] verbs: ["get", "list"] - apiGroups: ["metrics.k8s.io"] resources: ["pods", "nodes"] verbs: ["get", "list"]
The Kubernetes API server evaluates these permissions during each request. For example, a role might grant read access to pods in the development namespace, while a ClusterRole could grant the ability to view pods across all namespaces.
RoleBindings and ClusterRoleBindings
RoleBindings and ClusterRoleBindings connect the defined permissions to actual users, groups, or service accounts.
A RoleBinding links a role to subjects within a single namespace. The Kubernetes API server uses RoleBindings to determine if a subject has permission to perform actions in that namespace.
Here’s a RoleBinding example:
# RoleBinding for development team apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: dev-pod-viewers namespace: development subjects: - kind: Group name: dev-team apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: pod-viewer apiGroup: rbac.authorization.k8s.io
ClusterRoleBindings serve a similar purpose but operate cluster-wide, granting permissions across all namespaces. For instance, a RoleBinding might give a developer read access to pods in the development namespace, while a ClusterRoleBinding could grant an administrator read access to pods across the entire cluster.
# ClusterRoleBinding for monitoring team apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: monitoring-team subjects: - kind: Group name: monitoring apiGroup: rbac.authorization.k8s.io roleRef: kind: ClusterRole name: metrics-collector apiGroup: rbac.authorization.k8s.io
Subjects: users, groups, and ServiceAccounts
Subjects in Kubernetes RBAC represent the entities that access the cluster resources:
- Users represent human users and are typically authenticated through X.509 certificates or external identity providers. The Kubernetes API server validates these credentials during authentication.
- Groups cluster multiple users together for easier permission management; for example, placing all developers in a developers group.
- ServiceAccounts are Kubernetes objects that provide identities for processes running in pods, enabling pod-to-API server authentication. When a pod starts, Kubernetes automatically mounts the ServiceAccount credentials, allowing the pod to interact with the API server according to its assigned permissions.
# ServiceAccount for an application apiVersion: v1 kind: ServiceAccount metadata: name: app-service namespace: development --- # RoleBinding for the ServiceAccount apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: app-service-binding namespace: development subjects: - kind: ServiceAccount name: app-service namespace: development roleRef: kind: Role name: pod-viewer apiGroup: rbac.authorization.k8s.io
This structured approach to access control enables you to implement precise permission schemes, ensuring that each entity has only the access it needs to perform its functions. The API server enforces these permissions by validating each request against the defined RBAC policies.
Watch this 1-min video to see how easily you can recover K8s, VMs, and containers
Implementing RBAC in Kubernetes
RBAC implementation in Kubernetes follows a layered security model. The Kubernetes API server processes each request through multiple stages: authentication, authorization, and admission control.
RBAC operates at the authorization layer. When a request arrives, the API server first authenticates the requester and then checks RBAC policies to authorize the action.
Creating and managing roles and ClusterRoles
Roles and ClusterRoles define permission sets through rules. Each rule specifies three key elements:
- apiGroups: The API groups containing the resource
- resources: The resource types being accessed
- verbs: The allowed operations on those resources
The Kubernetes API server evaluates these rules for each request. A single role can contain multiple rules, enabling fine-grained access control.
# Example of multiple rules in a Role apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: namespace: development name: deployment-manager rules: - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] - apiGroups: [""] resources: ["pods", "services"] verbs: ["get", "list", "watch"]
Assigning permissions with RoleBindings and ClusterRoleBindings
Bindings create the relationships between subjects and roles. The API server uses these bindings to determine access rights. A key concept is binding aggregation: Multiple bindings can grant permissions to the same subject, and their permissions are combined.
Binding evaluation follows specific rules:
- RoleBindings only grant permissions within their namespace.
- ClusterRoleBindings grant cluster-wide permissions.
- Permissions are additive—a subject gets all permissions from all applicable bindings.
# Example RoleBinding with multiple subjects apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: deployment-access namespace: development subjects: - kind: Group name: developers apiGroup: rbac.authorization.k8s.io - kind: ServiceAccount name: ci-pipeline roleRef: kind: Role name: deployment-manager apiGroup: rbac.authorization.k8s.io
Hands-on demo of RBAC implementation in a Kubernetes cluster
This demo walks through setting up RBAC for a typical development scenario where we establish role-based access control for development and operations teams in a Kubernetes cluster.
Pre-requisites
Create a new directory for our RBAC configuration files:
mkdir k8s-rbac-demo cd k8s-rbac-demo
Step 1: Initial setup
Create namespaces to logically separate development and operations resources:
kubectl create namespace dev kubectl create namespace ops
Step 2: Create service accounts
Create a file named service-accounts.yaml
:
# service-accounts.yaml apiVersion: v1 kind: ServiceAccount metadata: name: dev-sa namespace: dev --- apiVersion: v1 kind: ServiceAccount metadata: name: ops-sa namespace: ops
Learn about the features that power Trilio’s intelligent backup and restore
These service accounts will be used to assign specific permissions to development and operations teams.
Step 3: Define roles
Create a file named role-bindings.yaml
:
# roles.yaml # Developer Role - Namespace specific (unchanged) apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: developer namespace: dev rules: # Allow developers to manage deployments and services - apiGroups: ["", "apps"] resources: ["pods", "pods/log", "deployments", "services"] verbs: ["get", "list", "watch", "create", "update", "delete"] # Limited access to pod execution and configs - apiGroups: [""] resources: ["pods/exec", "configmaps"] verbs: ["create", "get"] --- # Operations Role - Modified for cluster-scoped resources apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: name: ops-admin rules: # Cluster-level read access for ops team - apiGroups: [""] resources: ["nodes"] verbs: ["get", "list", "watch"] # Namespace-scoped resources - apiGroups: [""] resources: ["namespaces", "pods", "services", "pods/log"] verbs: ["get", "list", "watch"] - apiGroups: ["apps"] resources: ["deployments", "daemonsets", "statefulsets"] verbs: ["get", "list", "watch"]
The developer role is namespace-scoped, while the ops-admin role has cluster-wide read access.
Step 4: Create role bindings
Create a file named role-bindings.yaml
:
# role-bindings.yaml # Developer RoleBinding apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: dev-binding namespace: dev subjects: - kind: ServiceAccount name: dev-sa namespace: dev roleRef: kind: Role name: developer apiGroup: rbac.authorization.k8s.io --- # Operations ClusterRoleBinding apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRoleBinding metadata: name: ops-binding subjects: - kind: ServiceAccount name: ops-sa namespace: ops roleRef: kind: ClusterRole name: ops-admin apiGroup: rbac.authorization.k8s.io
These bindings connect our service accounts to their respective roles.
Step 5: Create a test application
Create a file named test-app.yaml
:
# test-app.yaml apiVersion: apps/v1 kind: Deployment metadata: name: web-app namespace: dev spec: replicas: 2 selector: matchLabels: app: web template: metadata: labels: app: web spec: serviceAccountName: dev-sa containers: - name: nginx image: nginx:latest ports: - containerPort: 80
This web-app
deployment will run with the development team’s permissions.
Next, apply all configurations.
# Apply service accounts first kubectl apply -f service-accounts.yaml # Apply roles and role bindings kubectl apply -f roles.yaml kubectl apply -f role-bindings.yaml # Deploy test application kubectl apply -f test-app.yaml
Next, check that all resources were created correctly:
# Check service accounts kubectl get serviceaccounts -n dev kubectl get serviceaccounts -n ops # Verify roles and bindings kubectl get roles,rolebindings -n dev kubectl get clusterroles,clusterrolebindings | grep ops # Check test deployment kubectl get deployments -n dev
Step 6: Test Permissions
Test the permissions for both service accounts:
# Test developer permissions # Should have full access in dev namespace kubectl auth can-i list pods --as=system:serviceaccount:dev:dev-sa -n dev # Expected: yes kubectl auth can-i create deployments --as=system:serviceaccount:dev:dev-sa -n dev # Expected: yes # Should not have cluster-wide access kubectl auth can-i list nodes --as=system:serviceaccount:dev:dev-sa # Expected: no # Test operations permissions # Should have read access across cluster kubectl auth can-i list pods --as=system:serviceaccount:ops:ops-sa --all-namespaces # Expected: yes kubectl auth can-i list nodes --as=system:serviceaccount:ops:ops-sa # Expected: yes # Should not have write access kubectl auth can-i create deployments --as=system:serviceaccount:ops:ops-sa -n dev # Expected: no
Step 6: Cleanup
When you’re done testing, clean up all resources:
# Delete all resources created in the demo kubectl delete -f service-accounts.yaml kubectl delete -f roles.yaml kubectl delete -f role-bindings.yaml kubectl delete -f test-app.yaml # Delete Namespaces # Note: This will delete all resources in these namespaces kubectl delete namespace dev kubectl delete namespace ops
RBAC and Kubernetes backup and restore operations
Backup and restore operations in Kubernetes must integrate with existing access control mechanisms. While RBAC itself is a critical cluster resource requiring backup, the backup solution must operate within RBAC boundaries.
RBAC’s role in backup and restore
RBAC configurations define security policies, role definitions, and access bindings, all of which are essential components of cluster security. When implementing backup strategies, organizations need backup solutions that respect existing RBAC policies while having sufficient permissions to capture and restore the entire security context.
Solutions like Trilio, a Kubernetes-native data protection platform, demonstrate this integration by operating within RBAC boundaries for backup, recovery, and migration operations. Such platforms capture application data along with associated configurations, service accounts, and security contexts, ensuring that restored applications maintain their complete security posture.
Backup and security considerations
Key security aspects for Kubernetes backup operations:
- Backup operators need specific, limited RBAC permissions.
- Restore operations must maintain a security context.
- Backup data itself requires proper access controls.
- Backup and restore permissions should be regularly validated.
This approach ensures that backup operations maintain security while enabling effective disaster recovery.
RBAC in OpenShift
Key differences in RBAC implementation for OpenShift
OpenShift builds upon Kubernetes RBAC by providing additional security features and preconfigured roles. While OpenShift maintains compatibility with standard Kubernetes RBAC resources—roles, ClusterRoles, RoleBindings, and ClusterRoleBindings—it extends this model with its security context constraints (SCCs) and default cluster roles.
OpenShift’s preconfigured cluster roles include the following:
- admin: A project manager who can view and modify any resource in the project except quota
- basic-user: A user who can get basic information about projects and users
- cluster-admin: A super-user with full control to perform any action in any project, including quota management
- cluster-status: A user who can get basic cluster status information
- cluster-reader: A user who can get or view most objects but cannot modify them
- edit: A user who can modify most objects in a project but cannot view or modify roles or bindings
- self-provisioner: A user who can create their own projects
- view: A user who can see most objects in a project but cannot make modifications or view roles/bindings
Special considerations for OpenShift environments
As mentioned above, OpenShift introduces security context constraints that interact with RBAC to provide additional pod-level security controls. SCCs define conditions that a pod must run under. For example, SCCs in OpenShift do the following:
- Control permissions for pod execution
- Restrict access to host resources
- Regulate the capabilities available to containers
OpenShift introduces the concept of projects, which are enhanced Kubernetes namespaces with additional annotations and features. Projects in OpenShift differ from Kubernetes namespaces by adding resource quota management, built-in role-based access controls, and unique naming requirements.
Local role bindings in OpenShift automatically inherit cluster roles, allowing for simplified role management. For example, when you bind a user to the admin role in a project, they automatically receive all permissions defined in the admin role for that project scope. The service account system in OpenShift also differs by:
- Automatically creating project-specific service accounts
- Providing default SCCs for service accounts
- Integrating with the built-in OAuth server
Advanced RBAC Techniques
Using groups for efficient permission management
Groups in Kubernetes RBAC provide a way to manage permissions for multiple users collectively. Instead of managing individual RoleBindings, you can assign roles to groups, streamlining access management across the cluster. Groups can represent teams, departments, or functional roles within an organization.
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: dev-group-binding namespace: development subjects: - kind: Group name: developers apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: developer apiGroup: rbac.authorization.k8s.io
Using Open Policy Agent for policy automation
Open Policy Agent (OPA) extends Kubernetes RBAC by providing dynamic policy enforcement. OPA allows you to implement complex access control policies beyond basic RBAC capabilities. It evaluates requests against custom policies written in Rego, making decisions about resource access.
Key capabilities of OPA include:
- Fine-grained access control based on resource attributes
- Dynamic policy enforcement using contextual information
- Centralized policy management across clusters
- Audit logging for policy decisions
- Real-time policy updates without cluster reconfiguration
Integrating RBAC with external identity providers
External identity providers enable centralized authentication and authorization management. Here are some common integrations.
Active Directory:
- Syncs AD groups to Kubernetes RBAC groups
- Manages user authentication via OAuth2/OIDC
- Supports single sign-on across clusters
Keycloak:
- Provides identity and access management
- Maps Keycloak roles to Kubernetes RBAC
- Enables granular access control through realm management
LDAP / Active Directory:
- Authenticates users against enterprise directories
- Maps LDAP groups to Kubernetes RBAC groups
- Maintains consistent access control across infrastructure
This integration ensures consistent access management across the organization while leveraging existing identity infrastructure.
RBAC best practices for Kubernetes administrators
Implementing effective RBAC policies requires understanding both security requirements and operational requirements. Here are key practices based on real-world Kubernetes deployments.
Principle of least privilege: Granting the minimum necessary permissions
Granting minimum required permissions starts with understanding workload requirements. Create roles that precisely match application needs rather than using broad permissions. A practical approach is to begin with read-only access and incrementally add permissions as needed.
For example, a deployment team role might only need permissions to manage deployments and view logs, without access to sensitive resources like secrets or the ability to delete resources.
# Example: Custom role for application deployment kind: Role metadata: name: app-deployer rules: # Note: Excluding delete verb to prevent accidental removal - apiGroups: ["apps"] resources: ["deployments"] verbs: ["get", "list", "create", "update", "patch"] # Allows log access for debugging without pod manipulation - apiGroups: [""] resources: ["pods", "pods/log"] verbs: ["get", "list"]
The above role gives developers the ability to deploy and monitor applications, while preventing delete operations.
Namespace isolation: Using namespaces to segment access
By segmenting access through namespaces, you can maintain clear boundaries between different teams and environments. This prevents accidental or unauthorized access across different parts of the cluster.
Resource quotas complement RBAC by enforcing resource usage limits within these boundaries. For instance, development and production workloads should operate in separate namespaces with distinct RBAC policies.
# Development Team Namespace Setup apiVersion: v1 kind: Namespace metadata: name: team-a-dev # Labels help with resource organization and policy enforcement labels: environment: development team: team-a --- # Role binding limited to this namespace apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: team-a-access namespace: team-a-dev # Scope is limited to just this namespace subjects: - kind: Group name: team-a apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: developer apiGroup: rbac.authorization.k8s.io
The examples above create a dedicated namespace for Team A’s development work, with role bindings scoped only to their namespace.
Avoid wildcards due to the risks of using “*” in roles and bindings
Wildcard permissions (*) in RBAC rules create significant security risks by potentially granting unintended access. Instead, explicitly define required resources and verbs.
This granular approach might require more initial configuration but provides clear visibility into permissions and reduces security risks. Always list specific resources like pods, services, or deployments rather than using wildcards.
Policy as code: Managing RBAC configurations with version control
Managing RBAC configurations through version control provides accountability and consistency. Store RBAC manifests alongside application code, implements review processes for changes, and maintains documentation that explains the purpose of each role. This approach ensures that RBAC changes follow the same rigorous process as application deployments and maintains a clear audit trail of security policy evolution.
Use automation tools to leverage open-source tools
Tools like rbac-manager help maintain consistent security policies across clusters. These tools can automate role creation, binding management, and policy enforcement. They integrate with existing CI/CD pipelines and can automatically adjust permissions based on predefined rules, reducing manual intervention and potential errors.
Use service account tokens
Service account tokens are JSON Web Token (JWT) credentials used for pod authentication to the Kubernetes API server. These tokens can be configured with time-bound validity, audience restrictions, and specific binding constraints to enhance security.
# Example: Service Account for a monitoring tool apiVersion: v1 kind: ServiceAccount metadata: name: prometheus namespace: monitoring annotations: # Prevent automatic token mounting in pods kubernetes.io/enforce-mountable-secrets: "true" automountServiceAccountToken: false --- # Token with specific expiry and audience apiVersion: v1 kind: Secret metadata: name: prometheus-token annotations: kubernetes.io/service-account.name: prometheus # Token expires after a set time kubernetes.io/service-account.expiration: "2024-12-31T23:59:59Z" # Restrict token usage to specific services kubernetes.io/service-account.audience: ["monitoring.company.com"] type: kubernetes.io/service-account-token
This setup creates a service account with a time-bound token, specific audience restrictions, and disabled automatic mounting. This means the token is only valid for specified services and expires automatically, reducing security risks.
Provide a read-only view of objects
The Kubernetes API server handles read operations differently from write operations in terms of performance and security impact. Read-only roles leverage this distinction by restricting verbs to non-mutating operations, making them ideal for monitoring and auditing scenarios.
# Example: Read-only role for monitoring dashboard apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole metadata: # Provides access to key metrics without modification rights name: readonly-viewer rules: # Core resource monitoring - apiGroups: [""] resources: ["pods", "services", "nodes"] verbs: ["get", "list", "watch"] # Metrics access for monitoring tools - apiGroups: ["metrics.k8s.io"] resources: ["pods", "nodes"] verbs: ["get", "list", "watch"]
This role configuration allows monitoring tools or auditors to view cluster resources without modification rights. The permissions are explicitly limited to read operations (get, list, watch), ensuring that observers cannot make changes even accidentally.
Scheduling periodic reviews of RBAC policies
Periodic RBAC audits are key for maintaining security. Review access patterns, validate permissions against security baselines, and check for unused role bindings.
These audits should verify compliance with security policies and identify potential vulnerabilities. Maintain logs of RBAC changes and regularly review them for unintended modifications.
Learn about a lead telecom firm solved K8s backup and recovery with Trilio
Conclusion
Kubernetes RBAC is more than just a permission based control—it’s a critical security component that determines the security posture of your entire cluster. Throughout this article, we’ve explored how RBAC components work together, from basic roles and ClusterRoles to advanced implementations with external identity providers and policy engines. We also covered how OPA can enhance traditional RBAC with dynamic policy decisions, and how techniques like token-bound audiences and time-bound permissions add extra security layers.
While technical implementations can strengthen the Kubernetes security model considerably, it is worth noting that staying on top of new RBAC features and best practices requires ongoing effort. To create a truly secure and resilient Kubernetes environment, make it a priority to continuously refine your RBAC policies, stay informed about new features, and integrate RBAC with other security tools.
Like This Article?
Subscribe to our LinkedIn Newsletter to receive more educational content