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