Karan Sharma

Ramblings on tech, cycling and finance

01 Nov 2019

Intro to RBAC in EKS

EKS uses a custom authenticator tool called “aws-iam-authenticator”. The basic idea is to make the auth flow in EKS easier by using the tools you already use in AWS.

eks-auth

To wrap your head around the flow, consider three separate entities:

  • A kubernetes resource (entire namespace, specific pods/configs etc)
  • An action (get, watch, list, create, delete etc)
  • An IAM role/user created on AWS

Your usecase might be to give an IAM role access to a Kubernetes namespace for example with certain restricted actions.

Since K8s is basically client-server communication with the API server, we must need to perform the following two things for every single API request which goes to the control plane:

  • Authentication

kubectl talks to the API server using the token generated by aws-iam-authenticator. The API server passes on this info to the AWS servers which validated if the originating call is coming from a valid IAM user or not. If not, the access is denied from K8s.

  • Authorization

Once the IAM user is validated, the IAM user needs to be mapped to a user to perform Authorization so K8s API server can know whether the action/resource requested for is to be allowed or not. This is where the aws-auth-cm.yml comes into the picture. It is basically a map of all IAM users with internal K8s groups or users created. The roles are assosciated to these users/groups so once the mapping is done, K8s API server can know what to do with the API request.

How does EKS know my IAM?

If you configured your KUBECONFIG correctly using aws eks update-kubeconfig then you’ll find the below lines in your config file. This basically runs a aws cli command to find your IAM user/role configured on your system to produce a token.

   exec:
      apiVersion: client.authentication.k8s.io/v1alpha1
      args:
      - token
      - -i
      - eks-zero-public
      command: aws-iam-authenticator

Show me the YAML already

  • To create a Role and RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: coolapp
  name: fullaccess
rules:
- apiGroups: [""]
  resources: ["*"]
  verbs: ["*"]
- apiGroups: ["apps"]
  resources: ["*"]
  verbs: ["*"]
- apiGroups: ["batch"]
  resources: ["*"]
  verbs: ["*"]
- apiGroups: ["extensions"]
  resources: ["*"]
  verbs: ["*"]
- apiGroups: ["autoscaling"]
  resources: ["*"]
  verbs: ["*"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: 10xdevs-fullaccess
  namespace: coolapp
subjects:
- kind: Group
  name: 10xdevs
  namespace: coolapp
roleRef:
  kind: Role
  name: fullaccess
  apiGroup: rbac.authorization.k8s.io

So, for all the normal folks who don’t grok YAML as fast as 10x devops engineers, I am basically creating a Role fullaccess with all permissions for a namespace coolapp (innovative, ikr). Then I am binding this Role to a Group called 10xdevs so that the group is allocated the role which has permissions. We will use this group 10xdevs to map our AWS user now.

  • To create the map of IAM Role/User ARN with the above Role

Edit your aws-auth-cm.yml and add the below stuff:

apiVersion: v1
kind: ConfigMap
metadata:
  name: aws-auth
  namespace: kube-system
data:
  mapRoles ... <skipping> ...

  mapUsers: |
    - userarn: arn:aws:iam::<account-id>:user/<user-name>
      username: 10xdevs-fullaccess # RoleBinding name created in previous step
      groups:
        - 10xdevs # Group name created in previous step

Verify it yourself

  • kubectl auth can-i create pods --all-namespaces: should fail

  • kubectl auth can-i create pods -n coolapp: should work

Fin!