How to add IAM User and Role to EKS Cluster
We are going to consider the action of adding users and roles to EKS Cluster. This may look like a similar task but there is a big difference. Unfortunately, Kubernetes does not support adding IAM groups. This means that whenever we want to add a new user, we must update Kubernetes configMap every time. Alternatively, we can create roles with different access to the cluster and let new user to use them (to assume those roles). It behaves like the groups in some way. It is a more flexible way of managing users and let us modify the K8s configMap only once.
To see how this work, we will first create a kubernetes roles and bind a user to that role. In this case we will create a role that allows only read access and map that role to a user. Then we will create another role with admin access, and we will create another user that assume that role.
Let’s start showing our working environment
We have a EKS cluster that was deployed with a bastion host which is accessed remotely over secure SSH by the EKS Cluster administrator. With this user we will do all the configurations. We also have two new users called w-eks-developer and w-eks-admin to whom we want to provide direct access to the EKS cluster without them, using the bastion host but “their” hypothetical local computer. We do this just for the sake of making the exercise more general and easier to follow. We could use only the bastion host session for all accesses, but we would have to go switching users contexts back and forth during the configuration.
Since the two new users are using the local computer they both are expected to have aws credentials configured in the .aws folder, for example for the user w-eks-developer it would look like: [w-eks-developer]
aws_access_key_id = AKIA6EK4KHDKS7SHHQOC
aws_secret_access_key = /z+ShSSQ0o3eq+UKA4gclpbEcbECuL7OcTOM9zeK
region= us-east-2
So now we can start configuring the access for the user “w-eks-developer”.
First we need to create a clusterRole and a clusterRoleBinding in the EKS cluster, for that we create the following document called rbac.yaml:
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: reader
rules:
- apiGroups: ["*"]
resources: ["deployments", "configmaps", "pods", "secrets", "services"]
verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: reader
subjects:
- kind: Group
name: reader
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: reader
apiGroup: rbac.authorization.k8s.io
The clusterRole allows users to “get”, “list” and “watch” the resources “deployments”, “configmaps”, “pods”, “secrets” and “services”. The clusterRoleBinding bids the role to the subject, which in this case is group reader.
Now we apply the configuration to the EKS cluster from the EKS Clouster Admin session (remote to bastion host)
Now we need to create the aws policy that will alow user to view nodes and workload across all the clusters. We will need to map IAM user to RBAC in Kubernetes.
In the aws console we create the following policy and¬¬ call it “w-eks-developer-policy”:{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"eks:DescribeNodegroup",
"eks:ListNodegroups",
"eks:DescribeCluster",
"eks:ListClusters",
"eks:AccessKubernetesApi",
"ssm:GetParameter",
"eks:ListUpdates",
"eks:ListFargateProfiles"
],
"Resource": "*"
}
]
}
Now we will create a IAM group to attach this policy instead of attaching directly to a user so later we can join other users to the group and make administration easier.
We create the group, call it w-eks-developers we attach the w-eks-developer-policy and we add the user w-eks-developer to it.
Now we need to modify the Kubernetes configmap for that we run the following command in the EKS Cluster Admin console:[willy@willy001-zu ~]$ kubectl edit -n kube-system configmap/aws-auth
And add an entry for the user as follow: mapUsers: |
- userarn: arn:aws:iam::971393087701:user/w-eks-developer
username: w-eks-developer
groups:
- reader
To verify that the developer user has read only access we use the w-eks-developer user from the local computer and there we first need to connect this user to the EKS Cluster which we do as shown below:
This worked first because we have in the local computer a aws credential for this user. And as result of this command a kubeconfig file is generated in the local computer. So now the user w-eks-developer in the local computer is connected to the EKS Clouster and we prove it with the following command:
We can now verify permission this user has with the command “can-I”.
Now we will work with the user w-eks-admin that is already created. We will create the role and map the role to Kubernetes. This user will be able to perform any action in the cluster.
We start creating the policy named w-eks-admin-policy {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"eks:*"
],
"Resource": "*"
},
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": "*",
"Condition": {
"StringEquals": {
"iam:PassedToService": "eks.amazonaws.com"
}
}
}
]
}
This policy will allow user to perform any action any EKS cluster. It also will allow to pass roles to eks service to perform action in your behalf. The next step is creating the w-eks-admin-role, and attaching to it the w-eks-admin-policy just created.
We can check the role we just created as show below
But any user in the account needs to establish trust with the role to effectively get access.
Now we need to establish a trust between the user and this role and in order to do that we crearte another aws policy that we call w-eks-assume-policy.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Resource": "arn:aws:iam::971393087701:role/w-eks-admin-role"
}
]
}
Now we attach this policy just created to the user w-eks-admin.
In the local machine in the file ~/.aws/credentials we have the following now:[w-eks-developer]
aws_access_key_id = AKIA6EK4KHDKS7SHQQOC
aws_secret_access_key = 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
region= us-east-2
[w-eks-admin]
aws_access_key_id = AKIA6EK4KHDK2QAKUJ7K
aws_secret_access_key = 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
region= us-east-2
now we can check if the user w-eks-admin can assume the role. Notice that we are running the command from the local computer and that for checking the e-eks-admin user we add its profile (“—profile w-eks-admin).
The screenshot shows that the user can assume the role.
Now, the last step is editing the Kubernetes configmap. This is done from the EKS Cluster admin console as we need administrator rights.[willy@willy001-g3 ~]$ kubectl edit -n kube-system configmap/aws-auth
We will add the following lines:mapRoles: |
- rolearn: arn:aws:iam::971393087701:role/w-eks-admin-role
username: w-eks-admin
groups:
- system:masters
Notice that “system:masters” imply administrator scope.
Now we need to create an additional aws profile for the role and put there the user that will be able to assume the role.
Notice that we called the profile w-eks-admin-role just for the sake of giving a unique name, we could called anything as long as it is not the same name the admin user has.
Let’s update the Kubernetes kubeconfig for the last time from the local computer session. In this case we use the profile we just created
Now we verify by running the kuebctl config.
We see above that context configure with the w-eks-admin-role profile. This means that the w-eks-admin credentials are going to be used. So now we can verify that the user w-eks-admin can have full access.
As we see the user w-eks-admin has access as EEKS Cloister admin.
So now we have the user w-eks-developer that can access the EKS Cluster and read information from it and the user w-eks-admin that can do cluster administration in the EKS Cluster.