Once you’ve set up Kubernetes Cluster and provisioned your applications, next in line is giving permissions to developers and other employees. Usually these requests range from ssh access to logs and consoles.

It’s needless to say that giving complete kubectl access for everyone in your organization. We can use RBAC in Kubernetes to restrict access based on roles. We are using AWS IAM as the authorization provider in this tutorial.

What is RBAC

RBAC(Role-based access control) is exactly what the name suggests, it let’s give fine grained permissions to users/groups in Kubernetes. You can create Role objects in Kubernetes which is just like a permission set and attach it to a user or group.

You should note that Kubernetes doesn’t recognise User and Group as native objects, which means you can’t just create those like kubectl create user. You’ll have to use a third party or cloud solution(AWS IAM in this demo) to manage it.

Prerequisites

How do we do it ?

We have to set up 2 logical parts for this to work, we’ve to set up Authentication part to verify identity of users and Authorization for defining specific permissions based on role.

Authentication

We are installing and configuring aws-iam-authenticator in this step, there is a detailed installation guide in Github page, feel free to skip this if you want to check that out.

First we need to create a IAM role for KubernetesAdmin which will be attached to your AWS IAM profile. You can either create role named KubernetesAdmin through UI or use AWS cli to create one.

# get your account ID
ACCOUNT_ID=$(aws sts get-caller-identity --output text --query 'Account')

# define a role trust policy that opens the role to users in your account (limited by IAM policy)
POLICY=$(echo -n '{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":"arn:aws:iam::'; echo -n "$ACCOUNT_ID"; echo -n ':root"},"Action":"sts:AssumeRole","Condition":{}}]}')

# create a role named KubernetesAdmin (will print the new role's ARN)
aws iam create-role \
  --role-name KubernetesAdmin \
  --description "Kubernetes administrator role (for AWS IAM Authenticator for Kubernetes)." \
  --assume-role-policy-document "$POLICY" \
  --output text \
  --query 'Role.Arn'

aws-iam-authenticator consists of a ConfigMap and DaemonSet . ConfigMap is where we map IAM user account with username, DaemonSet is to be installed in all master nodes.

You can find both configurations from here. Apply above configurations before moving on to next steps.

Once both objects are created, now we need to setup aws-iam-authenticator in local machine. Download aws-iam-authencator binary based on your OS, give executable permission and copy to $PATH(Usually /usr/local/bin).

We need to update our local kubectl configuration to authenticate user everytime before issuing any kubectl command. Update your kubernetes config file(Usually ~/.kube/config) and add/update user section to use aws-iam-authentication.

users:
- name: kubernetes-admin
  user:
    exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      command: aws-iam-authenticator
      args:
        - "token"
        - "-i"
        - "CLUSTER_ID"
        - "-r"
        - "AWS_IAM_ROLE_ARN"

Replace CLUSTER_ID with clusterID you’ve provided while creating ConfigMap above, replace AWS_IAM_ROLE_ARN as well. Now your KubernetesAdmin is ready for action.

Authorization

In authorization, we’ll have to create 2 kinds of objects in Kubernetes to get our job done. First one is called Role and second one is RoleBinding.

Role is nothing but permission to access resources kubectl provides. RoleBinding is an object which links Role and User/Groups.

For example, You want to create a Group of users named quality-tester who can only read logs of pods.

We’ll start with creating role named QA

kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  namespace: staging # You can provide any arbitory namespace.
  name: pod-reader
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"] # You can target any other resources like deployments
  verbs: ["get", "watch", "list"]

You can see from above configuration, this role allows to perform any of “get”, “watch”, “list” actions to “pods”.

Next we need to bind this role with a group with RoleBinding,

kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: read-pods
  namespace: staging
subjects:
- kind: Group # We can also use User to bind role to Users directly.
  name: quality-tester
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
  apiGroup: rbac.authorization.k8s.io

Just like we read role, this RoleBinding binds pod-reader role with quality-tester group. Check out Kubernetes Docs for more role variations. Create both objects by applying above .yamls through kubectl.

We’ve successfully created Role and RoleBinding. Now any User in quality-tester group will be able to read logs.

Now let’s assume we’ve an employee named jeff.johns who work as a quality tester and he needs to read pod logs, we’ll see how we can add jeff to quality-tester group.

We need to update ConfigMap we created initially along with DaemonSet to include jeff,

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: kube-system
  name: aws-iam-authenticator
  labels:
    k8s-app: aws-iam-authenticator
data:
  config.yaml: |
    clusterID: some-cool-cluster.klastar.com
    server:
      mapUsers:
      - userARN: arn:aws:iam::000000000000:user/jeff.johns
        username: jeff.johns
        groups:
        - quality-tester

Once you’ve apply these change, jeff.jones will be really happy to checkout all the logs by himself.

Make sure you’ve setup AWS CLI, aws-iam-authenticator and kubernet configuration in jeff’s machine(Refer steps we’ve already done to setup our own mechine).

Thanks for taking time to read this, if you’ve had any issues while setting up, more than happy to help, suggestions are welcome.

Resources

meme