> ## Documentation Index
> Fetch the complete documentation index at: https://www.truefoundry.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Authenticate To AWS Services Using IAM Service Account

> Connect your TrueFoundry applications to AWS services from EKS using IAM roles and ServiceAccounts.

Connecting applications to AWS services from inside an Amazon Elastic Kubernetes Service (EKS) cluster is streamlined through native integration. Leveraging Kubernetes-native constructs like ServiceAccounts and IAM roles for pods, applications can securely access various AWS services using AWS SDKs. This enhances scalability and flexibility while maintaining robust security protocols.

Below document is an example of connecting to S3 from inside of EKS cluster.

## Pre-requisites

<CodeGroup>
  ```bash Shell lines theme={"dark"}
  export CLUSTER_NAME=""
  export ACCOUNT_ID=""
  export AWS_REGION=""
  ```
</CodeGroup>

## Step 1 - Get the OIDC provider

Get the OIDC issuer URL and check if the OIDC provider exists

<CodeGroup>
  ```bash Shell lines theme={"dark"}
  OIDC_ISSUER_URL=$(aws eks describe-cluster --name $CLUSTER_NAME --query "cluster.identity.oidc.issuer" --output text | sed 's/https:\/\///')
  ```
</CodeGroup>

## Step 2 - Create IAM role with assume role policy and required permissions

1. Create an following assume role policy

   <CodeGroup>
     ```bash Shell lines theme={"dark"}
     # enter your namespace and serviceaccount details
     export APP_NS=""
     export APP_SA=""

     cat > assume-role-policy.json <<EOF
     {
       "Version": "2012-10-17",
       "Statement": [
         {
           "Effect": "Allow",
           "Principal": {
             "Federated": "arn:aws:iam::${ACCOUNT_ID}:oidc-provider/${OIDC_ISSUER_URL}"
           },
           "Action": "sts:AssumeRoleWithWebIdentity",
           "Condition": {
             "StringEquals": {
               "${OIDC_ISSUER_URL}:aud": "sts.amazonaws.com",
               "${OIDC_ISSUER_URL}:sub": "system:serviceaccount:${APP_NS}:${APP_SA}"
             }
           }
         }
       ]
     }
     EOF
     ```
   </CodeGroup>

2. Create an IAM role using this assume role policy

   <CodeGroup>
     ```bash Shell lines theme={"dark"}
     IAM_ROLE_ARN=$(aws iam create-role --role-name access-to-s3-role --assume-role-policy-document file://assume-role-policy.json --output text --query 'Role.Arn')
     ```
   </CodeGroup>

3. Create the IAM policy with the required permissions.

   <CodeGroup>
     ```bash Shell lines theme={"dark"}
     # enter your bucket name details
     export S3_BUCKET=""

     cat > aws-policy.json <<EOF
     {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": "s3:*",
                  "Resource": [
                    "arn:aws:s3:::$S3_BUCKET",
                    "arn:aws:s3:::$S3_BUCKET/*"
                  ]
              }
          ]
     }
     EOF

     aws iam create-policy \
         --policy-name "${CLUSTER_NAME}-s3-policy" \
         --policy-document file://aws-policy.json
     ```
   </CodeGroup>

4. Attach the policy to the IAM role

   <CodeGroup>
     ```bash Shell lines theme={"dark"}
     aws iam attach-role-policy --role-name "$CLUSTER_NAME-s3-role" --policy-arn="arn:aws:iam::${ACCOUNT_ID}:policy/${CLUSTER_NAME}-s3-policy"
     ```
   </CodeGroup>

## Step 4 - Annotate the serviceaccount with IAM role ARN

Create a service account in the namespace and annotate it with the IAM role ARN using TrueFoundry platform [here](https://docs.truefoundry.com/docs/create-custom-k8s-objects) with the following serviceaccount spec:

<CodeGroup>
  ```bash Shell lines theme={"dark"}
  apiVersion: v1
  kind: ServiceAccount
  metadata:
    name: $APP_SA
    namespace: $APP_NS
    annotations:
      eks.amazonaws.com/role-arn: $IAM_ROLE_ARN
  ```
</CodeGroup>

## Step 5 - Test

1. Run a pod and test if you are able to perform operations on the AWS S3 bucket

   <CodeGroup>
     ```powershell Shell lines theme={"dark"}
     kubectl apply -f -<<EOF
     apiVersion: v1
     kind: Pod
     metadata:
       name: my-pod
     spec:
       containers:
         - name: aws-cli-container
           image: amazon/aws-cli
           env:
             - name: AWS_S3_BUCKET_NAME
               value: "${S3_BUCKET}"
           command: ["/bin/bash"]
           args: ["-c", "sleep 3600"]
       serviceAccountName: demo
     EOF
     ```
   </CodeGroup>

2. Go inside the pod and execute the following command

   <CodeGroup>
     ```shell Shell lines theme={"dark"}
     kubectl exec -it my-pod -- /bin/bash
     bash-4.2#
     ```
   </CodeGroup>

3. Run the command

   <CodeGroup>
     ```bash Shell lines theme={"dark"}
     aws s3 ls s3://$AWS_S3_BUCKET_NAME/
     ```
   </CodeGroup>
