Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
steps:
- name: Get Changed Terraform directories
id: search
uses: mozilla/tf-actions/matrixify@ddd76d971c53359fd7c89099197a6cc26adc72b8
uses: mozilla/tf-actions/matrixify@7996ff5055b387b609ae78a52d004faa973ca580 # https://github.com/mozilla/tf-actions/pull/36
with:
ignore_dir: "**/example**"
- name: Outputs
Expand All @@ -35,14 +35,9 @@ jobs:
matrix: ${{fromJson(needs.matrixify.outputs.matrix)}}

steps:
- name: Install terraform
uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd #v3
with:
terraform_wrapper: false

- id: terraform-checks
name: Terraform Checks
uses: mozilla/tf-actions/ci@4c2eeab2ff55a389cd171aa90b1c64c345ec8af7 #v0.0.4
uses: mozilla/tf-actions/ci@7996ff5055b387b609ae78a52d004faa973ca580 # https://github.com/mozilla/tf-actions/pull/36
with:
readme_check: "true"
tfpath: ${{ matrix.directory }}
64 changes: 41 additions & 23 deletions aws_gke_oidc_role/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,16 +49,24 @@ 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 = [
"system:serviceaccount:atlantis-sandbox:atlantis-sandbox"
]

iam_policy_arns = {}
}
```

Expand All @@ -70,14 +78,22 @@ 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 = [
"system:serviceaccount:bar:foo"
]

iam_policy_arns = {
example_policy = aws_iam_policy.example_policy.arn
ViewOnlyAccess = data.aws_iam_policy.view_only.arn
Expand Down Expand Up @@ -115,12 +131,14 @@ data "aws_iam_policy" "view_only" {
| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| <a name="input_aws_region"></a> [aws\_region](#input\_aws\_region) | AWS region | `string` | n/a | yes |
| <a name="input_gcp_project_id"></a> [gcp\_project\_id](#input\_gcp\_project\_id) | GKE cluster's project ID | `string` | n/a | yes |
| <a name="input_gcp_region"></a> [gcp\_region](#input\_gcp\_region) | GKE cluster's GCP region | `string` | n/a | yes |
| <a name="input_gke_cluster_name"></a> [gke\_cluster\_name](#input\_gke\_cluster\_name) | GKE cluster name | `string` | n/a | yes |
| <a name="input_gke_namespace"></a> [gke\_namespace](#input\_gke\_namespace) | Namespace for GKE workload | `string` | n/a | yes |
| <a name="input_gke_service_account"></a> [gke\_service\_account](#input\_gke\_service\_account) | GKE service account to grant role assumption privilleges | `string` | n/a | yes |
| <a name="input_gcp_project_id"></a> [gcp\_project\_id](#input\_gcp\_project\_id) | GKE cluster's project ID | `string` | `null` | no |
| <a name="input_gcp_region"></a> [gcp\_region](#input\_gcp\_region) | GKE cluster's GCP region | `string` | `null` | no |
| <a name="input_gke_cluster_name"></a> [gke\_cluster\_name](#input\_gke\_cluster\_name) | GKE cluster name | `string` | `null` | no |
| <a name="input_gke_clusters"></a> [gke\_clusters](#input\_gke\_clusters) | GKE clusters to grant role assumption privileges | <pre>map(object({<br/> gcp_project_id = string<br/> gcp_region = string<br/> gke_cluster_name = string<br/> }))</pre> | `{}` | no |
| <a name="input_gke_namespace"></a> [gke\_namespace](#input\_gke\_namespace) | Namespace for GKE workload | `string` | `null` | no |
| <a name="input_gke_service_account"></a> [gke\_service\_account](#input\_gke\_service\_account) | GKE service account to grant role assumption privilleges | `string` | `null` | no |
| <a name="input_iam_policy_arns"></a> [iam\_policy\_arns](#input\_iam\_policy\_arns) | One or more policy arns to attach to created AWS role | `map(string)` | n/a | yes |
| <a name="input_k8s_service_accounts"></a> [k8s\_service\_accounts](#input\_k8s\_service\_accounts) | List of Kubernetes service accounts that are allowed to assume role. Sub claim format is `system:serviceaccount:${namespace}:${service_account}` | `list(string)` | `[]` | no |
| <a name="input_role_name"></a> [role\_name](#input\_role\_name) | Name to give the AWS role | `string` | n/a | yes |
| <a name="input_spacelift_instance"></a> [spacelift\_instance](#input\_spacelift\_instance) | Spacelift instance to grant role assumption privilleges | `string` | `"mozilla.app.spacelift.io"` | no |
| <a name="input_spacelift_prefixes"></a> [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 |
Expand Down
28 changes: 18 additions & 10 deletions aws_gke_oidc_role/examples/role_and_config/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,22 @@ 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 = [
"system:serviceaccount:atlantis-sandbox:atlantis-sandbox"
]

iam_policy_arns = {}
}
24 changes: 16 additions & 8 deletions aws_gke_oidc_role/examples/role_with_policy/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,22 @@
*/

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 = [
"system:serviceaccount:bar:foo"
]

iam_policy_arns = {
example_policy = aws_iam_policy.example_policy.arn
ViewOnlyAccess = data.aws_iam_policy.view_only.arn
Expand Down
28 changes: 23 additions & 5 deletions aws_gke_oidc_role/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,44 @@
* ```
*/

locals {
deprecated_cluster_vars = var.gcp_project_id != null && var.gcp_region != null && var.gke_cluster_name != null
single_cluster = local.deprecated_cluster_vars ? { single = { gcp_project_id = var.gcp_project_id, gcp_region = var.gcp_region, gke_cluster_name = var.gke_cluster_name } } : {}
gke_clusters = merge(var.gke_clusters, local.single_cluster)

deprecated_service_account_vars = var.gke_namespace != null && var.gke_service_account != null
single_service_account = local.deprecated_service_account_vars ? ["system:serviceaccount:${var.gke_namespace}:${var.gke_service_account}"] : []
k8s_service_accounts = concat(local.single_service_account, var.k8s_service_accounts)

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 = local.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" {
Expand Down
26 changes: 26 additions & 0 deletions aws_gke_oidc_role/variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,56 @@ variable "aws_region" {
}

variable "gcp_project_id" {
default = null
deprecated = "Use var.gke_clusters instead"
description = "GKE cluster's project ID"
type = string
}

variable "gcp_region" {
default = null
deprecated = "Use var.gke_clusters instead"
description = "GKE cluster's GCP region"
type = string
}

variable "gke_cluster_name" {
default = null
deprecated = "Use var.gke_clusters instead"
description = "GKE cluster name"
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 "gke_namespace" {
default = null
description = "Namespace for GKE workload"
deprecated = "Use var.k8s_service_accounts instead"
type = string
}

variable "gke_service_account" {
default = null
description = "GKE service account to grant role assumption privilleges"
deprecated = "Use var.k8s_service_accounts instead"
type = string
}

variable "k8s_service_accounts" {
default = []
description = "List of Kubernetes service accounts that are allowed to assume role. Sub claim format is `system:serviceaccount:$${namespace}:$${service_account}`"
type = list(string)
}

variable "spacelift_instance" {
description = "Spacelift instance to grant role assumption privilleges"
default = "mozilla.app.spacelift.io"
Expand Down
Loading