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" }