Granting Pods AWS Privileges: A Step-by-Step Guide

In modern cloud-native applications, pods often need to interact with external services, such as AWS S3. To enable secure and efficient communication, we typically employ service accounts. This blog post will guide you through creating a service account and configuring your pod to leverage it for accessing AWS services.

Prerequisites:

  • An EKS cluster with nodes running in AWS.
  • AWS CLI installed and configured with sufficient permissions to create IAM roles and policies.

Understanding Service Accounts

A service account is a special type of account within a Kubernetes cluster that pods can use to authenticate with other services. It’s analogous to a user account, but instead of representing a human user, it means a pod or a group of pods.

Step 1: Enable IAM Roles for Service Accounts on EKS

  1. Associate IAM OIDC Provider with Your EKS Cluster
    First, verify if your EKS cluster has an IAM OIDC provider. This provider allows EKS to validate the IAM role for each pod using OpenID Connect (OIDC).
aws eks describe-cluster --name <your-cluster-name> --query "cluster.identity.oidc.issuer" --output text

If this returns an OIDC URL, your cluster is already associated with an OIDC provider. Otherwise, create one using:

aws eks update-cluster-config --name <your-cluster-name> --region <your-region> --resources-vpc-config endpointPublicAccess=true

Create the OIDC Identity Provider

eksctl utils associate-iam-oidc-provider --region <your-region> --cluster <your-cluster-name> --approve

Step 2: Create an IAM Policy for S3 Access

Next, create an IAM policy that grants necessary permissions to access S3. For example, you might need to list and read objects in an S3 bucket.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListBucket",
        "s3:GetObject"
      ],
      "Resource": [
        "arn:aws:s3:::<your-bucket-name>",
        "arn:aws:s3:::<your-bucket-name>/*"
      ]
    }
  ]
}

Save the above JSON to a file, say s3-access-policy.json.

Then create the policy:

aws iam create-policy --policy-name S3AccessPolicy --policy-document file://s3-access-policy.json

Note down the ARN of the created policy, as you’ll need it to attach to the IAM role.

Step 3: Create an IAM Role for the Kubernetes Service Account

Define a Trust Relationship
This allows the Kubernetes service account to assume the IAM role. Replace <eks-cluster-id> with the cluster’s OIDC issuer URL and <namespace> and <service-account-name> with the actual values you will use for the namespace and service account:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Federated": "arn:aws:iam::<account-id>:oidc-provider/<eks-cluster-id>"
      },
      "Action": "sts:AssumeRoleWithWebIdentity",
      "Condition": {
        "StringEquals": {
          "<eks-cluster-id>:sub": "system:serviceaccount:<namespace>:<service-account-name>"
        }
      }
    }
  ]
}

Create the Role

Create the IAM role with this trust policy, and attach the S3 policy to the role.

aws iam create-role --role-name EKS_S3_Access_Role --assume-role-policy-document file://trust-policy.json

Attach the S3 Policy

aws iam attach-role-policy --role-name EKS_S3_Access_Role --policy-arn <policy-arn>

Step 4: Create a Kubernetes Service Account and Link It to the IAM Role

Create the Kubernetes Service Account
Define the service account in your cluster’s namespace. This YAML configuration links the service account with the IAM role you created.

apiVersion: v1
kind: ServiceAccount
metadata:
  name: s3-access-sa
  namespace: default
  annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::<account-id>:role/EKS_S3_Access_Role

Apply the YAML configuration to create the service account:

kubectl apply -f service-account.yaml

Step 5: Update Pod Specification to Use the Service Account

Update your pod specification to use this new service account. Here’s an example pod configuration:

apiVersion: v1
kind: Pod
metadata:
  name: s3-access-pod
  namespace: default
spec:
  serviceAccountName: s3-access-sa
  containers:
  - name: app-container
    image: amazon/aws-cli
    command: ["sh", "-c", "aws s3 ls s3://<your-bucket-name>"]

Deploy the pod, and it should inherit the permissions from the IAM role associated with the service account.

Conclusion

With the service account and secret configured, you can now use the AWS SDK within your pod’s container to interact with AWS services. For example, to use the AWS SDK for Java, you would include the necessary dependencies in your application and configure the SDK to use the environment variables.

Best Practices:

  • Least Privilege Principle: Grant the service account only the necessary permissions to perform its tasks.
  • Secret Rotation: Regularly rotate your AWS credentials and update the Kubernetes secret.
  • Secure Communication: Use HTTPS to communicate with AWS services.
  • Error Handling: Implement robust error handling and logging to identify and troubleshoot issues.
  • Security Audits: Regularly review and audit your service account configurations and permissions.

By following these steps and best practices, you can securely configure your pods to access AWS services, ensuring efficient and reliable communication.

Atiqur Rahman

I am MD. Atiqur Rahman graduated from BUET and is an AWS-certified solutions architect. I have successfully achieved 6 certifications from AWS including Cloud Practitioner, Solutions Architect, SysOps Administrator, and Developer Associate. I have more than 8 years of working experience as a DevOps engineer designing complex SAAS applications.

Leave a Reply