diff --git a/aws_gke_oidc_role/README.md b/aws_gke_oidc_role/README.md index 30c00aca..04efd449 100644 --- a/aws_gke_oidc_role/README.md +++ b/aws_gke_oidc_role/README.md @@ -49,16 +49,27 @@ module "oidc_config" { } module "oidc_role" { - depends_on = [module.oidc_config] - source = "../.././" - role_name = "opst-1509-oidc-test" - aws_region = "us-west-1" - gcp_region = "us-west1" - gke_cluster_name = "global-platform-admin-mgmt" - gcp_project_id = "moz-fx-platform-mgmt-global" - gke_namespace = "atlantis-sandbox" - gke_service_account = "atlantis-sandbox" - iam_policy_arns = {} + depends_on = [module.oidc_config] + source = "../.././" + role_name = "opst-1509-oidc-test" + aws_region = "us-west-1" + + gke_clusters = { + mgmt = { + gcp_project_id = "moz-fx-platform-mgmt-global" + gcp_region = "us-west1" + gke_cluster_name = "global-platform-admin-mgmt" + } + } + + k8s_service_accounts = { + atlantis-sandbox = { + namespace = "atlantis-sandbox" + service_account = "atlantis-sandbox" + } + } + + iam_policy_arns = {} } ``` @@ -70,14 +81,25 @@ module "oidc_role" { */ module "oidc_role" { - source = "../.././" - role_name = "oidc-example-role" - aws_region = "us-west-1" - gcp_region = "us-west1" - gke_cluster_name = "baz" - gcp_project_id = "example-project" - gke_namespace = "bar" - gke_service_account = "foo" + source = "../.././" + role_name = "oidc-example-role" + aws_region = "us-west-1" + + gke_clusters = { + baz = { + gcp_region = "us-west1" + gke_cluster_name = "baz" + gcp_project_id = "example-project" + } + } + + k8s_service_accounts = { + foobar = { + namespace = "foo" + service_account = "bar" + } + } + iam_policy_arns = { example_policy = aws_iam_policy.example_policy.arn ViewOnlyAccess = data.aws_iam_policy.view_only.arn @@ -115,12 +137,9 @@ data "aws_iam_policy" "view_only" { | Name | Description | Type | Default | Required | |------|-------------|------|---------|:--------:| | [aws\_region](#input\_aws\_region) | AWS region | `string` | n/a | yes | -| [gcp\_project\_id](#input\_gcp\_project\_id) | GKE cluster's project ID | `string` | n/a | yes | -| [gcp\_region](#input\_gcp\_region) | GKE cluster's GCP region | `string` | n/a | yes | -| [gke\_cluster\_name](#input\_gke\_cluster\_name) | GKE cluster name | `string` | n/a | yes | -| [gke\_namespace](#input\_gke\_namespace) | Namespace for GKE workload | `string` | n/a | yes | -| [gke\_service\_account](#input\_gke\_service\_account) | GKE service account to grant role assumption privilleges | `string` | n/a | yes | +| [gke\_clusters](#input\_gke\_clusters) | GKE clusters to grant role assumption privileges |
map(object({
gcp_project_id = string
gcp_region = string
gke_cluster_name = string
})) | `{}` | no |
| [iam\_policy\_arns](#input\_iam\_policy\_arns) | One or more policy arns to attach to created AWS role | `map(string)` | n/a | yes |
+| [k8s\_service\_accounts](#input\_k8s\_service\_accounts) | Map of Kubernetes service accounts that are allowed to assume role. Sub claim format is `system:serviceaccount:${namespace}:${service_account}` | map(object({
namespace = string
service_account = string
})) | `{}` | no |
| [role\_name](#input\_role\_name) | Name to give the AWS role | `string` | n/a | yes |
| [spacelift\_instance](#input\_spacelift\_instance) | Spacelift instance to grant role assumption privilleges | `string` | `"mozilla.app.spacelift.io"` | no |
| [spacelift\_prefixes](#input\_spacelift\_prefixes) | List of prefixes for Spacelift spaces/stacks that are allowed to assume role. See sub claim at https://docs.spacelift.io/integrations/cloud-providers/oidc#standard-claims for format | `list(string)` | `[]` | no |
diff --git a/aws_gke_oidc_role/examples/role_and_config/main.tf b/aws_gke_oidc_role/examples/role_and_config/main.tf
index 9b5ecb75..a48636f1 100644
--- a/aws_gke_oidc_role/examples/role_and_config/main.tf
+++ b/aws_gke_oidc_role/examples/role_and_config/main.tf
@@ -10,14 +10,25 @@ module "oidc_config" {
}
module "oidc_role" {
- depends_on = [module.oidc_config]
- source = "../.././"
- role_name = "opst-1509-oidc-test"
- aws_region = "us-west-1"
- gcp_region = "us-west1"
- gke_cluster_name = "global-platform-admin-mgmt"
- gcp_project_id = "moz-fx-platform-mgmt-global"
- gke_namespace = "atlantis-sandbox"
- gke_service_account = "atlantis-sandbox"
- iam_policy_arns = {}
+ depends_on = [module.oidc_config]
+ source = "../.././"
+ role_name = "opst-1509-oidc-test"
+ aws_region = "us-west-1"
+
+ gke_clusters = {
+ mgmt = {
+ gcp_project_id = "moz-fx-platform-mgmt-global"
+ gcp_region = "us-west1"
+ gke_cluster_name = "global-platform-admin-mgmt"
+ }
+ }
+
+ k8s_service_accounts = {
+ atlantis-sandbox = {
+ namespace = "atlantis-sandbox"
+ service_account = "atlantis-sandbox"
+ }
+ }
+
+ iam_policy_arns = {}
}
diff --git a/aws_gke_oidc_role/examples/role_with_policy/main.tf b/aws_gke_oidc_role/examples/role_with_policy/main.tf
index 9811ca75..39636277 100644
--- a/aws_gke_oidc_role/examples/role_with_policy/main.tf
+++ b/aws_gke_oidc_role/examples/role_with_policy/main.tf
@@ -5,14 +5,25 @@
*/
module "oidc_role" {
- source = "../.././"
- role_name = "oidc-example-role"
- aws_region = "us-west-1"
- gcp_region = "us-west1"
- gke_cluster_name = "baz"
- gcp_project_id = "example-project"
- gke_namespace = "bar"
- gke_service_account = "foo"
+ source = "../.././"
+ role_name = "oidc-example-role"
+ aws_region = "us-west-1"
+
+ gke_clusters = {
+ baz = {
+ gcp_region = "us-west1"
+ gke_cluster_name = "baz"
+ gcp_project_id = "example-project"
+ }
+ }
+
+ k8s_service_accounts = {
+ foobar = {
+ namespace = "foo"
+ service_account = "bar"
+ }
+ }
+
iam_policy_arns = {
example_policy = aws_iam_policy.example_policy.arn
ViewOnlyAccess = data.aws_iam_policy.view_only.arn
diff --git a/aws_gke_oidc_role/main.tf b/aws_gke_oidc_role/main.tf
index 2fef871d..98a3bf98 100644
--- a/aws_gke_oidc_role/main.tf
+++ b/aws_gke_oidc_role/main.tf
@@ -35,26 +35,38 @@
* ```
*/
+locals {
+ k8s_service_accounts = [for k, v in var.k8s_service_accounts : "system:serviceaccount:${v.namespace}:${v.service_account}"]
+
+ oidc_provider_urls = concat([
+ for k, v in data.aws_iam_openid_connect_provider.gke_oidc : replace(v.url, "https://", "")
+ ], [data.aws_iam_openid_connect_provider.spacelift.url])
+}
+
module "iam_assumable_role_for_oidc" {
source = "terraform-aws-modules/iam/aws//modules/iam-role"
version = "~> v6.2.1"
- description = "Role for ${var.gke_cluster_name}/${var.gke_namespace}/${var.gke_service_account} and Spacelift to assume"
+ description = "Role for GKE clusters and Spacelift to assume"
enable_oidc = true
name = var.role_name
- oidc_provider_urls = [replace(data.aws_iam_openid_connect_provider.gke_oidc.url, "https://", ""), data.aws_iam_openid_connect_provider.spacelift.url]
+ oidc_provider_urls = local.oidc_provider_urls
# TODO - look into using https://registry.terraform.io/modules/terraform-aws-modules/iam/aws/latest/submodules/iam-role#input_trust_policy_conditions for the Spacelift subject
# GKE subject doesn't need wildcards so it can be an `oidc_subject`, but setting both `oidc_subjects` and `wilcard_subjects` results in an AND
oidc_wildcard_subjects = setunion(
- ["system:serviceaccount:${var.gke_namespace}:${var.gke_service_account}"],
- var.spacelift_prefixes
+ local.k8s_service_accounts,
+ var.spacelift_prefixes,
)
policies = var.iam_policy_arns
use_name_prefix = false
}
+
+
data "aws_iam_openid_connect_provider" "gke_oidc" {
- url = "https://container.googleapis.com/v1/projects/${var.gcp_project_id}/locations/${var.gcp_region}/clusters/${var.gke_cluster_name}"
+ for_each = var.gke_clusters
+
+ url = "https://container.googleapis.com/v1/projects/${each.value.gcp_project_id}/locations/${each.value.gcp_region}/clusters/${each.value.gke_cluster_name}"
}
data "aws_iam_openid_connect_provider" "spacelift" {
diff --git a/aws_gke_oidc_role/variables.tf b/aws_gke_oidc_role/variables.tf
index 6d56324f..4c9f4d21 100644
--- a/aws_gke_oidc_role/variables.tf
+++ b/aws_gke_oidc_role/variables.tf
@@ -15,29 +15,23 @@ variable "aws_region" {
type = string
}
-variable "gcp_project_id" {
- description = "GKE cluster's project ID"
- type = string
-}
-
-variable "gcp_region" {
- description = "GKE cluster's GCP region"
- type = string
-}
-
-variable "gke_cluster_name" {
- description = "GKE cluster name"
- type = string
-}
-
-variable "gke_namespace" {
- description = "Namespace for GKE workload"
- type = string
-}
-
-variable "gke_service_account" {
- description = "GKE service account to grant role assumption privilleges"
- type = string
+variable "gke_clusters" {
+ default = {}
+ description = "GKE clusters to grant role assumption privileges"
+ type = map(object({
+ gcp_project_id = string
+ gcp_region = string
+ gke_cluster_name = string
+ }))
+}
+
+variable "k8s_service_accounts" {
+ default = {}
+ description = "Map of Kubernetes service accounts that are allowed to assume role. Sub claim format is `system:serviceaccount:$${namespace}:$${service_account}`"
+ type = map(object({
+ namespace = string
+ service_account = string
+ }))
}
variable "spacelift_instance" {