Panfactum LogoPanfactum
Infrastructure ModulesSubmodulesKuberneteskube_sa_auth_aws
kube_sa_auth_aws
Stable
Submodule
Source Code Link

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:

  1. The pod's service account has the eks.amazonaws.com/role-arn annotation set.
  2. 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:

  1. The role identified by AWS_ROLE_ARN has the correct permissions.
  2. 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:

  1. Ensure your region is set to your cluster's region.
  2. 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.