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 IAM role with assume role policy and required permissions

  1. Create an following assume role policy

    # 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
  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. Create the IAM policy with the required permissions.

    # 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
  4. 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

Create a service account in the namespace and annotate it with the IAM role ARN using TrueFoundry platform here with the following serviceaccount spec:

apiVersion: v1
kind: ServiceAccount
metadata:
  name: $APP_SA
  namespace: $APP_NS
  annotations:
    eks.amazonaws.com/role-arn: $IAM_ROLE_ARN

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/