diff --git a/fast/stages/0-org-setup/README.md b/fast/stages/0-org-setup/README.md index bbb34dd2e..aa4c714d4 100644 --- a/fast/stages/0-org-setup/README.md +++ b/fast/stages/0-org-setup/README.md @@ -17,6 +17,9 @@ - ["Hardened" dataset](#hardened-dataset) - ["Minimal" dataset (TBD)](#minimal-dataset-tbd) - ["Tenants" dataset (TBD)](#tenants-dataset-tbd) + - [Enabling Optional Features](#enabling-optional-features) + - [SCC Custom SHA Modules](#scc-custom-sha-modules) + - [Observability](#observability) - [Detailed configuration](#detailed-configuration) - [Context interpolation](#context-interpolation) - [Factory data](#factory-data) @@ -297,6 +300,35 @@ This dataset is meant as a minimalistic starting point for organizations where a This dataset implements a design where internal tenants are given control over parts of the organization, while still retaining a degree of central control over core policies and resources. +### Enabling Optional Features + +The "Classic FAST" dataset is designed to be more lightweight than the "Hardened FAST" dataset regarding controls and policies. +But, it fully supports more advanced features like SCC Custom SHA modules and Observability factories if needed. +Note that the configuration described below is already implemented when using the "Hardened FAST" dataset. + +#### SCC Custom SHA Modules + +To configure and provision Security Command Center Custom SHA module detectors: + +1. Create a folder `datasets/classic/organization/scc-sha-custom-modules`. +2. Place your custom SHA policies in this folder. Sample of existing custom SHA policies can be found in the [hardened dataset](./datasets/hardened/organization/scc-sha-custom-modules). +3. Add the `roles/securitycentermanagement.customModulesEditor` role to the `.config.yaml` file to ensure the service account has enough permissions to provision custom modules. + +```yaml +# datasets/classic/organization/.config.yaml +iam_by_principals: + $iam_principals:service_accounts/iac-0/iac-org-rw: + - roles/securitycentermanagement.customModulesEditor +``` + +#### Observability + +To configure and provision observability resources such as log-based metrics and monitoring alerts: + +1. Create a folder `datasets/classic/observability`. +2. Place your monitoring alerts and log-based metrics in this folder. Sample of existing alerts and log-based metrics can be found in the [hardened dataset](./datasets/hardened/observability). + + ## Detailed configuration The following sections explain how to configure and run this stage, and should be read in sequence when using it for the first time. @@ -804,6 +836,7 @@ Define values for the `var.environments` variable in a tfvars file. | [identity-providers-defs.tf](./identity-providers-defs.tf) | None | | | | [imports.tf](./imports.tf) | None | | | | [main.tf](./main.tf) | Module-level locals and resources. | | terraform_data | +| [observability.tf](./observability.tf) | None | project | | | [organization.tf](./organization.tf) | None | organization | | | [output-files.tf](./output-files.tf) | None | | google_storage_bucket_object ยท local_file | | [outputs.tf](./outputs.tf) | Module outputs. | | | @@ -814,8 +847,8 @@ Define values for the `var.environments` variable in a tfvars file. | name | description | type | required | default | |---|---|:---:|:---:|:---:| | [context](variables.tf#L17) | Context-specific interpolations. | object({…}) | | {} | -| [factories_config](variables.tf#L40) | Configuration for the resource factories or external data. | object({…}) | | {} | -| [org_policies_imports](variables.tf#L55) | List of org policies to import. These need to also be defined in data files. | list(string) | | [] | +| [factories_config](variables.tf#L40) | Configuration for the resource factories or external data. | object({…}) | | {} | +| [org_policies_imports](variables.tf#L56) | List of org policies to import. These need to also be defined in data files. | list(string) | | [] | ## Outputs diff --git a/fast/stages/0-org-setup/datasets/classic/defaults.yaml b/fast/stages/0-org-setup/datasets/classic/defaults.yaml index 2c04275f2..20572f443 100644 --- a/fast/stages/0-org-setup/datasets/classic/defaults.yaml +++ b/fast/stages/0-org-setup/datasets/classic/defaults.yaml @@ -30,6 +30,9 @@ projects: bigquery: $locations:primary logging: $locations:primary storage: $locations:primary + observability: + project_id: $project_ids:log-0 + project_number: $project_numbers:log-0 overrides: {} context: # you can populate context variables here for use in YAML replacements diff --git a/fast/stages/2-security/data/folders/dev/.config.yaml b/fast/stages/0-org-setup/datasets/classic/folders/security/dev/.config.yaml similarity index 100% rename from fast/stages/2-security/data/folders/dev/.config.yaml rename to fast/stages/0-org-setup/datasets/classic/folders/security/dev/.config.yaml diff --git a/fast/stages/2-security/data/folders/prod/.config.yaml b/fast/stages/0-org-setup/datasets/classic/folders/security/prod/.config.yaml similarity index 100% rename from fast/stages/2-security/data/folders/prod/.config.yaml rename to fast/stages/0-org-setup/datasets/classic/folders/security/prod/.config.yaml diff --git a/fast/stages/0-org-setup/datasets/hardened/defaults.yaml b/fast/stages/0-org-setup/datasets/hardened/defaults.yaml index 2c04275f2..20572f443 100644 --- a/fast/stages/0-org-setup/datasets/hardened/defaults.yaml +++ b/fast/stages/0-org-setup/datasets/hardened/defaults.yaml @@ -30,6 +30,9 @@ projects: bigquery: $locations:primary logging: $locations:primary storage: $locations:primary + observability: + project_id: $project_ids:log-0 + project_number: $project_numbers:log-0 overrides: {} context: # you can populate context variables here for use in YAML replacements diff --git a/fast/stages/0-org-setup/datasets/hardened/organization/observability/auditConfigChanges.yaml b/fast/stages/0-org-setup/datasets/hardened/observability/auditConfigChanges.yaml similarity index 100% rename from fast/stages/0-org-setup/datasets/hardened/organization/observability/auditConfigChanges.yaml rename to fast/stages/0-org-setup/datasets/hardened/observability/auditConfigChanges.yaml diff --git a/fast/stages/0-org-setup/datasets/hardened/organization/observability/binaryAuthorizationPolicyChanges.yaml b/fast/stages/0-org-setup/datasets/hardened/observability/binaryAuthorizationPolicyChanges.yaml similarity index 100% rename from fast/stages/0-org-setup/datasets/hardened/organization/observability/binaryAuthorizationPolicyChanges.yaml rename to fast/stages/0-org-setup/datasets/hardened/observability/binaryAuthorizationPolicyChanges.yaml diff --git a/fast/stages/0-org-setup/datasets/hardened/organization/observability/cloudsqlInstanceChanges.yaml b/fast/stages/0-org-setup/datasets/hardened/observability/cloudsqlInstanceChanges.yaml similarity index 100% rename from fast/stages/0-org-setup/datasets/hardened/organization/observability/cloudsqlInstanceChanges.yaml rename to fast/stages/0-org-setup/datasets/hardened/observability/cloudsqlInstanceChanges.yaml diff --git a/fast/stages/0-org-setup/datasets/hardened/organization/observability/customRoleChanges.yaml b/fast/stages/0-org-setup/datasets/hardened/observability/customRoleChanges.yaml similarity index 100% rename from fast/stages/0-org-setup/datasets/hardened/organization/observability/customRoleChanges.yaml rename to fast/stages/0-org-setup/datasets/hardened/observability/customRoleChanges.yaml diff --git a/fast/stages/0-org-setup/datasets/hardened/organization/observability/firewallPolicyRuleChanges.yaml b/fast/stages/0-org-setup/datasets/hardened/observability/firewallPolicyRuleChanges.yaml similarity index 100% rename from fast/stages/0-org-setup/datasets/hardened/organization/observability/firewallPolicyRuleChanges.yaml rename to fast/stages/0-org-setup/datasets/hardened/observability/firewallPolicyRuleChanges.yaml diff --git a/fast/stages/0-org-setup/datasets/hardened/organization/observability/firewallRuleChanges.yaml b/fast/stages/0-org-setup/datasets/hardened/observability/firewallRuleChanges.yaml similarity index 100% rename from fast/stages/0-org-setup/datasets/hardened/organization/observability/firewallRuleChanges.yaml rename to fast/stages/0-org-setup/datasets/hardened/observability/firewallRuleChanges.yaml diff --git a/fast/stages/0-org-setup/datasets/hardened/organization/observability/networkChanges.yaml b/fast/stages/0-org-setup/datasets/hardened/observability/networkChanges.yaml similarity index 100% rename from fast/stages/0-org-setup/datasets/hardened/organization/observability/networkChanges.yaml rename to fast/stages/0-org-setup/datasets/hardened/observability/networkChanges.yaml diff --git a/fast/stages/0-org-setup/datasets/hardened/organization/observability/networkRouteChanges.yaml b/fast/stages/0-org-setup/datasets/hardened/observability/networkRouteChanges.yaml similarity index 100% rename from fast/stages/0-org-setup/datasets/hardened/organization/observability/networkRouteChanges.yaml rename to fast/stages/0-org-setup/datasets/hardened/observability/networkRouteChanges.yaml diff --git a/fast/stages/0-org-setup/datasets/hardened/organization/observability/projectOwnershipChange.yaml b/fast/stages/0-org-setup/datasets/hardened/observability/projectOwnershipChange.yaml similarity index 100% rename from fast/stages/0-org-setup/datasets/hardened/organization/observability/projectOwnershipChange.yaml rename to fast/stages/0-org-setup/datasets/hardened/observability/projectOwnershipChange.yaml diff --git a/fast/stages/0-org-setup/datasets/hardened/organization/observability/storageIamChanges.yaml b/fast/stages/0-org-setup/datasets/hardened/observability/storageIamChanges.yaml similarity index 100% rename from fast/stages/0-org-setup/datasets/hardened/organization/observability/storageIamChanges.yaml rename to fast/stages/0-org-setup/datasets/hardened/observability/storageIamChanges.yaml diff --git a/fast/stages/0-org-setup/datasets/hardened/organization/.config.yaml b/fast/stages/0-org-setup/datasets/hardened/organization/.config.yaml index 235749a61..ae282ba27 100644 --- a/fast/stages/0-org-setup/datasets/hardened/organization/.config.yaml +++ b/fast/stages/0-org-setup/datasets/hardened/organization/.config.yaml @@ -81,12 +81,25 @@ iam_by_principals: - $custom_roles:organization_admin_viewer - $custom_roles:tag_viewer $iam_principals:service_accounts/iac-0/iac-networking-rw: + # uncomment for cooperative VPC-SC configurations + # - roles/accesscontextmanager.policyEditor - roles/compute.orgFirewallPolicyAdmin - roles/compute.xpnAdmin $iam_principals:service_accounts/iac-0/iac-networking-ro: + # uncomment for cooperative VPC-SC configurations + # - roles/accesscontextmanager.policyViewer - roles/compute.orgFirewallPolicyUser - roles/compute.viewer + # uncomment for cooperative VPC-SC configurations + # $iam_principals:service_accounts/iac-0/iac-pw-rw: + # - roles/accesscontextmanager.policyEditor $iam_principals:service_accounts/iac-0/iac-security-rw: + # uncomment for cooperative VPC-SC configurations + # - roles/accesscontextmanager.policyEditor + - roles/cloudasset.viewer + $iam_principals:service_accounts/iac-0/iac-security-ro: + # uncomment for cooperative VPC-SC configurations + # - roles/accesscontextmanager.policyViewer - roles/cloudasset.viewer $iam_principals:service_accounts/iac-0/iac-vpcsc-rw: - roles/accesscontextmanager.policyAdmin @@ -94,6 +107,9 @@ iam_by_principals: $iam_principals:service_accounts/iac-0/iac-vpcsc-ro: - roles/accesscontextmanager.policyReader - roles/cloudasset.viewer + # Uncomment if you want to use PAM. + # $service_agents:pam: + # - roles/privilegedaccessmanager.serviceAgent data_access_logs: allServices: ADMIN_READ: {} diff --git a/fast/stages/0-org-setup/datasets/hardened/organization/org-policies/cloudkms.yaml b/fast/stages/0-org-setup/datasets/hardened/organization/org-policies/cloudkms.yaml index 48b8a7a13..a8b5a71ee 100644 --- a/fast/stages/0-org-setup/datasets/hardened/organization/org-policies/cloudkms.yaml +++ b/fast/stages/0-org-setup/datasets/hardened/organization/org-policies/cloudkms.yaml @@ -21,3 +21,66 @@ custom.cloudkmsAllowedProtectionLevel: rules: - enforce: true + +gcp.restrictCmekCryptoKeyProjects: + rules: + - allow: + values: + - 'under:${folder_ids["security/dev"]}' + condition: + title: Restrict CMEK Projects for development projects + expression: | + resource.matchTag('${organization.id}/environment', 'development') + - allow: + values: + - 'under:${folder_ids["security/prod"]}' + condition: + title: Restrict CMEK Projects for non-development projects + expression: | + !resource.matchTag('${organization.id}/environment', 'development') + +gcp.restrictNonCmekServices: + rules: + - deny: + values: + - "aiplatform.googleapis.com" + - "alloydb.googleapis.com" + - "apigee.googleapis.com" + - "artifactregistry.googleapis.com" + - "bigquery.googleapis.com" + - "bigquerydatatransfer.googleapis.com" + - "bigtable.googleapis.com" + - "cloudfunctions.googleapis.com" + - "cloudtasks.googleapis.com" + - "composer.googleapis.com" + - "compute.googleapis.com" + - "contactcenterinsights.googleapis.com" + - "container.googleapis.com" + - "dataflow.googleapis.com" + - "dataform.googleapis.com" + - "datafusion.googleapis.com" + # To enable when Terraform provider is ready: https://docs.cloud.google.com/dataplex/docs/cmek + # - "dataplex.googleapis.com" + - "dataproc.googleapis.com" + - "dialogflow.googleapis.com" + - "discoveryengine.googleapis.com" + - "documentai.googleapis.com" + - "file.googleapis.com" + - "firestore.googleapis.com" + - "gkebackup.googleapis.com" + - "integrations.googleapis.com" + - "logging.googleapis.com" + - "looker.googleapis.com" + - "notebooks.googleapis.com" + - "pubsub.googleapis.com" + - "redis.googleapis.com" + - "run.googleapis.com" + - "secretmanager.googleapis.com" + - "securesourcemanager.googleapis.com" + - "securitycenter.googleapis.com" + - "spanner.googleapis.com" + - "speech.googleapis.com" + - "sqladmin.googleapis.com" + - "storage.googleapis.com" + - "storagetransfer.googleapis.com" + - "workstations.googleapis.com" diff --git a/fast/stages/0-org-setup/datasets/hardened/projects/core/billing-0.yaml b/fast/stages/0-org-setup/datasets/hardened/projects/core/billing-0.yaml index 29070bbc2..38b7756ec 100644 --- a/fast/stages/0-org-setup/datasets/hardened/projects/core/billing-0.yaml +++ b/fast/stages/0-org-setup/datasets/hardened/projects/core/billing-0.yaml @@ -23,7 +23,24 @@ iam_by_principals: services: - bigquery.googleapis.com - bigquerydatatransfer.googleapis.com + - cloudkms.googleapis.com - storage.googleapis.com +kms: + keyrings: + ew1: + location: europe-west1 + keys: + bigquery: + rotation_period: 7776000s +service_encryption_key_ids: + bigquery.googleapis.com: + - $kms_keys:billing-0/ew1/bigquery +org_policies: + gcp.restrictCmekCryptoKeyProjects: + rules: + - allow: + all: true datasets: billing_export: friendly_name: Billing export + encryption_key: $kms_keys:billing-0/ew1/bigquery diff --git a/fast/stages/0-org-setup/datasets/hardened/projects/core/iac-0.yaml b/fast/stages/0-org-setup/datasets/hardened/projects/core/iac-0.yaml index 9763e3e52..d1879bfe8 100644 --- a/fast/stages/0-org-setup/datasets/hardened/projects/core/iac-0.yaml +++ b/fast/stages/0-org-setup/datasets/hardened/projects/core/iac-0.yaml @@ -74,7 +74,21 @@ services: - storage-component.googleapis.com - storage.googleapis.com - sts.googleapis.com +kms: + keyrings: + ew1: + location: europe-west1 + keys: + storage: + rotation_period: 7776000s +service_encryption_key_ids: + storage.googleapis.com: + - $kms_keys:iac-0/ew1/storage org_policies: + gcp.restrictCmekCryptoKeyProjects: + rules: + - allow: + all: true iam.workloadIdentityPoolProviders: rules: - allow: @@ -87,6 +101,7 @@ buckets: iac-org-state: description: Terraform state for the org-level automation. versioning: true + encryption_key: $kms_keys:iac-0/ew1/storage iam: roles/storage.admin: - $iam_principals:service_accounts/iac-0/iac-org-rw @@ -96,6 +111,7 @@ buckets: iac-stage-state: description: Terraform state for stage automation. versioning: true + encryption_key: $kms_keys:iac-0/ew1/storage managed_folders: 1-vpcsc: iam: @@ -131,6 +147,7 @@ buckets: iac-outputs: description: Terraform state for the org-level automation. versioning: true + encryption_key: $kms_keys:iac-0/ew1/storage iam: roles/storage.admin: - $iam_principals:service_accounts/iac-0/iac-org-rw @@ -192,3 +209,13 @@ service_accounts: display_name: IaC service account for data platform dev (read-only). iac-dp-dev-rw: display_name: IaC service account for data platform dev (read-write). +# workload_identity_pools: +# default: +# display_name: Default pool for CI/CD. +# providers: +# github-default: +# display_name: GitHub (my org). +# attribute_condition: attribute.repository_owner=="myorg" +# identity_provider: +# oidc: +# template: github diff --git a/fast/stages/0-org-setup/datasets/hardened/projects/core/log-0.yaml b/fast/stages/0-org-setup/datasets/hardened/projects/core/log-0.yaml index 2c8930638..df3da935e 100644 --- a/fast/stages/0-org-setup/datasets/hardened/projects/core/log-0.yaml +++ b/fast/stages/0-org-setup/datasets/hardened/projects/core/log-0.yaml @@ -21,19 +21,37 @@ iam_by_principals: $iam_principals:service_accounts/iac-0/iac-org-rw: - roles/owner services: + - cloudkms.googleapis.com - logging.googleapis.com - pubsub.googleapis.com - storage.googleapis.com +kms: + keyrings: + ew1: + location: europe-west1 + keys: + logging: + rotation_period: 7776000s +service_encryption_key_ids: + logging.googleapis.com: + - $kms_keys:log-0/ew1/logging log_buckets: - audit-logs: {} - iam: {} + audit-logs: + kms_key_name: $kms_keys:log-0/ew1/logging + iam: + kms_key_name: $kms_keys:log-0/ew1/logging vpc-sc: + kms_key_name: $kms_keys:log-0/ew1/logging log_analytics: enable: true retention: 31 factories_config: observability: datasets/hardened/organization/observability/ org_policies: + gcp.restrictCmekCryptoKeyProjects: + rules: + - allow: + all: true custom.storageRequireBucketObjectVersionning: rules: - enforce: true diff --git a/fast/stages/0-org-setup/main.tf b/fast/stages/0-org-setup/main.tf index a09508278..e9fd20f77 100644 --- a/fast/stages/0-org-setup/main.tf +++ b/fast/stages/0-org-setup/main.tf @@ -41,6 +41,11 @@ locals { local.project_defaults.overrides.prefix, null ) + observability = try( + local.project_defaults.defaults.observability, + local.project_defaults.overrides.observability, + null + ) } iam_principals = merge( local.org_iam_principals, diff --git a/fast/stages/0-org-setup/observability.tf b/fast/stages/0-org-setup/observability.tf new file mode 100644 index 000000000..ebc855d4f --- /dev/null +++ b/fast/stages/0-org-setup/observability.tf @@ -0,0 +1,65 @@ +/** + * Copyright 2025 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +locals { + _observability_project = ( + try(local.project_defaults.defaults.observability, null) != null || + try(local.project_defaults.overrides.observability, null) != null + ) ? { + project_id = local.defaults.observability.project_id + project_number = local.defaults.observability.project_number + } : {} + + observability_project_id = try(lookup( + module.factory.project_ids, + replace(local._observability_project.project_id, "$project_ids:", ""), + local._observability_project.project_id + ), null) + + observability_project_number = try(lookup( + module.factory.project_numbers, + replace(local._observability_project.project_number, "$project_numbers:", ""), + local._observability_project.project_number + ), null) +} + +module "projects-observability" { + source = "../../../modules/project" + count = length(local._observability_project) > 0 ? 1 : 0 + + name = local.observability_project_id + project_reuse = { + use_data_source = false + attributes = { + name = local.observability_project_id + number = local.observability_project_number + } + } + + context = merge(local.ctx, { + folder_ids = module.factory.folder_ids + kms_keys = module.factory.kms_keys + log_buckets = module.factory.log_buckets + project_ids = module.factory.project_ids + }) + + factories_config = { + observability = var.factories_config.observability + } +} + + diff --git a/fast/stages/0-org-setup/organization.tf b/fast/stages/0-org-setup/organization.tf index 659ed2ccb..9205d8519 100644 --- a/fast/stages/0-org-setup/organization.tf +++ b/fast/stages/0-org-setup/organization.tf @@ -104,7 +104,8 @@ module "organization-iam" { context = merge(local.ctx, { condition_vars = merge( local.ctx_condition_vars, - { folder_ids = module.factory.folder_ids } + { folder_ids = module.factory.folder_ids }, + { project_ids = module.factory.project_ids } ) custom_roles = merge( local.ctx.custom_roles, diff --git a/fast/stages/0-org-setup/variables.tf b/fast/stages/0-org-setup/variables.tf index 1e0d63513..fcb679900 100644 --- a/fast/stages/0-org-setup/variables.tf +++ b/fast/stages/0-org-setup/variables.tf @@ -44,6 +44,7 @@ variable "factories_config" { cicd_workflows = optional(string) defaults = optional(string, "datasets/classic/defaults.yaml") folders = optional(string, "datasets/classic/folders") + observability = optional(string, "datasets/classic/observability") organization = optional(string, "datasets/classic/organization") project_templates = optional(string, "datasets/classic/templates") projects = optional(string, "datasets/classic/projects") diff --git a/fast/stages/2-project-factory/data/projects/dev-app-a-0.yaml b/fast/stages/2-project-factory/data/projects/dev-app-a-0.yaml index 6cf40436d..4e3c1d883 100644 --- a/fast/stages/2-project-factory/data/projects/dev-app-a-0.yaml +++ b/fast/stages/2-project-factory/data/projects/dev-app-a-0.yaml @@ -15,6 +15,8 @@ # yaml-language-server: $schema=../../schemas/project.schema.json parent: $folder_ids:team-a/dev +services: + - compute.googleapis.com shared_vpc_service_config: host_project: $project_ids:net-dev-0 # network_users: diff --git a/fast/stages/2-project-factory/data/projects/prod-app-a-0.yaml b/fast/stages/2-project-factory/data/projects/prod-app-a-0.yaml index de6c24e3b..46f15217c 100644 --- a/fast/stages/2-project-factory/data/projects/prod-app-a-0.yaml +++ b/fast/stages/2-project-factory/data/projects/prod-app-a-0.yaml @@ -15,6 +15,8 @@ # yaml-language-server: $schema=../../schemas/project.schema.json parent: $folder_ids:team-a/prod +services: + - compute.googleapis.com shared_vpc_service_config: host_project: $project_ids:net-prod-0 # network_users: diff --git a/fast/stages/2-security/data/keyrings/dev-primary-default.yaml b/fast/stages/2-security/data/keyrings/dev-primary-default.yaml new file mode 100644 index 000000000..0626fb51e --- /dev/null +++ b/fast/stages/2-security/data/keyrings/dev-primary-default.yaml @@ -0,0 +1,30 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# yaml-language-server: $schema=../../schemas/keyring.schema.json + +location: $locations:primary +project_id: $project_ids:dev-sec-core-0 +keys: + bigquery: + rotation_period: 7776000s + composer: + rotation_period: 7776000s + compute: + rotation_period: 7776000s + storage: + rotation_period: 7776000s + gke: + rotation_period: 7776000s + diff --git a/fast/stages/2-security/data/keyrings/prod-primary-default.yaml b/fast/stages/2-security/data/keyrings/prod-primary-default.yaml index 5a7c2ab1f..fbcfd5c21 100644 --- a/fast/stages/2-security/data/keyrings/prod-primary-default.yaml +++ b/fast/stages/2-security/data/keyrings/prod-primary-default.yaml @@ -17,5 +17,7 @@ location: $locations:primary project_id: $project_ids:prod-sec-core-0 keys: - compute: {} - storage: {} + compute: + rotation_period: 7776000s + storage: + rotation_period: 7776000s diff --git a/fast/stages/2-security/data/projects/dev-sec-core-0.yaml b/fast/stages/2-security/data/projects/dev-sec-core-0.yaml index 2cd66af3c..1c7040348 100644 --- a/fast/stages/2-security/data/projects/dev-sec-core-0.yaml +++ b/fast/stages/2-security/data/projects/dev-sec-core-0.yaml @@ -14,7 +14,7 @@ # yaml-language-server: $schema=../../../0-org-setup/schemas/project.schema.json -parent: $folder_ids:dev +parent: $folder_ids:security/dev services: - certificatemanager.googleapis.com - cloudkms.googleapis.com diff --git a/fast/stages/2-security/data/projects/prod-sec-core-0.yaml b/fast/stages/2-security/data/projects/prod-sec-core-0.yaml index b339aa5b3..fed149071 100644 --- a/fast/stages/2-security/data/projects/prod-sec-core-0.yaml +++ b/fast/stages/2-security/data/projects/prod-sec-core-0.yaml @@ -14,7 +14,7 @@ # yaml-language-server: $schema=../../../0-org-setup/schemas/project.schema.json -parent: $folder_ids:prod +parent: $folder_ids:security/prod services: - certificatemanager.googleapis.com - cloudkms.googleapis.com diff --git a/fast/stages/3-data-platform-dev/README.md b/fast/stages/3-data-platform-dev/README.md index 3f048009f..accbbeca1 100644 --- a/fast/stages/3-data-platform-dev/README.md +++ b/fast/stages/3-data-platform-dev/README.md @@ -21,6 +21,7 @@ While our solution is conceptually guided by [Data Mesh principles on Google Clo - [FAST prerequisites](#fast-prerequisites) - [Provider and Terraform variables](#provider-and-terraform-variables) - [Variable Configuration](#variable-configuration) + - [CMEK Configuration](#cmek-configuration) - [Data Domain and Product Data Files](#data-domain-and-product-data-files) - [Context replacements](#context-replacements) - [Files](#files) @@ -239,6 +240,24 @@ The default data files provided as an example makes a few assumptions that needs - the domain `deploy_config.composer.node_config.subnetwork` attribute needs to match the location defined above; Composer network and subnetwork use interpolation from FAST networking outputs, explicit IDs can be used instead if needed - IAM roles for the domain and product refer to generic `dp-product-a-0` and `data-consumer-bi` groups, these need to be defined via the `factories_config.context.iam_principals` variable, or changed to explicit IAM principals (e.g. `group:foo@example.com`) +### CMEK Configuration + +The stage can be provisioned with CMEK keys configured for composer, bigquery datasets and storage bucket by using this configuration for the `encryption_keys` variable: + +```hcl +encryption_keys = { + bigquery = { + "europe-west1" = "projects/myproject/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/bigquery" + } + composer = { + "europe-west1" = "projects/myproject/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/composer" + } + storage = { + "europe-west1" = "projects/myproject/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/storage" + } +} +``` + ### Data Domain and Product Data Files The formats for both types of data files are controlled via [schemas](./schemas/), which can generally be used directly in development environments to provide error checking and autocompletion. diff --git a/fast/stages/3-data-platform-dev/data-domains-automation.tf b/fast/stages/3-data-platform-dev/data-domains-automation.tf index 841363a66..f149ed323 100644 --- a/fast/stages/3-data-platform-dev/data-domains-automation.tf +++ b/fast/stages/3-data-platform-dev/data-domains-automation.tf @@ -16,12 +16,26 @@ # tfdoc:file:description Data product automation resources. -module "dd-automation-bucket" { - source = "../../../modules/gcs" - for_each = { +locals { + dd_automation = { for k, v in local.data_domains : k => v if v.automation != null } + dd_automation_keys = { + for k, v in local.dd_automation : k => try( + v.automation.encryption_key, + var.encryption_keys.storage[try( + v.automation.location, + var.location + )], + null + ) + } +} + +module "dd-automation-bucket" { + source = "../../../modules/gcs" + for_each = local.dd_automation project_id = module.dd-projects[each.key].project_id prefix = local.prefix name = "${each.value.short_name}-state" @@ -29,6 +43,7 @@ module "dd-automation-bucket" { each.value.automation.location, var.location ) + encryption_key = local.dd_automation_keys[each.key] iam = { "roles/storage.admin" = [ module.dd-automation-sa["${each.key}/rw"].iam_email diff --git a/fast/stages/3-data-platform-dev/data-domains.tf b/fast/stages/3-data-platform-dev/data-domains.tf index f14031d97..4d70747f9 100644 --- a/fast/stages/3-data-platform-dev/data-domains.tf +++ b/fast/stages/3-data-platform-dev/data-domains.tf @@ -100,7 +100,7 @@ module "dd-projects" { data_domain = each.key } services = local.dd_services[each.key] - service_encryption_key_ids = ( + service_encryption_key_ids = merge( lookup(local.dd_composer, each.key, null) == null ? {} : { "composer.googleapis.com" = compact([ try(local.dd_composer_keys[each.key], null) == null @@ -111,7 +111,18 @@ module "dd-projects" { local.dd_composer_keys[each.key] ) ]) - } + }, + lookup(local.dd_automation_keys, each.key, null) == null ? {} : { + "storage.googleapis.com" = compact([ + try(local.dd_automation_keys[each.key], null) == null + ? null + : lookup( + local.kms_keys, + local.dd_automation_keys[each.key], + local.dd_automation_keys[each.key] + ) + ]) + }, ) } diff --git a/fast/stages/3-data-platform-dev/data-products-automation.tf b/fast/stages/3-data-platform-dev/data-products-automation.tf index 884f626d9..eadf61c18 100644 --- a/fast/stages/3-data-platform-dev/data-products-automation.tf +++ b/fast/stages/3-data-platform-dev/data-products-automation.tf @@ -16,12 +16,26 @@ # tfdoc:file:description Data product automation resources. -module "dp-automation-bucket" { - source = "../../../modules/gcs" - for_each = { +locals { + dp_automation_products = { for k, v in local.data_products : k => v if v.automation != null } + dp_automation_products_keys = { + for k, v in local.dp_automation_products : k => try( + v.automation.encryption_key, + var.encryption_keys.storage[try( + v.automation.location, + var.location + )], + null + ) + } +} + +module "dp-automation-bucket" { + source = "../../../modules/gcs" + for_each = local.dp_automation_products project_id = module.dd-projects[each.value.dd].project_id prefix = local.prefix name = "${each.value.short_name}-state" @@ -29,6 +43,7 @@ module "dp-automation-bucket" { each.value.automation.location, var.location ) + encryption_key = local.dp_automation_products_keys[each.key] iam = { "roles/storage.admin" = [ module.dp-automation-sa["${each.key}/rw"].iam_email diff --git a/fast/stages/3-gke-dev/README.md b/fast/stages/3-gke-dev/README.md index 830e5b4dd..cf8a63421 100644 --- a/fast/stages/3-gke-dev/README.md +++ b/fast/stages/3-gke-dev/README.md @@ -185,18 +185,18 @@ Clusters can then be configured for fleet registration and one of the config man | [billing_account](variables-fast.tf#L26) | Billing account id. If billing account is not part of the same org set `is_org_level` to false. | object({…}) | โœ“ | | 0-org-setup | | [environments](variables-fast.tf#L34) | Long environment names. | object({…}) | โœ“ | | 1-resman | | [prefix](variables-fast.tf#L60) | Prefix used for resources that need unique names. Use a maximum of 9 chars for organizations, and 11 chars for tenants. | string | โœ“ | | 0-org-setup | -| [clusters](variables.tf#L17) | Clusters configuration. Refer to the gke-cluster module for type details. | map(object({…})) | | {} | | -| [deletion_protection](variables.tf#L99) | Prevent Terraform from destroying data resources. | bool | | false | | +| [clusters](variables.tf#L17) | Clusters configuration. Refer to the gke-cluster module for type details. | map(object({…})) | | {} | | +| [deletion_protection](variables.tf#L102) | Prevent Terraform from destroying data resources. | bool | | false | | | [fleet_config](variables-fleet.tf#L19) | Fleet configuration. | object({…}) | | null | | | [fleet_configmanagement_templates](variables-fleet.tf#L35) | Sets of fleet configurations that can be applied to member clusters, in config name => {options} format. | map(object({…})) | | {} | | | [folder_ids](variables-fast.tf#L44) | Folder name => id mappings. | map(string) | | {} | 1-resman | | [host_project_ids](variables-fast.tf#L52) | Shared VPC host project name => id mappings. | map(string) | | {} | 2-networking | -| [iam](variables.tf#L106) | Project-level authoritative IAM bindings for users and service accounts in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} | | -| [iam_by_principals](variables.tf#L113) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable. | map(list(string)) | | {} | | -| [nodepools](variables.tf#L120) | Nodepools configuration. Refer to the gke-nodepool module for type details. | map(map(object({…}))) | | {} | | -| [stage_config](variables.tf#L169) | FAST stage configuration used to find resource ids. Must match name defined for the stage in resource management. | object({…}) | | {…} | | +| [iam](variables.tf#L109) | Project-level authoritative IAM bindings for users and service accounts in {ROLE => [MEMBERS]} format. | map(list(string)) | | {} | | +| [iam_by_principals](variables.tf#L116) | Authoritative IAM binding in {PRINCIPAL => [ROLES]} format. Principals need to be statically defined to avoid cycle errors. Merged internally with the `iam` variable. | map(list(string)) | | {} | | +| [nodepools](variables.tf#L123) | Nodepools configuration. Refer to the gke-nodepool module for type details. | map(map(object({…}))) | | {} | | +| [stage_config](variables.tf#L172) | FAST stage configuration used to find resource ids. Must match name defined for the stage in resource management. | object({…}) | | {…} | | | [subnet_self_links](variables-fast.tf#L70) | Subnet VPC name => { name => self link } mappings. | map(map(string)) | | {} | 2-networking | -| [vpc_config](variables.tf#L181) | VPC-level configuration for project and clusters. | object({…}) | | {…} | | +| [vpc_config](variables.tf#L184) | VPC-level configuration for project and clusters. | object({…}) | | {…} | | | [vpc_self_links](variables-fast.tf#L78) | Shared VPC name => self link mappings. | map(string) | | {} | 2-networking | ## Outputs diff --git a/fast/stages/3-gke-dev/gke-clusters.tf b/fast/stages/3-gke-dev/gke-clusters.tf index f79d2233f..3cd0f3807 100644 --- a/fast/stages/3-gke-dev/gke-clusters.tf +++ b/fast/stages/3-gke-dev/gke-clusters.tf @@ -69,13 +69,13 @@ module "gke-cluster" { ) }) deletion_protection = var.deletion_protection - node_config = { + node_config = merge(coalesce(each.value.node_config, {}), { service_account = ( each.value.service_account == null ? module.gke-nodes-service-account.email : each.value.service_account ) - } + }) } module "gke-nodepool" { diff --git a/fast/stages/3-gke-dev/main.tf b/fast/stages/3-gke-dev/main.tf index 348506d1c..6ccb22ed8 100644 --- a/fast/stages/3-gke-dev/main.tf +++ b/fast/stages/3-gke-dev/main.tf @@ -26,6 +26,23 @@ locals { "stackdriver.resourceMetadata.writer" ] project_name = "${var.stage_config.environment}-gke-core-0" + _cmek_keys_container = toset(compact(flatten([ + [for k, v in var.clusters : try(v.node_config.boot_disk_kms_key, null)], + [ + for k, v in var.nodepools : [ + for nk, nv in v : try(nv.node_config.boot_disk_kms_key, null) + ] + ] + ]))) + _cmek_keys_pubsub = toset(compact(flatten([ + [for k, v in var.clusters : try(v.enable_features.upgrade_notifications.kms_key_name, null)], + ]))) + service_encryption_key_ids = { + for k, v in { + "container.googleapis.com" = local._cmek_keys_container + "pubsub.googleapis.com" = local._cmek_keys_pubsub + } : k => v if length(v) > 0 + } } module "gke-project-0" { @@ -60,17 +77,20 @@ module "gke-project-0" { "anthosconfigmanagement.googleapis.com", "cloudresourcemanager.googleapis.com", "container.googleapis.com", + "compute.googleapis.com", "dns.googleapis.com", "gkeconnect.googleapis.com", "gkehub.googleapis.com", "iam.googleapis.com", "logging.googleapis.com", "monitoring.googleapis.com", + "pubsub.googleapis.com", "multiclusteringress.googleapis.com", "multiclusterservicediscovery.googleapis.com", "orgpolicy.googleapis.com", "trafficdirector.googleapis.com" ] + service_encryption_key_ids = local.service_encryption_key_ids shared_vpc_service_config = { attach = true host_project = lookup( diff --git a/fast/stages/3-gke-dev/variables.tf b/fast/stages/3-gke-dev/variables.tf index bde373d98..31bfc62fc 100644 --- a/fast/stages/3-gke-dev/variables.tf +++ b/fast/stages/3-gke-dev/variables.tf @@ -91,6 +91,9 @@ variable "clusters" { services = string }), { pods = "pods", services = "services" }) }) + node_config = optional(object({ + boot_disk_kms_key = optional(string) + })) })) default = {} nullable = false diff --git a/fast/stages/CLEANUP.md b/fast/stages/CLEANUP.md index a8c989d89..b707143a1 100644 --- a/fast/stages/CLEANUP.md +++ b/fast/stages/CLEANUP.md @@ -80,10 +80,18 @@ for x in $(terraform state list | grep google_storage_bucket.bucket); do terraform state rm "$x"; done +for x in $(terraform state list | grep google_storage_managed_folder.folder); do + terraform state rm "$x"; +done + for x in $(terraform state list | grep google_bigquery_dataset); do terraform state rm "$x"; done +for x in $(terraform state list | grep google_logging_project_bucket_config); do + terraform state rm "$x"; +done + # remove custom constraint to avoid future issue during reprovisionnning. # comment this part if permanent removed is needed for x in $(terraform state list | grep google_org_policy_custom_constraint); do diff --git a/modules/folder/README.md b/modules/folder/README.md index 0bf3cae3e..c77bf7333 100644 --- a/modules/folder/README.md +++ b/modules/folder/README.md @@ -398,7 +398,7 @@ module "folder-sink" { no-gce-instances = "resource.type=gce_instance" } } -# tftest modules=6 resources=18 inventory=logging.yaml e2e +# tftest inventory=logging.yaml e2e ``` ## Data Access Logs diff --git a/modules/organization/README.md b/modules/organization/README.md index 3548c7254..d1f18c1ea 100644 --- a/modules/organization/README.md +++ b/modules/organization/README.md @@ -417,7 +417,7 @@ module "org" { no-gce-instances = "resource.type=gce_instance" } } -# tftest modules=6 resources=19 inventory=logging.yaml +# tftest inventory=logging.yaml ``` ## Data Access Logs diff --git a/modules/project-factory/projects-log-buckets.tf b/modules/project-factory/projects-log-buckets.tf index 95eb1ac19..abdd76df4 100644 --- a/modules/project-factory/projects-log-buckets.tf +++ b/modules/project-factory/projects-log-buckets.tf @@ -41,7 +41,7 @@ module "log-buckets" { for_each = { for k in local.projects_log_buckets : "${k.project_key}/${k.name}" => k } - parent = module.projects[each.value.project_key].project_id + parent = module.projects-iam[each.value.project_key].project_id name = each.value.name location = each.value.location kms_key_name = each.value.kms_key_name diff --git a/modules/project-factory/projects.tf b/modules/project-factory/projects.tf index 4dfeb0413..bfe1c4f4d 100644 --- a/modules/project-factory/projects.tf +++ b/modules/project-factory/projects.tf @@ -55,10 +55,6 @@ locals { project_numbers = { for k, v in module.projects : k => v.number } - ctx_log_buckets = merge(local.ctx.log_buckets, local.log_buckets) - log_buckets = { - for key, log_bucket in module.log-buckets : key => log_bucket.id - } projects_input = merge(var.projects, local._projects_output) projects_service_agents = merge([ for k, v in module.projects : { @@ -150,13 +146,12 @@ module "projects-iam" { } context = merge(local.ctx, { folder_ids = local.ctx.folder_ids - kms_keys = local.ctx.kms_keys + kms_keys = merge(local.ctx.kms_keys, local.kms_keys) iam_principals = merge( local.ctx_iam_principals, lookup(local.self_sas_iam_emails, each.key, {}), local.projects_service_agents ) - log_buckets = local.ctx_log_buckets project_ids = merge( local.ctx.project_ids, { for k, v in module.projects : k => v.project_id } @@ -164,7 +159,6 @@ module "projects-iam" { }) factories_config = { # we do anything that can refer to IAM and custom roles in this call - observability = try(each.value.factories_config.observability, null) pam_entitlements = try(each.value.factories_config.pam_entitlements, null) } iam = lookup(each.value, "iam", {}) diff --git a/modules/project/README.md b/modules/project/README.md index 9b56f81fe..7404bbed7 100644 --- a/modules/project/README.md +++ b/modules/project/README.md @@ -774,7 +774,7 @@ module "project-host" { no-gce-instances = "resource.type=gce_instance" } } -# tftest modules=6 resources=19 inventory=logging.yaml e2e +# tftest inventory=logging.yaml e2e ``` ## Data Access Logs @@ -842,7 +842,7 @@ module "project" { } } } -# tftest modules=2 resources=6 inventory=log-scopes.yaml +# tftest inventory=log-scopes.yaml ``` ## Cloud KMS Encryption Keys diff --git a/modules/project/cmek.tf b/modules/project/cmek.tf index 3a3efbbf1..0c3f22e9d 100644 --- a/modules/project/cmek.tf +++ b/modules/project/cmek.tf @@ -91,5 +91,6 @@ resource "google_kms_crypto_key_iam_member" "service_agent_cmek" { data.google_project.project, data.google_bigquery_default_service_account.bq_sa, data.google_storage_project_service_account.gcs_sa, + data.google_logging_project_settings.logging_sa ] } diff --git a/modules/project/service-agents.tf b/modules/project/service-agents.tf index d11b9aa3e..1a1927df1 100644 --- a/modules/project/service-agents.tf +++ b/modules/project/service-agents.tf @@ -139,6 +139,12 @@ data "google_bigquery_default_service_account" "bq_sa" { depends_on = [google_project_service.project_services] } +data "google_logging_project_settings" "logging_sa" { + count = contains(var.services, "logging.googleapis.com") ? 1 : 0 + project = local.project.project_id + depends_on = [google_project_service.project_services] +} + moved { from = google_project_service_identity.jit_si to = google_project_service_identity.default diff --git a/modules/project/shared-vpc.tf b/modules/project/shared-vpc.tf index cf9f0d64c..49404eb8f 100644 --- a/modules/project/shared-vpc.tf +++ b/modules/project/shared-vpc.tf @@ -154,6 +154,7 @@ resource "google_project_iam_member" "shared_vpc_host_robots" { google_project_default_service_accounts.default_service_accounts, data.google_bigquery_default_service_account.bq_sa, data.google_storage_project_service_account.gcs_sa, + data.google_logging_project_settings.logging_sa ] } diff --git a/tests/fast/stages/s0_org_setup/data-hardened/cicd-workflows.yaml b/tests/fast/stages/s0_org_setup/data-hardened/cicd-workflows.yaml new file mode 100644 index 000000000..c9b0ea7e5 --- /dev/null +++ b/tests/fast/stages/s0_org_setup/data-hardened/cicd-workflows.yaml @@ -0,0 +1,36 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# yaml-language-server: $schema=../../../../../fast/stages/0-org-setup/schemas/cicd-workflows.schema.json + +org-setup: + provider_files: + apply: 0-org-setup-providers.tf + plan: 0-org-setup-providers-ro.tf + repository: + name: gh-org/gh-repo + type: github + apply_branches: + - master + - fast-dev + service_accounts: + apply: $iam_principals:service_accounts/iac-0/iac-org-cicd-rw + plan: $iam_principals:service_accounts/iac-0/iac-org-cicd-ro + tfvars_files: + - 0-org-setup.auto.tfvars + workload_identity: + pool: $workload_identity_pools:iac-0/default + provider: $workload_identity_providers:iac-0/default/github-default + iam_principalsets: + template: github diff --git a/tests/fast/stages/s0_org_setup/data-hardened/defaults.yaml b/tests/fast/stages/s0_org_setup/data-hardened/defaults.yaml new file mode 100644 index 000000000..3cea6693e --- /dev/null +++ b/tests/fast/stages/s0_org_setup/data-hardened/defaults.yaml @@ -0,0 +1,68 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# yaml-language-server: $schema=../../../../../fast/stages/0-org-setup/schemas/defaults.schema.json + +# defaults: +# storage_location: europe-west1 +global: + billing_account: 012345-012345-012345 + organization: + domain: example.org + id: 1234567890 + customer_id: abcd123456 +projects: + defaults: + prefix: ft0 + locations: + bigquery: $locations:primary + logging: $locations:primary + storage: $locations:primary + observability: + project_id: $project_ids:log-0 + project_number: $project_numbers:log-0 + overrides: {} +output_files: + local_path: /tmp/fast-config + storage_bucket: $storage_buckets:iac-0/iac-outputs + providers: + 0-org-setup: + bucket: $storage_buckets:iac-0/iac-org-state + service_account: $iam_principals:service_accounts/iac-0/iac-org-rw + 0-org-setup-ro: + bucket: $storage_buckets:iac-0/iac-org-state + service_account: $iam_principals:service_accounts/iac-0/iac-org-rw + 1-vpcsc: + bucket: $storage_buckets:iac-0/iac-stage-state + prefix: 1-vpcsc + service_account: $iam_principals:service_accounts/iac-0/iac-vpcsc-rw + 2-networking: + bucket: $storage_buckets:iac-0/iac-stage-state + prefix: 2-networking + service_account: $iam_principals:service_accounts/iac-0/iac-networking-rw + 2-security: + bucket: $storage_buckets:iac-0/iac-stage-state + prefix: 2-security + service_account: $iam_principals:service_accounts/iac-0/iac-security-rw + 2-project-factory: + bucket: $storage_buckets:iac-0/iac-stage-state + prefix: 2-project-factory + service_account: $iam_principals:service_accounts/iac-0/iac-pf-rw +context: + iam_principals: + gcp-organization-admins: group:fabric-fast-owners@google.com + locations: + primary: europe-west1 + workload_identity_providers: + iac-0/default/github-default: projects/1234567890/locations/global/workloadIdentityPools/default diff --git a/tests/fast/stages/s0_org_setup/hardened.tfvars b/tests/fast/stages/s0_org_setup/hardened.tfvars index 96e0ac93a..4d75407fb 100644 --- a/tests/fast/stages/s0_org_setup/hardened.tfvars +++ b/tests/fast/stages/s0_org_setup/hardened.tfvars @@ -1,6 +1,7 @@ factories_config = { - cicd_workflows = "data-simple/cicd-workflows.yaml" - defaults = "data-simple/defaults.yaml" + cicd_workflows = "data-hardened/cicd-workflows.yaml" + defaults = "data-hardened/defaults.yaml" + observability = "datasets/hardened/observability" organization = "datasets/hardened/organization" projects = "datasets/hardened/projects" } diff --git a/tests/fast/stages/s0_org_setup/hardened.yaml b/tests/fast/stages/s0_org_setup/hardened.yaml index 179a60b40..77184317f 100644 --- a/tests/fast/stages/s0_org_setup/hardened.yaml +++ b/tests/fast/stages/s0_org_setup/hardened.yaml @@ -422,9 +422,23 @@ values: condition: [] member: serviceAccount:iac-org-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com role: roles/billing.viewer + module.cicd-sa-apply["org-setup"].google_service_account_iam_binding.authoritative["roles/iam.workloadIdentityUser"]: + condition: [] + members: + - principalSet://iam.googleapis.com/$workload_identity_pools:iac-0/default/attribute.fast_sub/repo:gh-org/gh-repo:ref:refs/heads/fast-dev + - principalSet://iam.googleapis.com/$workload_identity_pools:iac-0/default/attribute.fast_sub/repo:gh-org/gh-repo:ref:refs/heads/master + role: roles/iam.workloadIdentityUser + service_account_id: projects/ft0-prod-iac-core-0/serviceAccounts/iac-org-cicd-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + module.cicd-sa-plan["org-setup"].google_service_account_iam_binding.authoritative["roles/iam.workloadIdentityUser"]: + condition: [] + members: + - principalSet://iam.googleapis.com/$workload_identity_pools:iac-0/default/attribute.repository/gh-org/gh-repo + role: roles/iam.workloadIdentityUser + service_account_id: projects/ft0-prod-iac-core-0/serviceAccounts/iac-org-cicd-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com module.factory.module.bigquery-datasets["billing-0/billing_export"].google_bigquery_dataset.default: dataset_id: billing_export - default_encryption_configuration: [] + default_encryption_configuration: + - {} default_partition_expiration_ms: null default_table_expiration_ms: null delete_contents_on_destroy: false @@ -450,7 +464,8 @@ values: effective_labels: goog-terraform-provisioned: 'true' enable_object_retention: null - encryption: [] + encryption: + - {} force_destroy: false hierarchical_namespace: [] ip_filter: [] @@ -491,7 +506,8 @@ values: effective_labels: goog-terraform-provisioned: 'true' enable_object_retention: null - encryption: [] + encryption: + - {} force_destroy: false hierarchical_namespace: [] ip_filter: [] @@ -544,7 +560,8 @@ values: effective_labels: goog-terraform-provisioned: 'true' enable_object_retention: null - encryption: [] + encryption: + - {} force_destroy: false hierarchical_namespace: [] ip_filter: [] @@ -743,7 +760,7 @@ values: - description: null expression: "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([\n\ \ 'roles/compute.networkUser', 'roles/composer.sharedVpcAgent',\n 'roles/container.hostServiceAgentUser',\ - \ 'roles/vpcaccess.user'\n])" + \ 'roles/vpcaccess.user'\n])\n" title: Project factory delegated IAM grant. members: - serviceAccount:iac-pf-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com @@ -807,7 +824,7 @@ values: condition: - description: null expression: "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([\n\ - \ 'roles/cloudkms.cryptoKeyEncrypterDecrypter'\n])" + \ 'roles/cloudkms.cryptoKeyEncrypterDecrypter'\n])\n" title: Project factory delegated IAM grant. members: - serviceAccount:iac-pf-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com @@ -955,9 +972,72 @@ values: timeouts: null module.factory.module.folder-2["networking/prod"].google_tags_tag_binding.binding["environment"]: timeouts: null + module.factory.module.folder-2["security/dev"].google_folder.folder[0]: + deletion_protection: false + display_name: Development + tags: null + timeouts: null + module.factory.module.folder-2["security/dev"].google_tags_tag_binding.binding["environment"]: + timeouts: null + module.factory.module.folder-2["security/prod"].google_folder.folder[0]: + deletion_protection: false + display_name: Production + tags: null + timeouts: null + module.factory.module.folder-2["security/prod"].google_tags_tag_binding.binding["environment"]: + timeouts: null + module.factory.module.kms["billing-0/ew1"].google_kms_crypto_key.default["bigquery"]: + effective_labels: + goog-terraform-provisioned: 'true' + labels: null + name: bigquery + purpose: ENCRYPT_DECRYPT + rotation_period: 7776000s + skip_initial_version_creation: false + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.factory.module.kms["billing-0/ew1"].google_kms_key_ring.default[0]: + location: europe-west1 + name: ew1 + project: ft0-prod-billing-exp-0 + timeouts: null + module.factory.module.kms["iac-0/ew1"].google_kms_crypto_key.default["storage"]: + effective_labels: + goog-terraform-provisioned: 'true' + labels: null + name: storage + purpose: ENCRYPT_DECRYPT + rotation_period: 7776000s + skip_initial_version_creation: false + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.factory.module.kms["iac-0/ew1"].google_kms_key_ring.default[0]: + location: europe-west1 + name: ew1 + project: ft0-prod-iac-core-0 + timeouts: null + module.factory.module.kms["log-0/ew1"].google_kms_crypto_key.default["logging"]: + effective_labels: + goog-terraform-provisioned: 'true' + labels: null + name: logging + purpose: ENCRYPT_DECRYPT + rotation_period: 7776000s + skip_initial_version_creation: false + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.factory.module.kms["log-0/ew1"].google_kms_key_ring.default[0]: + location: europe-west1 + name: ew1 + project: ft0-prod-audit-logs-0 + timeouts: null module.factory.module.log-buckets["log-0/audit-logs"].google_logging_project_bucket_config.bucket[0]: bucket_id: audit-logs - cmek_settings: [] + cmek_settings: + - {} enable_analytics: false index_configs: [] location: europe-west1 @@ -966,7 +1046,8 @@ values: retention_days: 30 module.factory.module.log-buckets["log-0/iam"].google_logging_project_bucket_config.bucket[0]: bucket_id: iam - cmek_settings: [] + cmek_settings: + - {} enable_analytics: false index_configs: [] location: europe-west1 @@ -975,13 +1056,17 @@ values: retention_days: 30 module.factory.module.log-buckets["log-0/vpc-sc"].google_logging_project_bucket_config.bucket[0]: bucket_id: vpc-sc - cmek_settings: [] + cmek_settings: + - {} enable_analytics: true index_configs: [] location: europe-west1 locked: null project: ft0-prod-audit-logs-0 retention_days: 31 + ? module.factory.module.projects-iam["billing-0"].google_kms_crypto_key_iam_member.service_agent_cmek["key-0.bigquery-encryption"] + : condition: [] + role: roles/cloudkms.cryptoKeyEncrypterDecrypter module.factory.module.projects-iam["billing-0"].google_project_iam_binding.authoritative["roles/owner"]: condition: [] members: @@ -994,6 +1079,9 @@ values: - serviceAccount:iac-org-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com project: ft0-prod-billing-exp-0 role: roles/viewer + ? module.factory.module.projects-iam["iac-0"].google_kms_crypto_key_iam_member.service_agent_cmek["key-0.gs-project-accounts"] + : condition: [] + role: roles/cloudkms.cryptoKeyEncrypterDecrypter module.factory.module.projects-iam["iac-0"].google_project_iam_binding.authoritative["$custom_roles:storage_viewer"]: condition: [] members: @@ -1055,6 +1143,17 @@ values: - serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com project: ft0-prod-iac-core-0 role: roles/owner + ? module.factory.module.projects-iam["iac-0"].google_project_iam_binding.authoritative["roles/serviceusage.serviceUsageConsumer"] + : condition: [] + members: + - serviceAccount:iac-networking-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com + - serviceAccount:iac-networking-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + - serviceAccount:iac-pf-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com + - serviceAccount:iac-pf-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + - serviceAccount:iac-security-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com + - serviceAccount:iac-security-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + project: ft0-prod-iac-core-0 + role: roles/serviceusage.serviceUsageConsumer module.factory.module.projects-iam["iac-0"].google_project_iam_binding.authoritative["roles/storage.admin"]: condition: [] members: @@ -1067,777 +1166,9 @@ values: - serviceAccount:iac-org-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com project: ft0-prod-iac-core-0 role: roles/viewer - module.factory.module.projects-iam["log-0"].google_logging_metric.metrics["auditConfigChanges"]: - bucket_options: [] - description: Audit Configuration Changes - disabled: null - filter: protoPayload.methodName="SetIamPolicy" AND protoPayload.serviceData.policyDelta.auditConfigDeltas:* - label_extractors: - folder_id: EXTRACT(labels.folder_id) - method_name: EXTRACT(protoPayload.methodName) - organization_id: EXTRACT(labels.organization_id) - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - project_id: EXTRACT(labels.project_id) - metric_descriptor: - - display_name: null - labels: - - description: folder_id - key: folder_id - value_type: STRING - - description: method_name - key: method_name - value_type: STRING - - description: organization_id - key: organization_id - value_type: STRING - - description: principal - key: principal - value_type: STRING - - description: project_id - key: project_id - value_type: STRING - metric_kind: DELTA - unit: '1' - value_type: INT64 - name: auditConfigChanges - project: ft0-prod-audit-logs-0 - timeouts: null - value_extractor: null - module.factory.module.projects-iam["log-0"].google_logging_metric.metrics["cloudsqlInstanceChanges"]: - bucket_options: [] - description: Cloud SQL Instance Configuration Changes - disabled: null - filter: protoPayload.methodName="cloudsql.instances.update" - label_extractors: - database_id: EXTRACT(labels.database_id) - method_name: EXTRACT(protoPayload.methodName) - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - project_id: EXTRACT(labels.project_id) - metric_descriptor: - - display_name: null - labels: - - description: database_id - key: database_id - value_type: STRING - - description: method_name - key: method_name - value_type: STRING - - description: principal - key: principal - value_type: STRING - - description: project_id - key: project_id - value_type: STRING - metric_kind: DELTA - unit: '1' - value_type: INT64 - name: cloudsqlInstanceChanges - project: ft0-prod-audit-logs-0 - timeouts: null - value_extractor: null - module.factory.module.projects-iam["log-0"].google_logging_metric.metrics["customRoleChanges"]: - bucket_options: [] - description: Custom Role Changes - disabled: null - filter: "resource.type=\"iam_role\" AND (\n protoPayload.methodName=\"google.iam.admin.v1.CreateRole\"\ - \ OR\n protoPayload.methodName=\"google.iam.admin.v1.UpdateRole\" OR\n protoPayload.methodName=\"\ - google.iam.admin.v1.DeleteRole\"\n)" - label_extractors: - method_name: EXTRACT(protoPayload.methodName) - organization_id: EXTRACT(labels.organization_id) - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - project_id: EXTRACT(labels.project_id) - role_name: EXTRACT(labels.role_name) - metric_descriptor: - - display_name: null - labels: - - description: method_name - key: method_name - value_type: STRING - - description: organization_id - key: organization_id - value_type: STRING - - description: principal - key: principal - value_type: STRING - - description: project_id - key: project_id - value_type: STRING - - description: role_name - key: role_name - value_type: STRING - metric_kind: DELTA - unit: '1' - value_type: INT64 - name: customRoleChanges - project: ft0-prod-audit-logs-0 - timeouts: null - value_extractor: null - module.factory.module.projects-iam["log-0"].google_logging_metric.metrics["firewallPolicyRuleChanges"]: - bucket_options: [] - description: Network Firewall Policy Rule Changes - disabled: null - filter: "resource.labels.method:\"compute.networkFirewallPolicies\" AND (\n protoPayload.methodName:\"\ - compute.networkFirewallPolicies.addRule\" OR\n protoPayload.methodName:\"compute.networkFirewallPolicies.removeRule\"\ - \ OR\n protoPayload.methodName:\"compute.networkFirewallPolicies.patchRule\"\ - \n)" - label_extractors: - method_name: EXTRACT(protoPayload.methodName) - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - metric_descriptor: - - display_name: null - labels: - - description: method_name - key: method_name - value_type: STRING - - description: principal - key: principal - value_type: STRING - metric_kind: DELTA - unit: '1' - value_type: INT64 - name: firewallPolicyRuleChanges - project: ft0-prod-audit-logs-0 - timeouts: null - value_extractor: null - module.factory.module.projects-iam["log-0"].google_logging_metric.metrics["firewallRuleChanges"]: - bucket_options: [] - description: VPC Network Firewall Rule Changes - disabled: null - filter: resource.type="gce_firewall_rule" AND (protoPayload.methodName:"compute.firewalls.patch" - OR protoPayload.methodName:"compute.firewalls.insert" OR protoPayload.methodName:"compute.firewalls.delete") - label_extractors: - firewall_rule_id: EXTRACT(labels.firewall_rule_id) - method_name: EXTRACT(protoPayload.methodName) - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - project_id: EXTRACT(labels.project_id) - metric_descriptor: - - display_name: null - labels: - - description: firewall_rule_id - key: firewall_rule_id - value_type: STRING - - description: method_name - key: method_name - value_type: STRING - - description: principal - key: principal - value_type: STRING - - description: project_id - key: project_id - value_type: STRING - metric_kind: DELTA - unit: '1' - value_type: INT64 - name: firewallRuleChanges - project: ft0-prod-audit-logs-0 - timeouts: null - value_extractor: null - module.factory.module.projects-iam["log-0"].google_logging_metric.metrics["networkChanges"]: - bucket_options: [] - description: VPC Network Changes - disabled: null - filter: "resource.type=\"gce_network\" AND (\n protoPayload.methodName:\"compute.networks.insert\"\ - \ OR\n protoPayload.methodName:\"compute.networks.patch\" OR\n protoPayload.methodName:\"\ - compute.networks.delete\" OR\n protoPayload.methodName:\"compute.networks.addPeering\"\ - \ OR\n protoPayload.methodName:\"compute.networks.updatePeering\" OR\n protoPayload.methodName:\"\ - compute.networks.removePeering\"\n)" - label_extractors: - method_name: EXTRACT(protoPayload.methodName) - network_id: EXTRACT(labels.network_id) - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - project_id: EXTRACT(labels.project_id) - metric_descriptor: - - display_name: null - labels: - - description: method_name - key: method_name - value_type: STRING - - description: network_id - key: network_id - value_type: STRING - - description: principal - key: principal - value_type: STRING - - description: project_id - key: project_id - value_type: STRING - metric_kind: DELTA - unit: '1' - value_type: INT64 - name: networkChanges - project: ft0-prod-audit-logs-0 - timeouts: null - value_extractor: null - module.factory.module.projects-iam["log-0"].google_logging_metric.metrics["networkRouteChanges"]: - bucket_options: [] - description: VPC Network Route Changes - disabled: null - filter: "resource.type=\"gce_route\" AND (\n protoPayload.methodName:\"compute.routes.insert\"\ - \ OR\n protoPayload.methodName:\"compute.routes.delete\"\n)" - label_extractors: - method_name: EXTRACT(protoPayload.methodName) - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - project_id: EXTRACT(labels.project_id) - route_id: EXTRACT(labels.route_id) - metric_descriptor: - - display_name: null - labels: - - description: method_name - key: method_name - value_type: STRING - - description: principal - key: principal - value_type: STRING - - description: project_id - key: project_id - value_type: STRING - - description: route_id - key: route_id - value_type: STRING - metric_kind: DELTA - unit: '1' - value_type: INT64 - name: networkRouteChanges - project: ft0-prod-audit-logs-0 - timeouts: null - value_extractor: null - module.factory.module.projects-iam["log-0"].google_logging_metric.metrics["projectOwnershipChange"]: - bucket_options: [] - description: Project Ownership Changes - disabled: null - filter: "(protoPayload.serviceName=\"cloudresourcemanager.googleapis.com\") AND\n\ - (ProjectOwnership OR projectOwnerInvitee)\nOR\n(\n protoPayload.serviceData.policyDelta.bindingDeltas.action=\"\ - REMOVE\" AND\n protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\"\ - \n)\nOR\n(\n protoPayload.serviceData.policyDelta.bindingDeltas.action=\"ADD\"\ - \ AND\n protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\"\ - \n)" - label_extractors: - folder_id: EXTRACT(labels.folder_id) - method_name: EXTRACT(protoPayload.methodName) - organization_id: EXTRACT(labels.organization_id) - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - project_id: EXTRACT(labels.project_id) - metric_descriptor: - - display_name: null - labels: - - description: folder_id - key: folder_id - value_type: STRING - - description: method_name - key: method_name - value_type: STRING - - description: organization_id - key: organization_id - value_type: STRING - - description: principal - key: principal - value_type: STRING - - description: project_id - key: project_id - value_type: STRING - metric_kind: DELTA - unit: '1' - value_type: INT64 - name: projectOwnershipChange - project: ft0-prod-audit-logs-0 - timeouts: null - value_extractor: null - module.factory.module.projects-iam["log-0"].google_logging_metric.metrics["storageIamChanges"]: - bucket_options: [] - description: Cloud Storage IAM Permission Changes - disabled: null - filter: resource.type="gcs_bucket" AND protoPayload.methodName="storage.setIamPermissions" - label_extractors: - bucket_name: EXTRACT(labels.bucket_name) - location: EXTRACT(labels.location) - method_name: EXTRACT(protoPayload.methodName) - principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) - project_id: EXTRACT(labels.project_id) - metric_descriptor: - - display_name: null - labels: - - description: bucket_name - key: bucket_name - value_type: STRING - - description: location - key: location - value_type: STRING - - description: method_name - key: method_name - value_type: STRING - - description: principal - key: principal - value_type: STRING - - description: project_id - key: project_id - value_type: STRING - metric_kind: DELTA - unit: '1' - value_type: INT64 - name: storageIamChanges - project: ft0-prod-audit-logs-0 - timeouts: null - value_extractor: null - module.factory.module.projects-iam["log-0"].google_monitoring_alert_policy.alerts["auditConfigChanges"]: - alert_strategy: [] - combiner: OR - conditions: - - condition_absent: [] - condition_matched_log: [] - condition_monitoring_query_language: [] - condition_prometheus_query_language: [] - condition_sql: [] - condition_threshold: - - aggregations: - - alignment_period: 60s - cross_series_reducer: REDUCE_SUM - group_by_fields: - - metric.label.principal - - metric.label.method_name - - metric.label.organization_id - - metric.label.folder_id - - metric.label.project_id - per_series_aligner: ALIGN_SUM - comparison: COMPARISON_GT - denominator_aggregations: [] - denominator_filter: null - duration: 0s - evaluation_missing_data: null - filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/auditConfigChanges" - forecast_options: [] - threshold_value: 0 - trigger: - - count: 1 - percent: null - display_name: 'Log match condition: Audit Configuration Changes' - display_name: Audit Configuration Changes - documentation: - - content: 'Log-based alerting policy in project ${project} detected audit configuration - changes. - - - This alert helps track GCP services audit log configuration changes to ensure - appropriate. - - audit logs are being collected - - ``` - - protoPayload.methodName="SetIamPolicy" AND - - protoPayload.serviceData.policyDelta.auditConfigDeltas:* - - ```' - links: [] - mime_type: text/markdown - subject: null - enabled: true - notification_channels: [] - project: ft0-prod-audit-logs-0 - severity: null - timeouts: null - user_labels: null - module.factory.module.projects-iam["log-0"].google_monitoring_alert_policy.alerts["cloudsqlInstanceChanges"]: - alert_strategy: [] - combiner: OR - conditions: - - condition_absent: [] - condition_matched_log: [] - condition_monitoring_query_language: [] - condition_prometheus_query_language: [] - condition_sql: [] - condition_threshold: - - aggregations: - - alignment_period: 60s - cross_series_reducer: REDUCE_SUM - group_by_fields: - - metric.label.principal - - metric.label.method_name - - metric.label.project_id - - metric.label.database_id - per_series_aligner: ALIGN_SUM - comparison: COMPARISON_GT - denominator_aggregations: [] - denominator_filter: null - duration: 0s - evaluation_missing_data: null - filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/cloudsqlInstanceChanges" - forecast_options: [] - threshold_value: 0 - trigger: - - count: 1 - percent: null - display_name: 'Log match condition: Cloud SQL instance configuration changes' - display_name: Cloud SQL Instance Configuration Changes - documentation: - - content: 'Log-based alerting policy in project ${project} detected Cloud SQL - instance configuration changes. - - - This alert helps ensure security by monitoring configuration changes to SQL - instances. - - ``` - - protoPayload.methodName="cloudsql.instances.update" - - ```' - links: [] - mime_type: text/markdown - subject: null - enabled: true - notification_channels: [] - project: ft0-prod-audit-logs-0 - severity: null - timeouts: null - user_labels: null - module.factory.module.projects-iam["log-0"].google_monitoring_alert_policy.alerts["customRoleChanges"]: - alert_strategy: [] - combiner: OR - conditions: - - condition_absent: [] - condition_matched_log: [] - condition_monitoring_query_language: [] - condition_prometheus_query_language: [] - condition_sql: [] - condition_threshold: - - aggregations: - - alignment_period: 60s - cross_series_reducer: REDUCE_SUM - group_by_fields: - - metric.label.principal - - metric.label.method_name - - metric.label.organization_id - - metric.label.project_id - - metric.label.role_name - per_series_aligner: ALIGN_SUM - comparison: COMPARISON_GT - denominator_aggregations: [] - denominator_filter: null - duration: 0s - evaluation_missing_data: null - filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/customRoleChanges" - forecast_options: [] - threshold_value: 0 - trigger: - - count: 1 - percent: null - display_name: 'Log match condition: custom role changes' - display_name: Custom Role Changes - documentation: - - content: "Log-based alerting policy in project ${project} detected custom IAM\ - \ role creation,\ndeletion or update activities.\n\nThis alert helps ensure\ - \ security by monitoring changes to Identity and Access Management (IAM) roles.\n\ - ```\nresource.type=\"iam_role\" AND (\n protoPayload.methodName=\"google.iam.admin.v1.CreateRole\"\ - \ OR\n protoPayload.methodName=\"google.iam.admin.v1.UpdateRole\" OR\n protoPayload.methodName=\"\ - google.iam.admin.v1.DeleteRole\"\n)\n```" - links: [] - mime_type: text/markdown - subject: null - enabled: true - notification_channels: [] - project: ft0-prod-audit-logs-0 - severity: null - timeouts: null - user_labels: null - module.factory.module.projects-iam["log-0"].google_monitoring_alert_policy.alerts["firewallPolicyRuleChanges"]: - alert_strategy: [] - combiner: OR - conditions: - - condition_absent: [] - condition_matched_log: [] - condition_monitoring_query_language: [] - condition_prometheus_query_language: [] - condition_sql: [] - condition_threshold: - - aggregations: - - alignment_period: 60s - cross_series_reducer: REDUCE_SUM - group_by_fields: - - metric.label.principal - - metric.label.method_name - per_series_aligner: ALIGN_SUM - comparison: COMPARISON_GT - denominator_aggregations: [] - denominator_filter: null - duration: 0s - evaluation_missing_data: null - filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/firewallPolicyRuleChanges" - forecast_options: [] - threshold_value: 0 - trigger: - - count: 1 - percent: null - display_name: 'Log match condition: Network Firewall Policy Rule Changes' - display_name: Network Firewall Policy Rule Changes - documentation: - - content: "Log-based alerting policy in project ${project} detected Firewall\ - \ Policy rule changes.\n\nThis alert helps ensure security by monitoring creation,\ - \ modification, or deletion of firewall rules.\n```\nresource.labels.method:\"\ - compute.networkFirewallPolicies\" AND (\n protoPayload.methodName:\"compute.networkFirewallPolicies.addRule\"\ - \ OR\n protoPayload.methodName:\"compute.networkFirewallPolicies.removeRule\"\ - \ OR\n protoPayload.methodName:\"compute.networkFirewallPolicies.patchRule\"\ - \n)\n```" - links: [] - mime_type: text/markdown - subject: null - enabled: true - notification_channels: [] - project: ft0-prod-audit-logs-0 - severity: null - timeouts: null - user_labels: null - module.factory.module.projects-iam["log-0"].google_monitoring_alert_policy.alerts["firewallRuleChanges"]: - alert_strategy: [] - combiner: OR - conditions: - - condition_absent: [] - condition_matched_log: [] - condition_monitoring_query_language: [] - condition_prometheus_query_language: [] - condition_sql: [] - condition_threshold: - - aggregations: - - alignment_period: 60s - cross_series_reducer: REDUCE_SUM - group_by_fields: - - metric.label.principal - - metric.label.method_name - - metric.label.project_id - - metric.label.firewall_rule_id - per_series_aligner: ALIGN_SUM - comparison: COMPARISON_GT - denominator_aggregations: [] - denominator_filter: null - duration: 0s - evaluation_missing_data: null - filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/firewallRuleChanges" - forecast_options: [] - threshold_value: 0 - trigger: - - count: 1 - percent: null - display_name: 'Log match condition: VPC Network Firewall Rule Changes' - display_name: VPC Network Firewall Rule Changes - documentation: - - content: "Log-based alerting policy in project ${project} detected VPC Network\ - \ Firewall rule changes.\n\nThis alert helps ensure security by monitoring\ - \ creation, modification, or deletion of firewall rules.\n```\nresource.type=\"\ - gce_firewall_rule\" AND (\n protoPayload.methodName:\"compute.firewalls.patch\"\ - \ OR\n protoPayload.methodName:\"compute.firewalls.insert\" OR\n protoPayload.methodName:\"\ - compute.firewalls.delete\"\n)\n```" - links: [] - mime_type: text/markdown - subject: null - enabled: true - notification_channels: [] - project: ft0-prod-audit-logs-0 - severity: null - timeouts: null - user_labels: null - module.factory.module.projects-iam["log-0"].google_monitoring_alert_policy.alerts["networkChanges"]: - alert_strategy: [] - combiner: OR - conditions: - - condition_absent: [] - condition_matched_log: [] - condition_monitoring_query_language: [] - condition_prometheus_query_language: [] - condition_sql: [] - condition_threshold: - - aggregations: - - alignment_period: 60s - cross_series_reducer: REDUCE_SUM - group_by_fields: - - metric.label.principal - - metric.label.method_name - - metric.label.project_id - - metric.label.network_id - per_series_aligner: ALIGN_SUM - comparison: COMPARISON_GT - denominator_aggregations: [] - denominator_filter: null - duration: 0s - evaluation_missing_data: null - filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/networkChanges" - forecast_options: [] - threshold_value: 0 - trigger: - - count: 1 - percent: null - display_name: 'Log match condition: VPC Network Changes' - display_name: VPC Network Changes - documentation: - - content: "Log-based alerting policy in project ${project} detected VPC Network\ - \ changes.\n\nThis alert helps ensure security by monitoring creation, modification,\ - \ deletion,\nor peering changes to VPC networks.\n```\nresource.type=\"gce_network\"\ - \ AND (\n protoPayload.methodName:\"compute.networks.insert\" OR\n protoPayload.methodName:\"\ - compute.networks.patch\" OR\n protoPayload.methodName:\"compute.networks.delete\"\ - \ OR\n protoPayload.methodName:\"compute.networks.addPeering\" OR\n protoPayload.methodName:\"\ - compute.networks.updatePeering\" OR\n protoPayload.methodName:\"compute.networks.removePeering\"\ - \n)\n```" - links: [] - mime_type: text/markdown - subject: null - enabled: true - notification_channels: [] - project: ft0-prod-audit-logs-0 - severity: null - timeouts: null - user_labels: null - module.factory.module.projects-iam["log-0"].google_monitoring_alert_policy.alerts["networkRouteChanges"]: - alert_strategy: [] - combiner: OR - conditions: - - condition_absent: [] - condition_matched_log: [] - condition_monitoring_query_language: [] - condition_prometheus_query_language: [] - condition_sql: [] - condition_threshold: - - aggregations: - - alignment_period: 60s - cross_series_reducer: REDUCE_SUM - group_by_fields: - - metric.label.principal - - metric.label.method_name - - metric.label.project_id - - metric.label.route_id - per_series_aligner: ALIGN_SUM - comparison: COMPARISON_GT - denominator_aggregations: [] - denominator_filter: null - duration: 0s - evaluation_missing_data: null - filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/networkRouteChanges" - forecast_options: [] - threshold_value: 0 - trigger: - - count: 1 - percent: null - display_name: 'Log match condition: VPC Network Route Changes' - display_name: VPC Network Route Changes - documentation: - - content: "Log-based alerting policy in project ${project} detected VPC Network\ - \ Route changes.\n\nThis alert helps ensure security by monitoring creation\ - \ or deletion of network routes.\n```\nresource.type=\"gce_route\" AND (\n\ - \ protoPayload.methodName:\"compute.routes.insert\" OR\n protoPayload.methodName:\"\ - compute.routes.delete\"\n)\n```" - links: [] - mime_type: text/markdown - subject: null - enabled: true - notification_channels: [] - project: ft0-prod-audit-logs-0 - severity: null - timeouts: null - user_labels: null - module.factory.module.projects-iam["log-0"].google_monitoring_alert_policy.alerts["projectOwnershipChange"]: - alert_strategy: [] - combiner: OR - conditions: - - condition_absent: [] - condition_matched_log: [] - condition_monitoring_query_language: [] - condition_prometheus_query_language: [] - condition_sql: [] - condition_threshold: - - aggregations: - - alignment_period: 60s - cross_series_reducer: REDUCE_SUM - group_by_fields: - - metric.label.principal - - metric.label.method_name - - metric.label.organization_id - - metric.label.folder_id - - metric.label.project_id - per_series_aligner: ALIGN_SUM - comparison: COMPARISON_GT - denominator_aggregations: [] - denominator_filter: null - duration: 0s - evaluation_missing_data: null - filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/projectOwnershipChange" - forecast_options: [] - threshold_value: 0 - trigger: - - count: 1 - percent: null - display_name: Project Ownership Changes - display_name: Project Ownership Changes - documentation: - - content: "Log-based alerting policy in project ${project} detected a project\ - \ ownership assignments or changes.\n```\n(protoPayload.serviceName=\"cloudresourcemanager.googleapis.com\"\ - ) AND\n(ProjectOwnership OR projectOwnerInvitee)\nOR\n(\n protoPayload.serviceData.policyDelta.bindingDeltas.action=\"\ - REMOVE\" AND\n protoPayload.serviceData.policyDelta.bindingDeltas.role=\"\ - roles/owner\"\n)\nOR\n(\n protoPayload.serviceData.policyDelta.bindingDeltas.action=\"\ - ADD\" AND\n protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\"\ - \n)\n```" - links: [] - mime_type: text/markdown - subject: null - enabled: true - notification_channels: [] - project: ft0-prod-audit-logs-0 - severity: null - timeouts: null - user_labels: null - module.factory.module.projects-iam["log-0"].google_monitoring_alert_policy.alerts["storageIamChanges"]: - alert_strategy: [] - combiner: OR - conditions: - - condition_absent: [] - condition_matched_log: [] - condition_monitoring_query_language: [] - condition_prometheus_query_language: [] - condition_sql: [] - condition_threshold: - - aggregations: - - alignment_period: 60s - cross_series_reducer: REDUCE_SUM - group_by_fields: - - metric.label.principal - - metric.label.method_name - - metric.label.project_id - - metric.label.location - - metric.label.bucket_name - per_series_aligner: ALIGN_SUM - comparison: COMPARISON_GT - denominator_aggregations: [] - denominator_filter: null - duration: 0s - evaluation_missing_data: null - filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/storageIamChanges" - forecast_options: [] - threshold_value: 0 - trigger: - - count: 1 - percent: null - display_name: Cloud Storage IAM Permission Changes - display_name: Cloud Storage IAM Permission Changes - documentation: - - content: 'Log-based alerting policy in project ${project} detected Cloud Storage - Bucket IAM changes. - - - This alert helps ensure security by monitoring IAM permission changes to Cloud - Storage buckets. - - ``` - - resource.type="gcs_bucket" AND protoPayload.methodName="storage.setIamPermissions" - - ```' - links: [] - mime_type: text/markdown - subject: null - enabled: true - notification_channels: [] - project: ft0-prod-audit-logs-0 - severity: null - timeouts: null - user_labels: null + module.factory.module.projects-iam["log-0"].google_kms_crypto_key_iam_member.service_agent_cmek["key-0.logging"]: + condition: [] + role: roles/cloudkms.cryptoKeyEncrypterDecrypter module.factory.module.projects-iam["log-0"].google_project_iam_binding.authoritative["roles/owner"]: condition: [] members: @@ -1855,6 +1186,21 @@ values: module.factory.module.projects["billing-0"].data.google_storage_project_service_account.gcs_sa[0]: project: ft0-prod-billing-exp-0 user_project: null + module.factory.module.projects["billing-0"].google_org_policy_policy.default["gcp.restrictCmekCryptoKeyProjects"]: + dry_run_spec: [] + name: projects/ft0-prod-billing-exp-0/policies/gcp.restrictCmekCryptoKeyProjects + parent: projects/ft0-prod-billing-exp-0 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: 'TRUE' + condition: [] + deny_all: null + enforce: null + parameters: null + values: [] + timeouts: null module.factory.module.projects["billing-0"].google_project.project[0]: auto_create_network: false billing_account: 012345-012345-012345 @@ -1874,6 +1220,10 @@ values: condition: [] project: ft0-prod-billing-exp-0 role: roles/bigquerydatatransfer.serviceAgent + module.factory.module.projects["billing-0"].google_project_iam_member.service_agents["cloudkms"]: + condition: [] + project: ft0-prod-billing-exp-0 + role: roles/cloudkms.serviceAgent module.factory.module.projects["billing-0"].google_project_service.project_services["bigquery.googleapis.com"]: disable_dependent_services: false disable_on_destroy: false @@ -1886,6 +1236,12 @@ values: project: ft0-prod-billing-exp-0 service: bigquerydatatransfer.googleapis.com timeouts: null + module.factory.module.projects["billing-0"].google_project_service.project_services["cloudkms.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-billing-exp-0 + service: cloudkms.googleapis.com + timeouts: null module.factory.module.projects["billing-0"].google_project_service.project_services["storage.googleapis.com"]: disable_dependent_services: false disable_on_destroy: false @@ -1896,11 +1252,32 @@ values: project: ft0-prod-billing-exp-0 service: bigquerydatatransfer.googleapis.com timeouts: null + module.factory.module.projects["billing-0"].google_project_service_identity.default["cloudkms.googleapis.com"]: + project: ft0-prod-billing-exp-0 + service: cloudkms.googleapis.com + timeouts: null module.factory.module.projects["iac-0"].data.google_bigquery_default_service_account.bq_sa[0]: project: ft0-prod-iac-core-0 + module.factory.module.projects["iac-0"].data.google_logging_project_settings.logging_sa[0]: + project: ft0-prod-iac-core-0 module.factory.module.projects["iac-0"].data.google_storage_project_service_account.gcs_sa[0]: project: ft0-prod-iac-core-0 user_project: null + module.factory.module.projects["iac-0"].google_org_policy_policy.default["gcp.restrictCmekCryptoKeyProjects"]: + dry_run_spec: [] + name: projects/ft0-prod-iac-core-0/policies/gcp.restrictCmekCryptoKeyProjects + parent: projects/ft0-prod-iac-core-0 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: 'TRUE' + condition: [] + deny_all: null + enforce: null + parameters: null + values: [] + timeouts: null module.factory.module.projects["iac-0"].google_org_policy_policy.default["iam.workloadIdentityPoolProviders"]: dry_run_spec: [] name: projects/ft0-prod-iac-core-0/policies/iam.workloadIdentityPoolProviders @@ -1976,6 +1353,12 @@ values: condition: [] project: ft0-prod-iac-core-0 role: roles/servicenetworking.serviceAgent + module.factory.module.projects["iac-0"].google_project_service.org_policy_service[0]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: orgpolicy.googleapis.com + timeouts: null module.factory.module.projects["iac-0"].google_project_service.project_services["accesscontextmanager.googleapis.com"]: disable_dependent_services: false disable_on_destroy: false @@ -2114,12 +1497,6 @@ values: project: ft0-prod-iac-core-0 service: servicenetworking.googleapis.com timeouts: null - module.factory.module.projects["iac-0"].google_project_service.org_policy_service[0]: - disable_dependent_services: false - disable_on_destroy: false - project: ft0-prod-iac-core-0 - service: orgpolicy.googleapis.com - timeouts: null module.factory.module.projects["iac-0"].google_project_service.project_services["serviceusage.googleapis.com"]: disable_dependent_services: false disable_on_destroy: false @@ -2172,9 +1549,41 @@ values: project: ft0-prod-iac-core-0 service: servicenetworking.googleapis.com timeouts: null + module.factory.module.projects["log-0"].data.google_logging_project_settings.logging_sa[0]: + project: ft0-prod-audit-logs-0 module.factory.module.projects["log-0"].data.google_storage_project_service_account.gcs_sa[0]: project: ft0-prod-audit-logs-0 user_project: null + module.factory.module.projects["log-0"].google_org_policy_policy.default["custom.storageRequireBucketObjectVersionning"]: + dry_run_spec: [] + name: projects/ft0-prod-audit-logs-0/policies/custom.storageRequireBucketObjectVersionning + parent: projects/ft0-prod-audit-logs-0 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.factory.module.projects["log-0"].google_org_policy_policy.default["gcp.restrictCmekCryptoKeyProjects"]: + dry_run_spec: [] + name: projects/ft0-prod-audit-logs-0/policies/gcp.restrictCmekCryptoKeyProjects + parent: projects/ft0-prod-audit-logs-0 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: 'TRUE' + condition: [] + deny_all: null + enforce: null + parameters: null + values: [] + timeouts: null module.factory.module.projects["log-0"].google_project.project[0]: auto_create_network: false billing_account: 012345-012345-012345 @@ -2190,10 +1599,20 @@ values: terraform_labels: goog-terraform-provisioned: 'true' timeouts: null + module.factory.module.projects["log-0"].google_project_iam_member.service_agents["cloudkms"]: + condition: [] + project: ft0-prod-audit-logs-0 + role: roles/cloudkms.serviceAgent module.factory.module.projects["log-0"].google_project_iam_member.service_agents["pubsub"]: condition: [] project: ft0-prod-audit-logs-0 role: roles/pubsub.serviceAgent + module.factory.module.projects["log-0"].google_project_service.project_services["cloudkms.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-audit-logs-0 + service: cloudkms.googleapis.com + timeouts: null module.factory.module.projects["log-0"].google_project_service.project_services["logging.googleapis.com"]: disable_dependent_services: false disable_on_destroy: false @@ -2212,6 +1631,10 @@ values: project: ft0-prod-audit-logs-0 service: storage.googleapis.com timeouts: null + module.factory.module.projects["log-0"].google_project_service_identity.default["cloudkms.googleapis.com"]: + project: ft0-prod-audit-logs-0 + service: cloudkms.googleapis.com + timeouts: null module.factory.module.projects["log-0"].google_project_service_identity.default["pubsub.googleapis.com"]: project: ft0-prod-audit-logs-0 service: pubsub.googleapis.com @@ -2376,6 +1799,10 @@ values: input: null output: null triggers_replace: null + module.factory.terraform_data.project-preconditions: + input: null + output: null + triggers_replace: null module.organization-iam[0].google_logging_organization_sink.sink["audit-logs"]: description: audit-logs (Terraform-managed). disabled: false @@ -2575,6 +2002,24 @@ values: parameters: null values: [] timeouts: null + module.organization-iam[0].google_org_policy_policy.default["cloudfunctions.allowedIngressSettings"]: + dry_run_spec: [] + name: organizations/1234567890/policies/cloudfunctions.allowedIngressSettings + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: null + parameters: null + values: + - allowed_values: + - ALLOW_INTERNAL_AND_GCLB + denied_values: null + timeouts: null module.organization-iam[0].google_org_policy_policy.default["cloudfunctions.allowedVpcConnectorEgressSettings"]: dry_run_spec: [] name: organizations/1234567890/policies/cloudfunctions.allowedVpcConnectorEgressSettings @@ -2698,6 +2143,36 @@ values: parameters: null values: [] timeouts: null + module.organization-iam[0].google_org_policy_policy.default["compute.managed.disableSerialPortLogging"]: + dry_run_spec: [] + name: organizations/1234567890/policies/compute.managed.disableSerialPortLogging + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["compute.managed.vmCanIpForward"]: + dry_run_spec: [] + name: organizations/1234567890/policies/compute.managed.vmCanIpForward + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null module.organization-iam[0].google_org_policy_policy.default["compute.requireOsLogin"]: dry_run_spec: [] name: organizations/1234567890/policies/compute.requireOsLogin @@ -3036,6 +2511,21 @@ values: parameters: null values: [] timeouts: null + module.organization-iam[0].google_org_policy_policy.default["container.managed.enableBinaryAuthorization"]: + dry_run_spec: [] + name: organizations/1234567890/policies/container.managed.enableBinaryAuthorization + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null module.organization-iam[0].google_org_policy_policy.default["container.managed.enableCloudLogging"]: dry_run_spec: [] name: organizations/1234567890/policies/container.managed.enableCloudLogging @@ -3051,6 +2541,21 @@ values: parameters: null values: [] timeouts: null + module.organization-iam[0].google_org_policy_policy.default["container.managed.enableGoogleGroupsRBAC"]: + dry_run_spec: [] + name: organizations/1234567890/policies/container.managed.enableGoogleGroupsRBAC + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null module.organization-iam[0].google_org_policy_policy.default["container.managed.enableNetworkPolicy"]: dry_run_spec: [] name: organizations/1234567890/policies/container.managed.enableNetworkPolicy @@ -3156,6 +2661,21 @@ values: parameters: null values: [] timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.cloudkmsAllowedProtectionLevel"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.cloudkmsAllowedProtectionLevel + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null module.organization-iam[0].google_org_policy_policy.default["custom.cloudrunDisableEnvironmentVariablePattern"]: dry_run_spec: [] name: organizations/1234567890/policies/custom.cloudrunDisableEnvironmentVariablePattern @@ -3171,6 +2691,66 @@ values: parameters: null values: [] timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.cloudrunJobDisableDefaultServiceAccount"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.cloudrunJobDisableDefaultServiceAccount + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.cloudrunJobRequireBinaryAuthorization"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.cloudrunJobRequireBinaryAuthorization + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.cloudrunServiceDisableDefaultServiceAccount"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.cloudrunServiceDisableDefaultServiceAccount + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.cloudrunServiceRequireBinaryAuthorization"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.cloudrunServiceRequireBinaryAuthorization + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null module.organization-iam[0].google_org_policy_policy.default["custom.cloudsqlDisablePublicAuthorizedNetworks"]: dry_run_spec: [] name: organizations/1234567890/policies/custom.cloudsqlDisablePublicAuthorizedNetworks @@ -3216,6 +2796,21 @@ values: parameters: null values: [] timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.cloudsqlRequireHighAvailability"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.cloudsqlRequireHighAvailability + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null module.organization-iam[0].google_org_policy_policy.default["custom.cloudsqlRequireMySQLDatabaseFlags"]: dry_run_spec: [] name: organizations/1234567890/policies/custom.cloudsqlRequireMySQLDatabaseFlags @@ -3246,6 +2841,21 @@ values: parameters: null values: [] timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.cloudsqlRequirePostgreSQLDatabaseAdditionalFlags + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'FALSE' + parameters: null + values: [] + timeouts: null module.organization-iam[0].google_org_policy_policy.default["custom.cloudsqlRequirePostgreSQLDatabaseFlags"]: dry_run_spec: [] name: organizations/1234567890/policies/custom.cloudsqlRequirePostgreSQLDatabaseFlags @@ -3306,6 +2916,51 @@ values: parameters: null values: [] timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.dataprocDisableDefaultServiceAccount"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.dataprocDisableDefaultServiceAccount + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.dataprocRequireInternalIp"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.dataprocRequireInternalIp + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.dataprocRequireKerberos"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.dataprocRequireKerberos + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null module.organization-iam[0].google_org_policy_policy.default["custom.dnsAllowedSigningAlgorithms"]: dry_run_spec: [] name: organizations/1234567890/policies/custom.dnsAllowedSigningAlgorithms @@ -3381,6 +3036,231 @@ values: parameters: null values: [] timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRequireDescription"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRequireDescription + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictCacheSearchDatabasesPolicyRule"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRestrictCacheSearchDatabasesPolicyRule + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictCacheSearchDatabasesRule"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRestrictCacheSearchDatabasesRule + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictDirectoryServicesPolicyRule"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRestrictDirectoryServicesPolicyRule + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictDirectoryServicesRule"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRestrictDirectoryServicesRule + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictInsecureProtocolsPolicyRule"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRestrictInsecureProtocolsPolicyRule + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictInsecureProtocolsRule"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRestrictInsecureProtocolsRule + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictMailProtocolsPolicyRule"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRestrictMailProtocolsPolicyRule + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictMailProtocolsRule"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRestrictMailProtocolsRule + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictManagementPortsPolicyRule"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRestrictManagementPortsPolicyRule + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictManagementPortsRule"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRestrictManagementPortsRule + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictNetworkServicesPolicyRule"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRestrictNetworkServicesPolicyRule + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictNetworkServicesRule"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRestrictNetworkServicesRule + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictNoSQLDatabasesPolicyRule"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRestrictNoSQLDatabasesPolicyRule + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictNoSQLDatabasesRule"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRestrictNoSQLDatabasesRule + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictPublicAccessRule"]: dry_run_spec: [] name: organizations/1234567890/policies/custom.firewallRestrictPublicAccessRule @@ -3426,6 +3306,36 @@ values: parameters: null values: [] timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictSQLDatabasesPolicyRule"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRestrictSQLDatabasesPolicyRule + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictSQLDatabasesRule"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.firewallRestrictSQLDatabasesRule + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null module.organization-iam[0].google_org_policy_policy.default["custom.firewallRestrictSshPolicyRule"]: dry_run_spec: [] name: organizations/1234567890/policies/custom.firewallRestrictSshPolicyRule @@ -3681,6 +3591,21 @@ values: parameters: null values: [] timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.gkeRequireNodePoolSandbox"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.gkeRequireNodePoolSandbox + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'TRUE' + parameters: null + values: [] + timeouts: null module.organization-iam[0].google_org_policy_policy.default["custom.gkeRequirePrivateEndpoint"]: dry_run_spec: [] name: organizations/1234567890/policies/custom.gkeRequirePrivateEndpoint @@ -3756,6 +3681,21 @@ values: parameters: null values: [] timeouts: null + module.organization-iam[0].google_org_policy_policy.default["custom.iamDisableRedisAdminRoles"]: + dry_run_spec: [] + name: organizations/1234567890/policies/custom.iamDisableRedisAdminRoles + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'FALSE' + parameters: null + values: [] + timeouts: null module.organization-iam[0].google_org_policy_policy.default["custom.networkDisableTargetHTTPProxy"]: dry_run_spec: [] name: organizations/1234567890/policies/custom.networkDisableTargetHTTPProxy @@ -3867,6 +3807,93 @@ values: parameters: null values: [] timeouts: null + module.organization-iam[0].google_org_policy_policy.default["gcp.restrictCmekCryptoKeyProjects"]: + dry_run_spec: [] + name: organizations/1234567890/policies/gcp.restrictCmekCryptoKeyProjects + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: + - description: null + expression: 'resource.matchTag(''1234567890/environment'', ''development'') + + ' + location: null + title: Restrict CMEK Projects for development projects + deny_all: null + enforce: null + parameters: null + - allow_all: null + condition: + - description: null + expression: '!resource.matchTag(''1234567890/environment'', ''development'') + + ' + location: null + title: Restrict CMEK Projects for non-development projects + deny_all: null + enforce: null + parameters: null + timeouts: null + module.organization-iam[0].google_org_policy_policy.default["gcp.restrictNonCmekServices"]: + dry_run_spec: [] + name: organizations/1234567890/policies/gcp.restrictNonCmekServices + parent: organizations/1234567890 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: null + parameters: null + values: + - allowed_values: null + denied_values: + - aiplatform.googleapis.com + - alloydb.googleapis.com + - apigee.googleapis.com + - artifactregistry.googleapis.com + - bigquery.googleapis.com + - bigquerydatatransfer.googleapis.com + - bigtable.googleapis.com + - cloudfunctions.googleapis.com + - cloudtasks.googleapis.com + - composer.googleapis.com + - compute.googleapis.com + - contactcenterinsights.googleapis.com + - container.googleapis.com + - dataflow.googleapis.com + - dataform.googleapis.com + - datafusion.googleapis.com + - dataproc.googleapis.com + - dialogflow.googleapis.com + - discoveryengine.googleapis.com + - documentai.googleapis.com + - file.googleapis.com + - firestore.googleapis.com + - gkebackup.googleapis.com + - integrations.googleapis.com + - logging.googleapis.com + - looker.googleapis.com + - notebooks.googleapis.com + - pubsub.googleapis.com + - redis.googleapis.com + - run.googleapis.com + - secretmanager.googleapis.com + - securesourcemanager.googleapis.com + - securitycenter.googleapis.com + - spanner.googleapis.com + - speech.googleapis.com + - sqladmin.googleapis.com + - storage.googleapis.com + - storagetransfer.googleapis.com + - workstations.googleapis.com + timeouts: null module.organization-iam[0].google_org_policy_policy.default["gcp.restrictTLSCipherSuites"]: dry_run_spec: [] name: organizations/1234567890/policies/gcp.restrictTLSCipherSuites @@ -4225,6 +4252,12 @@ values: parameters: null values: [] timeouts: null + module.organization-iam[0].google_organization_iam_audit_config.default["allServices"]: + audit_log_config: + - exempted_members: [] + log_type: ADMIN_READ + org_id: '1234567890' + service: allServices module.organization-iam[0].google_organization_iam_binding.authoritative["$custom_roles:organization_admin_viewer"]: condition: [] members: @@ -4266,6 +4299,7 @@ values: members: - serviceAccount:iac-org-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com - serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + - serviceAccount:iac-security-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com - serviceAccount:iac-security-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com - serviceAccount:iac-vpcsc-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com - serviceAccount:iac-vpcsc-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com @@ -4277,6 +4311,12 @@ values: - group:fabric-fast-owners@google.com org_id: '1234567890' role: roles/cloudsupport.admin + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/cloudsupport.techSupportEditor"]: + condition: [] + members: + - group:fabric-fast-owners@google.com + org_id: '1234567890' + role: roles/cloudsupport.techSupportEditor module.organization-iam[0].google_organization_iam_binding.authoritative["roles/compute.orgFirewallPolicyAdmin"]: condition: [] members: @@ -4542,6 +4582,20 @@ values: resource_types: - cloudbuild.googleapis.com/WorkerPool timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.cloudkmsAllowedProtectionLevel"]: + action_type: DENY + condition: has(resource.versionTemplate.protectionLevel) && resource.versionTemplate.protectionLevel + in ["SOFTWARE"] == false + description: Ensure the protection level for Cloud KMS keys is configured correctly + display_name: Require Cloud KMS keys protection level to be configured correctly + method_types: + - CREATE + - UPDATE + name: custom.cloudkmsAllowedProtectionLevel + parent: organizations/1234567890 + resource_types: + - cloudkms.googleapis.com/CryptoKey + timeouts: null module.organization[0].google_org_policy_custom_constraint.constraint["custom.cloudrunDisableEnvironmentVariablePattern"]: action_type: DENY condition: "resource.spec.template.spec.containers.exists(container,\n container.env.exists(env,\n\ @@ -4560,6 +4614,20 @@ values: resource_types: - run.googleapis.com/Service timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.cloudrunJobDisableDefaultServiceAccount"]: + action_type: DENY + condition: resource.spec.template.spec.template.spec.serviceAccountName.endsWith('@developer.gserviceaccount.com') + description: Enforce that service account associated with Cloud Run Job use a + non-default service account + display_name: Disable creation of Cloud Run Job using default service account + method_types: + - CREATE + - UPDATE + name: custom.cloudrunJobDisableDefaultServiceAccount + parent: organizations/1234567890 + resource_types: + - run.googleapis.com/Job + timeouts: null module.organization[0].google_org_policy_custom_constraint.constraint["custom.cloudrunJobRequireBinaryAuthorization"]: action_type: DENY condition: '!(''run.googleapis.com/binary-authorization'' in resource.metadata.annotations)' @@ -4573,6 +4641,20 @@ values: resource_types: - run.googleapis.com/Job timeouts: null + ? module.organization[0].google_org_policy_custom_constraint.constraint["custom.cloudrunServiceDisableDefaultServiceAccount"] + : action_type: DENY + condition: resource.spec.template.spec.serviceAccountName.endsWith('@developer.gserviceaccount.com') + description: Enforce that service account associated with Cloud Run Service use + a non-default service account + display_name: Disable creation of Cloud Run Service using default service account + method_types: + - CREATE + - UPDATE + name: custom.cloudrunServiceDisableDefaultServiceAccount + parent: organizations/1234567890 + resource_types: + - run.googleapis.com/Service + timeouts: null module.organization[0].google_org_policy_custom_constraint.constraint["custom.cloudrunServiceRequireBinaryAuthorization"]: action_type: DENY condition: '!(''run.googleapis.com/binary-authorization'' in resource.metadata.annotations)' @@ -4633,6 +4715,19 @@ values: resource_types: - sqladmin.googleapis.com/Instance timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.cloudsqlRequireHighAvailability"]: + action_type: DENY + condition: resource.settings.availabilityType != "REGIONAL" + description: Ensure that Cloud SQL instance is configured with high availability + display_name: Require Cloud SQL instances to be configured with high availability + method_types: + - CREATE + - UPDATE + name: custom.cloudsqlRequireHighAvailability + parent: organizations/1234567890 + resource_types: + - sqladmin.googleapis.com/Instance + timeouts: null module.organization[0].google_org_policy_custom_constraint.constraint["custom.cloudsqlRequireMySQLDatabaseFlags"]: action_type: DENY condition: "resource.databaseVersion.startsWith('MYSQL') && (\n !resource.settings.databaseFlags.exists(flag,\n\ @@ -4762,6 +4857,48 @@ values: resource_types: - sqladmin.googleapis.com/Instance timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.dataprocDisableDefaultServiceAccount"]: + action_type: DENY + condition: "has(resource.config.gceClusterConfig.serviceAccount) == false ||\n\ + \ resource.config.gceClusterConfig.serviceAccount.contains('-compute@developer.gserviceaccount.com')" + description: Enforce that the Dataproc VMs is not using default user-managed service + accounts + display_name: Disable Dataproc cluster with default service accounts + method_types: + - CREATE + - UPDATE + name: custom.dataprocDisableDefaultServiceAccount + parent: organizations/1234567890 + resource_types: + - dataproc.googleapis.com/Cluster + timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.dataprocRequireInternalIp"]: + action_type: DENY + condition: resource.config.gceClusterConfig.internalIpOnly == false + description: Enforce that the Dataproc cluster is created with Internal IPs only + display_name: Require Dataproc with internal IPs + method_types: + - CREATE + - UPDATE + name: custom.dataprocRequireInternalIp + parent: organizations/1234567890 + resource_types: + - dataproc.googleapis.com/Cluster + timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.dataprocRequireKerberos"]: + action_type: DENY + condition: resource.config.securityConfig.kerberosConfig.enableKerberos == false + description: Enforce that Dataproc cluster is configured using secure mode via + Kerberos for authentication + display_name: Require Dataproc with Kerberos authentication + method_types: + - CREATE + - UPDATE + name: custom.dataprocRequireKerberos + parent: organizations/1234567890 + resource_types: + - dataproc.googleapis.com/Cluster + timeouts: null module.organization[0].google_org_policy_custom_constraint.constraint["custom.dnsAllowedSigningAlgorithms"]: action_type: DENY condition: "resource.visibility == 'PUBLIC' &&\nresource.dnssecConfig.state ==\ @@ -4839,6 +4976,313 @@ values: resource_types: - compute.googleapis.com/Firewall timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRequireDescription"]: + action_type: DENY + condition: "(\n resource.description == \"\" &&\n !resource.name.startsWith(\"\ + gke-\") &&\n !resource.name.startsWith(\"k8s-\") &&\n !resource.name.endsWith(\"\ + -hc\") &&\n !resource.name.startsWith(\"k8s2-\") &&\n !resource.name.startsWith(\"\ + gkegw1-l7-\") &&\n !resource.name.startsWith(\"gkemcg1-l7-\")\n)" + description: Prevent the creation of VPC firewall rule that does not have description + provided. Description can be used for auditing to refer to security control + display_name: Require description on Firewall rule + method_types: + - CREATE + name: custom.firewallRequireDescription + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/Firewall + timeouts: null + ? module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictCacheSearchDatabasesPolicyRule"] + : action_type: DENY + condition: "resource.rules.exists(r, r.priority < 2147483644 && r.direction ==\ + \ 'INGRESS' &&\n r.match.srcIpRanges.exists(r, r == '0.0.0.0/0') &&\n (\n\ + \ r.match.layer4Configs.containsIpProtocolAndPort('tcp', '6379') ||\n \ + \ r.match.layer4Configs.containsIpProtocolAndPort('udp', '6379') ||\n r.match.layer4Configs.containsIpProtocolAndPort('tcp',\ + \ '9200') ||\n r.match.layer4Configs.containsIpProtocolAndPort('udp', '9200')\ + \ ||\n r.match.layer4Configs.containsIpProtocolAndPort('tcp', '9300') ||\n\ + \ r.match.layer4Configs.containsIpProtocolAndPort('udp', '9300') ||\n \ + \ r.match.layer4Configs.containsIpProtocolAndPort('tcp', '11211') ||\n r.match.layer4Configs.containsIpProtocolAndPort('udp',\ + \ '11211') ||\n r.match.layer4Configs.containsIpProtocolAndPort('tcp', '11214')\ + \ ||\n r.match.layer4Configs.containsIpProtocolAndPort('udp', '11214') ||\n\ + \ r.match.layer4Configs.containsIpProtocolAndPort('tcp', '11215') ||\n \ + \ r.match.layer4Configs.containsIpProtocolAndPort('udp', '11215')\n )\n)" + description: Ensure that cache and search database ports (Elasticsearch, Memcached, + Redis) are not accessible from any source when using Firewall Policy Rule + display_name: Restrict Firewall Policy rules allowing cache/search database port + access from any source + method_types: + - CREATE + - UPDATE + name: custom.firewallRestrictCacheSearchDatabasesPolicyRule + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/FirewallPolicy + timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictCacheSearchDatabasesRule"]: + action_type: DENY + condition: "resource.direction.matches('INGRESS') &&\n resource.sourceRanges.exists(range,\ + \ range == '0.0.0.0/0') &&\n (\n resource.allowed.containsFirewallPort('tcp',\ + \ '9200') ||\n resource.allowed.containsFirewallPort('tcp', '9300') ||\n\ + \ resource.allowed.containsFirewallPort('tcp', '11211') ||\n resource.allowed.containsFirewallPort('tcp',\ + \ '11214') ||\n resource.allowed.containsFirewallPort('tcp', '11215') ||\n\ + \ resource.allowed.containsFirewallPort('tcp', '6379') ||\n resource.allowed.containsFirewallPort('udp',\ + \ '11211') ||\n resource.allowed.containsFirewallPort('udp', '11214') ||\n\ + \ resource.allowed.containsFirewallPort('udp', '11215')\n )" + description: Ensure that cache and search database ports (Elasticsearch, Memcached, + Redis) are not accessible from any source when using VPC Firewall Rule. + display_name: Restrict VPC Firewall rules allowing cache/search database port + access from any source + method_types: + - CREATE + - UPDATE + name: custom.firewallRestrictCacheSearchDatabasesRule + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/Firewall + timeouts: null + ? module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictDirectoryServicesPolicyRule"] + : action_type: DENY + condition: "resource.rules.exists(rule,\n rule.priority < 2147483644 &&\n rule.direction\ + \ == 'INGRESS' &&\n rule.match.srcIpRanges.exists(range, range == '0.0.0.0/0')\ + \ &&\n (\n rule.match.layer4Configs.containsIpProtocolAndPort('udp', '445')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('udp', '389') ||\n\ + \ rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '445') ||\n \ + \ rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '389') ||\n \ + \ rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '636')\n )\n)" + description: Ensure that directory and authentication services (SMB/CIFS, LDAP) + are not accessible from the Internet when using Firewall Policy Rule + display_name: Restrict Firewall Policy rules allowing directory service access + from any source + method_types: + - CREATE + - UPDATE + name: custom.firewallRestrictDirectoryServicesPolicyRule + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/FirewallPolicy + timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictDirectoryServicesRule"]: + action_type: DENY + condition: "resource.direction.matches('INGRESS') &&\n resource.sourceRanges.exists(range,\ + \ range == '0.0.0.0/0') &&\n (\n resource.allowed.containsFirewallPort('tcp',\ + \ '445') ||\n resource.allowed.containsFirewallPort('tcp', '389') ||\n \ + \ resource.allowed.containsFirewallPort('tcp', '636') ||\n resource.allowed.containsFirewallPort('udp',\ + \ '445') ||\n resource.allowed.containsFirewallPort('udp', '389')\n )" + description: Ensure that directory and authentication services (SMB/CIFS, LDAP) + are not accessible from the Internet when using VPC Firewall Rule + display_name: Restrict VPC Firewall rules allowing directory service access from + any source + method_types: + - CREATE + - UPDATE + name: custom.firewallRestrictDirectoryServicesRule + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/Firewall + timeouts: null + ? module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictInsecureProtocolsPolicyRule"] + : action_type: DENY + condition: "resource.rules.exists(rule,\n rule.priority < 2147483644 &&\n rule.direction\ + \ == 'INGRESS' &&\n rule.match.srcIpRanges.exists(range, range == '0.0.0.0/0')\ + \ &&\n (\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '21')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '23') ||\n\ + \ rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '80')\n )\n)" + description: Ensure that insecure legacy protocols (Telnet, FTP, HTTP) are not + accessible from any source when using Firewall Policy Rule + display_name: Restrict Firewall Policy rules allowing insecure protocol access + from any source + method_types: + - CREATE + - UPDATE + name: custom.firewallRestrictInsecureProtocolsPolicyRule + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/FirewallPolicy + timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictInsecureProtocolsRule"]: + action_type: DENY + condition: "resource.direction.matches('INGRESS') &&\n resource.sourceRanges.exists(range,\ + \ range == '0.0.0.0/0') &&\n (\n resource.allowed.containsFirewallPort('tcp',\ + \ '21') ||\n resource.allowed.containsFirewallPort('tcp', '23') ||\n resource.allowed.containsFirewallPort('tcp',\ + \ '80')\n )" + description: Ensure that insecure legacy protocols (Telnet, FTP, HTTP) are not + accessible from any source when using VPC Firewall Rule + display_name: Restrict VPC Firewall rules allowing insecure protocol access from + any source + method_types: + - CREATE + - UPDATE + name: custom.firewallRestrictInsecureProtocolsRule + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/Firewall + timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictMailProtocolsPolicyRule"]: + action_type: DENY + condition: "resource.rules.exists(rule,\n rule.priority < 2147483644 &&\n rule.direction\ + \ == 'INGRESS' &&\n rule.match.srcIpRanges.exists(range, range == '0.0.0.0/0')\ + \ &&\n (\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '25')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '110')\n\ + \ )\n)" + description: Ensure that mail protocols (SMTP, POP3) are not accessible from any + source when using Firewall Policy Rule + display_name: Restrict Firewall Policy rules allowing mail protocol access from + any source + method_types: + - CREATE + - UPDATE + name: custom.firewallRestrictMailProtocolsPolicyRule + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/FirewallPolicy + timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictMailProtocolsRule"]: + action_type: DENY + condition: "resource.direction.matches('INGRESS') &&\n resource.sourceRanges.exists(range,\ + \ range == '0.0.0.0/0') &&\n (\n resource.allowed.containsFirewallPort('tcp',\ + \ '25') ||\n resource.allowed.containsFirewallPort('tcp', '110')\n )" + description: Ensure that mail protocols (SMTP, POP3) are not accessible from any + source when using VPC Firewall Rule + display_name: Restrict VPC Firewall rules allowing mail protocol access from any + source + method_types: + - CREATE + - UPDATE + name: custom.firewallRestrictMailProtocolsRule + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/Firewall + timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictManagementPortsPolicyRule"]: + action_type: DENY + condition: "resource.rules.exists(rule,\n rule.priority < 2147483644 &&\n rule.direction\ + \ == 'INGRESS' &&\n rule.match.srcIpRanges.exists(range, range == '0.0.0.0/0')\ + \ &&\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '9090')\n)" + description: Ensure that management interfaces (Cisco Secure WebSM) are not accessible + from any source when using Firewall Policy Rule + display_name: Restrict Firewall Policy rules allowing management port access from + any source + method_types: + - CREATE + - UPDATE + name: custom.firewallRestrictManagementPortsPolicyRule + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/FirewallPolicy + timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictManagementPortsRule"]: + action_type: DENY + condition: "resource.direction.matches('INGRESS') &&\n resource.sourceRanges.exists(range,\ + \ range == '0.0.0.0/0') &&\n resource.allowed.containsFirewallPort('tcp', '9090')" + description: Ensure that management interfaces (Cisco Secure WebSM) are not accessible + from any source when using VPC Firewall Rule + display_name: Restrict VPC Firewall rules allowing management port access from + any source + method_types: + - CREATE + - UPDATE + name: custom.firewallRestrictManagementPortsRule + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/Firewall + timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictNetworkServicesPolicyRule"]: + action_type: DENY + condition: "resource.rules.exists(rule,\n rule.priority < 2147483644 &&\n rule.direction\ + \ == 'INGRESS' &&\n rule.match.srcIpRanges.exists(range, range == '0.0.0.0/0')\ + \ &&\n (\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '53')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('udp', '53') ||\n\ + \ rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '137') ||\n \ + \ rule.match.layer4Configs.containsIpProtocolAndPort('udp', '137') ||\n \ + \ rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '138') ||\n \ + \ rule.match.layer4Configs.containsIpProtocolAndPort('udp', '138') ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp',\ + \ '139') ||\n rule.match.layer4Configs.containsIpProtocolAndPort('udp', '139')\n\ + \ )\n)" + description: Ensure that network infrastructure services (DNS, NetBIOS) are not + accessible from any source when using Firewall Policy Rule + display_name: Restrict Firewall Policy rules allowing network service access from + any source + method_types: + - CREATE + - UPDATE + name: custom.firewallRestrictNetworkServicesPolicyRule + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/FirewallPolicy + timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictNetworkServicesRule"]: + action_type: DENY + condition: "resource.direction.matches('INGRESS') &&\n resource.sourceRanges.exists(range,\ + \ range == '0.0.0.0/0') &&\n (\n resource.allowed.containsFirewallPort('tcp',\ + \ '53') ||\n resource.allowed.containsFirewallPort('udp', '53') ||\n resource.allowed.containsFirewallPort('tcp',\ + \ '137') ||\n resource.allowed.containsFirewallPort('udp', '137') ||\n \ + \ resource.allowed.containsFirewallPort('tcp', '138') ||\n resource.allowed.containsFirewallPort('udp',\ + \ '138') ||\n resource.allowed.containsFirewallPort('tcp', '139') ||\n \ + \ resource.allowed.containsFirewallPort('udp', '139')\n )" + description: Ensure that network infrastructure services (DNS, NetBIOS) are not + accessible from any source when using VPC Firewall Rule + display_name: Restrict VPC Firewall rules allowing network service access from + any source + method_types: + - CREATE + - UPDATE + name: custom.firewallRestrictNetworkServicesRule + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/Firewall + timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictNoSQLDatabasesPolicyRule"]: + action_type: DENY + condition: "resource.rules.exists(rule,\n rule.priority < 2147483644 &&\n rule.direction\ + \ == 'INGRESS' &&\n rule.match.srcIpRanges.exists(range, range == '0.0.0.0/0')\ + \ &&\n (\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '7000')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '7001')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '7199')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '8888')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '9042')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '9160')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '61620')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '61621')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '27017')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '27018')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '27019')\n\ + \ )\n)" + description: Ensure that NoSQL database ports (Cassandra, MongoDB) are not accessible + from any source when using Firewall Policy Rule + display_name: Restrict Firewall Policy rules allowing NoSQL database port access + from any source + method_types: + - CREATE + - UPDATE + name: custom.firewallRestrictNoSQLDatabasesPolicyRule + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/FirewallPolicy + timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictNoSQLDatabasesRule"]: + action_type: DENY + condition: "resource.direction.matches('INGRESS') &&\n resource.sourceRanges.exists(range,\ + \ range == '0.0.0.0/0') &&\n (\n resource.allowed.containsFirewallPort('tcp',\ + \ '7000') ||\n resource.allowed.containsFirewallPort('tcp', '7001') ||\n\ + \ resource.allowed.containsFirewallPort('tcp', '7199') ||\n resource.allowed.containsFirewallPort('tcp',\ + \ '8888') ||\n resource.allowed.containsFirewallPort('tcp', '9042') ||\n\ + \ resource.allowed.containsFirewallPort('tcp', '9160') ||\n resource.allowed.containsFirewallPort('tcp',\ + \ '61620') ||\n resource.allowed.containsFirewallPort('tcp', '61621') ||\n\ + \ resource.allowed.containsFirewallPort('tcp', '27017') ||\n resource.allowed.containsFirewallPort('tcp',\ + \ '27018') ||\n resource.allowed.containsFirewallPort('tcp', '27019')\n \ + \ )" + description: Ensure that NoSQL database ports (Cassandra, MongoDB) are not accessible + from any source when using Firewall Policy Rule + display_name: Restrict VPC Firewall rules allowing NoSQL database port access + from any source + method_types: + - CREATE + - UPDATE + name: custom.firewallRestrictNoSQLDatabasesRule + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/Firewall + timeouts: null module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictPublicAccessRule"]: action_type: DENY condition: "(size(resource.allowed) > 0) &&\n(\n resource.sourceRanges.exists(range,\ @@ -4894,6 +5338,52 @@ values: resource_types: - compute.googleapis.com/Firewall timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictSQLDatabasesPolicyRule"]: + action_type: DENY + condition: "resource.rules.exists(rule,\n rule.priority < 2147483644 &&\n rule.direction\ + \ == 'INGRESS' &&\n rule.match.srcIpRanges.exists(range, range == '0.0.0.0/0')\ + \ &&\n (\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '3306')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '1521')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '2483')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '2484')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('tcp', '5432')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('udp', '2483')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('udp', '2484')\ + \ ||\n rule.match.layer4Configs.containsIpProtocolAndPort('udp', '5432')\n\ + \ )\n)" + description: Ensure that SQL database ports (MySQL, Oracle, PostgreSQL) are not + accessible from any source when using Firewall Policy Rule + display_name: Restrict Firewall Policy rules allowing SQL database port access + from any source + method_types: + - CREATE + - UPDATE + name: custom.firewallRestrictSQLDatabasesPolicyRule + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/FirewallPolicy + timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictSQLDatabasesRule"]: + action_type: DENY + condition: "resource.direction.matches('INGRESS') &&\n resource.sourceRanges.exists(range,\ + \ range == '0.0.0.0/0') &&\n (\n resource.allowed.containsFirewallPort('tcp',\ + \ '3306') ||\n resource.allowed.containsFirewallPort('tcp', '1521') ||\n\ + \ resource.allowed.containsFirewallPort('tcp', '2483') ||\n resource.allowed.containsFirewallPort('tcp',\ + \ '2484') ||\n resource.allowed.containsFirewallPort('tcp', '5432') ||\n\ + \ resource.allowed.containsFirewallPort('udp', '2483') ||\n resource.allowed.containsFirewallPort('udp',\ + \ '2484') ||\n resource.allowed.containsFirewallPort('udp', '5432')\n )" + description: Ensure that SQL database ports (MySQL, Oracle, PostgreSQL) are not + accessible from any source when using VPC Firewall Rule + display_name: Restrict VPC Firewall rules allowing SQL database port access from + any source + method_types: + - CREATE + - UPDATE + name: custom.firewallRestrictSQLDatabasesRule + parent: organizations/1234567890 + resource_types: + - compute.googleapis.com/Firewall + timeouts: null module.organization[0].google_org_policy_custom_constraint.constraint["custom.firewallRestrictSshPolicyRule"]: action_type: DENY condition: "resource.rules.exists(rule,\n rule.priority < 2147483644 &&\n \ @@ -5030,6 +5520,19 @@ values: resource_types: - container.googleapis.com/NodePool timeouts: null + module.organization[0].google_org_policy_custom_constraint.constraint["custom.gkeRequireConfidentialNodes"]: + action_type: DENY + condition: resource.confidentialNodes.enabled == false + description: Enforce that the GKE clusters is using confidential nodes + display_name: Require confidential nodes + method_types: + - CREATE + - UPDATE + name: custom.gkeRequireConfidentialNodes + parent: organizations/1234567890 + resource_types: + - container.googleapis.com/Cluster + timeouts: null module.organization[0].google_org_policy_custom_constraint.constraint["custom.gkeRequireDataplaneV2"]: action_type: DENY condition: resource.networkConfig.datapathProvider != 'ADVANCED_DATAPATH' @@ -5562,6 +6065,67 @@ values: location: global organization: '1234567890' timeouts: null + ? module.organization[0].google_scc_management_organization_security_health_analytics_custom_module.scc_organization_custom_module["cloudkmsAllowedProtectionLevel"] + : custom_config: + - custom_output: [] + description: Detect if the protection level for Cloud KMS keys is not configured + correctly + predicate: + - description: null + expression: resource.primary.protectionLevel in ["SOFTWARE"] == false + location: null + title: null + recommendation: Ensure the protection level for Cloud KMS keys is configured + correctly + resource_selector: + - resource_types: + - cloudkms.googleapis.com/CryptoKey + severity: MEDIUM + display_name: cloudkmsAllowedProtectionLevel + enablement_state: ENABLED + location: global + organization: '1234567890' + timeouts: null + ? module.organization[0].google_scc_management_organization_security_health_analytics_custom_module.scc_organization_custom_module["cloudrunDisableJobDefaultServiceAccount"] + : custom_config: + - custom_output: [] + description: Detect if default service accounts are used by Cloud Run jobs + predicate: + - description: null + expression: resource.spec.template.spec.template.spec.serviceAccountName.endsWith("@developer.gserviceaccount.com") + location: null + title: null + recommendation: Ensure only authorized non-default service accounts are used + by Cloud Run jobs + resource_selector: + - resource_types: + - run.googleapis.com/Job + severity: HIGH + display_name: cloudrunDisableJobDefaultServiceAccount + enablement_state: ENABLED + location: global + organization: '1234567890' + timeouts: null + ? module.organization[0].google_scc_management_organization_security_health_analytics_custom_module.scc_organization_custom_module["cloudrunDisableServiceDefaultServiceAccount"] + : custom_config: + - custom_output: [] + description: Detect if default service accounts are used by Cloud Run services + predicate: + - description: null + expression: resource.spec.template.spec.serviceAccountName.endsWith("@developer.gserviceaccount.com") + location: null + title: null + recommendation: Ensure only authorized non-default service accounts are used + by Cloud Run services + resource_selector: + - resource_types: + - run.googleapis.com/Service + severity: HIGH + display_name: cloudrunDisableServiceDefaultServiceAccount + enablement_state: ENABLED + location: global + organization: '1234567890' + timeouts: null ? module.organization[0].google_scc_management_organization_security_health_analytics_custom_module.scc_organization_custom_module["cloudrunRequireBinaryAuthorization"] : custom_config: - custom_output: [] @@ -5585,6 +6149,29 @@ values: location: global organization: '1234567890' timeouts: null + ? module.organization[0].google_scc_management_organization_security_health_analytics_custom_module.scc_organization_custom_module["cloudrunRequireEgressAllTraffic"] + : custom_config: + - custom_output: [] + description: Detect if Cloud Run services and jobs are not configured to route + all egress traffic through the VPC network + predicate: + - description: null + expression: "(\n !resource.spec.template.metadata.annotations['run.googleapis.com/vpc-access-egress'].matches('all-traffic')\n\ + )" + location: null + title: null + recommendation: Ensure Cloud Run services and jobs are configured to route all + egress traffic through the VPC network + resource_selector: + - resource_types: + - run.googleapis.com/Service + - run.googleapis.com/Job + severity: HIGH + display_name: cloudrunRequireEgressAllTraffic + enablement_state: ENABLED + location: global + organization: '1234567890' + timeouts: null ? module.organization[0].google_scc_management_organization_security_health_analytics_custom_module.scc_organization_custom_module["cloudrunRequireIngressInternalAndLoadBalancer"] : custom_config: - custom_output: [] @@ -5607,6 +6194,27 @@ values: location: global organization: '1234567890' timeouts: null + ? module.organization[0].google_scc_management_organization_security_health_analytics_custom_module.scc_organization_custom_module["cloudsqlRequireHighAvailability"] + : custom_config: + - custom_output: [] + description: Detect if the high availability (HA) configuration for Cloud SQL + instances is not set to regional + predicate: + - description: null + expression: (resource.settings.availabilityType != "REGIONAL") + location: null + title: null + recommendation: Ensure if the HA configuration for all Cloud SQL instances is + set regional + resource_selector: + - resource_types: + - sqladmin.googleapis.com/Instance + severity: MEDIUM + display_name: cloudsqlRequireHighAvailability + enablement_state: ENABLED + location: global + organization: '1234567890' + timeouts: null ? module.organization[0].google_scc_management_organization_security_health_analytics_custom_module.scc_organization_custom_module["cloudsqlRequirePointInTimeRecovery"] : custom_config: - custom_output: [] @@ -5668,6 +6276,27 @@ values: location: global organization: '1234567890' timeouts: null + ? module.organization[0].google_scc_management_organization_security_health_analytics_custom_module.scc_organization_custom_module["gkeRequireConfidentialNodes"] + : custom_config: + - custom_output: [] + description: Detect if any GKE clusters are running without Confidential GKE + nodes + predicate: + - description: null + expression: (resource.confidentialNodes.enabled == false) + location: null + title: null + recommendation: Ensure GKE clusters are running with Confidential GKE nodes + enabled + resource_selector: + - resource_types: + - container.googleapis.com/Cluster + severity: MEDIUM + display_name: gkeRequireConfidentialNodes + enablement_state: ENABLED + location: global + organization: '1234567890' + timeouts: null ? module.organization[0].google_scc_management_organization_security_health_analytics_custom_module.scc_organization_custom_module["gkeRequireDataplaneV2"] : custom_config: - custom_output: [] @@ -5707,6 +6336,26 @@ values: location: global organization: '1234567890' timeouts: null + ? module.organization[0].google_scc_management_organization_security_health_analytics_custom_module.scc_organization_custom_module["secretmanagerAllowedRotationPeriod"] + : custom_config: + - custom_output: [] + description: Detect if the rotation period for secrets are not configured correctly + predicate: + - description: null + expression: (!has(resource.rotation.rotationPeriod)) || (resource.rotation.rotationPeriod + > duration("31536000s")) + location: null + title: null + recommendation: Ensure the rotation period for secrets are configured correctly + resource_selector: + - resource_types: + - secretmanager.googleapis.com/Secret + severity: MEDIUM + display_name: secretmanagerAllowedRotationPeriod + enablement_state: ENABLED + location: global + organization: '1234567890' + timeouts: null module.organization[0].google_tags_tag_key.default["context"]: description: Organization-level contexts. parent: organizations/1234567890 @@ -5748,33 +6397,903 @@ values: description: Allow all domains in DRS org policy. short_name: allowed-policy-member-domains-all timeouts: null + module.projects-observability[0].google_logging_metric.metrics["auditConfigChanges"]: + bucket_options: [] + description: Audit Configuration Changes + disabled: null + filter: protoPayload.methodName="SetIamPolicy" AND protoPayload.serviceData.policyDelta.auditConfigDeltas:* + label_extractors: + folder_id: EXTRACT(labels.folder_id) + method_name: EXTRACT(protoPayload.methodName) + organization_id: EXTRACT(labels.organization_id) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + metric_descriptor: + - display_name: null + labels: + - description: folder_id + key: folder_id + value_type: STRING + - description: method_name + key: method_name + value_type: STRING + - description: organization_id + key: organization_id + value_type: STRING + - description: principal + key: principal + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 + name: auditConfigChanges + project: ft0-prod-audit-logs-0 + timeouts: null + value_extractor: null + module.projects-observability[0].google_logging_metric.metrics["binaryAuthorizationPolicyChanges"]: + bucket_options: [] + description: Binary Authorization Policy Changes + disabled: null + filter: protoPayload.methodName="google.cloud.binaryauthorization.v1.BinauthzManagementServiceV1.UpdatePolicy" + AND protoPayload.serviceName="binaryauthorization.googleapis.com" AND ("ALWAYS_ALLOW" + OR "DRYRUN_AUDIT_LOG_ONLY") + label_extractors: + method_name: EXTRACT(protoPayload.methodName) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + metric_descriptor: + - display_name: null + labels: + - description: method_name + key: method_name + value_type: STRING + - description: principal + key: principal + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 + name: binaryAuthorizationPolicyChanges + project: ft0-prod-audit-logs-0 + timeouts: null + value_extractor: null + module.projects-observability[0].google_logging_metric.metrics["cloudsqlInstanceChanges"]: + bucket_options: [] + description: Cloud SQL Instance Configuration Changes + disabled: null + filter: protoPayload.methodName="cloudsql.instances.update" + label_extractors: + database_id: EXTRACT(labels.database_id) + method_name: EXTRACT(protoPayload.methodName) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + metric_descriptor: + - display_name: null + labels: + - description: database_id + key: database_id + value_type: STRING + - description: method_name + key: method_name + value_type: STRING + - description: principal + key: principal + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 + name: cloudsqlInstanceChanges + project: ft0-prod-audit-logs-0 + timeouts: null + value_extractor: null + module.projects-observability[0].google_logging_metric.metrics["customRoleChanges"]: + bucket_options: [] + description: Custom Role Changes + disabled: null + filter: "resource.type=\"iam_role\" AND (\n protoPayload.methodName=\"google.iam.admin.v1.CreateRole\"\ + \ OR\n protoPayload.methodName=\"google.iam.admin.v1.UpdateRole\" OR\n protoPayload.methodName=\"\ + google.iam.admin.v1.DeleteRole\"\n)" + label_extractors: + method_name: EXTRACT(protoPayload.methodName) + organization_id: EXTRACT(labels.organization_id) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + role_name: EXTRACT(labels.role_name) + metric_descriptor: + - display_name: null + labels: + - description: method_name + key: method_name + value_type: STRING + - description: organization_id + key: organization_id + value_type: STRING + - description: principal + key: principal + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + - description: role_name + key: role_name + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 + name: customRoleChanges + project: ft0-prod-audit-logs-0 + timeouts: null + value_extractor: null + module.projects-observability[0].google_logging_metric.metrics["firewallPolicyRuleChanges"]: + bucket_options: [] + description: Network Firewall Policy Rule Changes + disabled: null + filter: "resource.labels.method:\"compute.networkFirewallPolicies\" AND (\n protoPayload.methodName:\"\ + compute.networkFirewallPolicies.addRule\" OR\n protoPayload.methodName:\"compute.networkFirewallPolicies.removeRule\"\ + \ OR\n protoPayload.methodName:\"compute.networkFirewallPolicies.patchRule\"\ + \n)" + label_extractors: + method_name: EXTRACT(protoPayload.methodName) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + metric_descriptor: + - display_name: null + labels: + - description: method_name + key: method_name + value_type: STRING + - description: principal + key: principal + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 + name: firewallPolicyRuleChanges + project: ft0-prod-audit-logs-0 + timeouts: null + value_extractor: null + module.projects-observability[0].google_logging_metric.metrics["firewallRuleChanges"]: + bucket_options: [] + description: VPC Network Firewall Rule Changes + disabled: null + filter: resource.type="gce_firewall_rule" AND (protoPayload.methodName:"compute.firewalls.patch" + OR protoPayload.methodName:"compute.firewalls.insert" OR protoPayload.methodName:"compute.firewalls.delete") + label_extractors: + firewall_rule_id: EXTRACT(labels.firewall_rule_id) + method_name: EXTRACT(protoPayload.methodName) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + metric_descriptor: + - display_name: null + labels: + - description: firewall_rule_id + key: firewall_rule_id + value_type: STRING + - description: method_name + key: method_name + value_type: STRING + - description: principal + key: principal + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 + name: firewallRuleChanges + project: ft0-prod-audit-logs-0 + timeouts: null + value_extractor: null + module.projects-observability[0].google_logging_metric.metrics["networkChanges"]: + bucket_options: [] + description: VPC Network Changes + disabled: null + filter: "resource.type=\"gce_network\" AND (\n protoPayload.methodName:\"compute.networks.insert\"\ + \ OR\n protoPayload.methodName:\"compute.networks.patch\" OR\n protoPayload.methodName:\"\ + compute.networks.delete\" OR\n protoPayload.methodName:\"compute.networks.addPeering\"\ + \ OR\n protoPayload.methodName:\"compute.networks.updatePeering\" OR\n protoPayload.methodName:\"\ + compute.networks.removePeering\"\n)" + label_extractors: + method_name: EXTRACT(protoPayload.methodName) + network_id: EXTRACT(labels.network_id) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + metric_descriptor: + - display_name: null + labels: + - description: method_name + key: method_name + value_type: STRING + - description: network_id + key: network_id + value_type: STRING + - description: principal + key: principal + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 + name: networkChanges + project: ft0-prod-audit-logs-0 + timeouts: null + value_extractor: null + module.projects-observability[0].google_logging_metric.metrics["networkRouteChanges"]: + bucket_options: [] + description: VPC Network Route Changes + disabled: null + filter: "resource.type=\"gce_route\" AND (\n protoPayload.methodName:\"compute.routes.insert\"\ + \ OR\n protoPayload.methodName:\"compute.routes.delete\"\n)" + label_extractors: + method_name: EXTRACT(protoPayload.methodName) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + route_id: EXTRACT(labels.route_id) + metric_descriptor: + - display_name: null + labels: + - description: method_name + key: method_name + value_type: STRING + - description: principal + key: principal + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + - description: route_id + key: route_id + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 + name: networkRouteChanges + project: ft0-prod-audit-logs-0 + timeouts: null + value_extractor: null + module.projects-observability[0].google_logging_metric.metrics["projectOwnershipChange"]: + bucket_options: [] + description: Project Ownership Changes + disabled: null + filter: "(protoPayload.serviceName=\"cloudresourcemanager.googleapis.com\") AND\n\ + (ProjectOwnership OR projectOwnerInvitee)\nOR\n(\n protoPayload.serviceData.policyDelta.bindingDeltas.action=\"\ + REMOVE\" AND\n protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\"\ + \n)\nOR\n(\n protoPayload.serviceData.policyDelta.bindingDeltas.action=\"ADD\"\ + \ AND\n protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\"\ + \n)" + label_extractors: + folder_id: EXTRACT(labels.folder_id) + method_name: EXTRACT(protoPayload.methodName) + organization_id: EXTRACT(labels.organization_id) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + metric_descriptor: + - display_name: null + labels: + - description: folder_id + key: folder_id + value_type: STRING + - description: method_name + key: method_name + value_type: STRING + - description: organization_id + key: organization_id + value_type: STRING + - description: principal + key: principal + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 + name: projectOwnershipChange + project: ft0-prod-audit-logs-0 + timeouts: null + value_extractor: null + module.projects-observability[0].google_logging_metric.metrics["storageIamChanges"]: + bucket_options: [] + description: Cloud Storage IAM Permission Changes + disabled: null + filter: resource.type="gcs_bucket" AND protoPayload.methodName="storage.setIamPermissions" + label_extractors: + bucket_name: EXTRACT(labels.bucket_name) + location: EXTRACT(labels.location) + method_name: EXTRACT(protoPayload.methodName) + principal: EXTRACT(protoPayload.authenticationInfo.principalEmail) + project_id: EXTRACT(labels.project_id) + metric_descriptor: + - display_name: null + labels: + - description: bucket_name + key: bucket_name + value_type: STRING + - description: location + key: location + value_type: STRING + - description: method_name + key: method_name + value_type: STRING + - description: principal + key: principal + value_type: STRING + - description: project_id + key: project_id + value_type: STRING + metric_kind: DELTA + unit: '1' + value_type: INT64 + name: storageIamChanges + project: ft0-prod-audit-logs-0 + timeouts: null + value_extractor: null + module.projects-observability[0].google_monitoring_alert_policy.alerts["auditConfigChanges"]: + alert_strategy: [] + combiner: OR + conditions: + - condition_absent: [] + condition_matched_log: [] + condition_monitoring_query_language: [] + condition_prometheus_query_language: [] + condition_sql: [] + condition_threshold: + - aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.organization_id + - metric.label.folder_id + - metric.label.project_id + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + denominator_aggregations: [] + denominator_filter: null + duration: 0s + evaluation_missing_data: null + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/auditConfigChanges" + forecast_options: [] + threshold_value: 0 + trigger: + - count: 1 + percent: null + display_name: 'Log match condition: Audit Configuration Changes' + display_name: Audit Configuration Changes + documentation: + - content: 'Log-based alerting policy in project ${project} detected audit configuration + changes. + + + This alert helps track GCP services audit log configuration changes to ensure + appropriate. + + audit logs are being collected + + ``` + + protoPayload.methodName="SetIamPolicy" AND + + protoPayload.serviceData.policyDelta.auditConfigDeltas:* + + ```' + links: [] + mime_type: text/markdown + subject: null + enabled: true + notification_channels: [] + project: ft0-prod-audit-logs-0 + severity: null + timeouts: null + user_labels: null + module.projects-observability[0].google_monitoring_alert_policy.alerts["binaryAuthorizationPolicyChanges"]: + alert_strategy: [] + combiner: OR + conditions: + - condition_absent: [] + condition_matched_log: [] + condition_monitoring_query_language: [] + condition_prometheus_query_language: [] + condition_sql: [] + condition_threshold: + - aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + denominator_aggregations: [] + denominator_filter: null + duration: 0s + evaluation_missing_data: null + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/binaryAuthorizationPolicyChanges" + forecast_options: [] + threshold_value: 0 + trigger: + - count: 1 + percent: null + display_name: 'Log match condition: Binary Authorization policy configuration + changes' + display_name: Binary Authorization Policy Changes + documentation: + - content: 'Log-based alerting policy in project ${project} detected for a change + to Binary Authorization + + project-singleton policy, weakening the enforcement or evaluation modes. + + + This alert helps ensure security by monitoring configuration changes to Binary + Authorization policies. + + ``` + + protoPayload.methodName="google.cloud.binaryauthorization.v1.BinauthzManagementServiceV1.UpdatePolicy" + AND + + protoPayload.serviceName="binaryauthorization.googleapis.com" AND + + ("ALWAYS_ALLOW" OR "DRYRUN_AUDIT_LOG_ONLY") + + ```' + links: [] + mime_type: text/markdown + subject: null + enabled: true + notification_channels: [] + project: ft0-prod-audit-logs-0 + severity: null + timeouts: null + user_labels: null + module.projects-observability[0].google_monitoring_alert_policy.alerts["cloudsqlInstanceChanges"]: + alert_strategy: [] + combiner: OR + conditions: + - condition_absent: [] + condition_matched_log: [] + condition_monitoring_query_language: [] + condition_prometheus_query_language: [] + condition_sql: [] + condition_threshold: + - aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.database_id + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + denominator_aggregations: [] + denominator_filter: null + duration: 0s + evaluation_missing_data: null + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/cloudsqlInstanceChanges" + forecast_options: [] + threshold_value: 0 + trigger: + - count: 1 + percent: null + display_name: 'Log match condition: Cloud SQL instance configuration changes' + display_name: Cloud SQL Instance Configuration Changes + documentation: + - content: 'Log-based alerting policy in project ${project} detected Cloud SQL + instance configuration changes. + + + This alert helps ensure security by monitoring configuration changes to SQL + instances. + + ``` + + protoPayload.methodName="cloudsql.instances.update" + + ```' + links: [] + mime_type: text/markdown + subject: null + enabled: true + notification_channels: [] + project: ft0-prod-audit-logs-0 + severity: null + timeouts: null + user_labels: null + module.projects-observability[0].google_monitoring_alert_policy.alerts["customRoleChanges"]: + alert_strategy: [] + combiner: OR + conditions: + - condition_absent: [] + condition_matched_log: [] + condition_monitoring_query_language: [] + condition_prometheus_query_language: [] + condition_sql: [] + condition_threshold: + - aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.organization_id + - metric.label.project_id + - metric.label.role_name + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + denominator_aggregations: [] + denominator_filter: null + duration: 0s + evaluation_missing_data: null + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/customRoleChanges" + forecast_options: [] + threshold_value: 0 + trigger: + - count: 1 + percent: null + display_name: 'Log match condition: custom role changes' + display_name: Custom Role Changes + documentation: + - content: "Log-based alerting policy in project ${project} detected custom IAM\ + \ role creation,\ndeletion or update activities.\n\nThis alert helps ensure\ + \ security by monitoring changes to Identity and Access Management (IAM) roles.\n\ + ```\nresource.type=\"iam_role\" AND (\n protoPayload.methodName=\"google.iam.admin.v1.CreateRole\"\ + \ OR\n protoPayload.methodName=\"google.iam.admin.v1.UpdateRole\" OR\n protoPayload.methodName=\"\ + google.iam.admin.v1.DeleteRole\"\n)\n```" + links: [] + mime_type: text/markdown + subject: null + enabled: true + notification_channels: [] + project: ft0-prod-audit-logs-0 + severity: null + timeouts: null + user_labels: null + module.projects-observability[0].google_monitoring_alert_policy.alerts["firewallPolicyRuleChanges"]: + alert_strategy: [] + combiner: OR + conditions: + - condition_absent: [] + condition_matched_log: [] + condition_monitoring_query_language: [] + condition_prometheus_query_language: [] + condition_sql: [] + condition_threshold: + - aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + denominator_aggregations: [] + denominator_filter: null + duration: 0s + evaluation_missing_data: null + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/firewallPolicyRuleChanges" + forecast_options: [] + threshold_value: 0 + trigger: + - count: 1 + percent: null + display_name: 'Log match condition: Network Firewall Policy Rule Changes' + display_name: Network Firewall Policy Rule Changes + documentation: + - content: "Log-based alerting policy in project ${project} detected Firewall\ + \ Policy rule changes.\n\nThis alert helps ensure security by monitoring creation,\ + \ modification, or deletion of firewall rules.\n```\nresource.labels.method:\"\ + compute.networkFirewallPolicies\" AND (\n protoPayload.methodName:\"compute.networkFirewallPolicies.addRule\"\ + \ OR\n protoPayload.methodName:\"compute.networkFirewallPolicies.removeRule\"\ + \ OR\n protoPayload.methodName:\"compute.networkFirewallPolicies.patchRule\"\ + \n)\n```" + links: [] + mime_type: text/markdown + subject: null + enabled: true + notification_channels: [] + project: ft0-prod-audit-logs-0 + severity: null + timeouts: null + user_labels: null + module.projects-observability[0].google_monitoring_alert_policy.alerts["firewallRuleChanges"]: + alert_strategy: [] + combiner: OR + conditions: + - condition_absent: [] + condition_matched_log: [] + condition_monitoring_query_language: [] + condition_prometheus_query_language: [] + condition_sql: [] + condition_threshold: + - aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.firewall_rule_id + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + denominator_aggregations: [] + denominator_filter: null + duration: 0s + evaluation_missing_data: null + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/firewallRuleChanges" + forecast_options: [] + threshold_value: 0 + trigger: + - count: 1 + percent: null + display_name: 'Log match condition: VPC Network Firewall Rule Changes' + display_name: VPC Network Firewall Rule Changes + documentation: + - content: "Log-based alerting policy in project ${project} detected VPC Network\ + \ Firewall rule changes.\n\nThis alert helps ensure security by monitoring\ + \ creation, modification, or deletion of firewall rules.\n```\nresource.type=\"\ + gce_firewall_rule\" AND (\n protoPayload.methodName:\"compute.firewalls.patch\"\ + \ OR\n protoPayload.methodName:\"compute.firewalls.insert\" OR\n protoPayload.methodName:\"\ + compute.firewalls.delete\"\n)\n```" + links: [] + mime_type: text/markdown + subject: null + enabled: true + notification_channels: [] + project: ft0-prod-audit-logs-0 + severity: null + timeouts: null + user_labels: null + module.projects-observability[0].google_monitoring_alert_policy.alerts["networkChanges"]: + alert_strategy: [] + combiner: OR + conditions: + - condition_absent: [] + condition_matched_log: [] + condition_monitoring_query_language: [] + condition_prometheus_query_language: [] + condition_sql: [] + condition_threshold: + - aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.network_id + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + denominator_aggregations: [] + denominator_filter: null + duration: 0s + evaluation_missing_data: null + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/networkChanges" + forecast_options: [] + threshold_value: 0 + trigger: + - count: 1 + percent: null + display_name: 'Log match condition: VPC Network Changes' + display_name: VPC Network Changes + documentation: + - content: "Log-based alerting policy in project ${project} detected VPC Network\ + \ changes.\n\nThis alert helps ensure security by monitoring creation, modification,\ + \ deletion,\nor peering changes to VPC networks.\n```\nresource.type=\"gce_network\"\ + \ AND (\n protoPayload.methodName:\"compute.networks.insert\" OR\n protoPayload.methodName:\"\ + compute.networks.patch\" OR\n protoPayload.methodName:\"compute.networks.delete\"\ + \ OR\n protoPayload.methodName:\"compute.networks.addPeering\" OR\n protoPayload.methodName:\"\ + compute.networks.updatePeering\" OR\n protoPayload.methodName:\"compute.networks.removePeering\"\ + \n)\n```" + links: [] + mime_type: text/markdown + subject: null + enabled: true + notification_channels: [] + project: ft0-prod-audit-logs-0 + severity: null + timeouts: null + user_labels: null + module.projects-observability[0].google_monitoring_alert_policy.alerts["networkRouteChanges"]: + alert_strategy: [] + combiner: OR + conditions: + - condition_absent: [] + condition_matched_log: [] + condition_monitoring_query_language: [] + condition_prometheus_query_language: [] + condition_sql: [] + condition_threshold: + - aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.route_id + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + denominator_aggregations: [] + denominator_filter: null + duration: 0s + evaluation_missing_data: null + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/networkRouteChanges" + forecast_options: [] + threshold_value: 0 + trigger: + - count: 1 + percent: null + display_name: 'Log match condition: VPC Network Route Changes' + display_name: VPC Network Route Changes + documentation: + - content: "Log-based alerting policy in project ${project} detected VPC Network\ + \ Route changes.\n\nThis alert helps ensure security by monitoring creation\ + \ or deletion of network routes.\n```\nresource.type=\"gce_route\" AND (\n\ + \ protoPayload.methodName:\"compute.routes.insert\" OR\n protoPayload.methodName:\"\ + compute.routes.delete\"\n)\n```" + links: [] + mime_type: text/markdown + subject: null + enabled: true + notification_channels: [] + project: ft0-prod-audit-logs-0 + severity: null + timeouts: null + user_labels: null + module.projects-observability[0].google_monitoring_alert_policy.alerts["projectOwnershipChange"]: + alert_strategy: [] + combiner: OR + conditions: + - condition_absent: [] + condition_matched_log: [] + condition_monitoring_query_language: [] + condition_prometheus_query_language: [] + condition_sql: [] + condition_threshold: + - aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.organization_id + - metric.label.folder_id + - metric.label.project_id + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + denominator_aggregations: [] + denominator_filter: null + duration: 0s + evaluation_missing_data: null + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/projectOwnershipChange" + forecast_options: [] + threshold_value: 0 + trigger: + - count: 1 + percent: null + display_name: Project Ownership Changes + display_name: Project Ownership Changes + documentation: + - content: "Log-based alerting policy in project ${project} detected a project\ + \ ownership assignments or changes.\n```\n(protoPayload.serviceName=\"cloudresourcemanager.googleapis.com\"\ + ) AND\n(ProjectOwnership OR projectOwnerInvitee)\nOR\n(\n protoPayload.serviceData.policyDelta.bindingDeltas.action=\"\ + REMOVE\" AND\n protoPayload.serviceData.policyDelta.bindingDeltas.role=\"\ + roles/owner\"\n)\nOR\n(\n protoPayload.serviceData.policyDelta.bindingDeltas.action=\"\ + ADD\" AND\n protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\"\ + \n)\n```" + links: [] + mime_type: text/markdown + subject: null + enabled: true + notification_channels: [] + project: ft0-prod-audit-logs-0 + severity: null + timeouts: null + user_labels: null + module.projects-observability[0].google_monitoring_alert_policy.alerts["storageIamChanges"]: + alert_strategy: [] + combiner: OR + conditions: + - condition_absent: [] + condition_matched_log: [] + condition_monitoring_query_language: [] + condition_prometheus_query_language: [] + condition_sql: [] + condition_threshold: + - aggregations: + - alignment_period: 60s + cross_series_reducer: REDUCE_SUM + group_by_fields: + - metric.label.principal + - metric.label.method_name + - metric.label.project_id + - metric.label.location + - metric.label.bucket_name + per_series_aligner: ALIGN_SUM + comparison: COMPARISON_GT + denominator_aggregations: [] + denominator_filter: null + duration: 0s + evaluation_missing_data: null + filter: resource.type = "logging_bucket" AND metric.type = "logging.googleapis.com/user/storageIamChanges" + forecast_options: [] + threshold_value: 0 + trigger: + - count: 1 + percent: null + display_name: Cloud Storage IAM Permission Changes + display_name: Cloud Storage IAM Permission Changes + documentation: + - content: 'Log-based alerting policy in project ${project} detected Cloud Storage + Bucket IAM changes. + + + This alert helps ensure security by monitoring IAM permission changes to Cloud + Storage buckets. + + ``` + + resource.type="gcs_bucket" AND protoPayload.methodName="storage.setIamPermissions" + + ```' + links: [] + mime_type: text/markdown + subject: null + enabled: true + notification_channels: [] + project: ft0-prod-audit-logs-0 + severity: null + timeouts: null + user_labels: null terraform_data.precondition: input: null output: null triggers_replace: null + terraform_data.precondition-cicd: + input: null + output: null + triggers_replace: null counts: google_bigquery_dataset: 1 google_bigquery_default_service_account: 2 google_billing_account_iam_member: 6 google_essential_contacts_contact: 1 - google_folder: 8 + google_folder: 10 google_folder_iam_binding: 44 + google_kms_crypto_key: 3 + google_kms_crypto_key_iam_member: 3 + google_kms_key_ring: 3 google_logging_metric: 10 google_logging_organization_settings: 1 google_logging_organization_sink: 3 google_logging_project_bucket_config: 3 + google_logging_project_settings: 2 google_monitoring_alert_policy: 10 google_org_policy_custom_constraint: 80 - google_org_policy_policy: 149 + google_org_policy_policy: 154 google_organization_iam_audit_config: 1 google_organization_iam_binding: 38 google_organization_iam_custom_role: 9 google_project: 3 google_project_iam_binding: 17 - google_project_iam_member: 15 - google_project_service: 34 - google_project_service_identity: 9 + google_project_iam_member: 17 + google_project_service: 36 + google_project_service_identity: 11 google_scc_management_organization_security_health_analytics_custom_module: 16 google_service_account: 14 google_service_account_iam_binding: 2 @@ -5785,11 +7304,11 @@ counts: google_storage_managed_folder: 5 google_storage_managed_folder_iam_binding: 10 google_storage_project_service_account: 3 - google_tags_tag_binding: 5 + google_tags_tag_binding: 7 google_tags_tag_key: 3 google_tags_tag_value: 5 google_tags_tag_value_iam_binding: 4 local_file: 9 - modules: 48 - resources: 544 + modules: 54 + resources: 570 terraform_data: 4 diff --git a/tests/fast/stages/s0_org_setup/simple.yaml b/tests/fast/stages/s0_org_setup/simple.yaml index aca561e46..f5bd7e1af 100644 --- a/tests/fast/stages/s0_org_setup/simple.yaml +++ b/tests/fast/stages/s0_org_setup/simple.yaml @@ -422,6 +422,19 @@ values: condition: [] member: serviceAccount:iac-org-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com role: roles/billing.viewer + module.cicd-sa-apply["org-setup"].google_service_account_iam_binding.authoritative["roles/iam.workloadIdentityUser"]: + condition: [] + members: + - principalSet://iam.googleapis.com/$workload_identity_pools:iac-0/default/attribute.fast_sub/repo:gh-org/gh-repo:ref:refs/heads/fast-dev + - principalSet://iam.googleapis.com/$workload_identity_pools:iac-0/default/attribute.fast_sub/repo:gh-org/gh-repo:ref:refs/heads/master + role: roles/iam.workloadIdentityUser + service_account_id: projects/ft0-prod-iac-core-0/serviceAccounts/iac-org-cicd-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + module.cicd-sa-plan["org-setup"].google_service_account_iam_binding.authoritative["roles/iam.workloadIdentityUser"]: + condition: [] + members: + - principalSet://iam.googleapis.com/$workload_identity_pools:iac-0/default/attribute.repository/gh-org/gh-repo + role: roles/iam.workloadIdentityUser + service_account_id: projects/ft0-prod-iac-core-0/serviceAccounts/iac-org-cicd-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com module.factory.module.bigquery-datasets["billing-0/billing_export"].google_bigquery_dataset.default: dataset_id: billing_export default_encryption_configuration: [] @@ -743,7 +756,7 @@ values: - description: null expression: "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([\n\ \ 'roles/compute.networkUser', 'roles/composer.sharedVpcAgent',\n 'roles/container.hostServiceAgentUser',\ - \ 'roles/vpcaccess.user'\n])" + \ 'roles/vpcaccess.user'\n])\n" title: Project factory delegated IAM grant. members: - serviceAccount:iac-pf-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com @@ -807,7 +820,7 @@ values: condition: - description: null expression: "api.getAttribute('iam.googleapis.com/modifiedGrantsByRole', []).hasOnly([\n\ - \ 'roles/cloudkms.cryptoKeyEncrypterDecrypter'\n])" + \ 'roles/cloudkms.cryptoKeyEncrypterDecrypter'\n])\n" title: Project factory delegated IAM grant. members: - serviceAccount:iac-pf-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com @@ -955,6 +968,20 @@ values: timeouts: null module.factory.module.folder-2["networking/prod"].google_tags_tag_binding.binding["environment"]: timeouts: null + module.factory.module.folder-2["security/dev"].google_folder.folder[0]: + deletion_protection: false + display_name: Development + tags: null + timeouts: null + module.factory.module.folder-2["security/dev"].google_tags_tag_binding.binding["environment"]: + timeouts: null + module.factory.module.folder-2["security/prod"].google_folder.folder[0]: + deletion_protection: false + display_name: Production + tags: null + timeouts: null + module.factory.module.folder-2["security/prod"].google_tags_tag_binding.binding["environment"]: + timeouts: null module.factory.module.log-buckets["log-0/audit-logs"].google_logging_project_bucket_config.bucket[0]: bucket_id: audit-logs cmek_settings: [] @@ -994,6 +1021,22 @@ values: - serviceAccount:iac-org-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com project: ft0-prod-billing-exp-0 role: roles/viewer + module.factory.module.projects-iam["iac-0"].google_project_iam_audit_config.default["storage.googleapis.com"]: + audit_log_config: + - exempted_members: [] + log_type: DATA_READ + - exempted_members: [] + log_type: DATA_WRITE + project: ft0-prod-iac-core-0 + service: storage.googleapis.com + module.factory.module.projects-iam["iac-0"].google_project_iam_audit_config.default["sts.googleapis.com"]: + audit_log_config: + - exempted_members: [] + log_type: DATA_READ + - exempted_members: [] + log_type: DATA_WRITE + project: ft0-prod-iac-core-0 + service: sts.googleapis.com module.factory.module.projects-iam["iac-0"].google_project_iam_binding.authoritative["$custom_roles:storage_viewer"]: condition: [] members: @@ -1055,6 +1098,17 @@ values: - serviceAccount:iac-org-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com project: ft0-prod-iac-core-0 role: roles/owner + ? module.factory.module.projects-iam["iac-0"].google_project_iam_binding.authoritative["roles/serviceusage.serviceUsageConsumer"] + : condition: [] + members: + - serviceAccount:iac-networking-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com + - serviceAccount:iac-networking-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + - serviceAccount:iac-pf-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com + - serviceAccount:iac-pf-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + - serviceAccount:iac-security-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com + - serviceAccount:iac-security-rw@ft0-prod-iac-core-0.iam.gserviceaccount.com + project: ft0-prod-iac-core-0 + role: roles/serviceusage.serviceUsageConsumer module.factory.module.projects-iam["iac-0"].google_project_iam_binding.authoritative["roles/storage.admin"]: condition: [] members: @@ -1127,6 +1181,8 @@ values: timeouts: null module.factory.module.projects["iac-0"].data.google_bigquery_default_service_account.bq_sa[0]: project: ft0-prod-iac-core-0 + module.factory.module.projects["iac-0"].data.google_logging_project_settings.logging_sa[0]: + project: ft0-prod-iac-core-0 module.factory.module.projects["iac-0"].data.google_storage_project_service_account.gcs_sa[0]: project: ft0-prod-iac-core-0 user_project: null @@ -1205,6 +1261,12 @@ values: condition: [] project: ft0-prod-iac-core-0 role: roles/servicenetworking.serviceAgent + module.factory.module.projects["iac-0"].google_project_service.org_policy_service[0]: + disable_dependent_services: false + disable_on_destroy: false + project: ft0-prod-iac-core-0 + service: orgpolicy.googleapis.com + timeouts: null module.factory.module.projects["iac-0"].google_project_service.project_services["accesscontextmanager.googleapis.com"]: disable_dependent_services: false disable_on_destroy: false @@ -1337,12 +1399,6 @@ values: project: ft0-prod-iac-core-0 service: servicenetworking.googleapis.com timeouts: null - module.factory.module.projects["iac-0"].google_project_service.org_policy_service[0]: - disable_dependent_services: false - disable_on_destroy: false - project: ft0-prod-iac-core-0 - service: orgpolicy.googleapis.com - timeouts: null module.factory.module.projects["iac-0"].google_project_service.project_services["serviceusage.googleapis.com"]: disable_dependent_services: false disable_on_destroy: false @@ -1395,6 +1451,8 @@ values: project: ft0-prod-iac-core-0 service: servicenetworking.googleapis.com timeouts: null + module.factory.module.projects["log-0"].data.google_logging_project_settings.logging_sa[0]: + project: ft0-prod-audit-logs-0 module.factory.module.projects["log-0"].data.google_storage_project_service_account.gcs_sa[0]: project: ft0-prod-audit-logs-0 user_project: null @@ -1599,6 +1657,10 @@ values: input: null output: null triggers_replace: null + module.factory.terraform_data.project-preconditions: + input: null + output: null + triggers_replace: null module.organization-iam[0].google_logging_organization_sink.sink["audit-logs"]: description: audit-logs (Terraform-managed). disabled: false @@ -2264,6 +2326,12 @@ values: parameters: null values: [] timeouts: null + module.organization-iam[0].google_organization_iam_audit_config.default["sts.googleapis.com"]: + audit_log_config: + - exempted_members: [] + log_type: ADMIN_READ + org_id: '1234567890' + service: sts.googleapis.com module.organization-iam[0].google_organization_iam_binding.authoritative["$custom_roles:organization_admin_viewer"]: condition: [] members: @@ -2317,6 +2385,12 @@ values: - group:fabric-fast-owners@google.com org_id: '1234567890' role: roles/cloudsupport.admin + module.organization-iam[0].google_organization_iam_binding.authoritative["roles/cloudsupport.techSupportEditor"]: + condition: [] + members: + - group:fabric-fast-owners@google.com + org_id: '1234567890' + role: roles/cloudsupport.techSupportEditor module.organization-iam[0].google_organization_iam_binding.authoritative["roles/compute.orgFirewallPolicyAdmin"]: condition: [] members: @@ -2538,6 +2612,13 @@ values: - serviceAccount:iac-pf-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com - serviceAccount:iac-security-ro@ft0-prod-iac-core-0.iam.gserviceaccount.com role: roles/resourcemanager.tagViewer + module.organization[0].google_essential_contacts_contact.contact["$email_addresses:gcp-organization-admins"]: + email: $email_addresses:gcp-organization-admins + language_tag: en + notification_category_subscriptions: + - ALL + parent: organizations/1234567890 + timeouts: null module.organization[0].google_logging_organization_settings.default[0]: organization: '1234567890' storage_location: europe-west1 @@ -2776,11 +2857,12 @@ counts: google_bigquery_default_service_account: 2 google_billing_account_iam_member: 6 google_essential_contacts_contact: 1 - google_folder: 8 + google_folder: 10 google_folder_iam_binding: 44 google_logging_organization_settings: 1 google_logging_organization_sink: 3 google_logging_project_bucket_config: 3 + google_logging_project_settings: 2 google_org_policy_custom_constraint: 1 google_org_policy_policy: 37 google_organization_iam_audit_config: 1 @@ -2801,11 +2883,11 @@ counts: google_storage_managed_folder: 5 google_storage_managed_folder_iam_binding: 10 google_storage_project_service_account: 3 - google_tags_tag_binding: 5 + google_tags_tag_binding: 7 google_tags_tag_key: 3 google_tags_tag_value: 5 google_tags_tag_value_iam_binding: 4 local_file: 9 - modules: 48 - resources: 317 + modules: 50 + resources: 323 terraform_data: 4 diff --git a/tests/fast/stages/s0_org_setup/tftest.yaml b/tests/fast/stages/s0_org_setup/tftest.yaml index e9db27288..6e9f91220 100644 --- a/tests/fast/stages/s0_org_setup/tftest.yaml +++ b/tests/fast/stages/s0_org_setup/tftest.yaml @@ -24,4 +24,4 @@ tests: inventory: - hardened.yaml extra_dirs: - - ../../../tests/fast/stages/s0_org_setup/data-simple + - ../../../tests/fast/stages/s0_org_setup/data-hardened diff --git a/tests/fast/stages/s2_project_factory/simple.yaml b/tests/fast/stages/s2_project_factory/simple.yaml index 0eff74fac..058e4a133 100644 --- a/tests/fast/stages/s2_project_factory/simple.yaml +++ b/tests/fast/stages/s2_project_factory/simple.yaml @@ -16,12 +16,13 @@ values: {} counts: google_compute_shared_vpc_service_project: 2 google_folder: 3 + google_logging_project_settings: 2 google_project: 2 - google_project_iam_member: 2 - google_project_service: 4 + google_project_iam_member: 4 + google_project_service: 6 google_project_service_identity: 2 google_storage_bucket_object: 1 google_tags_tag_binding: 2 modules: 8 - resources: 20 + resources: 26 terraform_data: 2 diff --git a/tests/fast/stages/s2_security/simple.yaml b/tests/fast/stages/s2_security/simple.yaml index c7e8116d4..2d0daaa4c 100644 --- a/tests/fast/stages/s2_security/simple.yaml +++ b/tests/fast/stages/s2_security/simple.yaml @@ -35,6 +35,7 @@ values: module.cas["prod-ca-0"].google_privateca_ca_pool.default[0]: effective_labels: goog-terraform-provisioned: 'true' + encryption_spec: [] issuance_policy: [] labels: null location: europe-west1 @@ -110,24 +111,6 @@ values: timeouts: null type: SELF_SIGNED user_defined_access_urls: [] - module.factory.module.folder-1["dev"].google_folder.folder[0]: - deletion_protection: false - display_name: Development - parent: folders/12345678 - tags: null - timeouts: null - module.factory.module.folder-1["dev"].google_tags_tag_binding.binding["environment"]: - tag_value: tagValues/12345 - timeouts: null - module.factory.module.folder-1["prod"].google_folder.folder[0]: - deletion_protection: false - display_name: Production - parent: folders/12345678 - tags: null - timeouts: null - module.factory.module.folder-1["prod"].google_tags_tag_binding.binding["environment"]: - tag_value: tagValues/12346 - timeouts: null module.factory.module.projects-iam["dev-sec-core-0"].google_project_iam_binding.bindings["key_delegated"]: condition: - description: null @@ -148,6 +131,8 @@ values: - serviceAccount:iac-pf-rw@test.iam.gserviceaccount.com project: fast-prod-sec-core-0 role: roles/cloudkms.admin + module.factory.module.projects["dev-sec-core-0"].data.google_logging_project_settings.logging_sa[0]: + project: fast-dev-sec-core-0 module.factory.module.projects["dev-sec-core-0"].google_project.project[0]: auto_create_network: false billing_account: 000000-111111-222222 @@ -155,6 +140,7 @@ values: effective_labels: environment: development goog-terraform-provisioned: 'true' + folder_id: $folder_ids:security/dev labels: environment: development name: fast-dev-sec-core-0 @@ -233,6 +219,8 @@ values: project: fast-dev-sec-core-0 service: secretmanager.googleapis.com timeouts: null + module.factory.module.projects["prod-sec-core-0"].data.google_logging_project_settings.logging_sa[0]: + project: fast-prod-sec-core-0 module.factory.module.projects["prod-sec-core-0"].google_project.project[0]: auto_create_network: false billing_account: 000000-111111-222222 @@ -240,6 +228,7 @@ values: effective_labels: environment: development goog-terraform-provisioned: 'true' + folder_id: $folder_ids:security/prod labels: environment: development name: fast-prod-sec-core-0 @@ -322,13 +311,77 @@ values: input: null output: null triggers_replace: null + module.factory.terraform_data.project-preconditions: + input: null + output: null + triggers_replace: null + module.kms["dev-primary-default"].google_kms_crypto_key.default["bigquery"]: + effective_labels: + goog-terraform-provisioned: 'true' + labels: null + name: bigquery + purpose: ENCRYPT_DECRYPT + rotation_period: 7776000s + skip_initial_version_creation: false + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.kms["dev-primary-default"].google_kms_crypto_key.default["composer"]: + effective_labels: + goog-terraform-provisioned: 'true' + labels: null + name: composer + purpose: ENCRYPT_DECRYPT + rotation_period: 7776000s + skip_initial_version_creation: false + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.kms["dev-primary-default"].google_kms_crypto_key.default["compute"]: + effective_labels: + goog-terraform-provisioned: 'true' + labels: null + name: compute + purpose: ENCRYPT_DECRYPT + rotation_period: 7776000s + skip_initial_version_creation: false + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.kms["dev-primary-default"].google_kms_crypto_key.default["gke"]: + effective_labels: + goog-terraform-provisioned: 'true' + labels: null + name: gke + purpose: ENCRYPT_DECRYPT + rotation_period: 7776000s + skip_initial_version_creation: false + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.kms["dev-primary-default"].google_kms_crypto_key.default["storage"]: + effective_labels: + goog-terraform-provisioned: 'true' + labels: null + name: storage + purpose: ENCRYPT_DECRYPT + rotation_period: 7776000s + skip_initial_version_creation: false + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.kms["dev-primary-default"].google_kms_key_ring.default[0]: + location: europe-west1 + name: dev-primary-default + project: fast-dev-sec-core-0 + timeouts: null module.kms["prod-primary-default"].google_kms_crypto_key.default["compute"]: effective_labels: goog-terraform-provisioned: 'true' labels: null name: compute purpose: ENCRYPT_DECRYPT - rotation_period: null + rotation_period: 7776000s skip_initial_version_creation: false terraform_labels: goog-terraform-provisioned: 'true' @@ -339,7 +392,7 @@ values: labels: null name: storage purpose: ENCRYPT_DECRYPT - rotation_period: null + rotation_period: 7776000s skip_initial_version_creation: false terraform_labels: goog-terraform-provisioned: 'true' @@ -351,9 +404,9 @@ values: timeouts: null counts: - google_folder: 2 - google_kms_crypto_key: 2 - google_kms_key_ring: 1 + google_kms_crypto_key: 7 + google_kms_key_ring: 2 + google_logging_project_settings: 2 google_privateca_ca_pool: 1 google_privateca_certificate_authority: 1 google_project: 2 @@ -362,7 +415,6 @@ counts: google_project_service: 12 google_project_service_identity: 10 google_storage_bucket_object: 2 - google_tags_tag_binding: 2 - modules: 9 - resources: 45 + modules: 8 + resources: 49 terraform_data: 2 diff --git a/tests/fast/stages/s3_data_platform_dev/hardened.tfvars b/tests/fast/stages/s3_data_platform_dev/hardened.tfvars new file mode 100644 index 000000000..94f2f4e9f --- /dev/null +++ b/tests/fast/stages/s3_data_platform_dev/hardened.tfvars @@ -0,0 +1,57 @@ +automation = { + outputs_bucket = "fast2-prod-iac-core-outputs" +} +billing_account = { + id = "000000-111111-222222" +} +encryption_keys = { + bigquery = { + "europe-west1" = "projects/fast2-dev-net-spoke-0/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/bigquery" + } + composer = { + "europe-west1" = "projects/fast2-dev-net-spoke-0/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/composer" + } + storage = { + "europe-west1" = "projects/fast2-dev-net-spoke-0/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/storage" + } +} +environments = { + dev = { + is_default = false + name = "Development" + short_name = "dev" + tag_name = "development" + } +} +factories_config = { + context = { + iam_principals = { + data-consumer-bi = "group:gcp-consumer-bi@example.com" + dp-product-a-0 = "group:gcp-data-product-a-0@example.com" + dp-domain-a = "group:gcp-data-domain-a@example.com" + dp-platform = "group:dp-platform-0@example.com" + } + } +} +folder_ids = { + data-platform-dev = "folders/00000000000000" +} +host_project_ids = { + dev-spoke-0 = "fast2-dev-net-spoke-0" +} +organization = { + domain = "fast.example.com" + id = 123456789012 + customer_id = "C00000000" +} +prefix = "fast2" +subnet_self_links = { + dev-spoke-0 = { + "europe-west8/dev-dataplatform" = "projects/fast2-dev-net-spoke-0/regions/europe-west8/subnetworks/dev-dataplatform" + } +} +vpc_self_links = { + dev-spoke-0 = "projects/fast2-dev-net-spoke-0/global/networks/dev-spoke-0" +} + + diff --git a/tests/fast/stages/s3_data_platform_dev/hardened.yaml b/tests/fast/stages/s3_data_platform_dev/hardened.yaml new file mode 100644 index 000000000..049fc048f --- /dev/null +++ b/tests/fast/stages/s3_data_platform_dev/hardened.yaml @@ -0,0 +1,42 @@ +# Copyright 2025 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +counts: + google_bigquery_dataset: 1 + google_bigquery_dataset_iam_binding: 1 + google_bigquery_default_service_account: 2 + google_composer_environment: 1 + google_data_catalog_policy_tag: 3 + google_data_catalog_taxonomy: 1 + google_dataplex_aspect_type: 1 + google_folder: 2 + google_folder_iam_binding: 3 + google_kms_crypto_key_iam_member: 5 + google_logging_project_settings: 1 + google_project: 3 + google_project_iam_binding: 23 + google_project_iam_member: 12 + google_project_service: 18 + google_project_service_identity: 6 + google_service_account: 6 + google_service_account_iam_binding: 4 + google_storage_bucket: 3 + google_storage_bucket_iam_binding: 6 + google_storage_bucket_object: 6 + google_storage_project_service_account: 3 + google_tags_location_tag_binding: 2 + google_tags_tag_key: 1 + google_tags_tag_value: 1 + modules: 19 + resources: 115 diff --git a/tests/fast/stages/s3_data_platform_dev/simple.yaml b/tests/fast/stages/s3_data_platform_dev/simple.yaml index 58f129757..43f6bd5fd 100644 --- a/tests/fast/stages/s3_data_platform_dev/simple.yaml +++ b/tests/fast/stages/s3_data_platform_dev/simple.yaml @@ -22,6 +22,7 @@ counts: google_dataplex_aspect_type: 1 google_folder: 2 google_folder_iam_binding: 3 + google_logging_project_settings: 1 google_project: 3 google_project_iam_binding: 23 google_project_iam_member: 12 @@ -37,4 +38,4 @@ counts: google_tags_tag_key: 1 google_tags_tag_value: 1 modules: 19 - resources: 109 + resources: 110 diff --git a/tests/fast/stages/s3_data_platform_dev/tftest.yaml b/tests/fast/stages/s3_data_platform_dev/tftest.yaml index 6d1d5c567..22393e1b3 100644 --- a/tests/fast/stages/s3_data_platform_dev/tftest.yaml +++ b/tests/fast/stages/s3_data_platform_dev/tftest.yaml @@ -16,3 +16,8 @@ module: fast/stages/3-data-platform-dev tests: simple: + inventory: + - simple.yaml + hardened: + inventory: + - hardened.yaml diff --git a/tests/fast/stages/s3_gcve_dev/simple.yaml b/tests/fast/stages/s3_gcve_dev/simple.yaml index b0cec777f..28e4b6c08 100644 --- a/tests/fast/stages/s3_gcve_dev/simple.yaml +++ b/tests/fast/stages/s3_gcve_dev/simple.yaml @@ -13,6 +13,7 @@ # limitations under the License. counts: + google_logging_project_settings: 1 google_project: 1 google_project_iam_member: 3 google_project_service: 4 @@ -22,4 +23,4 @@ counts: google_vmwareengine_network_peering: 2 google_vmwareengine_private_cloud: 1 modules: 2 - resources: 15 + resources: 16 diff --git a/tests/fast/stages/s3_gke_dev/hardened.tfvars b/tests/fast/stages/s3_gke_dev/hardened.tfvars index 9e2bb560f..13941346f 100644 --- a/tests/fast/stages/s3_gke_dev/hardened.tfvars +++ b/tests/fast/stages/s3_gke_dev/hardened.tfvars @@ -24,6 +24,10 @@ clusters = { } enable_features = { binary_authorization = true + database_encryption = { + state = "ENCRYPTED" + key_name = "projects/prj-host/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/gke" + } groups_for_rbac = "gke-security-groups@google.com" intranode_visibility = true rbac_binding_config = { @@ -32,10 +36,14 @@ clusters = { } shielded_nodes = true upgrade_notifications = { - event_types = ["SECURITY_BULLETIN_EVENT", "UPGRADE_AVAILABLE_EVENT", "UPGRADE_INFO_EVENT", "UPGRADE_EVENT"] + event_types = ["SECURITY_BULLETIN_EVENT", "UPGRADE_AVAILABLE_EVENT", "UPGRADE_INFO_EVENT", "UPGRADE_EVENT"] + kms_key_name = "projects/prj-host/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/gke" } workload_identity = true } + node_config = { + boot_disk_kms_key = "projects/prj-host/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/gke" + } vpc_config = { subnetwork = "projects/prj-host/regions/europe-west1/subnetworks/gke-0" master_ipv4_cidr_block = "172.16.20.0/28" @@ -57,6 +65,11 @@ nodepools = { node_count = { initial = 1 } node_config = { sandbox_config_gvisor = true + boot_disk_kms_key = "projects/prj-host/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/gke" + shielded_instance_config = { + enable_integrity_monitoring = true + enable_secure_boot = true + } } } } diff --git a/tests/fast/stages/s3_gke_dev/hardened.yaml b/tests/fast/stages/s3_gke_dev/hardened.yaml index e060c7f02..5e9dabf53 100644 --- a/tests/fast/stages/s3_gke_dev/hardened.yaml +++ b/tests/fast/stages/s3_gke_dev/hardened.yaml @@ -1,4 +1,4 @@ -# Copyright 2024 Google LLC +# Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,18 +12,577 @@ # See the License for the specific language governing permissions and # limitations under the License. +# yamllint disable rule:line-length + +values: + google_storage_bucket_object.version[0]: + bucket: fast2-prod-iac-core-outputs + cache_control: null + content_disposition: null + content_encoding: null + content_language: null + customer_encryption: [] + deletion_policy: null + detect_md5hash: different hash + event_based_hold: null + force_empty_content_type: null + metadata: null + name: versions/3-gke-dev-version.txt + retention: [] + source: fast_version.txt + source_md5hash: null + temporary_hold: null + timeouts: null + module.gke-cluster["mycluster"].google_container_cluster.cluster: + addons_config: + - cloudrun_config: + - disabled: true + load_balancer_type: null + config_connector_config: + - enabled: false + dns_cache_config: + - enabled: true + gce_persistent_disk_csi_driver_config: + - enabled: true + gcp_filestore_csi_driver_config: + - enabled: true + gcs_fuse_csi_driver_config: + - enabled: true + gke_backup_agent_config: + - enabled: false + horizontal_pod_autoscaling: + - disabled: false + http_load_balancing: + - disabled: false + istio_config: + - auth: null + disabled: true + kalm_config: + - enabled: false + network_policy_config: + - disabled: true + stateful_ha_config: + - enabled: false + allow_net_admin: null + authenticator_groups_config: + - security_group: gke-security-groups@google.com + binary_authorization: + - enabled: null + evaluation_mode: PROJECT_SINGLETON_POLICY_ENFORCE + control_plane_endpoints_config: + - dns_endpoint_config: + - allow_external_traffic: true + enable_k8s_certs_via_dns: null + enable_k8s_tokens_via_dns: null + ip_endpoints_config: + - enabled: true + cost_management_config: + - enabled: true + database_encryption: + - key_name: projects/prj-host/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/gke + state: ENCRYPTED + datapath_provider: ADVANCED_DATAPATH + default_max_pods_per_node: 110 + deletion_protection: false + description: my cluster + disable_l4_lb_firewall_reconciliation: false + dns_config: [] + effective_labels: + goog-terraform-provisioned: 'true' + enable_autopilot: null + enable_cilium_clusterwide_network_policy: false + enable_fqdn_network_policy: true + enable_intranode_visibility: true + enable_k8s_beta_apis: [] + enable_kubernetes_alpha: false + enable_l4_ilb_subsetting: false + enable_legacy_abac: false + enable_multi_networking: false + enable_shielded_nodes: true + enable_tpu: false + fleet: [] + in_transit_encryption_config: null + initial_node_count: 1 + ip_allocation_policy: + - additional_ip_ranges_config: [] + additional_pod_ranges_config: [] + cluster_secondary_range_name: pods + services_secondary_range_name: services + stack_type: IPV4 + location: europe-west1 + logging_config: + - enable_components: + - SYSTEM_COMPONENTS + - WORKLOADS + maintenance_policy: + - daily_maintenance_window: + - start_time: 03:00 + maintenance_exclusion: [] + recurring_window: [] + master_auth: + - client_certificate_config: + - issue_client_certificate: false + master_authorized_networks_config: + - cidr_blocks: [] + gcp_public_cidrs_access_enabled: false + min_master_version: null + monitoring_config: + - enable_components: + - SYSTEM_COMPONENTS + managed_prometheus: + - enabled: true + name: mycluster + network: default + network_performance_config: [] + network_policy: [] + node_config: + - advanced_machine_features: [] + boot_disk_kms_key: projects/prj-host/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/gke + containerd_config: [] + enable_confidential_storage: null + ephemeral_storage_config: [] + ephemeral_storage_local_ssd_config: [] + fast_socket: [] + flex_start: null + gvnic: [] + host_maintenance_policy: [] + local_nvme_ssd_block_config: [] + local_ssd_encryption_mode: null + max_run_duration: null + node_group: null + preemptible: false + reservation_affinity: [] + resource_labels: null + resource_manager_tags: null + sandbox_config: [] + secondary_boot_disks: [] + service_account: gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + shielded_instance_config: + - enable_integrity_monitoring: true + enable_secure_boot: true + sole_tenant_config: [] + spot: false + storage_pools: null + tags: null + taint: [] + node_pool_defaults: + - node_config_defaults: + - containerd_config: [] + gcfs_config: + - enabled: false + notification_config: + - pubsub: + - enabled: true + filter: + - event_type: + - SECURITY_BULLETIN_EVENT + - UPGRADE_AVAILABLE_EVENT + - UPGRADE_INFO_EVENT + - UPGRADE_EVENT + pod_security_policy_config: [] + private_cluster_config: + - enable_private_endpoint: true + enable_private_nodes: true + master_global_access_config: + - enabled: true + private_endpoint_subnetwork: null + project: fast-dev-gke-core-0 + rbac_binding_config: + - enable_insecure_binding_system_authenticated: false + enable_insecure_binding_system_unauthenticated: false + remove_default_node_pool: true + resource_labels: null + resource_usage_export_config: [] + secret_manager_config: [] + secret_sync_config: [] + subnetwork: projects/prj-host/regions/europe-west1/subnetworks/gke-0 + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + user_managed_keys_config: [] + workload_identity_config: + - workload_pool: fast-dev-gke-core-0.svc.id.goog + module.gke-cluster["mycluster"].google_pubsub_topic.notifications[0]: + effective_labels: + content: gke-notifications + goog-terraform-provisioned: 'true' + ingestion_data_source_settings: [] + kms_key_name: projects/prj-host/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/gke + labels: + content: gke-notifications + message_retention_duration: null + message_transforms: [] + name: gke-pubsub-notifications + project: fast-dev-gke-core-0 + schema_settings: [] + tags: null + terraform_labels: + content: gke-notifications + goog-terraform-provisioned: 'true' + timeouts: null + module.gke-dataset-resource-usage.google_bigquery_dataset.default: + dataset_id: gke_resource_usage + default_encryption_configuration: [] + default_partition_expiration_ms: null + default_table_expiration_ms: null + delete_contents_on_destroy: false + description: Terraform managed. + effective_labels: + goog-terraform-provisioned: 'true' + external_catalog_dataset_options: [] + external_dataset_reference: [] + friendly_name: GKE resource usage. + labels: null + location: EU + max_time_travel_hours: '168' + project: fast-dev-gke-core-0 + resource_tags: null + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.gke-nodepool["mycluster/mynodepool"].google_container_node_pool.nodepool: + autoscaling: [] + cluster: mycluster + initial_node_count: 1 + location: europe-west1 + name: mynodepool + node_config: + - advanced_machine_features: [] + boot_disk_kms_key: projects/prj-host/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/gke + containerd_config: [] + disk_type: pd-balanced + enable_confidential_storage: null + ephemeral_storage_config: [] + ephemeral_storage_local_ssd_config: [] + fast_socket: [] + flex_start: null + gvnic: [] + host_maintenance_policy: [] + local_nvme_ssd_block_config: [] + local_ssd_encryption_mode: null + max_run_duration: null + node_group: null + oauth_scopes: + - https://www.googleapis.com/auth/devstorage.read_only + - https://www.googleapis.com/auth/logging.write + - https://www.googleapis.com/auth/monitoring + - https://www.googleapis.com/auth/monitoring.write + - https://www.googleapis.com/auth/userinfo.email + preemptible: false + reservation_affinity: [] + resource_labels: null + resource_manager_tags: null + sandbox_config: + - sandbox_type: gvisor + secondary_boot_disks: [] + service_account: gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + shielded_instance_config: + - enable_integrity_monitoring: true + enable_secure_boot: true + sole_tenant_config: [] + spot: false + storage_pools: null + tags: null + taint: [] + placement_policy: [] + project: fast-dev-gke-core-0 + queued_provisioning: [] + timeouts: null + module.gke-nodes-service-account.google_service_account.service_account[0]: + account_id: gke-node-default + create_ignore_already_exists: null + description: null + disabled: false + display_name: Terraform-managed. + email: gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + member: serviceAccount:gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + project: fast-dev-gke-core-0 + timeouts: null + module.gke-project-0.data.google_logging_project_settings.logging_sa[0]: + project: fast-dev-gke-core-0 + module.gke-project-0.google_compute_shared_vpc_service_project.shared_vpc_service[0]: + deletion_policy: null + host_project: fast-dev-net-spoke-0 + service_project: fast-dev-gke-core-0 + timeouts: null + module.gke-project-0.google_kms_crypto_key_iam_member.service_agent_cmek["key-0.compute-system"]: + condition: [] + crypto_key_id: projects/prj-host/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/gke + role: roles/cloudkms.cryptoKeyEncrypterDecrypter + module.gke-project-0.google_kms_crypto_key_iam_member.service_agent_cmek["key-0.container-engine-robot"]: + condition: [] + crypto_key_id: projects/prj-host/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/gke + role: roles/cloudkms.cryptoKeyEncrypterDecrypter + module.gke-project-0.google_kms_crypto_key_iam_member.service_agent_cmek["key-0.pubsub"]: + condition: [] + crypto_key_id: projects/prj-host/locations/europe-west1/keyRings/dev-primary-default/cryptoKeys/gke + role: roles/cloudkms.cryptoKeyEncrypterDecrypter + module.gke-project-0.google_org_policy_policy.default["compute.managed.disableSerialPortLogging"]: + dry_run_spec: [] + name: projects/fast-dev-gke-core-0/policies/compute.managed.disableSerialPortLogging + parent: projects/fast-dev-gke-core-0 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'FALSE' + parameters: null + values: [] + timeouts: null + module.gke-project-0.google_project.project[0]: + auto_create_network: false + billing_account: 012345-67890A-BCDEF0 + deletion_policy: DELETE + effective_labels: + environment: development + goog-terraform-provisioned: 'true' + folder_id: '12345678' + labels: + environment: development + name: fast-dev-gke-core-0 + org_id: null + project_id: fast-dev-gke-core-0 + tags: null + terraform_labels: + environment: development + goog-terraform-provisioned: 'true' + timeouts: null + module.gke-project-0.google_project_iam_binding.authoritative["roles/gkehub.serviceAgent"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/gkehub.serviceAgent + module.gke-project-0.google_project_iam_member.bindings["gke-nodes-sa-autoscaling.metricsWriter"]: + condition: [] + member: serviceAccount:gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + project: fast-dev-gke-core-0 + role: roles/autoscaling.metricsWriter + module.gke-project-0.google_project_iam_member.bindings["gke-nodes-sa-logging.logWriter"]: + condition: [] + member: serviceAccount:gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + project: fast-dev-gke-core-0 + role: roles/logging.logWriter + module.gke-project-0.google_project_iam_member.bindings["gke-nodes-sa-monitoring.metricWriter"]: + condition: [] + member: serviceAccount:gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + project: fast-dev-gke-core-0 + role: roles/monitoring.metricWriter + module.gke-project-0.google_project_iam_member.bindings["gke-nodes-sa-monitoring.viewer"]: + condition: [] + member: serviceAccount:gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + project: fast-dev-gke-core-0 + role: roles/monitoring.viewer + module.gke-project-0.google_project_iam_member.bindings["gke-nodes-sa-stackdriver.resourceMetadata.writer"]: + condition: [] + member: serviceAccount:gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + project: fast-dev-gke-core-0 + role: roles/stackdriver.resourceMetadata.writer + module.gke-project-0.google_project_iam_member.service_agents["anthos"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/anthos.serviceAgent + module.gke-project-0.google_project_iam_member.service_agents["anthosconfigmanagement"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/anthosconfigmanagement.serviceAgent + module.gke-project-0.google_project_iam_member.service_agents["compute-system"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/compute.serviceAgent + module.gke-project-0.google_project_iam_member.service_agents["container-engine-robot"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/container.serviceAgent + module.gke-project-0.google_project_iam_member.service_agents["dns"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/dns.serviceAgent + module.gke-project-0.google_project_iam_member.service_agents["gkehub"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/gkehub.serviceAgent + module.gke-project-0.google_project_iam_member.service_agents["gkenode"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/container.defaultNodeServiceAgent + module.gke-project-0.google_project_iam_member.service_agents["mcsd"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/multiclusterservicediscovery.serviceAgent + module.gke-project-0.google_project_iam_member.service_agents["monitoring-notification"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/monitoring.notificationServiceAgent + module.gke-project-0.google_project_iam_member.service_agents["multiclusteringress"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/multiclusteringress.serviceAgent + module.gke-project-0.google_project_iam_member.service_agents["pubsub"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/pubsub.serviceAgent + module.gke-project-0.google_project_iam_member.shared_vpc_host_robots["roles/compute.networkUser:cloudservices"]: + condition: [] + project: fast-dev-net-spoke-0 + role: roles/compute.networkUser + module.gke-project-0.google_project_iam_member.shared_vpc_host_robots["roles/compute.networkUser:container-engine"]: + condition: [] + project: fast-dev-net-spoke-0 + role: roles/compute.networkUser + ? module.gke-project-0.google_project_iam_member.shared_vpc_host_robots["roles/container.hostServiceAgentUser:container-engine"] + : condition: [] + project: fast-dev-net-spoke-0 + role: roles/container.hostServiceAgentUser + module.gke-project-0.google_project_service.org_policy_service[0]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: orgpolicy.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["anthos.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: anthos.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["anthosconfigmanagement.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: anthosconfigmanagement.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["cloudresourcemanager.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: cloudresourcemanager.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["compute.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: compute.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["container.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: container.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["dns.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: dns.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["gkeconnect.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: gkeconnect.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["gkehub.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: gkehub.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["iam.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: iam.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["logging.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: logging.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["monitoring.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: monitoring.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["multiclusteringress.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: multiclusteringress.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["multiclusterservicediscovery.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: multiclusterservicediscovery.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["pubsub.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: pubsub.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["trafficdirector.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: trafficdirector.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["anthos.googleapis.com"]: + project: fast-dev-gke-core-0 + service: anthos.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["anthosconfigmanagement.googleapis.com"]: + project: fast-dev-gke-core-0 + service: anthosconfigmanagement.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["container.googleapis.com"]: + project: fast-dev-gke-core-0 + service: container.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["dns.googleapis.com"]: + project: fast-dev-gke-core-0 + service: dns.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["gkehub.googleapis.com"]: + project: fast-dev-gke-core-0 + service: gkehub.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["monitoring.googleapis.com"]: + project: fast-dev-gke-core-0 + service: monitoring.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["multiclusteringress.googleapis.com"]: + project: fast-dev-gke-core-0 + service: multiclusteringress.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["multiclusterservicediscovery.googleapis.com"]: + project: fast-dev-gke-core-0 + service: multiclusterservicediscovery.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["pubsub.googleapis.com"]: + project: fast-dev-gke-core-0 + service: pubsub.googleapis.com + timeouts: null + counts: google_bigquery_dataset: 1 google_compute_shared_vpc_service_project: 1 google_container_cluster: 1 google_container_node_pool: 1 + google_kms_crypto_key_iam_member: 3 + google_logging_project_settings: 1 + google_org_policy_policy: 1 google_project: 1 google_project_iam_binding: 1 - google_project_iam_member: 17 - google_project_service: 14 - google_project_service_identity: 8 + google_project_iam_member: 19 + google_project_service: 16 + google_project_service_identity: 9 google_pubsub_topic: 1 google_service_account: 1 google_storage_bucket_object: 1 modules: 5 - resources: 49 + resources: 58 diff --git a/tests/fast/stages/s3_gke_dev/simple.yaml b/tests/fast/stages/s3_gke_dev/simple.yaml index d7fbffb8b..cdf8f8e46 100644 --- a/tests/fast/stages/s3_gke_dev/simple.yaml +++ b/tests/fast/stages/s3_gke_dev/simple.yaml @@ -1,4 +1,4 @@ -# Copyright 2024 Google LLC +# Copyright 2025 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -12,17 +12,520 @@ # See the License for the specific language governing permissions and # limitations under the License. +# yamllint disable rule:line-length + +values: + google_storage_bucket_object.version[0]: + bucket: fast2-prod-iac-core-outputs + cache_control: null + content_disposition: null + content_encoding: null + content_language: null + customer_encryption: [] + deletion_policy: null + detect_md5hash: different hash + event_based_hold: null + force_empty_content_type: null + metadata: null + name: versions/3-gke-dev-version.txt + retention: [] + source: fast_version.txt + source_md5hash: null + temporary_hold: null + timeouts: null + module.gke-cluster["mycluster"].google_container_cluster.cluster: + addons_config: + - cloudrun_config: + - disabled: true + load_balancer_type: null + config_connector_config: + - enabled: false + dns_cache_config: + - enabled: true + gce_persistent_disk_csi_driver_config: + - enabled: true + gcp_filestore_csi_driver_config: + - enabled: true + gcs_fuse_csi_driver_config: + - enabled: true + gke_backup_agent_config: + - enabled: false + horizontal_pod_autoscaling: + - disabled: false + http_load_balancing: + - disabled: false + istio_config: + - auth: null + disabled: true + kalm_config: + - enabled: false + network_policy_config: + - disabled: true + stateful_ha_config: + - enabled: false + allow_net_admin: null + binary_authorization: [] + control_plane_endpoints_config: + - dns_endpoint_config: + - allow_external_traffic: true + enable_k8s_certs_via_dns: null + enable_k8s_tokens_via_dns: null + ip_endpoints_config: + - enabled: false + cost_management_config: + - enabled: true + datapath_provider: ADVANCED_DATAPATH + default_max_pods_per_node: 110 + deletion_protection: false + description: my cluster + disable_l4_lb_firewall_reconciliation: false + dns_config: [] + effective_labels: + goog-terraform-provisioned: 'true' + enable_autopilot: null + enable_cilium_clusterwide_network_policy: false + enable_fqdn_network_policy: true + enable_intranode_visibility: false + enable_k8s_beta_apis: [] + enable_kubernetes_alpha: false + enable_l4_ilb_subsetting: false + enable_legacy_abac: false + enable_multi_networking: false + enable_shielded_nodes: true + enable_tpu: false + fleet: [] + in_transit_encryption_config: null + initial_node_count: 1 + ip_allocation_policy: + - additional_ip_ranges_config: [] + additional_pod_ranges_config: [] + cluster_secondary_range_name: pods + services_secondary_range_name: services + stack_type: IPV4 + location: europe-west1 + logging_config: + - enable_components: + - SYSTEM_COMPONENTS + - WORKLOADS + maintenance_policy: + - daily_maintenance_window: + - start_time: 03:00 + maintenance_exclusion: [] + recurring_window: [] + master_auth: + - client_certificate_config: + - issue_client_certificate: false + min_master_version: null + monitoring_config: + - enable_components: + - SYSTEM_COMPONENTS + managed_prometheus: + - enabled: true + name: mycluster + network: default + network_performance_config: [] + network_policy: [] + node_config: + - advanced_machine_features: [] + boot_disk_kms_key: null + containerd_config: [] + enable_confidential_storage: null + ephemeral_storage_config: [] + ephemeral_storage_local_ssd_config: [] + fast_socket: [] + flex_start: null + gvnic: [] + host_maintenance_policy: [] + local_nvme_ssd_block_config: [] + local_ssd_encryption_mode: null + max_run_duration: null + node_group: null + preemptible: false + reservation_affinity: [] + resource_labels: null + resource_manager_tags: null + sandbox_config: [] + secondary_boot_disks: [] + service_account: gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + shielded_instance_config: + - enable_integrity_monitoring: true + enable_secure_boot: true + sole_tenant_config: [] + spot: false + storage_pools: null + tags: null + taint: [] + node_pool_defaults: + - node_config_defaults: + - containerd_config: [] + gcfs_config: + - enabled: false + pod_security_policy_config: [] + private_cluster_config: + - enable_private_endpoint: true + enable_private_nodes: true + private_endpoint_subnetwork: null + project: fast-dev-gke-core-0 + remove_default_node_pool: true + resource_labels: null + resource_usage_export_config: [] + secret_manager_config: [] + secret_sync_config: [] + subnetwork: projects/prj-host/regions/europe-west1/subnetworks/gke-0 + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + user_managed_keys_config: [] + workload_identity_config: + - workload_pool: fast-dev-gke-core-0.svc.id.goog + module.gke-dataset-resource-usage.google_bigquery_dataset.default: + dataset_id: gke_resource_usage + default_encryption_configuration: [] + default_partition_expiration_ms: null + default_table_expiration_ms: null + delete_contents_on_destroy: false + description: Terraform managed. + effective_labels: + goog-terraform-provisioned: 'true' + external_catalog_dataset_options: [] + external_dataset_reference: [] + friendly_name: GKE resource usage. + labels: null + location: EU + max_time_travel_hours: '168' + project: fast-dev-gke-core-0 + resource_tags: null + terraform_labels: + goog-terraform-provisioned: 'true' + timeouts: null + module.gke-nodepool["mycluster/mynodepool"].google_container_node_pool.nodepool: + autoscaling: [] + cluster: mycluster + initial_node_count: 1 + location: europe-west1 + name: mynodepool + node_config: + - advanced_machine_features: [] + boot_disk_kms_key: null + containerd_config: [] + disk_type: pd-balanced + enable_confidential_storage: null + ephemeral_storage_config: [] + ephemeral_storage_local_ssd_config: [] + fast_socket: [] + flex_start: null + gvnic: [] + host_maintenance_policy: [] + local_nvme_ssd_block_config: [] + local_ssd_encryption_mode: null + max_run_duration: null + node_group: null + oauth_scopes: + - https://www.googleapis.com/auth/devstorage.read_only + - https://www.googleapis.com/auth/logging.write + - https://www.googleapis.com/auth/monitoring + - https://www.googleapis.com/auth/monitoring.write + - https://www.googleapis.com/auth/userinfo.email + preemptible: false + reservation_affinity: [] + resource_labels: null + resource_manager_tags: null + sandbox_config: [] + secondary_boot_disks: [] + service_account: gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + shielded_instance_config: + - enable_integrity_monitoring: true + enable_secure_boot: true + sole_tenant_config: [] + spot: false + storage_pools: null + tags: null + taint: [] + placement_policy: [] + project: fast-dev-gke-core-0 + queued_provisioning: [] + timeouts: null + module.gke-nodes-service-account.google_service_account.service_account[0]: + account_id: gke-node-default + create_ignore_already_exists: null + description: null + disabled: false + display_name: Terraform-managed. + email: gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + member: serviceAccount:gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + project: fast-dev-gke-core-0 + timeouts: null + module.gke-project-0.data.google_logging_project_settings.logging_sa[0]: + project: fast-dev-gke-core-0 + module.gke-project-0.google_compute_shared_vpc_service_project.shared_vpc_service[0]: + deletion_policy: null + host_project: fast-dev-net-spoke-0 + service_project: fast-dev-gke-core-0 + timeouts: null + module.gke-project-0.google_org_policy_policy.default["compute.managed.disableSerialPortLogging"]: + dry_run_spec: [] + name: projects/fast-dev-gke-core-0/policies/compute.managed.disableSerialPortLogging + parent: projects/fast-dev-gke-core-0 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'FALSE' + parameters: null + values: [] + timeouts: null + module.gke-project-0.google_project.project[0]: + auto_create_network: false + billing_account: 012345-67890A-BCDEF0 + deletion_policy: DELETE + effective_labels: + environment: development + goog-terraform-provisioned: 'true' + folder_id: '12345678' + labels: + environment: development + name: fast-dev-gke-core-0 + org_id: null + project_id: fast-dev-gke-core-0 + tags: null + terraform_labels: + environment: development + goog-terraform-provisioned: 'true' + timeouts: null + module.gke-project-0.google_project_iam_binding.authoritative["roles/gkehub.serviceAgent"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/gkehub.serviceAgent + module.gke-project-0.google_project_iam_member.bindings["gke-nodes-sa-autoscaling.metricsWriter"]: + condition: [] + member: serviceAccount:gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + project: fast-dev-gke-core-0 + role: roles/autoscaling.metricsWriter + module.gke-project-0.google_project_iam_member.bindings["gke-nodes-sa-logging.logWriter"]: + condition: [] + member: serviceAccount:gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + project: fast-dev-gke-core-0 + role: roles/logging.logWriter + module.gke-project-0.google_project_iam_member.bindings["gke-nodes-sa-monitoring.metricWriter"]: + condition: [] + member: serviceAccount:gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + project: fast-dev-gke-core-0 + role: roles/monitoring.metricWriter + module.gke-project-0.google_project_iam_member.bindings["gke-nodes-sa-monitoring.viewer"]: + condition: [] + member: serviceAccount:gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + project: fast-dev-gke-core-0 + role: roles/monitoring.viewer + module.gke-project-0.google_project_iam_member.bindings["gke-nodes-sa-stackdriver.resourceMetadata.writer"]: + condition: [] + member: serviceAccount:gke-node-default@fast-dev-gke-core-0.iam.gserviceaccount.com + project: fast-dev-gke-core-0 + role: roles/stackdriver.resourceMetadata.writer + module.gke-project-0.google_project_iam_member.service_agents["anthos"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/anthos.serviceAgent + module.gke-project-0.google_project_iam_member.service_agents["anthosconfigmanagement"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/anthosconfigmanagement.serviceAgent + module.gke-project-0.google_project_iam_member.service_agents["compute-system"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/compute.serviceAgent + module.gke-project-0.google_project_iam_member.service_agents["container-engine-robot"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/container.serviceAgent + module.gke-project-0.google_project_iam_member.service_agents["dns"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/dns.serviceAgent + module.gke-project-0.google_project_iam_member.service_agents["gkehub"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/gkehub.serviceAgent + module.gke-project-0.google_project_iam_member.service_agents["gkenode"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/container.defaultNodeServiceAgent + module.gke-project-0.google_project_iam_member.service_agents["mcsd"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/multiclusterservicediscovery.serviceAgent + module.gke-project-0.google_project_iam_member.service_agents["monitoring-notification"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/monitoring.notificationServiceAgent + module.gke-project-0.google_project_iam_member.service_agents["multiclusteringress"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/multiclusteringress.serviceAgent + module.gke-project-0.google_project_iam_member.service_agents["pubsub"]: + condition: [] + project: fast-dev-gke-core-0 + role: roles/pubsub.serviceAgent + module.gke-project-0.google_project_iam_member.shared_vpc_host_robots["roles/compute.networkUser:cloudservices"]: + condition: [] + project: fast-dev-net-spoke-0 + role: roles/compute.networkUser + module.gke-project-0.google_project_iam_member.shared_vpc_host_robots["roles/compute.networkUser:container-engine"]: + condition: [] + project: fast-dev-net-spoke-0 + role: roles/compute.networkUser + ? module.gke-project-0.google_project_iam_member.shared_vpc_host_robots["roles/container.hostServiceAgentUser:container-engine"] + : condition: [] + project: fast-dev-net-spoke-0 + role: roles/container.hostServiceAgentUser + module.gke-project-0.google_project_service.org_policy_service[0]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: orgpolicy.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["anthos.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: anthos.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["anthosconfigmanagement.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: anthosconfigmanagement.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["cloudresourcemanager.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: cloudresourcemanager.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["compute.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: compute.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["container.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: container.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["dns.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: dns.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["gkeconnect.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: gkeconnect.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["gkehub.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: gkehub.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["iam.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: iam.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["logging.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: logging.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["monitoring.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: monitoring.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["multiclusteringress.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: multiclusteringress.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["multiclusterservicediscovery.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: multiclusterservicediscovery.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["pubsub.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: pubsub.googleapis.com + timeouts: null + module.gke-project-0.google_project_service.project_services["trafficdirector.googleapis.com"]: + disable_dependent_services: false + disable_on_destroy: false + project: fast-dev-gke-core-0 + service: trafficdirector.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["anthos.googleapis.com"]: + project: fast-dev-gke-core-0 + service: anthos.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["anthosconfigmanagement.googleapis.com"]: + project: fast-dev-gke-core-0 + service: anthosconfigmanagement.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["container.googleapis.com"]: + project: fast-dev-gke-core-0 + service: container.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["dns.googleapis.com"]: + project: fast-dev-gke-core-0 + service: dns.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["gkehub.googleapis.com"]: + project: fast-dev-gke-core-0 + service: gkehub.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["monitoring.googleapis.com"]: + project: fast-dev-gke-core-0 + service: monitoring.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["multiclusteringress.googleapis.com"]: + project: fast-dev-gke-core-0 + service: multiclusteringress.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["multiclusterservicediscovery.googleapis.com"]: + project: fast-dev-gke-core-0 + service: multiclusterservicediscovery.googleapis.com + timeouts: null + module.gke-project-0.google_project_service_identity.default["pubsub.googleapis.com"]: + project: fast-dev-gke-core-0 + service: pubsub.googleapis.com + timeouts: null + counts: google_bigquery_dataset: 1 google_compute_shared_vpc_service_project: 1 google_container_cluster: 1 google_container_node_pool: 1 + google_logging_project_settings: 1 + google_org_policy_policy: 1 google_project: 1 google_project_iam_binding: 1 - google_project_iam_member: 17 - google_project_service: 14 - google_project_service_identity: 8 + google_project_iam_member: 19 + google_project_service: 16 + google_project_service_identity: 9 google_service_account: 1 google_storage_bucket_object: 1 modules: 5 - resources: 48 + resources: 54 diff --git a/tests/fast/stages/s3_gke_dev/tftest.yaml b/tests/fast/stages/s3_gke_dev/tftest.yaml index 0ec9d9c07..fe36b8373 100644 --- a/tests/fast/stages/s3_gke_dev/tftest.yaml +++ b/tests/fast/stages/s3_gke_dev/tftest.yaml @@ -15,5 +15,9 @@ module: fast/stages/3-gke-dev/ tests: - simple: {} - hardened: {} + simple: + inventory: + - simple.yaml + hardened: + inventory: + - hardened.yaml diff --git a/tests/modules/folder/examples/logging.yaml b/tests/modules/folder/examples/logging.yaml index 4ce27c2e1..fa783fbbb 100644 --- a/tests/modules/folder/examples/logging.yaml +++ b/tests/modules/folder/examples/logging.yaml @@ -34,6 +34,8 @@ values: location: EU max_time_travel_hours: '168' project: project-id + module.destination-project.data.google_logging_project_settings.logging_sa[0]: + project: test-dest-prj module.destination-project.google_project.project[0]: auto_create_network: false billing_account: 123456-123456-123456 @@ -152,6 +154,7 @@ counts: google_logging_folder_exclusion: 1 google_logging_folder_sink: 5 google_logging_project_bucket_config: 1 + google_logging_project_settings: 1 google_project: 1 google_project_iam_member: 2 google_project_service: 1 @@ -160,4 +163,4 @@ counts: google_storage_bucket: 1 google_storage_bucket_iam_member: 1 modules: 6 - resources: 18 + resources: 19 diff --git a/tests/modules/organization/examples/logging.yaml b/tests/modules/organization/examples/logging.yaml index bdb578627..1cc061cfd 100644 --- a/tests/modules/organization/examples/logging.yaml +++ b/tests/modules/organization/examples/logging.yaml @@ -42,6 +42,8 @@ values: terraform_labels: goog-terraform-provisioned: 'true' timeouts: null + module.destination-project.data.google_logging_project_settings.logging_sa[0]: + project: test-dest-prj module.destination-project.google_project.project[0]: auto_create_network: false billing_account: 123456-123456-123456 @@ -203,6 +205,7 @@ counts: google_logging_organization_exclusion: 1 google_logging_organization_sink: 6 google_logging_project_bucket_config: 1 + google_logging_project_settings: 1 google_project: 1 google_project_iam_member: 2 google_project_service: 1 @@ -211,4 +214,4 @@ counts: google_storage_bucket: 1 google_storage_bucket_iam_member: 2 modules: 6 - resources: 19 + resources: 20 diff --git a/tests/modules/project/examples/data.yaml b/tests/modules/project/examples/data.yaml index d563ffddd..a7fa255b5 100644 --- a/tests/modules/project/examples/data.yaml +++ b/tests/modules/project/examples/data.yaml @@ -119,6 +119,8 @@ values: role: roles/cloudkms.cryptoKeyEncrypterDecrypter module.project.data.google_bigquery_default_service_account.bq_sa[0]: project: test-project + module.project.data.google_logging_project_settings.logging_sa[0]: + project: test-project module.project.data.google_storage_project_service_account.gcs_sa[0]: project: test-project user_project: null @@ -511,6 +513,7 @@ counts: google_kms_key_ring_iam_binding: 1 google_logging_project_bucket_config: 1 google_logging_project_exclusion: 1 + google_logging_project_settings: 1 google_logging_project_sink: 4 google_org_policy_policy: 7 google_project: 2 @@ -525,6 +528,6 @@ counts: google_storage_bucket_iam_member: 1 google_storage_project_service_account: 1 modules: 8 - resources: 63 + resources: 64 outputs: {} diff --git a/tests/modules/project/examples/log-scopes.yaml b/tests/modules/project/examples/log-scopes.yaml index d4cacb3ab..52fbd47bf 100644 --- a/tests/modules/project/examples/log-scopes.yaml +++ b/tests/modules/project/examples/log-scopes.yaml @@ -66,3 +66,5 @@ counts: google_logging_project_bucket_config: 1 google_project: 1 google_project_service: 1 + modules: 2 + resources: 7 diff --git a/tests/modules/project/examples/logging.yaml b/tests/modules/project/examples/logging.yaml index 64840f8ad..1e7aacf35 100644 --- a/tests/modules/project/examples/logging.yaml +++ b/tests/modules/project/examples/logging.yaml @@ -34,6 +34,8 @@ values: location: EU max_time_travel_hours: '168' project: project-id + module.destination-project.data.google_logging_project_settings.logging_sa[0]: + project: test-dest-prj module.destination-project.google_project.project[0]: auto_create_network: false billing_account: 123456-123456-123456 @@ -66,6 +68,8 @@ values: retention_policy: [] storage_class: STANDARD uniform_bucket_level_access: true + module.project-host.data.google_logging_project_settings.logging_sa[0]: + project: test-project module.project-host.google_bigquery_dataset_iam_member.bq-sinks-binding["info"]: condition: [] role: roles/bigquery.dataEditor @@ -172,6 +176,7 @@ counts: google_bigquery_dataset_iam_member: 1 google_logging_project_bucket_config: 1 google_logging_project_exclusion: 1 + google_logging_project_settings: 2 google_logging_project_sink: 5 google_project: 2 google_project_iam_member: 2 @@ -181,4 +186,4 @@ counts: google_storage_bucket: 1 google_storage_bucket_iam_member: 1 modules: 6 - resources: 19 + resources: 21 diff --git a/tools/duplicate-diff.py b/tools/duplicate-diff.py index 274bffe8f..3b57508aa 100755 --- a/tools/duplicate-diff.py +++ b/tools/duplicate-diff.py @@ -21,15 +21,6 @@ import os # List of folders and files that are expected to have same content duplicates = [ - # file comparison - [ - "fast/stages/0-org-setup/datasets/classic/defaults.yaml", - "fast/stages/0-org-setup/datasets/hardened/defaults.yaml", - ], - [ - "fast/stages/0-org-setup/datasets/classic/projects/core/billing-0.yaml", - "fast/stages/0-org-setup/datasets/hardened/projects/core/billing-0.yaml", - ], # deep recursive folder comparison [ "fast/stages/0-org-setup/datasets/classic/organization/custom-roles",