Granting cross-account access to an Amazon EKS cluster means allowing users or services in a different AWS account to interact with your Kubernetes cluster. This is a common requirement for organizations with multiple AWS accounts for different teams, environments, or compliance reasons.

Let’s say you have an EKS cluster in AccountA and a CI/CD pipeline in AccountB that needs to deploy applications to it. Or maybe a security team in AccountC needs read-only access to audit cluster state.

Here’s how you can achieve this, focusing on the EKS control plane access and then the Kubernetes RBAC.

EKS Control Plane Access

The EKS control plane itself is an AWS resource. To grant access to it from another account, you need to configure IAM policies.

The core mechanism is an IAM role in the EKS cluster’s account (AccountA) that the principals (users or roles) in the other account (AccountB or AccountC) can assume.

  1. Create an IAM Role in the EKS Cluster Account (AccountA) This role will be trusted by AccountB and will have permissions to interact with the EKS control plane.

    • Create the Role: In AccountA, go to IAM -> Roles -> Create role.
    • Trusted entity type: Select "AWS account".
    • Another AWS account: Enter the AWS Account ID of AccountB.
    • Attach Permissions Policies:
      • AmazonEKSClusterPolicy: This managed policy grants broad permissions to interact with EKS clusters. For stricter security, you’d create a custom inline policy.
      • For read-only access, you might use a custom policy like this:
        {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Action": [
                        "eks:DescribeCluster",
                        "eks:ListClusters",
                        "eks:ListNodegroups",
                        "eks:DescribeNodegroup",
                        "eks:ListTagsForResource"
                    ],
                    "Resource": "*" // Or specify your cluster ARN for better security
                }
            ]
        }
        
    • Role Name: Give it a descriptive name, e.g., CrossAccountEKSAdminRole or CrossAccountEKSReadOnlyRole.
  2. Grant Assume Role Permission to Principals in the Other Account (AccountB) Now, in AccountB, you need to grant your users or roles permission to assume the role you just created in AccountA.

    • Create an IAM Policy in AccountB:
      {
          "Version": "2012-10-17",
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": "sts:AssumeRole",
                  "Resource": "arn:aws:iam::<AccountA_ID>:role/<CrossAccountEKSAdminRoleName>"
              }
          ]
      }
      
    • Attach this policy to the IAM users or roles in AccountB that need to access the EKS cluster.
  3. Assume the Role and Configure kubectl From AccountB, a user or an assumed role can now assume the CrossAccountEKSAdminRole in AccountA.

    • Using AWS CLI:

      aws sts assume-role --role-arn arn:aws:iam::<AccountA_ID>:role/<CrossAccountEKSAdminRoleName> --role-session-name "MyEKSClusterSession"
      

      This will output temporary credentials (AccessKeyId, SecretAccessKey, SessionToken). You can then set these as environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN) or use them to configure your ~/.aws/credentials file.

    • Using aws-iam-authenticator or aws eks update-kubeconfig: The aws eks update-kubeconfig command is the modern and recommended way. It handles the authentication flow for you. First, ensure your local AWS CLI is configured with credentials that have sts:AssumeRole permission to the role in AccountA. Then, run:

      aws eks update-kubeconfig --region <eks-cluster-region> --name <eks-cluster-name> --role-arn arn:aws:iam::<AccountA_ID>:role/<CrossAccountEKSAdminRoleName> --profile <your-profile-in-accountB>
      

      If you’re running this from within an EC2 instance or Lambda in AccountB with an IAM role attached that has sts:AssumeRole permission, you might not need --profile.

      This command updates your ~/.kube/config file, setting up a context that uses the aws eks update-kubeconfig helper to authenticate with the EKS control plane. When you run kubectl commands, it will automatically call sts:AssumeRole in the background.

Kubernetes RBAC Access

Granting access to the EKS control plane (AWS API) is only half the story. You also need to grant permissions within the Kubernetes cluster using Kubernetes Role-Based Access Control (RBAC).

The IAM role you assumed in AccountA needs to be mapped to a Kubernetes user or group.

  1. Identify the ARN of the Assumed Role When you assume the role, the ARN of the assumed role will look like: arn:aws:sts::<AccountA_ID>:assumed-role/<CrossAccountEKSAdminRoleName>/<SessionName>

  2. Create a aws-auth ConfigMap in the EKS Cluster (AccountA) The aws-auth ConfigMap in the kube-system namespace is how EKS maps IAM identities to Kubernetes RBAC. You need to edit this ConfigMap.

    • Get the current ConfigMap:

      kubectl get configmap aws-auth -n kube-system -o yaml
      
    • Add a mapping: In the mapRoles or mapUsers section, add an entry. For a role, it’s mapRoles.

      Example for granting cluster-admin privileges to the assumed role:

      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: aws-auth
        namespace: kube-system
      data:
        mapRoles: |
          - rolearn: arn:aws:sts::<AccountA_ID>:assumed-role/<CrossAccountEKSAdminRoleName>/<SessionName>
      
            username: system:node:{{EC2PrivateDNSName}} # This is for node roles, not for assumed roles. Use a distinct username.
      
            # For assumed roles, the username is derived from the ARN.
            # The EKS documentation recommends a format like:
            username: <AccountB_ID>-<CrossAccountEKSAdminRoleName> # Or a more specific identifier
            groups:
              - system:masters # This grants cluster-admin privileges
      

      Important: The username field is crucial. It must be unique and will be the identity kubectl uses. EKS usually derives a username from the IAM role ARN. You can explicitly define it.

      Example for granting specific namespace access: Let’s say you want the assumed role to have edit permissions in the my-app-ns namespace.

      First, create a Kubernetes ClusterRole (or use an existing one like edit) and a ClusterRoleBinding or RoleBinding.

      You’ll typically bind the Kubernetes Role to a Kubernetes User or Group. The username you defined in aws-auth becomes the Kubernetes User. You can also map IAM roles to Kubernetes Groups.

      Let’s map the assumed role ARN to a Kubernetes group called cross-account-developers.

      In aws-auth ConfigMap:

      data:
        mapRoles: |
          - rolearn: arn:aws:sts::<AccountA_ID>:assumed-role/<CrossAccountEKSAdminRoleName>/<SessionName>
            username: cross-account-developer-user # A unique username
            groups:
              - cross-account-developers # This IAM role is now part of this K8s group
      

      Create a ClusterRoleBinding in AccountA’s EKS cluster:

      apiVersion: rbac.authorization.k8s.io/v1
      kind: ClusterRoleBinding
      metadata:
        name: cross-account-dev-binding
      subjects:
        - kind: Group
          name: cross-account-developers # Matches the group in mapRoles
          apiGroup: rbac.authorization.k8s.io
      roleRef:
        kind: ClusterRole # Or Role for namespaced access
        name: edit # A built-in ClusterRole for editing resources
        apiGroup: rbac.authorization.k8s.io
      

      Now, any user or role in AccountB that assumes the CrossAccountEKSAdminRole and gets mapped to the cross-account-developers group will have edit permissions within the Kubernetes cluster.

The most surprising thing about this setup is how EKS bridges the AWS IAM world and the Kubernetes RBAC world through the aws-auth ConfigMap. It’s not just about IAM permissions; it’s about mapping those IAM identities to distinct Kubernetes users or groups that then get Kubernetes roles.

When you use aws eks update-kubeconfig, it automatically configures your kubectl context to use the aws-iam-authenticator (or its successor, the EKS credential helper) to fetch temporary AWS credentials and then use the IAM ARN to perform the sts:AssumeRole operation. The aws-auth ConfigMap in AccountA then dictates what Kubernetes permissions that assumed role gets.

The next hurdle you’ll likely face is managing secrets for cross-account access, especially if your CI/CD pipeline needs to pull images from a private ECR repository in a different account or needs credentials to access other AWS services.

Want structured learning?

Take the full Eks course →