From f34f18d382b27eaa13d56e98f89ee51be580d937 Mon Sep 17 00:00:00 2001 From: Aleksandr Cupacenko Date: Wed, 11 Dec 2024 17:40:36 +0200 Subject: [PATCH] add eks pod identity support add conditional creation of IAM role based on variable update README feat(iam)!: update iam policy to be compatible with the latest release --- README.md | 13 +++++--- examples/basic/README.md | 4 +-- examples/basic/main.tf | 8 ++--- iam.tf | 71 +++++++++++++++++++++++++++------------- values.tf | 2 +- variables.tf | 28 +++++++++++----- 6 files changed, 83 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 6a99e21..cb1fd3b 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Create helm release resource and deploy it as argo application (set `enabled = t ## AWS IAM resources -To disable of creation IRSA role and IRSA policy, set `irsa_role_create = false` and `irsa_policy_enabled = false`, respectively +To disable of creation IAM role and IAM policy, set `iam_role_create = false` and `iam_policy_enabled = false`, respectively ## Examples @@ -93,6 +93,8 @@ No modules. | [argo\_project](#input\_argo\_project) | ArgoCD Application project | `string` | `"default"` | no | | [argo\_spec](#input\_argo\_spec) | ArgoCD Application spec configuration. Override or create additional spec parameters | `any` | `{}` | no | | [argo\_sync\_policy](#input\_argo\_sync\_policy) | ArgoCD syncPolicy manifest parameter | `any` | `{}` | no | +| [enable\_irsa](#input\_enable\_irsa) | Determines whether to enable support for IAM role for service accounts | `bool` | `true` | no | +| [enable\_pod\_identity](#input\_enable\_pod\_identity) | Determines whether to enable support for EKS pod identity | `bool` | `false` | no | | [enabled](#input\_enabled) | Variable indicating whether deployment is enabled | `bool` | `true` | no | | [helm\_atomic](#input\_helm\_atomic) | If set, installation process purges chart on fail. The wait flag will be set automatically if atomic is used | `bool` | `false` | no | | [helm\_chart\_name](#input\_helm\_chart\_name) | Helm chart name to be installed | `string` | `"aws-load-balancer-controller"` | no | @@ -104,6 +106,7 @@ No modules. | [helm\_devel](#input\_helm\_devel) | Use helm chart development versions, too. Equivalent to version '>0.0.0-0'. If version is set, this is ignored | `bool` | `false` | no | | [helm\_disable\_openapi\_validation](#input\_helm\_disable\_openapi\_validation) | If set, the installation process will not validate rendered helm templates against the Kubernetes OpenAPI Schema | `bool` | `false` | no | | [helm\_disable\_webhooks](#input\_helm\_disable\_webhooks) | Prevent helm chart hooks from running | `bool` | `false` | no | +| [helm\_enabled](#input\_helm\_enabled) | Determines if the helm chart should be installed | `bool` | `true` | no | | [helm\_force\_update](#input\_helm\_force\_update) | Force helm resource update through delete/recreate if needed | `bool` | `false` | no | | [helm\_keyring](#input\_helm\_keyring) | Location of public keys used for verification. Used only if helm\_package\_verify is true | `string` | `"~/.gnupg/pubring.gpg"` | no | | [helm\_lint](#input\_helm\_lint) | Run the helm chart linter during the plan | `bool` | `false` | no | @@ -127,10 +130,10 @@ No modules. | [helm\_timeout](#input\_helm\_timeout) | Time in seconds to wait for any individual kubernetes operation (like Jobs for hooks) | `number` | `300` | no | | [helm\_wait](#input\_helm\_wait) | Will wait until all helm release resources are in a ready state before marking the release as successful. It will wait for as long as timeout | `bool` | `false` | no | | [helm\_wait\_for\_jobs](#input\_helm\_wait\_for\_jobs) | If wait is enabled, will wait until all helm Jobs have been completed before marking the release as successful. It will wait for as long as timeout | `bool` | `false` | no | -| [irsa\_policy\_enabled](#input\_irsa\_policy\_enabled) | Whether to create opinionated policy for LB controller, see https://github.com/kubernetes-sigs/aws-load-balancer-controller/blob/v2.4.0/docs/install/iam_policy.json | `bool` | `true` | no | -| [irsa\_role\_create](#input\_irsa\_role\_create) | Whether to create IRSA role and annotate service account | `bool` | `true` | no | -| [irsa\_role\_name\_prefix](#input\_irsa\_role\_name\_prefix) | The IRSA role name prefix for LB controller | `string` | `"lb-controller-irsa"` | no | -| [irsa\_tags](#input\_irsa\_tags) | IRSA resources tags | `map(string)` | `{}` | no | +| [iam\_policy\_enabled](#input\_iam\_policy\_enabled) | Whether to create opinionated policy for LB controller, see https://github.com/kubernetes-sigs/aws-load-balancer-controller/blob/v2.4.0/docs/install/iam_policy.json | `bool` | `true` | no | +| [iam\_role\_create](#input\_iam\_role\_create) | Whether to create IAM role and annotate service account | `bool` | `true` | no | +| [iam\_role\_name\_prefix](#input\_iam\_role\_name\_prefix) | The IAM role name prefix for LB controller | `string` | `"lb-controller-iam"` | no | +| [iam\_tags](#input\_iam\_tags) | IAM resources tags | `map(string)` | `{}` | no | | [namespace](#input\_namespace) | The K8s namespace in which the aws-load-balancer-controller service account has been created | `string` | `"aws-lb-controller"` | no | | [service\_account\_create](#input\_service\_account\_create) | Whether to create Service Account | `bool` | `true` | no | | [service\_account\_name](#input\_service\_account\_name) | The k8s aws-loab-balancer-controller service account name | `string` | `"aws-load-balancer-controller"` | no | diff --git a/examples/basic/README.md b/examples/basic/README.md index dea494f..48a1cfc 100644 --- a/examples/basic/README.md +++ b/examples/basic/README.md @@ -22,8 +22,8 @@ The code in this example shows how to use the module with basic configuration an | [lb\_controller\_argo\_kubernetes](#module\_lb\_controller\_argo\_kubernetes) | ../../ | n/a | | [lb\_controller\_helm](#module\_lb\_controller\_helm) | ../../ | n/a | | [lbc\_disabled](#module\_lbc\_disabled) | ../../ | n/a | -| [lbc\_without\_irsa\_policy](#module\_lbc\_without\_irsa\_policy) | ../../ | n/a | -| [lbc\_without\_irsa\_role](#module\_lbc\_without\_irsa\_role) | ../../ | n/a | +| [lbc\_without\_iam\_policy](#module\_lbc\_without\_iam\_policy) | ../../ | n/a | +| [lbc\_without\_iam\_role](#module\_lbc\_without\_iam\_role) | ../../ | n/a | | [vpc](#module\_vpc) | terraform-aws-modules/vpc/aws | 5.5.1 | ## Resources diff --git a/examples/basic/main.tf b/examples/basic/main.tf index 62e6279..ed8043b 100644 --- a/examples/basic/main.tf +++ b/examples/basic/main.tf @@ -43,20 +43,20 @@ module "lbc_disabled" { } -module "lbc_without_irsa_role" { +module "lbc_without_iam_role" { source = "../../" - irsa_role_create = false + iam_role_create = false cluster_name = module.eks_cluster.eks_cluster_id cluster_identity_oidc_issuer = module.eks_cluster.eks_cluster_identity_oidc_issuer cluster_identity_oidc_issuer_arn = module.eks_cluster.eks_cluster_identity_oidc_issuer_arn } -module "lbc_without_irsa_policy" { +module "lbc_without_iam_policy" { source = "../../" - irsa_policy_enabled = false + iam_policy_enabled = false cluster_name = module.eks_cluster.eks_cluster_id cluster_identity_oidc_issuer = module.eks_cluster.eks_cluster_identity_oidc_issuer cluster_identity_oidc_issuer_arn = module.eks_cluster.eks_cluster_identity_oidc_issuer_arn diff --git a/iam.tf b/iam.tf index 47996c6..e714714 100644 --- a/iam.tf +++ b/iam.tf @@ -1,9 +1,10 @@ locals { - irsa_role_create = var.enabled && var.service_account_create && var.irsa_role_create + enable_irsa = var.enabled && var.service_account_create && var.enable_irsa + enable_pod_identity = var.enabled && var.service_account_create && var.enable_pod_identity } data "aws_iam_policy_document" "this" { - count = local.irsa_role_create && var.irsa_policy_enabled ? 1 : 0 + count = var.iam_role_create && var.iam_policy_enabled ? 1 : 0 # https://github.com/kubernetes-sigs/aws-load-balancer-controller/blob/v2.10.1/docs/install/iam_policy.json #checkov:skip=CKV_AWS_109:The official documentation was used to define these policies @@ -280,50 +281,74 @@ data "aws_iam_policy_document" "this" { } resource "aws_iam_policy" "this" { - count = local.irsa_role_create && var.irsa_policy_enabled ? 1 : 0 - name = "${var.irsa_role_name_prefix}-${var.helm_release_name}" + count = var.iam_role_create && var.iam_policy_enabled ? 1 : 0 + name = "${var.iam_role_name_prefix}-${var.helm_release_name}" path = "/" description = "Policy for aws-load-balancer-controller service" policy = data.aws_iam_policy_document.this[0].json - tags = var.irsa_tags + tags = var.iam_tags } data "aws_iam_policy_document" "this_assume" { - count = local.irsa_role_create ? 1 : 0 + count = var.iam_role_create ? 1 : 0 - statement { - actions = ["sts:AssumeRoleWithWebIdentity"] + # Pod Identity + dynamic "statement" { + for_each = local.enable_pod_identity ? [1] : [] - principals { - type = "Federated" - identifiers = [var.cluster_identity_oidc_issuer_arn] - } + content { + actions = [ + "sts:AssumeRole", + "sts:TagSession", + ] - condition { - test = "StringEquals" - variable = "${replace(var.cluster_identity_oidc_issuer, "https://", "")}:sub" + principals { + type = "Service" + identifiers = ["pods.eks.amazonaws.com"] + } - values = [ - "system:serviceaccount:${var.namespace}:${var.service_account_name}", - ] + effect = "Allow" } + } - effect = "Allow" + # IAM Roles for Service Accounts (IRSA) + dynamic "statement" { + for_each = local.enable_irsa ? [1] : [] + + content { + actions = ["sts:AssumeRoleWithWebIdentity"] + + principals { + type = "Federated" + identifiers = [var.cluster_identity_oidc_issuer_arn] + } + + condition { + test = "StringEquals" + variable = "${replace(var.cluster_identity_oidc_issuer, "https://", "")}:sub" + + values = [ + "system:serviceaccount:${var.namespace}:${var.service_account_name}", + ] + } + + effect = "Allow" + } } } resource "aws_iam_role" "this" { - count = local.irsa_role_create ? 1 : 0 + count = var.iam_role_create ? 1 : 0 - name = "${var.irsa_role_name_prefix}-${var.helm_release_name}" + name = "${var.iam_role_name_prefix}-${var.helm_release_name}" assume_role_policy = data.aws_iam_policy_document.this_assume[0].json - tags = var.irsa_tags + tags = var.iam_tags } resource "aws_iam_role_policy_attachment" "this" { - count = local.irsa_role_create ? 1 : 0 + count = var.iam_role_create ? 1 : 0 role = aws_iam_role.this[0].name policy_arn = aws_iam_policy.this[0].arn diff --git a/values.tf b/values.tf index 2e15930..5c038f8 100644 --- a/values.tf +++ b/values.tf @@ -5,7 +5,7 @@ locals { "create" : var.service_account_create "name" : var.service_account_name "annotations" : { - "eks.amazonaws.com/role-arn" : local.irsa_role_create ? aws_iam_role.this[0].arn : "" + "eks.amazonaws.com/role-arn" : local.enable_irsa ? aws_iam_role.this[0].arn : "" } } }) diff --git a/variables.tf b/variables.tf index 753f421..2fc4916 100644 --- a/variables.tf +++ b/variables.tf @@ -55,28 +55,40 @@ variable "service_account_name" { description = "The k8s aws-loab-balancer-controller service account name" } -variable "irsa_role_create" { +variable "enable_pod_identity" { + description = "Determines whether to enable support for EKS pod identity" + type = bool + default = false +} + +variable "enable_irsa" { + description = "Determines whether to enable support for IAM role for service accounts" + type = bool + default = true +} + +variable "iam_role_create" { type = bool default = true - description = "Whether to create IRSA role and annotate service account" + description = "Whether to create IAM role and annotate service account" } -variable "irsa_role_name_prefix" { +variable "iam_role_name_prefix" { type = string - default = "lb-controller-irsa" - description = "The IRSA role name prefix for LB controller" + default = "lb-controller-iam" + description = "The IAM role name prefix for LB controller" } -variable "irsa_policy_enabled" { +variable "iam_policy_enabled" { type = bool default = true description = "Whether to create opinionated policy for LB controller, see https://github.com/kubernetes-sigs/aws-load-balancer-controller/blob/v2.4.0/docs/install/iam_policy.json" } -variable "irsa_tags" { +variable "iam_tags" { type = map(string) default = {} - description = "IRSA resources tags" + description = "IAM resources tags" } variable "cluster_name" {