# How to attach IAM roles to Pods in AWS EKS Cluster

Hello World! 🌎 I hope everyone is doing well and learning new things.

![](https://i.giphy.com/media/zOvBKUUEERdNm/giphy.webp align="left")

When you are running an **EKS cluster**, you may have encountered some situations where you wanted to authorize your **PODs** to access AWS services. For Ex - Read/Write a file to/from S3, Trigger lambda functions, etc.

**So How do you do it?**

There are multiple ways to do it -

1. [**Kiam**](https://github.com/uswitch/kiam)
    
2. [**kube2iam**](https://github.com/jtblin/kube2iam)
    
3. Associate an IAM role with a **Kubernetes service account**
    

In this blog, we will be focusing on point **#3**

---

Out of Curiosity, Do you know what access your Pods get by default in an EKS Cluster?

I assume you don't know, so let's check :

First of all, Create a pod that has AWS CLI Installed so you can run the `aws sts get-caller-identity` command. For that apply below YAML file :

```bash
apiVersion: v1
kind: Pod
metadata:
  name: aws-cli
spec:
  containers:
    - image: amazon/aws-cli:latest
      name: aws-cli
      command: ["sleep", "36000"]
```

```bash
kubectl apply -f aws-cli-pod.yml
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1651669752760/o8kfaC4ey.png align="left")

Now, let's [exec](https://jamesdefabia.github.io/docs/user-guide/kubectl/kubectl_exec/) into that pod and run the aws cli command to know what IAM identity is currently logged in.

```bash
kubectl exec -it aws-cli -- aws sts get-caller-identity
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1651670161639/yBL9wHLvt.png align="left")

Oh Okay! Do you know what role this is?

Let's observe the `UserId`

According to **official AWS Documentation** [here](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_variables.html#policy-vars-infotouse) :

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1651671180241/I_1l4wuwJ.png align="left")

This means this is a role assigned to an EC2. Digging it further ([documentation reference](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html#identifiers-unique-ids)), I got to know that the first part in the `UserId` (**AROASPNKLQGHF35FHTBBB**:i-0f066b892b87973af) is a unique identifier for a role. **AROA** *represents that this particular identity is a role.*

---

Ok, So the next question, From where this role is getting assigned and being assumed?

**Answer** - When we create **EKS cluster**/**Node Groups**, either using CloudFormation, Terraform, or AWS Console, we have to assign a role to the EKS Worker Nodes, and as our Pods run on those nodes they inherit(or assume) those permissions of that role, which assigned to EKS Worker nodes.

AWS CloudFormation [Reference](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-eks-nodegroup.html#cfn-eks-nodegroup-noderole)

AWS Console Reference (check image below)

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1651670257625/Nsojd4wSq.png align="left")

Terraform [Reference](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/eks_node_group#node_role_arn)

You can check more about the purpose of the EKS Node Role [here](https://docs.aws.amazon.com/eks/latest/userguide/create-node-role.html).

---

Now as we saw earlier, by default, every pod will **assume** the IAM role which is assigned to the node, on which the pod is running.

Coming back to the point, I can see a way now using which any Pod can have required IAM access: I just need to **add those policies to the EKS Node IAM Role**, right?

But wait, it can work for you but NOT A GOOD PRACTICE!!! (All of your pods will be getting that access, even though they don't need that access. \[ ⚠️ Violation of the [Principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege)\])

🤔 Then what should we do now to assign pod a specific role and we won't have to mess with the IAM role of EKS Nodes?

## Service Account for the Rescue 😉

![](https://media2.giphy.com/media/6DJr4v3f6AXx6cfdiz/giphy.gif?cid=790b7611a04963b504d10c0fb59c2422f7793395063bcffd&rid=giphy.gif align="left")

### 1\. Create an OIDC provider for your EKS cluster

I am using `eksctl`([link](https://github.com/weaveworks/eksctl)) utility here for managing and performing operations on my EKS Cluster.

```bash
eksctl utils associate-iam-oidc-provider --cluster NAME_OF_YOUR_CLUSTER --approve
```

**Sidenote** - also check [this AWS article](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html) which also includes one more step to check for existing OIDC Issuer for your cluster.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1651719978275/cRuUKSipp.png align="left")

\**Open image in New Tab if not clear!*

### 2\. Create the role you want to attach to your Pod

#### 2.1 Create the JSON policy document

`IAM-Policy-for-listing-buckets.json`

```bash
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListAllMyBuckets"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}
```

#### 2.2 Create the IAM policy

Now fire up the AWS CLI Command to create your policy :

```bash
aws iam create-policy --policy-name s3-list-buckets-policy --policy-document file://IAM-Policy-for-listing-buckets.json
```

You will see something like below output :

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1651720212183/5mDMh1kes.png align="left")

Copy the ARN of this new policy here.

#### 2.3 Create an IAM role for a service account

let's run eksctl command as below and create IAM role and service account

```bash
eksctl create iamserviceaccount \
    --name NAME_OF_YOUR_SERVICE_ACCOUNT \
    --namespace NAME_OF_YOUR_K8S_NAMESPACE \
    --cluster NAME_OF_EKS_CLUSTER \
    --role-name NAME_OF_YOUR_IAM_ROLE \
    --attach-policy-arn ARN_OF_POLICY_YOU_JUST_CREATED \
    --approve \
    --override-existing-serviceaccounts
```

**Output**

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1651720955482/zQRCsz7--.png align="left")

This will create a CloudFormation Stack (which will create an IAM role) and our service account which we defined in the command args.

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1651721223007/Wm0tKIdaZ.png align="left")

*I encourage you all to go and check the above CF template, check how the ROLE was created, and most importantly: How the role's* ***AssumeRolePolicyDocument*** *is defined.*

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1651721655459/oXO2nhmQf.png align="left")

To check what happened in our EKS Cluster :

```bash
kubectl get serviceaccounts
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1651721169665/PHiEJjclb.png align="left")

```bash
kubectl get serviceaccounts s3-service-account -o yaml
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1651721201846/NYxduNkA_.png align="left")

### 3\. Associate the service account with your Pod so it can have access to your Role

Do you remember, at the start of our blog, we created an `aws-cli` pod, lets tweak it a bit and see what happens now :

delete the old pod

```bash
kubectl delete po aws-cli
```

Update the file `aws-cli-pod.yml` as follows :

```bash
apiVersion: v1
kind: Pod
metadata:
  name: aws-cli
spec:
  containers:
    - image: amazon/aws-cli:latest
      name: aws-cli
      command: ["sleep", "36000"]
  serviceAccountName: s3-service-account
```

```bash
kubectl apply -f aws-cli-pod.yml
```

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1651722093983/aYJ9Y7Bfh.png align="left")

Now check the current logged in IAM entity in our POD :

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1651722160215/-qPPEmghq.png align="left")

Wait, this time it is different, Also our new role is there and it is being assumed by our Pod.

Let's verify the access by listing out all S3 buckets :

![image.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1651722192346/wG5UIHY8I.png align="left")

Woohoo! That works!!!

![](https://media4.giphy.com/media/l0MYMPis1gRhiYNk4/giphy.gif align="left")

wait let me add more excitement

![](https://i.giphy.com/media/K3RxMSrERT8iI/giphy.webp align="left")

What do you think about this whole IAM & Service Account thing? Did you learn something new?

Let me know in the comments. Thanks for reading.
