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.
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:
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.
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
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