Least privilege of Kubernetes subjects
Kubernetes service accounts, users, and groups communicate with kube-apiserver to manage Kubernetes objects. With RBAC enabled, different users or service accounts may have different privileges to operate Kubernetes objects. For example, users in the system:master group have the cluster-admin role granted, meaning they can manage the entire Kubernetes cluster, while users in the system:kube-proxy group can only access the resources required by the kube-proxy component. First, let's briefly talk about what RBAC is.
Introduction to RBAC
As discussed earlier, RBAC is a model of regulating access to resources based on roles granted to users or groups. From version 1.6 onward, RBAC is enabled by default in Kubernetes. Before version 1.6, RBAC could be enabled by running the Application Programming Interface (API) server with the --authorization-mode=RBAC flag. RBAC eases the dynamic configuration of permission policies using the API server.
The core elements of RBAC include the following:
- Subject: Service accounts, users, or groups requesting access to the Kubernetes API.
- Resources: Kubernetes objects that need to be accessed by the subject.
- Verbs: Different types of access the subject needs on a resource—for example, create, update, list, delete.
Kubernetes RBAC defines the subjects and the type of access they have to different resources in the Kubernetes ecosystem.
Service accounts, users, and groups
Kubernetes supports three types of subject, as follows:
- Regular users: These users are created by cluster administrators. They do not have a corresponding object in the Kubernetes ecosystem. Cluster administrators usually create users by using the Lightweight Directory Access Protocol (LDAP), Active Directory (AD), or private keys.
- Service accounts: Pods authenticate to the kube-apiserver object using a service account. Service accounts are created using API calls. They are restricted to namespaces and have associated credentials stored as secrets. By default, pods authenticate as a default service account.
- Anonymous users: Any API request that is not associated with a regular or a service account is associated with an anonymous user.
Cluster administrators can create new service accounts to be associated with pods by running the following command:
$ kubectl create serviceaccount new_account
A new_account service account will be created in the default namespace. To ensure least privilege, cluster administrators should associate every Kubernetes resource with a service account with least privilege to operate.
Role
A role is a collection of permissions—for example, a role in namespace A can allow users to create pods in namespace A and list secrets in namespace A. In Kubernetes, there are no deny permissions. Thus, a role is an addition of a set of permissions.
A role is restricted to a namespace. On the other hand, a ClusterRole works at the cluster level. Users can create a ClusterRole that spans across the complete cluster. A ClusterRole can be used to mediate access to resources that span across a cluster, such as nodes, health checks, and namespaced objects, such as pods across multiple namespaces. Here is a simple example of a role definition:
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
namespace: default
name: role-1
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get"]
This simple rule allows the get operation to over-resource pods in the default namespace. This role can be created using kubectl by executing the following command:
$ kubectl apply -f role.yaml
A user can only create or modify a role if either one of the following is true:
- The user has all permissions contained in the role in the same scope (namespaced or cluster-wide).
- The user is associated with an escalated role in the given scope.
This prevents users from performing privilege escalation attacks by modifying user roles and permissions.
RoleBinding
A RoleBinding object is used to associate a role with subjects. Similar to ClusterRole, ClusterRoleBinding can grant a set of permissions to subjects across namespaces. Let's see a couple of examples:
- Create a RoleBinding object to associate a custom-clusterole cluster role to the demo-sa service account in the default namespace, like this:
kubectl create rolebinding new-rolebinding-sa \
--clusterrole=custom-clusterrole \
--serviceaccount=default:demo-sa
- Create a RoleBinding object to associate a custom-clusterrole cluster role to the group-1 group, like this:
kubectl create rolebinding new-rolebinding-group \
--clusterrole=custom-clusterrole \
--group=group-1 \
--namespace=namespace-1
The RoleBinding object links roles to subjects and makes roles reusable and easy to manage.
Kubernetes namespaces
A namespace is a common concept in computer science that provides a logical grouping for related resources. Namespaces are used to avoid name collisions; resources within the same namespace should have unique names, but resources across namespaces can share names. In the Linux ecosystem, namespaces allow the isolation of system resources.
In Kubernetes, namespaces allow a single cluster to be shared between teams and projects logically. With Kubernetes namespaces, the following applies:
- They allow different applications, teams, and users to work in the same cluster.
- They allow cluster administrators to use namespace resource quotas for the applications.
- They use RBAC policies to control access to specific resources within the namespaces. RoleBinding helps cluster administrators' control permissions granted to users within the namespace.
- They allow network segmentation with the network policy defined in the namespace. By default, all pods can communicate with each other across different namespaces.
By default, Kubernetes has three different namespaces. Run the following command to view them:
$ kubectl get namespace
NAME STATUS AGE
default Active 1d
kube-system Active 1d
kube-public Active 1d
The three namespaces are described as follows:
- default: A namespace for resources that are not part of any other namespace.
- kube-system: A namespace for objects created by Kubernetes such as kube-apiserver, kube-scheduler, controller-manager, and coredns.
- kube-public: Resources within this namespace are accessible to all. By default, nothing will be created in this namespace.
Let's take a look at how to create a namespace.
Creating a namespace
A new namespace in Kubernetes can be created by using the following command:
$ kubectl create namespace test
Once a new namespace is created, objects can be assigned to a namespace by using the namespace property, as follows:
$ kubectl apply --namespace=test -f pod.yaml
Objects within the namespace can similarly be accessed by using the namespace property, as follows:
$ kubectl get pods --namespace=test
In Kubernetes, not all objects are namespaced. Lower-level objects such as Nodes and persistentVolumes span across namespaces.
Wrapping up least privilege for Kubernetes subjects
By now, you should be familiar with the concepts of ClusterRole/Role, ClusterRoleBinding/RoleBinding, service accounts, and namespaces. In order to implement least privilege for Kubernetes subjects, you may ask yourself the following questions before you create a Role or RoleBinding object in Kubernetes:
- Does the subject need privileges for a namespace or across namespaces?
This is important because once the subject has cluster-level privileges it may be able to exercise the privileges across all namespaces.
- Should the privileges be granted to a user, group, or service account?
When you grant a role to a group, it means all the users in the group will automatically get the privileges from the newly granted role. Be sure you understand the impact before you grant a role to a group. Next, a user in Kubernetes is for humans, while a service account is for microservices in pods. Be sure you know what the Kubernetes user's responsibility is and assign privileges accordingly. Also, note that some microservices do not need any privilege at all as they don't interact with kube-apiserver or any Kubernetes objects directly.
- What are the resources that the subjects need to access?
When creating a role, if you don't specify the resource name or do set * in the resourceNames field, it means access is granted to all the resources of the resource type. If you know which resource name the subject is going to access, do specify the resource name when creating a role.
Kubernetes subjects interact with Kubernetes objects with the granted privileges. Understanding the actual tasks your Kubernetes subjects perform will help you grant privileges properly.