DEV Community

Arseny Zinchenko
Arseny Zinchenko

Posted on • Originally published at on

Kubernetes: part 5 — RBAC authorization with a Role and RoleBinding example

The next task is to add a new user who will have access to check pods state and watch logs – any other operations must be prohibited.

AWS EKS uses AWS IAM for authentification in a Kubernetes cluster (check the Kubernetes: part 4 – AWS EKS authentification, aws-iam-authenticator and AWS IAM post for details), bot the authorization, e.g. to determine if a user has permissions for specific operations – Kubernetes uses its own Role-Based Authorization Control mechanism.

Previous parts of this series:

Let’s first take a quick overview of RBAC in general, and then create a new user with necessary permissions.

Kubernetes RBAC overview

Documentation – Authorization Overview and Using RBAC Authorization.

RBAC model in Kubernetes consists of the three main components:

  • Roles: defines permissions boundaries
  • Subjects: Users (human or an application), or user groups
  • RoleBingdings: specifies which Subjects have which Roles


A Role example named example-role which allows access to the mynamespace with get, watch, and list operations:

kind: Role
  namespace: mynamespace
  name: example-role
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

To obtain Kubernetes apiGroups one can use kubectl api-resources:

kubectl api-resources -o wide

NAME                              SHORTNAMES   APIGROUP                       NAMESPACED   KIND                             VERBS
pods                              po                                          true         Pod                              [create delete deletecollection get list patch update watch]

In the rules above we:

  1. apiGroups: [""] – set core API group
  2. resources: ["pods"] – which resources are allowed for access
  3. ["get", "watch", "list"] – which actions are allowed over the resources above

RBAC RoleBingding

To “map” those permissions to users we are using Kubernetes RoleBingding, which sets example-role in the mynamespace for the example-user user:

kind: RoleBinding
  name: example-rolebinding
  namespace: mynamespace
- kind: User
  name: example-user
  kind: Role
  name: example-role

Here we set:

  • subjects:
    • kind: User – an object type which will have access, in our case this is a regular user
    • name: example-user – a user’s name to set the permissions
  • roleRef:
    • kind: Role – what exactly will be attached to the user, in this case, it is the Role object type
    • name: example-role – and the role name as it was set in the name: example-role in the example above

Role vs ClusterRole

Alongside with the Role and ClusterRole which are set of rules to describe permissions – Kubernetes also has RoleBinding and ClusterRoleBinding objects.

The difference is that Role is used inside of a namespace, while ClusterRole is cluster-wide permission without a namespace boundaries, for example:

  • allow access to a cluster nodes
  • resources in all namespaces
  • allow access to endpoints like /healthz

A ClusterRole looks similar to a Role with the only difference that we have to set its kind as ClusterRole:

kind: ClusterRole
  name: example-clusterrole
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]

And a ClusterRoleBinding example:

kind: ClusterRoleBinding
  name: example-clusterrolebinding
- kind: User
  name: example-user
  kind: ClusterRole
  name: example-clusterrole

Keep in mind that once you’ll create a Binding you’ll not be able to edit its roleRef value – instead, you’ll have to delete a Binding and recreate and again

EKS Authentification and Authorization

In a short, the Authentification and Authorization process flow is the next:

  1. Authentification
    1. a client makes a request to a Kubernetes cluster passing the client’s token with a user’s ID
    2. Kubernetes using aws-iam-authenticator asks AWS IAM to check if such a user really exist and is he is really who he claims to be
  2. Authorization
    1. if the user passed the Authentification step – Kubernetes sens him over the RBAC mechanism with all user’s data and action requests
    2. Kubernetes looks for a RoleBinding which maps a user with a Role
    3. by a Rolу name, Kubernetes will check the user’s permissions
    4. and finally, Kubernreteds will allow or decline the user’s request

Next, we will:

  1. create an IAM user
  2. configure AWS CLI
  3. add an RBAC Role with the read-only permissions to pods
  4. add an RBAC RoleBinding to connect our user and the Role

IAM user

Let’s begin by creating an IAM user.

Add a new one with the only Programmatic Access:

Save its keys:

IAM policy

If a user will need to have access to the AWS API, for example, to get a list of clusters – need to add an IAM policy for him.

Go to the Policies – Add Policy:

    "Version": "2012-10-17",
    "Statement": [
            "Effect": "Allow",
            "Action": [
            "Resource": "*"

Here we are allowing only two API calls – eks:DescribeCluster and eks:ListClusters, in all regions for all EKS clusters.

Save it and attach to the user:

AWS CLI config

To configure kubectl, first we need to configure our AWS CLI, we can do it in a dedicated CLI profile, check the AWS: CLI named profiles post:

$ aws configure --profile eks-ro-user
AWS Access Key ID [None]: AKI***FYC
AWS Secret Access Key [None]: SzH***VGi
Default region name [None]: eu-north-1
Default output format [None]: json

Check the user ID you are using now:

$ aws --profile eks-ro-user sts get-caller-identity
  "UserId": "AID***XGK",
  "Account": "534***385",
  "Arn": "arn:aws:iam::534***385:user/eks-ro-user"

And check access to the EKS clusters (better to say access to the AWS API):

$ aws --profile eks-ro-user eks list-clusters --output text
CLUSTERS        eks-alb-testing-3
CLUSTERS        eks-alb-testing-2

Kubernetes RBAC – an example


Now, let’s create a real user and a Role.

We’ll begin from creating a Role to allow access to pods, their logs and to create a port-forwarding, and only for the get, list, create operations:

kind: Role
  name: eks-ro-role
- apiGroups: [""]
  resources: ["pods", "pods/log", "pods/portforward"]
  verbs: ["get", "list", "create"]

Apply it:

$ kubectl apply -f rbac-role.yml created

And check:

$ kubectl get roles -o yaml
apiVersion: v1
- apiVersion:
kind: Role
annotations: |
creationTimestamp: "2020-03-24T10:34:27Z"
name: eks-ro-role
namespace: default
resourceVersion: "681997"
selfLink: /apis/
uid: 09a78b6f-6dbb-11ea-827f-0a9eb3e1782e
- apiGroups:
- ""
- pods
- pods/log
- get
- list
kind: List
resourceVersion: ""
selfLink: ""


The next thing is to add a RoleBinding to map our username and the Role created above:

kind: RoleBinding
  name: eks-ro-role-binding
- kind: User
  name: eks-ro-user
  kind: Role
  name: eks-ro-role


$ kubectl apply -f rbac-rolebinding.yml created

aws-auth ConfigMap

As we are using AWS – need to update the aws-auth ConfigMap (see the AWS EKS aws-auth ConfigMap):

$ kubectl edit configmap aws-auth -n kube-system

Add the mapUsers and specify the user’s ARN, name and his group(s):

apiVersion: v1
  mapRoles: |
    - groups:
      - system:bootstrappers
      - system:nodes
      rolearn: arn:aws:iam::534***385:role/eksctl-eks-alb-testing-2-nodegrou-NodeInstanceRole-M6BS1WV48RLR
      username: system:node:{{EC2PrivateDNSName}}
  mapUsers: |
    - userarn: arn:aws:iam::534***385:user/eks-ro-user
      username: eks-ro-user
      groups: eks-ro-role

Save, and check it:

$ kubectl get pods --as eks-ro-user
NAME                     READY   STATUS    RESTARTS   AGE
nginx-7db9fccd9b-7d4rq   1/1     Running   0          58m

Try to get Worker Nodes – we did not gave access to this resource:

$ kubectl get nodes --as eks-ro-user
Error from server (Forbidden): nodes is forbidden: User "eks-ro-user" cannot list resource "nodes" in API group "" at the cluster scope


Now, let’s see a pod’s logs – run a port-forwarding to a testing pod with NGINX:

$ kubectl --as eks-ro-user port-forward nginx-7db9fccd9b-7d4rq 8000:80
Forwarding from -> 80
Forwarding from [::1]:8000 -> 80

Make a request to the pod:

$ curl -I localhost:8000
HTTP/1.1 200 OK

And check its logs:

$ kubectl --as eks-ro-user logs -f nginx-7db9fccd9b-7d4rq - - [25/Mar/2020:07:29:06 +0000] "GET / HTTP/1.1" 200 612 "-" "curl/7.69.1" "-"


Useful links

Similar posts

Top comments (1)

gadinaor profile image
Gadi Naor

Excellent post series on complex aspect of kubernetes. Check this RBAC tool