Lab 1: RBAC - Users, Roles and RoleBindings

RBAC policies are vital for the correct management of your cluster, as they allow you to specify which types of actions are permitted depending on the user and their role in your organization. Examples include:

Secure your cluster by granting privileged operations (accessing secrets, for example) only to admin users. Force user authentication in your cluster. Limit resource creation (such as pods, persistent volumes, deployments) to specific namespaces. You can also use quotas to ensure that resource usage is limited and under control. Have a user only see resources in their authorized namespace. This allows you to isolate resources within your organization (for example, between departments).

RBAC Roles

Rbac Roles are composed of

  • RBAC API objects

    • Pods
    • PersistentVolumes
    • ConfigMaps
    • Deployments
    • Nodes
    • Secrets
    • Namespaces
  • Possible operations over these resources are:

    • create
    • get
    • delete
    • list
    • update
    • edit
    • watch
    • exec

RBAC Elements

  • Rules: A rule is a set of operations (verbs) that can be carried out on a group of resources which belong to different API Groups.

  • Roles and ClusterRoles: Both consist of rules. The difference between a Role and a ClusterRole is the scope: in a Role, the rules are applicable to a single namespace, whereas a ClusterRole is cluster-wide, so the rules are applicable to more than one namespace. ClusterRoles can define rules for cluster-scoped resources (such as nodes) as well. Both Roles and ClusterRoles are mapped as API Resources inside our cluster.

  • RoleBindings and ClusterRoleBindings: Just as the names imply, these bind subjects to roles (i.e. the operations a given user can perform). As for Roles and ClusterRoles, the difference lies in the scope: a RoleBinding will make the rules effective inside a namespace, whereas a ClusterRoleBinding will make the rules effective in all namespaces.

  • Subjects: These correspond to the entity that attempts an operation in the cluster. There are three types of subjects:

    • User Accounts: These are global, and meant for humans or processes living outside the cluster. There is no associated resource API Object in the Kubernetes cluster.
    • Service Accounts: This kind of account is namespaced and meant for intra-cluster processes running inside pods, which want to authenticate against the API.
    • Groups: This is used for referring to multiple accounts. There are some groups created by default such as cluster-admin (explained in later sections).

You can get more detailed information in the official Kubernetes documentation here.

Create user with limited namespace access

In this example, we will create a user with limited namespace access.

The following User Account will be created:

  • Username: demo
  • Group: demogroup

We will add the necessary RBAC policies so this user can fully manage deployments (i.e. use kubectl run command) only inside the rbactest namespace. At the end, we will test the policies to make sure they work as expected.

Create the rbactest namespace

  • Execute the kubectl create command to create the namespace (as the admin user):

    kubectl create namespace rbactest 
    

Create the user credentials

Kubernetes does not have API Objects for User Accounts. Of the available ways to manage authentication (see Kubernetes official documentation for a complete list), we will use OpenSSL certificates for their simplicity.

Create the certificate

  1. Create a private key for your user. In this example, we will name the file demo.key.

    Go to a temporary working directory in your terminal.

    mkdir rbacdemo
    cd rbacdemo
    
    openssl genrsa -out demo.key 2048 
           
    > Generating RSA private key, 2048 bit long modulus (2 primes)
    ...
    

    The private key file demo.key has been created:

    ls
           
    > demo.key
    
  2. Create a certificate sign request demo.csr using the private key you just created (demo.key in this example). Make sure you specify your username and group in the -subj section (CN is for the username and O for the group). As previously mentioned, we will use demo as the name and demogroup as the group

  openssl req -new -key demo.key -out demo.csr -subj "/CN=demo/O=demogroup" 
The certificate sign request `demo.csr` has been created:

```bash
ls
    
> demo.csr  demo.key
```
  1. We will use the Kubernetes cluster certificate authority (CA) for approving the request and generating the necessary certificate to access the cluster API.

Its location usually is /etc/kubernetes/pki/. But in our case (for Minikube), it would be ~/.minikube/.

![](../images/cloud.png) **Cloud/Standalone**

> If you are **NOT** using the training VM, you have to use your own certificates.
  1. Generate the final certificate demo.crt by approving the certificate sign request, demo.csr, you made earlier. In this example, the certificate will be valid for 500 days:

    openssl x509 -req -in demo.csr -CA ~/.minikube/ca.crt -CAkey ~/.minikube/ca.key -CAcreateserial -out demo.crt -days 500 
           
    > key -CAcreateserial -out demo.crt -days 500 
    > Signature ok
    > subject=CN = demo, O = demogroup
    > Getting CA Private Key
       
    

    ``

    The final certificate demo.crt has been created:

    ls
           
    > demo.crt  demo.csr  demo.key
    

    ``

  2. In a real world example you would now save both demo.crt and demo.key in a safe location.

Create the context

Add a new context with the new credentials for your Kubernetes cluster. This example is for a Minikube cluster but it should be similar for others:

  1. Set credentials

    kubectl config set-credentials demo --client-certificate=./demo.crt --client-key=./demo.key 
          
    > User "demo" set.
    

    ``

  2. Create context

    kubectl config set-context demo-context --cluster=minikube --namespace=rbactest --user=demo 
           
    > Context "demo-context" created.
    

    ``

    Cloud/Standalone

    If you are NOT using the training VM, you have to use your own cluster name instead of --cluster=minikube You should be able to get it with kubectl config current-context.

  3. Check configuration

    kubectl config view 
           
    

    ``

We can see that we now have a context demo-context and a user demo in our configuration that will be used to access the Kubernetes API via kubectl.

You should get an access denied error when using the kubectl CLI with this configuration file. This is expected as we have not defined any permitted operations for this user.

kubectl --context=demo-context get pods 
    
> No resources found.
> Error from server (Forbidden): pods is forbidden: User "demo" cannot list resource "pods" in API group "" in the namespace "rbactest"

Create the role for viewing deployments

We are creating the Rule that allows a user to execute several Read Only operations on Deployments, Pods and ReplicaSets, which belong to the core (expressed by “” in the yaml file), apps, and extensions API Groups:

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: deployment-viewer
  namespace: rbactest
rules:
- apiGroups: ["", "extensions", "apps"]
  resources: ["deployments", "replicasets", "pods"]
  verbs: ["get", "list"] # You can also use ["*"]

Create the Role in the cluster using:

kubectl create -f ~/training/rbac/deployment-viewer.yaml 

Bind the viewer role to the demo user

In this step we are creating the RuleBinding that binds the deployment-viewer Role to the User Account demo inside the rbactest namespace:

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: deployment-viewer-binding
  namespace: rbactest
subjects:
- kind: User
  name: demo
  apiGroup: ""
roleRef:
  kind: Role
  name: deployment-viewer
  apiGroup: ""

Create the Role in the cluster using:

kubectl create -f ~/training/rbac/deployment-viewer-binding.yaml 

Test the RBAC viewer rule

Now you should be able to execute the following command without any issues:

kubectl --context=demo-context get pods 

> No resources found.

No resources found. simply means that we don’t have any Pods deployed in this Namespace.

If you run the same command for the default namespace with the --namespace=default argument, it will fail, as the demo user does not have access to this namespace.

kubectl --context=demo-context get pods --namespace=default 

> No resources found.
> Error from server (Forbidden): pods is forbidden: User "demo" cannot list resource "pods" in API group "" in the namespace "default"

Also you still don’t have the rights to create or delete Deployments:

kubectl --context=demo-context run --image alpine alpine                                                                                                                                                                                                                                                                                              

> Error from server (Forbidden): deployments.apps is forbidden: User "demo" cannot create resource "deployments" in API group "apps" in the namespace "rbactest"

Now you have created a user with limited Read Only permissions in your cluster.

Create the role for managing deployments

We are creating the Rule that allows a user to execute several Read and Write operations on Deployments, Pods and ReplicaSets, which belong to the core (expressed by “” in the yaml file), apps, and extensions API Groups:

kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: deployment-manager
  namespace: rbactest
rules:
- apiGroups: ["", "extensions", "apps"]
  resources: ["deployments", "replicasets", "pods"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"] # You can also use ["*"]

Create the Role in the cluster using:

kubectl create -f ~/training/rbac/deployment-manager.yaml 

Bind the Manager role to the demo user

In this step we are creating the RuleBinding that binds the deployment-manager Role to the User Account demo inside the rbactest namespace:

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: deployment-manager-binding
  namespace: rbactest
subjects:
- kind: User
  name: demo
  apiGroup: ""
roleRef:
  kind: Role
  name: deployment-manager
  apiGroup: ""

Create the Role in the cluster using:

kubectl create -f ~/training/rbac/deployment-manager-binding.yaml 

Test the RBAC manager rule

Now you should be able to execute the following commands without any issues:

kubectl --context=demo-context run --image alpine alpine                                                                                                                                                                                                                                                                                              

> deployment.apps/alpine created

Check that the alpine Pod is running

kubectl --context=demo-context get pods 

> NAME                      READY     STATUS      RESTARTS   AGE
> alpine-7f866557df-dkmks   0/1       Completed   0          6s

However if you run the same command for the default namespace with the --namespace=default argument, it will still fail, as the demo user still does not have access to this namespace.

kubectl --context=demo-context get pods --namespace=default 

> No resources found.
> Error from server (Forbidden): pods is forbidden: User "demo" cannot list resource "pods" in API group "" in the namespace "default"

Now you have created a user with limited permissions in your cluster but with full Management rights for Deployments in the rbactest namespace.

Congratulations!!!

This concludes Lab 1 on RBAC and Roles/RoleBindings.