With the release of Kubernetes 1.8, role-based access control (RBAC) has been promoted from beta to general availability. CoreOS, through our participation in the Kubernetes SIG Auth group, played a significant role in getting RBAC implemented in upstream Kubernetes. With its graduation to general availability, the feature and its core APIs can be considered stable.
RBAC policies are powerful tools to limit authorization permissions within a cluster. There's been much discussion about how RBAC works in Kubernetes; for a brief overview, see the Kubernetes project blog post on the topic. But how, exactly, does an admin work with RBAC? For this post, we'll demonstrate how to setup RBAC with a service account and verify that the access controls are working. Note: All examples assume Kubernetes 1.8.
Central to RBAC is the concept of roles, which are essentially just collections of permissions. A "developer" role might grant one set of privileges, for example, while an "administrator" role grants another set.
Kubernetes's RBAC implementation includes both Roles and ClusterRoles. Roles are limited to a single namespace, while ClusterRoles can be applied to any namespace or cluster wide. This allows for finer control of privileges; for example, it makes it possible to assign a user (perhaps a developer) to just one or a handful of namespaces (
staging-project1), or to the entire cluster as an administrator.
The default ClusterRoles are a great place to start for a basic set of permissions. To view all the ClusterRoles, cluster wide:
$ kubectl get clusterroles NAME KIND RULES admin ClusterRole.v1.rbac.authorization.k8s.io 11 item(s) cluster-admin ClusterRole.v1.rbac.authorization.k8s.io 2 item(s) edit ClusterRole.v1.rbac.authorization.k8s.io 9 item(s) view ClusterRole.v1.rbac.authorization.k8s.io 7 item(s) … [truncated] …
Note that there are a number of system accounts and four default user-facing Roles. For Tectonic users, another way to view ClusterRoles and other RBAC objects is through the Tectonic Console:
Granting default view permissions on a namespace
To get a read-only view of a particular namespace, we can use the default ClusterRole named
view. By binding the
view ClusterRole to a user, and then impersonating that user, we will be able to test out their privileges.
To create the binding, we create an object aptly called a RoleBinding. To create the RoleBinding we pass a name, a Role or ClusterRole, a user, and optionally a namespace.
$ kubectl create namespace dev $ kubectl create rolebinding joe-view --clusterrole view --user joe --namespace dev # to view the rolebindings $ kubectl get rolebindings --namespace dev
We have created the RoleBinding, but how does an administrator verify the Roles for a user? For this, we'll use the
auth can-i command to impersonate users and test their accounts against the RBAC policies in place.
For example, to verify Joe’s access to pods in the dev namespace:
$ kubectl auth can-i get pods --namespace dev --as joe yes
Does Joe have access to nodes in the dev namespace?
$ kubectl auth can-i create deployments --namespace dev --as joe no
So far we've been working with user accounts, but our goal for this exercise is to create policies for service accounts. While user accounts are for humans, service accounts are used to manage privileges for processes. Typically they are used to generate credentials for automated systems, such as Jenkins or Travis. In the Kubernetes ecosystem, service accounts are created and then attached to pods to allow access to the Kubernetes API.
Service accounts require a Service Account object, a Role object, and a RoleBinding object.
Creating the service account
The following yaml file creates the service accounts
sa-read-deployments account will only be able to read deployments. The
sa-write-deployments account will be able to write.
$ kubectl create serviceaccount --namespace dev sa-read-deployments $ kubectl create serviceaccount --namespace dev sa-write-deployments
In practice, a service account is managed just like a regular user. We can impersonate these service accounts just like we do user accounts, but first we need to assign the Roles with a RoleBinding to the service accounts.
Assigning the RoleBinding
This RoleBinding example creates a two new RoleBindings:
rb-read-deployments. We attach the ServiceAccount and reference to each Role to create the binding:
rb-deployments.yml: --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: rb-read-deployments subjects: - kind: ServiceAccount name: sa-read-deployments roleRef: kind: ClusterRole name: view apiGroup: rbac.authorization.k8s.io --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: rb-write-deployments subjects: - kind: ServiceAccount name: sa-write-deployments roleRef: kind: ClusterRole name: edit apiGroup: rbac.authorization.k8s.io $ kubectl create -f rb-deployments.yml --namespace dev # to view the rolebindings $ kubectl get rolebindings --namespace dev
Now that we have the RoleBindings setup we can create a Deployment with a running application.
Creating the Deployments
To test the RBAC privileges for our new service accounts, first create the following
deployment.yml apiVersion: extensions/v1beta1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 1 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.13 ports: - containerPort: 80
Now let's see what we can do with it. First, let's try creating our Deployment using the
sa-read-deployments service account:
$ kubectl create -f deployment.yml --as system:serviceaccount:dev:sa-read-deployments --namespace dev Error from server (Forbidden): error when creating "deployment.yml": deployments.extensions is forbidden: User "system:serviceaccount:dev:sa-read-deployments" cannot create deployments.extensions in the namespace "dev".
The read-only service account is forbidden from completing the action, which is exactly what we want. Now let's try running the same command, only using the
$ kubectl create -f deployment.yml --as system:serviceaccount:dev:sa-write-deployments --namespace dev deployment "nginx-deployment" created
This time, the Deployment is created and the pod starts running:
$ kubectl get pod --namespace dev NAME READY STATUS RESTARTS AGE nginx-deployment-7d749c9b8b-cjpcp 1/1 Running 0 1h
Namespaces can also contain more than one service account, and each account can have its own distinct Roles, giving the administrator an extremely flexible and secure, policy-based method of granting and restricting access.
Extending RBAC in Tectonic
With the RBAC APIs moving to stable, enterprises can have increased confidence in the security mechanisms built into Kubernetes. CoreOS was an early adopter of RBAC, and it has been enabled in our Tectonic Kubernetes platform since version 1.4. Tectonic Identity further extends user management with authentication using LDAP and SAML.
If you'd like to see for yourself how Tectonic makes Kubernetes user management easy and seamless, the Tectonic Sandbox is an easy, pain-free way to set up a complete Tectonic test and experimentation environment on your local machine. Try it today!