Reference Guide: Optimizing Backup Strategies for Red Hat OpenShift Virtualization

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

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

  • Kubernetes Cluster (You can setup locally using Kind)
  • kubectl

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.