From f3cfdaf9c202214477b16a0bb1ef3caced0f4420 Mon Sep 17 00:00:00 2001 From: Benjamin Smith Date: Fri, 23 Dec 2022 14:37:13 -0800 Subject: [PATCH 1/7] supports a list of any or all value list --- main.tf | 22 ++++++++++++++++++---- variables.tf | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/main.tf b/main.tf index e2586a2..c692bb0 100644 --- a/main.tf +++ b/main.tf @@ -74,10 +74,24 @@ data "aws_iam_policy_document" "service_account_assume_role" { identifiers = [format("arn:%s:iam::%s:oidc-provider/%s", var.aws_partition, local.aws_account_number, local.eks_cluster_oidc_issuer)] } - condition { - test = "StringLike" - values = [format("system:serviceaccount:%s:%s", coalesce(var.service_account_namespace, "*"), coalesce(var.service_account_name, "*"))] - variable = format("%s:sub", local.eks_cluster_oidc_issuer) + dynamic "condition" { + for_each = var.service_account_name != null && var.service_account_namespace != null ? ["true"] : [] + content { + test = "StringLike" + values = [ + format("system:serviceaccount:%s:%s", coalesce(var.service_account_namespace, "*"), coalesce(var.service_account_name, "*")) + ] + variable = format("%s:sub", local.eks_cluster_oidc_issuer) + } + } + + dynamic "condition" { + for_each = var.service_account_namespace_name_list != null ? ["true"] : [] + content { + test = format("%s:StringLike", var.service_account_list_qualifier) + values = formatlist("system:serviceaccount:%s", var.service_account_namespace_name_list) + variable = format("%s:sub", local.eks_cluster_oidc_issuer) + } } } } diff --git a/variables.tf b/variables.tf index aa4d6cd..6b7fe81 100644 --- a/variables.tf +++ b/variables.tf @@ -1,11 +1,29 @@ variable "service_account_name" { type = string description = "Kubernetes ServiceAccount name" + default = null } variable "service_account_namespace" { type = string description = "Kubernetes Namespace where service account is deployed" + default = null +} + +variable "service_account_list_qualifier" { + type = string + description = "Kubernetes ServiceAccount list qualifier, must be one of `ForAllValues` or `ForAnyValue`" + validation { + condition = contains(["ForAllValues", "ForAnyValue"], var.service_account_list_qualifier) + error_message = "Kubernetes ServiceAccount list qualifier must be one of `ForAllValues` or `ForAnyValue`" + } + default = "ForAnyValue" +} + +variable "service_account_namespace_name_list" { + type = list(string) + description = "List of `namespace:name` for service account" + default = null } variable "aws_account_number" { From 7e8dd0ab48fc36dd9ad0cd34479217c67df632c3 Mon Sep 17 00:00:00 2001 From: cloudpossebot <11232728+cloudpossebot@users.noreply.github.com> Date: Fri, 23 Dec 2022 22:39:08 +0000 Subject: [PATCH 2/7] Auto Format --- .github/workflows/validate-codeowners.yml | 1 + README.md | 9 ++++++--- docs/terraform.md | 6 ++++-- main.tf | 4 ++-- variables.tf | 4 ++-- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/.github/workflows/validate-codeowners.yml b/.github/workflows/validate-codeowners.yml index 70f829e..4b4a226 100644 --- a/.github/workflows/validate-codeowners.yml +++ b/.github/workflows/validate-codeowners.yml @@ -10,6 +10,7 @@ jobs: steps: - name: "Checkout source code at current commit" uses: actions/checkout@v2 + # Leave pinned at 0.7.1 until https://github.com/mszostok/codeowners-validator/issues/173 is resolved - uses: mszostok/codeowners-validator@v0.7.1 if: github.event.pull_request.head.repo.full_name == github.repository name: "Full check of CODEOWNERS" diff --git a/README.md b/README.md index cf9d711..b257feb 100644 --- a/README.md +++ b/README.md @@ -218,8 +218,10 @@ Available targets: | [namespace](#input\_namespace) | ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique | `string` | `null` | no | | [permissions\_boundary](#input\_permissions\_boundary) | ARN of the policy that is used to set the permissions boundary for the role. | `string` | `null` | no | | [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.
Characters matching the regex will be removed from the ID elements.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | -| [service\_account\_name](#input\_service\_account\_name) | Kubernetes ServiceAccount name | `string` | n/a | yes | -| [service\_account\_namespace](#input\_service\_account\_namespace) | Kubernetes Namespace where service account is deployed | `string` | n/a | yes | +| [service\_account\_list\_qualifier](#input\_service\_account\_list\_qualifier) | Kubernetes ServiceAccount list qualifier, must be one of `ForAllValues` or `ForAnyValue` | `string` | `"ForAnyValue"` | no | +| [service\_account\_name](#input\_service\_account\_name) | Kubernetes ServiceAccount name | `string` | `null` | no | +| [service\_account\_namespace](#input\_service\_account\_namespace) | Kubernetes Namespace where service account is deployed | `string` | `null` | no | +| [service\_account\_namespace\_name\_list](#input\_service\_account\_namespace\_name\_list) | List of `namespace:name` for service account | `list(string)` | `null` | no | | [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no | | [tenant](#input\_tenant) | ID element \_(Rarely used, not included by default)\_. A customer identifier, indicating who this instance of a resource is for | `string` | `null` | no | @@ -410,7 +412,7 @@ Check out [our other projects][github], [follow us on twitter][twitter], [apply [![README Footer][readme_footer_img]][readme_footer_link] [![Beacon][beacon]][website] - + [logo]: https://cloudposse.com/logo-300x69.svg [docs]: https://cpco.io/docs?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-eks-iam-role&utm_content=docs [website]: https://cpco.io/homepage?utm_source=github&utm_medium=readme&utm_campaign=cloudposse/terraform-aws-eks-iam-role&utm_content=website @@ -441,3 +443,4 @@ Check out [our other projects][github], [follow us on twitter][twitter], [apply [share_googleplus]: https://plus.google.com/share?url=https://github.com/cloudposse/terraform-aws-eks-iam-role [share_email]: mailto:?subject=terraform-aws-eks-iam-role&body=https://github.com/cloudposse/terraform-aws-eks-iam-role [beacon]: https://ga-beacon.cloudposse.com/UA-76589703-4/cloudposse/terraform-aws-eks-iam-role?pixel&cs=github&cm=readme&an=terraform-aws-eks-iam-role + diff --git a/docs/terraform.md b/docs/terraform.md index 23ce40d..86272ed 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -54,8 +54,10 @@ | [namespace](#input\_namespace) | ID element. Usually an abbreviation of your organization name, e.g. 'eg' or 'cp', to help ensure generated IDs are globally unique | `string` | `null` | no | | [permissions\_boundary](#input\_permissions\_boundary) | ARN of the policy that is used to set the permissions boundary for the role. | `string` | `null` | no | | [regex\_replace\_chars](#input\_regex\_replace\_chars) | Terraform regular expression (regex) string.
Characters matching the regex will be removed from the ID elements.
If not set, `"/[^a-zA-Z0-9-]/"` is used to remove all characters other than hyphens, letters and digits. | `string` | `null` | no | -| [service\_account\_name](#input\_service\_account\_name) | Kubernetes ServiceAccount name | `string` | n/a | yes | -| [service\_account\_namespace](#input\_service\_account\_namespace) | Kubernetes Namespace where service account is deployed | `string` | n/a | yes | +| [service\_account\_list\_qualifier](#input\_service\_account\_list\_qualifier) | Kubernetes ServiceAccount list qualifier, must be one of `ForAllValues` or `ForAnyValue` | `string` | `"ForAnyValue"` | no | +| [service\_account\_name](#input\_service\_account\_name) | Kubernetes ServiceAccount name | `string` | `null` | no | +| [service\_account\_namespace](#input\_service\_account\_namespace) | Kubernetes Namespace where service account is deployed | `string` | `null` | no | +| [service\_account\_namespace\_name\_list](#input\_service\_account\_namespace\_name\_list) | List of `namespace:name` for service account | `list(string)` | `null` | no | | [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no | | [tenant](#input\_tenant) | ID element \_(Rarely used, not included by default)\_. A customer identifier, indicating who this instance of a resource is for | `string` | `null` | no | diff --git a/main.tf b/main.tf index c692bb0..d466530 100644 --- a/main.tf +++ b/main.tf @@ -77,8 +77,8 @@ data "aws_iam_policy_document" "service_account_assume_role" { dynamic "condition" { for_each = var.service_account_name != null && var.service_account_namespace != null ? ["true"] : [] content { - test = "StringLike" - values = [ + test = "StringLike" + values = [ format("system:serviceaccount:%s:%s", coalesce(var.service_account_namespace, "*"), coalesce(var.service_account_name, "*")) ] variable = format("%s:sub", local.eks_cluster_oidc_issuer) diff --git a/variables.tf b/variables.tf index 6b7fe81..90db11a 100644 --- a/variables.tf +++ b/variables.tf @@ -1,13 +1,13 @@ variable "service_account_name" { type = string description = "Kubernetes ServiceAccount name" - default = null + default = null } variable "service_account_namespace" { type = string description = "Kubernetes Namespace where service account is deployed" - default = null + default = null } variable "service_account_list_qualifier" { From 03cbe13efe1cacd97bfe3a581306900cdc4685e3 Mon Sep 17 00:00:00 2001 From: Benjamin Smith Date: Tue, 27 Dec 2022 08:20:48 -0800 Subject: [PATCH 3/7] Update variables.tf Co-authored-by: Andriy Knysh --- variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/variables.tf b/variables.tf index 90db11a..9a0f6a6 100644 --- a/variables.tf +++ b/variables.tf @@ -22,7 +22,7 @@ variable "service_account_list_qualifier" { variable "service_account_namespace_name_list" { type = list(string) - description = "List of `namespace:name` for service account" + description = "List of `namespace:name` for service account assume role IAM policy" default = null } From 6c6c865cd2da1fb8b9cab1ddcd9e0457c88f086b Mon Sep 17 00:00:00 2001 From: cloudpossebot <11232728+cloudpossebot@users.noreply.github.com> Date: Tue, 27 Dec 2022 16:21:42 +0000 Subject: [PATCH 4/7] Auto Format --- README.md | 2 +- docs/terraform.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b257feb..74f4b6f 100644 --- a/README.md +++ b/README.md @@ -221,7 +221,7 @@ Available targets: | [service\_account\_list\_qualifier](#input\_service\_account\_list\_qualifier) | Kubernetes ServiceAccount list qualifier, must be one of `ForAllValues` or `ForAnyValue` | `string` | `"ForAnyValue"` | no | | [service\_account\_name](#input\_service\_account\_name) | Kubernetes ServiceAccount name | `string` | `null` | no | | [service\_account\_namespace](#input\_service\_account\_namespace) | Kubernetes Namespace where service account is deployed | `string` | `null` | no | -| [service\_account\_namespace\_name\_list](#input\_service\_account\_namespace\_name\_list) | List of `namespace:name` for service account | `list(string)` | `null` | no | +| [service\_account\_namespace\_name\_list](#input\_service\_account\_namespace\_name\_list) | List of `namespace:name` for service account assume role IAM policy | `list(string)` | `null` | no | | [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no | | [tenant](#input\_tenant) | ID element \_(Rarely used, not included by default)\_. A customer identifier, indicating who this instance of a resource is for | `string` | `null` | no | diff --git a/docs/terraform.md b/docs/terraform.md index 86272ed..aabf674 100644 --- a/docs/terraform.md +++ b/docs/terraform.md @@ -57,7 +57,7 @@ | [service\_account\_list\_qualifier](#input\_service\_account\_list\_qualifier) | Kubernetes ServiceAccount list qualifier, must be one of `ForAllValues` or `ForAnyValue` | `string` | `"ForAnyValue"` | no | | [service\_account\_name](#input\_service\_account\_name) | Kubernetes ServiceAccount name | `string` | `null` | no | | [service\_account\_namespace](#input\_service\_account\_namespace) | Kubernetes Namespace where service account is deployed | `string` | `null` | no | -| [service\_account\_namespace\_name\_list](#input\_service\_account\_namespace\_name\_list) | List of `namespace:name` for service account | `list(string)` | `null` | no | +| [service\_account\_namespace\_name\_list](#input\_service\_account\_namespace\_name\_list) | List of `namespace:name` for service account assume role IAM policy | `list(string)` | `null` | no | | [stage](#input\_stage) | ID element. Usually used to indicate role, e.g. 'prod', 'staging', 'source', 'build', 'test', 'deploy', 'release' | `string` | `null` | no | | [tags](#input\_tags) | Additional tags (e.g. `{'BusinessUnit': 'XYZ'}`).
Neither the tag keys nor the tag values will be modified by this module. | `map(string)` | `{}` | no | | [tenant](#input\_tenant) | ID element \_(Rarely used, not included by default)\_. A customer identifier, indicating who this instance of a resource is for | `string` | `null` | no | From d2d5619e09524e158f1e04ae1849abbb6653bed4 Mon Sep 17 00:00:00 2001 From: Benjamin Smith Date: Tue, 27 Dec 2022 08:26:14 -0800 Subject: [PATCH 5/7] update test and variable description for lint --- examples/complete/main.tf | 9 +++++++++ variables.tf | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/examples/complete/main.tf b/examples/complete/main.tf index abebd52..b3488cf 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -7,9 +7,18 @@ data "aws_caller_identity" "current" {} module "autoscaler_role" { source = "../.." + # Singular Service Account attachment service_account_name = "autoscaler" service_account_namespace = "kube-system" + # Usually there is no need to add both service account methods of attachment. But there is precluding you from doing so. + # Multiple Service Account attachments + service_account_namespace_name_list = [ + "kube-system:autoscaler", + "default:foo", + ] + service_account_list_qualifier = "ForAnyValue" + aws_account_number = data.aws_caller_identity.current.account_id # Rather than create a whole cluster, just fake the OIDC URL # eks_cluster_oidc_issuer_url = module.eks_cluster.eks_cluster_identity_oidc_issuer diff --git a/variables.tf b/variables.tf index 9a0f6a6..e16e176 100644 --- a/variables.tf +++ b/variables.tf @@ -15,7 +15,7 @@ variable "service_account_list_qualifier" { description = "Kubernetes ServiceAccount list qualifier, must be one of `ForAllValues` or `ForAnyValue`" validation { condition = contains(["ForAllValues", "ForAnyValue"], var.service_account_list_qualifier) - error_message = "Kubernetes ServiceAccount list qualifier must be one of `ForAllValues` or `ForAnyValue`" + error_message = "Kubernetes ServiceAccount list qualifier must be one of `ForAllValues` or `ForAnyValue`?" } default = "ForAnyValue" } From acc13027d7569f3e3ac3f32c3ab0807cda8157f9 Mon Sep 17 00:00:00 2001 From: Benjamin Smith Date: Tue, 27 Dec 2022 12:15:34 -0800 Subject: [PATCH 6/7] cleanup and docs --- examples/complete/main.tf | 19 +++++++++++++++++-- variables.tf | 2 +- 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/examples/complete/main.tf b/examples/complete/main.tf index b3488cf..a1837e4 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -11,7 +11,23 @@ module "autoscaler_role" { service_account_name = "autoscaler" service_account_namespace = "kube-system" - # Usually there is no need to add both service account methods of attachment. But there is precluding you from doing so. + aws_account_number = data.aws_caller_identity.current.account_id + # Rather than create a whole cluster, just fake the OIDC URL + # eks_cluster_oidc_issuer_url = module.eks_cluster.eks_cluster_identity_oidc_issuer + eks_cluster_oidc_issuer_url = "https://oidc.eks.us-west-2.amazonaws.com/id/FEDCBA9876543210FEDCBA9876543210" + aws_iam_policy_document = [data.aws_iam_policy_document.autoscaler.json] + + context = module.this.context +} + +module "autoscaler_role_multiple_service_accounts" { + source = "../.." + attributes = ["multiple", "sa"] + + # Usually there is no need to add both service account methods of attachment. + # If you add both, they are joined via AND. + # See https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_multi-value-conditions.html#reference_policies_multiple-conditions-eval + # Multiple Service Account attachments service_account_namespace_name_list = [ "kube-system:autoscaler", @@ -27,7 +43,6 @@ module "autoscaler_role" { context = module.this.context } - data "aws_iam_policy_document" "autoscaler" { statement { sid = "AllowToScaleEKSNodeGroupAutoScalingGroup" diff --git a/variables.tf b/variables.tf index e16e176..0d3e937 100644 --- a/variables.tf +++ b/variables.tf @@ -15,7 +15,7 @@ variable "service_account_list_qualifier" { description = "Kubernetes ServiceAccount list qualifier, must be one of `ForAllValues` or `ForAnyValue`" validation { condition = contains(["ForAllValues", "ForAnyValue"], var.service_account_list_qualifier) - error_message = "Kubernetes ServiceAccount list qualifier must be one of `ForAllValues` or `ForAnyValue`?" + error_message = "Kubernetes ServiceAccount list qualifier must be one of `ForAllValues` or `ForAnyValue`." } default = "ForAnyValue" } From d4d5a67b4105e46f2ef4dc717befaaf561acba68 Mon Sep 17 00:00:00 2001 From: cloudpossebot <11232728+cloudpossebot@users.noreply.github.com> Date: Tue, 27 Dec 2022 20:16:34 +0000 Subject: [PATCH 7/7] Auto Format --- examples/complete/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/complete/main.tf b/examples/complete/main.tf index a1837e4..a7a79cc 100644 --- a/examples/complete/main.tf +++ b/examples/complete/main.tf @@ -21,7 +21,7 @@ module "autoscaler_role" { } module "autoscaler_role_multiple_service_accounts" { - source = "../.." + source = "../.." attributes = ["multiple", "sa"] # Usually there is no need to add both service account methods of attachment.