Question: How do I use the IAM roles for service accounts (IRSA) feature with Amazon EKS to restrict access to an Amazon S3 bucket?

I want to restrict the access of an Amazon Simple Storage Service (Amazon S3) bucket at the pod level in Amazon Elastic Kubernetes Service (Amazon EKS). I also want to keep minimum privileges for my application with AWS Identity and Access Management (IAM) roles for service accounts (IRSA).

ResolutionImportant: Before you use IRSA with Amazon EKS, you must create an IAM OIDC provider for your cluster.Create an IAM policy and role1.    Create a JSON file called iam-policy.json.The following example policy restricts Amazon S3 and Amazon DynamoDB permissions. IAM users are allowed to access one S3 bucket and access a specific DynamoDB table.{    "Version": "2012-10-17",    "Statement": [        {            "Sid": "ListAndDescribe",            "Effect": "Allow",            "Action": [                "dynamodb:List*",                "dynamodb:Describe*"            ],            "Resource": "arn:aws:dynamodb:*:*:table/YOUR_TABLE"        },        {            "Effect": "Allow",            "Action": [                "s3:ListBucket"            ],            "Resource": "arn:aws:s3:::YOUR_BUCKET"        },        {            "Sid": "List",            "Effect": "Allow",            "Action": [                "s3:GetObject",                "s3:GetObjectVersion"            ],            "Resource": "arn:aws:s3:::YOUR_BUCKET/*"        }    ]}Note: Replace YOUR_TABLE with your table. Replace YOUR_NAMESPACE with your namespace.2.    Create an IAM policy called YOUR-IAM-POLICY.$ aws iam create-policy \    --policy-name YOUR-IAM-POLICY \    --policy-document file://iam-policy.jsonNote: Replace YOUR-IAM-POLICY with your policy name.3.    Use the IAM console to create an IAM role for your service account, and then annotate a service account with that IAM role. Or, use eksctl to create an IAM role for your service account. For example:$ eksctl create iamserviceaccount \  --name YOUR-SERVICEACCOUNT \  --namespace YOUR-NAMESPACE \  --cluster YOUR-CLUSTER \  --attach-policy-arn arn:aws:iam::1111122222:policy/YOUR-IAM-POLICY \  --approveNote: Replace 1111122222 your Amazon Resource Name (ARN). You can also create an IAM role for your service account using the IAM console.Create an Amazon EKS podIn the following steps, replace your own application with an aws-cli image. This allows you to check if your pod can assume the specified IAM role with the correct IAM permissions.1.    Create a YAML file called aws-cli-pod.yaml. apiVersion: v1kind: Podmetadata:  name: aws-cli  namespace: YOUR_NAMESPACEspec:  serviceAccountName: YOUR_SERVICEACCOUNT  containers:  - name: aws-cli    image: amazon/aws-cli:latest    command:      - sleep      - "3600"    imagePullPolicy: IfNotPresent  restartPolicy: AlwaysNote: Replace YOUR_NAMESPACE with your namespace. Replace SERVICE_ACCOUNT with your Kubernetes service account name. 2.    Create an Amazon EKS pod:$ kubectl apply -f ./aws-cli.yamlTest your Amazon EKS podConfirm that your pod uses the correct IAM role with limit actions for Amazon S3 and DynamoDB. In the following example, the pod can list only the S3 bucket (YOUR_BUCKET) and DynamoDB table (YOUR_TABLE).1.    Find the IAM role that's using the credentials:$ kubectl exec -it aws-cli -- aws sts get-caller-identityThe output will look similar to: {    "UserId": "AIDACKCEVSQ6C2EXAMPLE:botocore-session-1111122222",    "Account": "111122223333",    "Arn": "arn:aws:sts::111122223333:assumed-role/eksctl-EKS-LAB-addon-iamserviceaccount-defau-Role1-ASA1UEXAMPLE/botocore-session-1111122222"}If you specify a namespace, append the namespace argument (-n) to all kubectl commands. Replace YOUR_NAMESPACE with your namespace. $ kubectl -n YOUR_NAMESPACE exec -it aws-cli -- aws sts get-caller-identity2.    Verify that your pod has s3:ListBuckets permissions for your S3 bucket (YOUR_BUCKET):$ kubectl exec -it aws-cli -- aws s3 ls s3://YOUR_BUCKETNote: Replace YOUR_BUCKET with your S3 bucket.Output:2021-09-28 09:59:22        269 demo-test-file3.    Verify that your pod can't delete the S3 bucket ( YOUR_BUCKET):$ kubectl exec -it aws-cli -- aws s3 rm s3://YOUR_BUCKET/demo-test-fileNote: Replace YOUR_BUCKET with your S3 bucket.The command returns the following "Access Denied" error because the pod doesn't have s3:DeleteObject permissions:delete failed: s3://YOUR_BUCKET/demo-test-file An error occurred (AccessDenied) when calling the DeleteObject operation: Access Deniedcommand terminated with exit code 14.    Verify that your pod has dynamodb:List permissions for your DynamoDB table (YOUR_TABLE):$ kubectl exec -it aws-cli -- aws dynamodb describe-table --table-name YOUR_TABLENote: Replace YOUR_TABLE with your DynamoDB table.Output:{    "Table": {        "AttributeDefinitions": [            {                "AttributeName": "demo",                "AttributeType": "S"            }        ],        "TableName": "YOUR_TABLE",        "KeySchema": [            {                "AttributeName": "demo",                "KeyType": "HASH"            }        ],        "TableStatus": "ACTIVE",        "CreationDateTime": "2021-09-28T10:05:53.599000+00:00",        "ProvisionedThroughput": {            "NumberOfDecreasesToday": 0,            "ReadCapacityUnits": 5,            "WriteCapacityUnits": 5        },        "TableSizeBytes": 0,        "ItemCount": 0,        "TableArn": "arn:aws:dynamodb:eu-west-1:000000000000:table/YOUR_TABLE",        "TableId": "42bd1238-e042-4016-b6b2-77548939c101"    }}5.    Verify that your pod can't delete the DynamoDB table ( YOUR_TABLE):$ kubectl exec -it aws-cli -- aws dynamodb delete-table --table-name YOUR_TABLENote: Replace YOUR_TABLE with your DynamoDB table.The command returns the following "Access Denied" error because the pod doesn't have dynamodb:DeleteTable permissions:An error occurred (AccessDeniedException) when calling the DeleteTable operation: User: arn:aws:sts::1111122222:assumed-role/eksctl-EKS-LAB-addon-iamserviceaccount-defau-Role1-ASA1U7NRNSEC/botocore-session-1632822777 is not authorized to perform: dynamodb:DeleteTable on resource: arn:aws:dynamodb:eu-west-1: 1111122222:table/MyTablecommand terminated with exit code 254