Understanding Kubernetes RBAC: Key Concepts and Examples

Understanding Kubernetes RBAC: Key Concepts and Examples
kuberntes rbac

Kubernetes has emerged as a titan in the world of container orchestration. It simplifies the management, automation, scaling, and deployment of containerized applications. A fundamental piece of this puzzle is managing access controls or, in other words, who is allowed to do what within your Kubernetes cluster. This is where Kubernetes Role-Based Access Control (RBAC) enters the scene.

In this blog post, we'll demystify RBAC in Kubernetes, starting with the basics, walking through its critical components, including Roles, RoleBindings, ServiceAccounts, and the built-in "system" accounts and diving into real-world implementation examples and best practices. Let's get started!

What is Kubernetes RBAC?

Role-Based Access Control (RBAC) in Kubernetes is an authorization method that allows admins to configure who can access the API resources in your Kubernetes cluster and what operations they can perform. It uses the rbac.authorization.k8s.io API group to drive its functionality.

rbac.authorization.k8s.io API group

The rbac.authorization.k8s.io API group is a part of the Kubernetes API that underpins the functionality of Role-Based Access Control (RBAC). It provides a set of resources and operations that allow you to control who can access specific parts of your Kubernetes API and what actions they can perform.

Here are the key resources that are part of this API group:

  • Role: This resource defines a set of permissions within a specific namespace. The permissions specify what actions (verbs) are allowed on which resources.
  • ClusterRole: Similar to a Role, but it applies cluster-wide, across all namespaces.
  • RoleBinding: This resource grants the permissions defined in a Role to a set of users. It connects ("binds") a Role with a set of Subjects (users, groups, or service accounts).
  • ClusterRoleBinding: Similar to a RoleBinding, but it applies cluster-wide, granting the permissions defined in a ClusterRole to a set of Subjects.

These resources are integral to defining and implementing RBAC within a Kubernetes system, providing a flexible and powerful way to manage access to resources and operations within your clusters.

Each of these resources can be defined using YAML or JSON syntax, and then applied to your Kubernetes cluster using the kubectl apply command.

Essential Components of Kubernetes RBAC

RBAC in Kubernetes revolves around four main components: Roles, RoleBindings, ClusterRoles, and ClusterRoleBindings.

Roles

Roles are at the heart of Kubernetes RBAC. Each Role represents a specific set of permissions that determine the actions allowed on various resources within a dedicated namespace. Contrastingly, a ClusterRole expands its reach, transcending namespace boundaries to govern permissions across the entire cluster.

A Role contains rules that represent a set of permissions within a particular namespace. These permissions define what actions (verbs like get, list, create, update, delete) are allowed on which resources (like pods, services).

RoleBindings

A RoleBinding confines itself to a particular namespace and connects the defined Role to the appropriate entities within that namespace.

RoleBindings link the permissions defined in a Role with one or more users or groups. It essentially says, "this user has these permissions in this namespace."

ClusterRoles and ClusterRoleBindings

A ClusterRoleBinding does not confine itself to namespace limitations, instead, it applies to the whole cluster, making it a powerful tool for managing cluster-wide permissions.

ClusterRoles and ClusterRoleBindings are similar to Roles and RoleBindings, but they apply to the entire cluster instead of a specific namespace. They are useful when you want to grant permissions across your entire Kubernetes cluster.

A ClusterRole expands its reach beyond a Role, transcending namespace boundaries to govern permissions across the entire cluster.

ServiceAccounts

ServiceAccounts provide an identity for processes that run in a Pod. By default, applications will authenticate as the default ServiceAccount in the namespace where the pod resides.

In Kubernetes, a ServiceAccount acts as the identity for processes running within a Pod. When a Pod operates in a namespace, it can associate with a ServiceAccount to interact with the API server.

Built-in "system" accounts

Kubernetes also includes some built-in "system" accounts. These are typically prefixed with "system:" and are used by various components of the Kubernetes system itself.

These special accounts, such as the controller manager and scheduler, perform pivotal roles in maintaining and orchestrating operations within the Kubernetes system. Understanding these "system" accounts is crucial for grasping the complete picture of RBAC in Kubernetes.

Decoupling users and permission with RBAC roles

Decoupling users and permissions with RBAC (Role-Based Access Control) roles is a fundamental security principle that enhances the security and manageability of a system, including Kubernetes clusters.

This approach separates the definition of permissions (roles) from the specific identities (users, groups, or service accounts) that will be granted those permissions. Here's how decoupling users and permissions with RBAC roles provides significant benefits:

  1. Granular Control and Least Privilege: Decoupling users from permissions allows for fine-grained control over access rights. RBAC roles can be defined with specific permissions for individual resources and actions. Each user or service account can be granted access only to the resources required to perform their tasks, reducing the attack surface and enhancing overall security.
  2. Centralized Policy Management: Decoupling users from permissions enables centralized management of access control policies. Instead of managing permissions for each user individually, administrators can define and update RBAC roles that apply to specific roles or groups of users.
  3. Scalability and Maintainability: As a system grows and evolves, managing permissions on a per-user basis becomes impractical and error-prone. Decoupling users from permissions with RBAC roles allows organizations to scale efficiently. Adding new users or service accounts only requires associating them with existing roles, rather than creating custom permission sets for each user.
  4. Easy User Role Mapping: With decoupled roles, mapping users to different roles becomes straightforward. User-role assignments can be easily managed through RoleBindings, which define which users, groups, or service accounts have access to specific RBAC roles. This approach streamlines user management and simplifies onboarding and offboarding processes.
  5. Security Auditing and Compliance: Decoupled RBAC roles provide a clear and auditable record of who has access to what resources and actions. This level of accountability is essential for security auditing and ensuring compliance with regulations and internal policies.
  6. Flexibility and Reusability: Decoupling users from permissions encourages the creation of reusable RBAC roles. Role definitions can be designed to cater to specific functional roles or application requirements. These roles can then be applied to multiple users or service accounts across various namespaces, promoting consistency and reducing configuration duplication.
  7. Enhanced Collaboration and Isolation: In multi-tenant environments or projects with multiple teams, decoupled RBAC roles promote better collaboration and isolation. Each team can have its own set of RBAC roles with specific permissions, enabling teams to work independently without interfering with others' resources.
  8. Clear Separation of Concerns: Decoupling users from permissions aligns with the principle of separation of concerns in software design. It helps maintain a clear distinction between identity management (authentication) and authorization, allowing each aspect to be handled independently and effectively.

Decoupling users and permissions with RBAC roles is a key best practice in access control. It enhances security by enforcing the least privilege, simplifies policy management, and provides a scalable and flexible approach to access control in large and dynamic systems like Kubernetes clusters.

By adopting RBAC principles and decoupling users from permissions, organizations can significantly improve their security posture and maintain a manageable and efficient access control infrastructure.

Steps and example to create a Role

Step 1: Define the Role manifest file

Here's an example of a Role that allows reading pods in a specific namespace, in this case the default namespace.

pod-reader-role.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

To apply the role run this command.

kubectl apply -f pod-reader-role.yaml

Step 2: Create a RoleBinding

Once you have defined a Role, you can assign it to a user, group, or service account through a RoleBinding. Here's an example of a RoleBinding:

pod-reader-rolebinding.yaml

apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: user1
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Step 3: Apply the Role and RoleBinding

Apply the Role and RoleBinding using kubectl:

kubectl apply -f pod-reader-role.yaml
kubectl apply -f pod-reader-rolebinding.yaml

Step 4: Verify the Configuration

Verify the configuration using kubectl auth can-i:

kubectl auth can-i get pods --as=user1 -n default

If everything is set up correctly, this should return yes.

Steps and examples to create a ClusterRole

Creating a ClusterRole in Kubernetes involves defining the permissions that apply across all namespaces in your cluster. Here's how you can do it:

Step 1: Define a ClusterRole

Create a YAML file to define your ClusterRole. In this example, we're creating a ClusterRole named "pod-reader" that allows reading ("get", "watch", "list") pods across all namespaces.

pod-reader-clusterrole.yaml

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

Step 2: Apply the ClusterRole

Apply the ClusterRole using kubectl command:

kubectl apply -f pod-reader-clusterrole.yaml

Step 3: Verify the ClusterRole

Verify the creation of the ClusterRole using the kubectl get clusterrole command:

kubectl get clusterrole pod-reader

This will display the details of the "pod-reader" ClusterRole if it was created successfully.

A ClusterRole by itself does not grant access to any users. To grant access, you would need to create a ClusterRoleBinding and bind it to the desired users, groups, or service accounts.

Steps and examples to create a ClusterRolebinding

Step 1: Define a ClusterRoleBinding

Create a YAML file, pod-reader-binding.yaml, to define the ClusterRoleBinding. In this example, we're creating a ClusterRoleBinding named "pod-reader-binding" that binds the "pod-reader" ClusterRole to a user named "john@example.com".

pod-reader-binding.yaml

kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: pod-reader-binding
subjects:
- kind: User
  name: john@example.com
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Step 2: Apply the ClusterRoleBinding

Apply the ClusterRoleBinding using the kubectl command:

kubectl apply -f pod-reader-binding.yaml

Step 3: Verify the ClusterRoleBinding

Verify the creation of the ClusterRoleBinding using the command:

kubectl get clusterrolebinding pod-reader-binding

This will display the details of the "pod-reader-binding" ClusterRoleBinding if it was created successfully.

Now, the user "john@example.com" will have the permissions defined in the "pod-reader" ClusterRole across all namespaces in the cluster.

API discovery roles

API Discovery Roles in Kubernetes provide a way to manage access to specific API resources based on API groups and resources discovered in the cluster.

This feature allows administrators to grant permissions to users, groups, or service accounts for resources that may not have been explicitly defined in RBAC policies at the time of their creation.

In Kubernetes, different API groups expose various API resources. For example, the core API group ("" or "v1") exposes resources like pods, services, and namespaces, while other API groups like "apps" or "extensions" expose resources like deployments, replicasets, and ingresses.

When an API request is made to the Kubernetes API server, it goes through an authorization process to determine if the requester has the necessary permissions. API discovery roles come into play during this authorization process. If an API request targets a resource that is not explicitly defined in a Role or ClusterRole, the API server can perform API discovery to determine the API group and resource of the request.

API discovery roles are defined using the special API group rbac.authorization.k8s.io and the resource resourceattributes. Here's an example of an API discovery role:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: api-discovery-role
rules:
- apiGroups: ["*"] # Use "*" to match all API groups
  resources: ["pods", "services"] # Resources for which this role is applicable
  verbs: ["get", "list"] # Allowed actions on the specified resources

In this example, the ClusterRole named api-discovery-role grants permissions to "get" and "list" pods and services in any API group.

The * wildcard is used to match all API groups, making this role applicable to any resource with the specified names.

API discovery roles are particularly useful in scenarios where certain resources may be dynamically introduced to the cluster by controllers or custom resource definitions. Instead of constantly updating RBAC policies whenever new resources are added, API discovery roles allow you to grant permissions for these resources without explicitly specifying them in the RBAC configuration.

Conclusion

Kubernetes RBAC is a powerful tool that empowers organizations to maintain secure, scalable, and manageable container orchestration environments. By comprehending the key concepts, embracing RBAC principles, and judiciously configuring access control policies, administrators can ensure the integrity and security of their Kubernetes clusters, ultimately leading to the efficient and seamless deployment of containerized applications.