diff --git a/fast/stages/02-security/README.md b/fast/stages/02-security/README.md
index 872d727e00..e61918bb1c 100644
--- a/fast/stages/02-security/README.md
+++ b/fast/stages/02-security/README.md
@@ -289,20 +289,20 @@ Some references that might be useful in setting up this stage:
| [automation](variables.tf#L17) | Automation resources created by the bootstrap stage. | object({…})
| ✓ | | 00-bootstrap
|
| [billing_account](variables.tf#L25) | Billing account id and organization id ('nnnnnnnn' or null). | object({…})
| ✓ | | 00-bootstrap
|
| [folder_ids](variables.tf#L34) | Folder name => id mappings, the 'security' folder name must exist. | object({…})
| ✓ | | 01-resman
|
-| [organization](variables.tf#L89) | Organization details. | object({…})
| ✓ | | 00-bootstrap
|
-| [prefix](variables.tf#L105) | Prefix used for resources that need unique names. Use 9 characters or less. | string
| ✓ | | 00-bootstrap
|
-| [service_accounts](variables.tf#L80) | Automation service accounts that can assign the encrypt/decrypt roles on keys. | object({…})
| ✓ | | 01-resman
|
+| [organization](variables.tf#L91) | Organization details. | object({…})
| ✓ | | 00-bootstrap
|
+| [prefix](variables.tf#L107) | Prefix used for resources that need unique names. Use 9 characters or less. | string
| ✓ | | 00-bootstrap
|
+| [service_accounts](variables.tf#L80) | Automation service accounts that can assign the encrypt/decrypt roles on keys. | object({…})
| ✓ | | 01-resman
|
| [groups](variables.tf#L42) | Group names to grant organization-level permissions. | map(string)
| | {…}
| 00-bootstrap
|
| [kms_defaults](variables.tf#L57) | Defaults used for KMS keys. | object({…})
| | {…}
| |
| [kms_keys](variables.tf#L69) | KMS keys to create, keyed by name. Null attributes will be interpolated with defaults. | map(object({…}))
| | {}
| |
-| [outputs_location](variables.tf#L99) | Path where providers, tfvars files, and lists for the following stages are written. Leave empty to disable. | string
| | null
| |
-| [vpc_sc_access_levels](variables.tf#L116) | VPC SC access level definitions. | map(object({…}))
| | {}
| |
-| [vpc_sc_egress_policies](variables.tf#L131) | VPC SC egress policy defnitions. | map(object({…}))
| | {}
| |
-| [vpc_sc_ingress_policies](variables.tf#L149) | VPC SC ingress policy defnitions. | map(object({…}))
| | {}
| |
-| [vpc_sc_perimeter_access_levels](variables.tf#L169) | VPC SC perimeter access_levels. | object({…})
| | null
| |
-| [vpc_sc_perimeter_egress_policies](variables.tf#L179) | VPC SC egress policies per perimeter, values reference keys defined in the `vpc_sc_ingress_policies` variable. | object({…})
| | null
| |
-| [vpc_sc_perimeter_ingress_policies](variables.tf#L189) | VPC SC ingress policies per perimeter, values reference keys defined in the `vpc_sc_ingress_policies` variable. | object({…})
| | null
| |
-| [vpc_sc_perimeter_projects](variables.tf#L199) | VPC SC perimeter resources. | object({…})
| | null
| |
+| [outputs_location](variables.tf#L101) | Path where providers, tfvars files, and lists for the following stages are written. Leave empty to disable. | string
| | null
| |
+| [vpc_sc_access_levels](variables.tf#L118) | VPC SC access level definitions. | map(object({…}))
| | {}
| |
+| [vpc_sc_egress_policies](variables.tf#L133) | VPC SC egress policy defnitions. | map(object({…}))
| | {}
| |
+| [vpc_sc_ingress_policies](variables.tf#L151) | VPC SC ingress policy defnitions. | map(object({…}))
| | {}
| |
+| [vpc_sc_perimeter_access_levels](variables.tf#L171) | VPC SC perimeter access_levels. | object({…})
| | null
| |
+| [vpc_sc_perimeter_egress_policies](variables.tf#L181) | VPC SC egress policies per perimeter, values reference keys defined in the `vpc_sc_ingress_policies` variable. | object({…})
| | null
| |
+| [vpc_sc_perimeter_ingress_policies](variables.tf#L191) | VPC SC ingress policies per perimeter, values reference keys defined in the `vpc_sc_ingress_policies` variable. | object({…})
| | null
| |
+| [vpc_sc_perimeter_projects](variables.tf#L201) | VPC SC perimeter resources. | object({…})
| | null
| |
## Outputs
diff --git a/fast/stages/02-security/core-dev.tf b/fast/stages/02-security/core-dev.tf
index 92fcaec0df..b917a5cc25 100644
--- a/fast/stages/02-security/core-dev.tf
+++ b/fast/stages/02-security/core-dev.tf
@@ -16,7 +16,8 @@
locals {
dev_kms_restricted_admins = [
- "serviceAccount:${var.service_accounts.project-factory-dev}"
+ "serviceAccount:${var.service_accounts.project-factory-dev}",
+ "serviceAccount:${var.service_accounts.data-platform-dev}"
]
}
@@ -49,7 +50,6 @@ module "dev-sec-kms" {
}
# TODO(ludo): add support for conditions to Fabric modules
-# TODO(ludo): grant delegated role at key instead of project level
resource "google_project_iam_member" "dev_key_admin_delegated" {
for_each = toset(local.dev_kms_restricted_admins)
@@ -60,7 +60,7 @@ resource "google_project_iam_member" "dev_key_admin_delegated" {
title = "kms_sa_delegated_grants"
description = "Automation service account delegated grants."
expression = format(
- "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
+ "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s]) && resource.type == 'cloudkms.googleapis.com/CryptoKey'",
join(",", formatlist("'%s'", [
"roles/cloudkms.cryptoKeyEncrypterDecrypter",
"roles/cloudkms.cryptoKeyEncrypterDecrypterViaDelegation"
diff --git a/fast/stages/02-security/core-prod.tf b/fast/stages/02-security/core-prod.tf
index d00c724daa..f792671fe3 100644
--- a/fast/stages/02-security/core-prod.tf
+++ b/fast/stages/02-security/core-prod.tf
@@ -16,7 +16,8 @@
locals {
prod_kms_restricted_admins = [
- "serviceAccount:${var.service_accounts.project-factory-prod}"
+ "serviceAccount:${var.service_accounts.project-factory-prod}",
+ "serviceAccount:${var.service_accounts.data-platform-prod}"
]
}
@@ -59,7 +60,7 @@ resource "google_project_iam_member" "prod_key_admin_delegated" {
title = "kms_sa_delegated_grants"
description = "Automation service account delegated grants."
expression = format(
- "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s])",
+ "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([%s]) && resource.type == 'cloudkms.googleapis.com/CryptoKey'",
join(",", formatlist("'%s'", [
"roles/cloudkms.cryptoKeyEncrypterDecrypter",
"roles/cloudkms.cryptoKeyEncrypterDecrypterViaDelegation"
diff --git a/fast/stages/02-security/variables.tf b/fast/stages/02-security/variables.tf
index 352f4f394f..ff0edc7757 100644
--- a/fast/stages/02-security/variables.tf
+++ b/fast/stages/02-security/variables.tf
@@ -81,6 +81,8 @@ variable "service_accounts" {
# tfdoc:variable:source 01-resman
description = "Automation service accounts that can assign the encrypt/decrypt roles on keys."
type = object({
+ data-platform-dev = string
+ data-platform-prod = string
project-factory-dev = string
project-factory-prod = string
})
diff --git a/fast/stages/03-data-platform/dev/README.md b/fast/stages/03-data-platform/dev/README.md
index 9174ae6e92..d62a1c0063 100644
--- a/fast/stages/03-data-platform/dev/README.md
+++ b/fast/stages/03-data-platform/dev/README.md
@@ -170,19 +170,20 @@ You can find examples in the `[demo](../../../../examples/data-solutions/data-pl
| [billing_account](variables.tf#L25) | Billing account id and organization id ('nnnnnnnn' or null). | object({…})
| ✓ | | 00-globals
|
| [folder_ids](variables.tf#L64) | Folder to be used for the networking resources in folders/nnnn format. | object({…})
| ✓ | | 01-resman
|
| [host_project_ids](variables.tf#L82) | Shared VPC project ids. | object({…})
| ✓ | | 02-networking
|
-| [organization](variables.tf#L108) | Organization details. | object({…})
| ✓ | | 00-globals
|
-| [prefix](variables.tf#L124) | Unique prefix used for resource names. Not used for projects if 'project_create' is null. | string
| ✓ | | 00-globals
|
+| [organization](variables.tf#L114) | Organization details. | object({…})
| ✓ | | 00-globals
|
+| [prefix](variables.tf#L130) | Unique prefix used for resource names. Not used for projects if 'project_create' is null. | string
| ✓ | | 00-globals
|
| [composer_config](variables.tf#L34) | | object({…})
| | {…}
| |
| [data_catalog_tags](variables.tf#L47) | List of Data Catalog Policy tags to be created with optional IAM binging configuration in {tag => {ROLE => [MEMBERS]}} format. | map(map(list(string)))
| | {…}
| |
| [data_force_destroy](variables.tf#L58) | Flag to set 'force_destroy' on data services like BigQery or Cloud Storage. | bool
| | false
| |
| [groups](variables.tf#L72) | Groups. | map(string)
| | {…}
| |
-| [network_config_composer](variables.tf#L90) | Network configurations to use for Composer. | object({…})
| | {…}
| |
-| [outputs_location](variables.tf#L118) | Path where providers, tfvars files, and lists for the following stages are written. Leave empty to disable. | string
| | null
| |
-| [project_services](variables.tf#L130) | List of core services enabled on all projects. | list(string)
| | […]
| |
-| [region](variables.tf#L141) | Region used for regional resources. | string
| | "europe-west1"
| |
-| [service_encryption_keys](variables.tf#L147) | Cloud KMS to use to encrypt different services. Key location should match service region. | object({…})
| | null
| |
-| [subnet_self_links](variables.tf#L159) | Shared VPC subnet self links. | object({…})
| | null
| 02-networking
|
-| [vpc_self_links](variables.tf#L168) | Shared VPC self links. | object({…})
| | null
| 02-networking
|
+| [location](variables.tf#L90) | Location used for multi-regional resources. | string
| | "eu"
| |
+| [network_config_composer](variables.tf#L96) | Network configurations to use for Composer. | object({…})
| | {…}
| |
+| [outputs_location](variables.tf#L124) | Path where providers, tfvars files, and lists for the following stages are written. Leave empty to disable. | string
| | null
| |
+| [project_services](variables.tf#L136) | List of core services enabled on all projects. | list(string)
| | […]
| |
+| [region](variables.tf#L147) | Region used for regional resources. | string
| | "europe-west1"
| |
+| [service_encryption_keys](variables.tf#L153) | Cloud KMS to use to encrypt different services. Key location should match service region. | object({…})
| | null
| |
+| [subnet_self_links](variables.tf#L165) | Shared VPC subnet self links. | object({…})
| | null
| 02-networking
|
+| [vpc_self_links](variables.tf#L174) | Shared VPC self links. | object({…})
| | null
| 02-networking
|
## Outputs
diff --git a/fast/stages/03-data-platform/dev/main.tf b/fast/stages/03-data-platform/dev/main.tf
index 536e187318..f26a528856 100644
--- a/fast/stages/03-data-platform/dev/main.tf
+++ b/fast/stages/03-data-platform/dev/main.tf
@@ -24,6 +24,7 @@ module "data-platform" {
data_catalog_tags = var.data_catalog_tags
folder_id = var.folder_ids.data-platform
groups = var.groups
+ location = var.location
network_config = {
host_project = var.host_project_ids.dev-spoke-0
network_self_link = var.vpc_self_links.dev-spoke-0
diff --git a/fast/stages/03-data-platform/dev/variables.tf b/fast/stages/03-data-platform/dev/variables.tf
index 9939d19400..5553037ef6 100644
--- a/fast/stages/03-data-platform/dev/variables.tf
+++ b/fast/stages/03-data-platform/dev/variables.tf
@@ -87,6 +87,12 @@ variable "host_project_ids" {
})
}
+variable "location" {
+ description = "Location used for multi-regional resources."
+ type = string
+ default = "eu"
+}
+
variable "network_config_composer" {
description = "Network configurations to use for Composer."
type = object({
diff --git a/tests/fast/stages/s02_security/fixture/main.tf b/tests/fast/stages/s02_security/fixture/main.tf
index 9947fc49eb..67173eb8c5 100644
--- a/tests/fast/stages/s02_security/fixture/main.tf
+++ b/tests/fast/stages/s02_security/fixture/main.tf
@@ -44,6 +44,8 @@ module "stage" {
}
service_accounts = {
security = "foobar@iam.gserviceaccount.com"
+ data-platform-dev = "foobar@iam.gserviceaccount.com"
+ data-platform-prod = "foobar@iam.gserviceaccount.com"
project-factory-dev = "foobar@iam.gserviceaccount.com"
project-factory-prod = "foobar@iam.gserviceaccount.com"
}