Authenticate to AWS services using IAM service account

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

export CLUSTER_NAME=""
export ACCOUNT_ID=""
export AWS_REGION=""

Step 1 - Get the OIDC provider

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

OIDC_ISSUER_URL=$(aws eks describe-cluster --name $CLUSTER_NAME --query "cluster.identity.oidc.issuer" --output text | sed 's/https:\/\///')

Step 2 - Create service account name

# namespace
export APP_NS=""

# serviceaccount name
export APP_SA=""
  • Go to Workspaces tab from the left panel of the portal and create the workspace with same name as of your namespace $APP_NS
    • Click on + New Workspace. If you already have a workspace created click on the Edit section from the right side of the workspace card. You can skip the next step.
    • Select the cluster where you want to create the serviceaccount and enter the name of the workspace (namespace).

Step 3 - Create a IAM role

3(A) - Export the bucket name

We will create a role which has S3 permissions on the bucket S3_BUCKET

# enter your bucket name details
export S3_BUCKET=""

3(B) Create an IAM role

  1. Create an following assume role policy

    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
    
  2. Create an IAM role using this assume role policy

    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')
    
    

3(C) - Export the IAM policy

  1. Create the IAM policy with the required permissions.
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
  1. Create the policy
    aws iam create-policy \
        --policy-name "${CLUSTER_NAME}-s3-policy" \
        --policy-document file://aws-policy.json
    

3(D) - Attach the policy to IAM role

  1. Attach the policy to the IAM role
    aws iam attach-role-policy --role-name "$CLUSTER_NAME-s3-role" --policy-arn="arn:aws:iam::${ACCOUNT_ID}:policy/${CLUSTER_NAME}-s3-policy"
    

Step 4 - Annotate the serviceaccount with IAM role ARN

  • Head over to the Workspaces tab from the left panel from the TrueFoundry platform.
  • Click on the pencil icon to edit the workspace.
  • Scroll down the service account section and add the $IAM_ROLE_ARN place of Aws Iam Role Arn
  • Click on Update

Step 5 - Test

  1. Run a pod and test if you are able to perform operations on the AWS S3 bucket
    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
    
  2. Go inside the pod and execute the following command
    kubectl exec -it my-pod -- /bin/bash
    bash-4.2#
    
  3. Run the command
    aws s3 ls s3://$AWS_S3_BUCKET_NAME/