AWS EKS AuthN and AuthZ — part 1

Fei Yao
5 min readFeb 28, 2020

--

A simple guide to give users access to EKS using IAM, end-2-end walk through.

Photo by chris panas on Unsplash

AWS makes it so easy to spin up a EKS cluster. Now, you are wondering what are the steps to get users access using IAM? That’s what this post is about. I’ll be using AWS CLI v2.0.1 for all CMD.

  • In Part 1, we will talk about how to use IAM User for Authentication
  • In Part 2, we will talk about how to use Role for Authentication, especially you are operating it from Shared Service Account that you cannot create AWS User in the AWS Account that EKS operates in.
  • In Part 3, we will use Role only for cross account access.

First, you need to create an IAM user, and let’s call it eks-admin. You also need to create access key and save them locally into a AWS Profile called eks-admin.

aws iam create-user --user-name eks-admin
aws iam create-access-key --user-name eks-admin

Since I’m using AWS CLI v2.0.1 I’ll be using aws eks get-token and you don’t need aws-iam-authenticator no more. For the cautious readers here that I didn’t create Policies associated with this IAM User because there is no need to so for the purpose of the authentication to the EKS.

Next, you need to either modify the existing kube-config file or add a new one with the following sections:

contexts:
- context:
cluster: <CLUSTER-NAME>
user: eks-admin
name: eks-admin
- name: eks-admin
user:
exec:
apiVersion: client.authentication.k8s.io/v1alpha1
args:
- eks
- get-token
- --cluster-name
- <MY-EKS-CLUSTER-NAME>
command: aws
env:
- name: AWS_PROFILE
value: eks-admin

At this point, you are fully authenticated to use kubectl to access the EKS cluster. Wait, how come I get the following error?

> kubectl get all
error: You must be logged in to the server (Unauthorized)
...

Because you are authenticated doesn’t mean you are authorized, yet. In Kubernetes, it is managed by RBAC system. So, let’s fix it. In order to integrate with AWS IAM you need to modify configmap/aws-auth -n kube-system as the following:

apiVersion: v1
data:
mapRoles: |
- groups:
- system:bootstrappers
- system:nodes
rolearn: <...>
username: system:node:{{EC2PrivateDNSName}}
mapUsers: |
- userarn: arn:aws:iam::<AWS-ACCOUNT>:user/eks-admin
username: admin
groups:
- system:masters
kind: ConfigMap
...

Now, if you try it again you will see success!

> kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 3h1m

In conclusion, you need an IAM user and you don’t need any Policies nor Permissions attached to it. The sole purpose of it is to map this IAM user to Kubernetes using configmap/aws-auth. Then, you can use Kubernetes’ native RBAC for authorization. Attention: since IAM user only serves as the authentication it can be any valid AWS IAM User, which doesn’t have to be in the same account that created EKS.

Wait, what if we want a user to only access a specific namespace? Or, we want to customize this user to only access some specific Kubernetes’ API? Kubernetes’ Roles and Rolebindings come to rescue. Here is how.

First, we will create a regular Kubernetes’ user in IAM called eks-user as the following:

aws iam create-user --user-name eks-user
aws iam create-access-key --user-name eks-user

And, follow the prior example you can add this user into kube-config like bellow:

contexts:
- context:
cluster: <CLUSTER-NAME>
user: eks-user
name: eks-user
- name: eks-user
user:
exec:
apiVersion: client.authentication.k8s.io/v1alpha1
args:
- eks
- get-token
- --cluster-name
- <MY-EKS-CLUSTER-NAME>
command: aws
env:
- name: AWS_PROFILE
value: eks-user

Let’s add this user to configmap/aws-auth. Be careful about the groups part that it can be anything as long as it matches with the Rolebindings in Kubernetes for this user group. However, the prefix system: is reserved for Kubernetes system use, and that string has no format requirements.

apiVersion: v1
data:
mapRoles: |
- groups:
- system:bootstrappers
- system:nodes
rolearn: <...>
username: system:node:{{EC2PrivateDNSName}}
mapUsers: |
- userarn: arn:aws:iam::<AWS-ACCOUNT>:user/eks-admin
username: admin
groups:
- system:masters
- userarn: arn:aws:iam::<AWS-ACCOUNT>:user/eks-user
username: user
groups:
- company:eng
kind: ConfigMap
...

Now, it comes the important part to configure Roles and Rolebindings for RBAC. This allows eks-user to have the full access to namespace dev ONLY.

---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: dev-all-access
namespace: dev
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["get", "list", "watch", "create", "update", "delete"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: dev-all-access-binding
namespace: dev
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: dev-all-access
subjects:
- kind: Group
name: company:eng

Did it really work? You will see authorization failure in the namespace default.

> kubectl get all -n default
Error from server (Forbidden): pods is forbidden: User "user" cannot list resource "pods" in API group "" in the namespace "default"
Error from server (Forbidden): replicationcontrollers is forbidden: User "user" cannot list resource "replicationcontrollers" in API group "" in the namespace "default"
Error from server (Forbidden): services is forbidden: User "user" cannot list resource "services" in API group "" in the namespace "default"
Error from server (Forbidden): daemonsets.apps is forbidden: User "user" cannot list resource "daemonsets" in API group "apps" in the namespace "default"
Error from server (Forbidden): deployments.apps is forbidden: User "user" cannot list resource "deployments" in API group "apps" in the namespace "default"
Error from server (Forbidden): replicasets.apps is forbidden: User "user" cannot list resource "replicasets" in API group "apps" in the namespace "default"
Error from server (Forbidden): statefulsets.apps is forbidden: User "user" cannot list resource "statefulsets" in API group "apps" in the namespace "default"
Error from server (Forbidden): horizontalpodautoscalers.autoscaling is forbidden: User "user" cannot list resource "horizontalpodautoscalers" in API group "autoscaling" in the namespace "default"
Error from server (Forbidden): jobs.batch is forbidden: User "user" cannot list resource "jobs" in API group "batch" in the namespace "default"
Error from server (Forbidden): cronjobs.batch is forbidden: User "user" cannot list resource "cronjobs" in API group "batch" in the namespace "default"

How about dev namespace?

> kubectl get all -n dev
No resources found in dev namespace.

Success!

If you are interested in learning how to access EKS cluster using Role with IAM instead, please read on the part 2.

--

--