Kubernetes IAM roles

The following Terraform file creates an IAM role for a Kubernetes ServiceAccount to use so that a workload resource is able to assume that IAM role via the ServiceAccount

variable "cluster_oidc_issuers" {
  description = "List of ODIC issuers of clusters which the application will be deployed into, this is needed for allowing the IAM role to be assumed by the cluster's workload resources"
  type = list(object({
    id = string,
    k8s_namespace = string,
    k8s_service_account = string,
    region = string,
  }))
}

locals {
  name_k8s = "iam_role_name"
}

data "aws_caller_identity" "current" {}

# ref https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/iam_role
resource "aws_iam_role" "k8s" {
  name               = local.name_k8s
  assume_role_policy = data.aws_iam_policy_document.allow_eks_to_assume_role.json
  inline_policy {
    name   = local.name_k8s
    policy = data.aws_iam_policy_document.main.json
  }
}

# ref https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document
data "aws_iam_policy_document" "allow_eks_to_assume_role" {
  dynamic "statement" {
    for_each = toset(var.cluster_oidc_issuers)
    content {
      actions = ["sts:AssumeRoleWithWebIdentity"]
      principals {
        type = "Federated"
        identifiers = [
          "arn:aws:iam::${data.aws_caller_identity.current.account_id}:oidc-provider/oidc.eks.${statement.value.region}.amazonaws.com/id/${statement.value.id}"
        ]
      }
      condition {
        test     = "StringEquals"
        variable = "oidc.eks.${statement.value.region}.amazonaws.com/id/${statement.value.id}:aud"
        values   = ["sts.amazonaws.com"]
      }
      condition {
        test     = "StringEquals"
        variable = "oidc.eks.${statement.value.region}.amazonaws.com/id/${statement.value.id}:sub"
        values   = [
          "system:serviceaccount:${statement.value.k8s_namespace}:${statement.value.k8s_service_account}",
        ]
      }
    }
  }
}

# ref https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/iam_policy_document
data "aws_iam_policy_document" "main" {
  statement {
    sid = "Placeholder"
    actions = [
      "sts:GetCallerIdentity",
    ]
    resources = [
      "*"
    ]
  }
}

output "iam_role_k8s" {
  description = "Details of the IAM role to bind to the application's ServiceAccount resource"
  value       = {
    arn = aws_iam_role.k8s.arn,
    assume_role_policy = jsondecode(aws_iam_role.k8s.assume_role_policy),
    inline_policy = [for inline_policy in aws_iam_role.k8s.inline_policy : jsondecode(inline_policy.policy)],
    name = aws_iam_role.k8s.name,
  }
}

Last updated