AWS Authentication via Kubernetes Service Account
Gives a Kubernetes service account in an EKS cluster access to an AWS IAM role through IRSA.
This allows our Kubernetes pods to utilize the AWS API without static credentials. The IRSA functionality is included in the latest version of all AWS SDKs so code should be able to pick up the IRSA credentials using the implicit AWS provider-chain resolver (i.e., code changes to utilize these credentials is generally not required).
See the IRSA docs for more information.
Usage
Simple Example
module "example_deployment" {
source = "github.com/Panfactum/stack.git//packages/infrastructure/kube_deployment?ref=edge.24-11-13" # pf-update
name = "example"
namespace = var.namespace
...
# pf-generate: pass_vars
pf_stack_version = var.pf_stack_version
pf_stack_commit = var.pf_stack_commit
environment = var.environment
region = var.region
pf_root_module = var.pf_root_module
is_local = var.is_local
extra_tags = var.extra_tags
# end-generate
}
data "aws_iam_policy_document" "example" {
# Replace with your IAM permissions
statement {
effect = "Allow"
actions = [
"ec2:DescribeAccountAttributes",
"ec2:DescribeAddresses",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeInternetGateways",
"ec2:DescribeVpcs",
"ec2:DescribeVpcPeeringConnections",
"ec2:DescribeSubnets",
"ec2:DescribeSecurityGroups",
"ec2:DescribeInstances",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeTags"
]
resources = ["*"]
}
}
module "aws_permissions" {
source = "github.com/Panfactum/stack.git//packages/infrastructure/kube_sa_auth_aws?ref=edge.24-11-13" # pf-update
service_account = module.example_deployment.service_account_name
service_account_namespace = var.namespace
eks_cluster_name = var.eks_cluster_name
iam_policy_json = data.aws_iam_policy_document.example.json
# pf-generate: pass_vars
pf_stack_version = var.pf_stack_version
pf_stack_commit = var.pf_stack_commit
environment = var.environment
region = var.region
pf_root_module = var.pf_root_module
is_local = var.is_local
extra_tags = var.extra_tags
# end-generate
}
IP Allowlists
To mitigate credential exfiltration attacks,
generated credentials may only be used by pods running inside the cluster's subnets. These
subnets are subnets with the kubernetes.io/cluster/<cluster_name>
tag set. This is automatically
configured by the aws_eks module.
If you need to allow additional entities to use these credentials, you must manually
add their CIDRs to the ip_allow_list
input.
Debugging
To verify that this module has created the correct permissions, you should check the following:
- The pod's service account has the
eks.amazonaws.com/role-arn
annotation set. - Each container have the following environment variables set (should be set automatically):
AWS_ROLE_ARN
AWS_WEB_IDENTITY_TOKEN_FILE
If both of those statements are true, that means that authentication via IRSA (OIDC) is working correctly; however, authorization might still be broken.
To verify, use the AWS console to check the following:
- The role identified by
AWS_ROLE_ARN
has the correct permissions. - The role's
*ip-block*
policy allows traffic from both your internal cluster IP address ranges (subnet CIDRs) and the public IP addresses assigned to the cluster's VPC's NAT nodes.
If you believe all of the above is true, you may finally verify by examining the AWS CloudTrail Event History:
- Ensure your region is set to your cluster's region.
- Examine the logs for any events with an error code. If you see any, resolve the indicated error.
Providers
The following providers are needed by this module:
-
aws (5.70.0)
-
kubectl (2.0.4)
-
kubernetes (2.27.0)
-
pf (0.0.3)
Required Inputs
The following input variables are required:
eks_cluster_name
Description: The name of the EKS cluster that contains the service account.
Type: string
iam_policy_json
Description: An IAM policy document in rendered JSON string form.
Type: string
service_account
Description: The name of the service account that should be able to assume the AWS permissions.
Type: string
service_account_namespace
Description: The namespace of the service account.
Type: string
Optional Inputs
The following input variables are optional (have default values):
annotate_service_account
Description: Whether or not to annotate the service account
Type: bool
Default: true
ip_allow_list
Description: A list of IPs that can use the service account token to authenticate with AWS API
Type: list(string)
Default: []
Outputs
The following outputs are exported:
policy_arn
Description: The ARN of the policy assigned to the role.
role_arn
Description: The ARN of the role created for the service account.
role_name
Description: The name of the role created for the service account.
service_account_annotations
Description: The annotations to apply to the service account
Maintainer Notes
No notes.