The aws-auth ConfigMap in kube-system is the authoritative mapping between AWS IAM principals and Kubernetes RBAC for an Amazon EKS cluster. Because AWS provides no REST API for updating this object, Terraform workflows must rely on the Kubernetes provider and the specific patterns exposed by the terraform-aws-modules/eks/aws module. The result is a narrow set of correct approaches, several deprecated workarounds, and common failure modes when multiple providers or legacy modules compete for ownership of the same ConfigMap.
The lifecycle of aws-auth ownership
EKS creates aws-auth automatically when the control plane is provisioned. The object lives in namespace kube-system with name aws-auth and contains three keys that are merged by EKS: mapRoles, mapUsers and mapAccounts. These keys are YAML-encoded lists that control which IAM roles, users, or accounts can authenticate to the cluster.
Historically the community filled the gap with the aidanmelen/eks-auth/aws module. The module used the Kubernetes provider to patch the ConfigMap after the EKS module created the cluster. A typical declaration looked like:
hcl
module "eks" {
source = "terraform-aws-modules/eks/aws"
}
module "eks_auth" {
source = "aidanmelen/eks-auth/aws"
eks = module.eks
map_roles = [
{
rolearn = "arn:aws:iam::66666666666:role/role1"
username = "role1"
groups = ["system:masters"]
},
]
map_users = [
{
userarn = "arn:aws:iam::66666666666:user/user1"
username = "user1"
groups = ["system:masters"]
},
{
userarn = "arn:aws:iam::66666666666:user/user2"
username = "user2"
groups = ["system:masters"]
},
]
map_accounts = [
"777777777777",
"888888888888",
]
}
This pattern worked until the EKS module began to manage the ConfigMap natively. Terraform v18.20.0 of terraform-aws-modules/eks/aws brought back support for aws-auth ConfigMap management. The recommended migration path is explicit and state-sensitive:
- Remove the aidanmelen/eks-auth/aws declaration for your Terraform code
- Remove the aidanmelen/eks-auth/aws resources from Terraform state
- The aws-auth ConfigMap should still exist on the cluster but will no longer be managed by this module
- A plan should show that there are no infrastructure changes to the EKS cluster
- Upgrade the version of the EKS module:
version = ">= v18.20.0" - Configure terraform-aws-modules/eks/aws with manageawsauth_configmap = true
With manageawsauthconfigmap enabled, the module uses the new kubernetesconfigmapv1_data resource to patch aws-auth ConfigMap data, just like the v1.0.0 version of this module. The ConfigMap should now be managed by the EKS module. A plan and apply will show no drift once the state is cleaned.
Why the Kubernetes provider is required
Most Terraform modules interact solely with the cloud provider. The AWS App Runner module for example uses just the AWS provider. The AWS EKS module is an exception because AWS provides no REST APIs to update the aws-auth ConfigMap, so the kubectl provider must be used instead.
This architectural constraint means the provider block for Kubernetes must be configured with a live credential to the EKS endpoint. A common pattern is:
hcl
provider "kubernetes" {
host = data.aws_eks_cluster.eks.endpoint
cluster_ca_certificate = base64decode(data.aws_eks_cluster.eks.certificate_authority[0].data)
token = data.aws_eks_cluster_auth.eks.token
}
The kubeconfig alternative is also used in testing:
hcl
provider "kubernetes" {
config_path = "~/.kube/config"
config_context = "docker-desktop"
}
The token, host and CA certificate must be correct, otherwise the Kubernetes provider cannot authenticate and the ConfigMap resource will fail at plan time.
Native EKS module management
With manageawsauthconfigmap = true, the EKS module accepts awsauthroles, awsauthusers and awsauth_accounts. These are translated into the mapRoles, mapUsers and mapAccounts keys of the aws-auth ConfigMap.
Example configuration:
hcl
manage_aws_auth_configmap = true
aws_auth_roles = [
{
rolearn = "arn:aws:iam::66666666666:role/role1"
username = "role1"
groups = ["system:masters"]
},
]
aws_auth_users = []
aws_auth_accounts = []
The module creates two Kubernetes resources internally:
- kubernetesconfigmapv1.awsauth
- kubernetesconfigmapv1data.aws_auth
The httphttp.waitfor_cluster data source is used to wait for the control plane to be reachable before patching. The required provider versions are:
| Name | Version |
|---|---|
| terraform | >= 0.14.8 |
| http | >= 2.4.1 |
| kubernetes | >= 2.10.0 |
No modules are required beyond the EKS module itself.
Editing an existing ConfigMap with Terraform
A general Kubernetes ConfigMap can be created and updated in place with the kubernetesconfigmap resource. A test example demonstrates in-place updates:
hcl
resource "kubernetes_config_map" "example_cm" {
metadata {
name = "my-config"
}
data = {
api_host = "myhost:443"
db_host = "dbhost:5432"
}
}
After an initial apply, changing values triggers an in-place update:
~ resource "kubernetes_config_map" "example_cm" {
~ data = {
~ "api_host" = "myhost:443" -> "abcd"
~ "db_host" = "dbhost:5432" -> "1234567898765432"
}
The plan shows 0 to add, 1 to change, 0 to destroy, and apply completes after modifications.
For aws-auth specifically, users often attempt a direct Kubernetes resource:
hcl
resource "kubernetes_config_map" "example" {
count = 1
depends_on = []
metadata {
name = "aws-auth-test"
namespace = "kube-system"
labels = {}
}
data = {
mapRoles = yamlencode(local.test)
}
lifecycle {
create_before_destroy = false
ignore_changes = []
}
}
locals {
test = {
rolearn = "arn:aws:iam::xx:role/workers"
username = "system:node:{{EC2PrivateDNSName}}"
groups = [
"system:bootstrappers",
"system:nodes"
]
}
}
When extra ARNs are added, a second ConfigMap is created instead of editing the existing one. This occurs because the AWS provider documentation states that by default it manages the aws-auth ConfigMap for you. The Kubernetes provider cannot just go modifying that object when it is managed by the AWS provider. The options are to add labels to it or just manage it yourself, and managing it yourself would probably require rebuilding the cluster.
Common failure modes and anti-patterns
Adding IAM principals to aws-auth is critical for access. If the ARN of a user or role is not present in the access control list, authentication steps that depend on that principal will fail. Steps 1 through 3 of an access flow may succeed, but step 4 will fail as the ARN is not present in the access control list.
Creating a cluster with a dedicated IAM role is recommended by EKS Best Practices Guides - Security. The kubeconfig used to authenticate Terraform should reflect that role:
- name: arn:aws:eks:ap-northeast-1:9999999999:cluster/eks-example
user:
exec:
apiVersion: client.authentication.k8s.io/v1alpha1
args:
- --region
- ap-northeast-1
- eks
- get-token
- --cluster-name
- eks-example
command: aws
env: null
provideClusterInfo: false
If the cluster was created with one IAM principal and Terraform runs with a different role, the first Terraform run will fail because the Terraform role is not yet in aws-auth. The solution is to bootstrap aws-auth with the EKS module before attempting any Kubernetes provider operations.
Migration checklist
- Remove legacy eks-auth module declarations and state entries
- Ensure the aws-auth ConfigMap exists on the cluster after removal
- Upgrade terraform-aws-modules/eks/aws to >= v18.20.0
- Set manageawsauth_configmap = true
- Define awsauthroles, awsauthusers, awsauthaccounts in the EKS module
- Configure the Kubernetes provider with host, clustercacertificate and token from awsekscluster and awsekscluster_auth data sources
- Run plan to confirm no infrastructure changes to the EKS cluster
- Apply to bring aws-auth under module management
The migration is not reversible without state manipulation. Once the module owns the ConfigMap, manual kubectl edits will be overwritten on the next Terraform apply.
Conclusion
Managing aws-auth with Terraform is possible but constrained by the absence of an AWS API for the ConfigMap. The correct long term approach is native management via terraform-aws-modules/eks/aws with manageawsauthconfigmap enabled and the Kubernetes provider correctly configured for the EKS endpoint. Legacy community modules such as aidanmelen/eks-auth/aws should be removed and their state entries cleaned before adopting the native approach. Direct kubernetesconfigmap resources for aws-auth are fragile and conflict with module ownership, often resulting in duplicate ConfigMaps or drift. Proper bootstrapping of IAM roles used by Terraform itself, careful version pinning, and a clear migration path from legacy modules to v18.20.0 plus manageawsauthconfigmap = true are the key practices for reliable, repeatable EKS authentication management.