diff --git a/CHANGELOG.md b/CHANGELOG.md index 5ab336693..3c7bac81f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,15 +7,22 @@ All notable changes to this project will be documented in this file. ### BREAKING CHANGES +- `modules/project-factory`: the `factories_config` attribute has been removed from project defaults and overrides. [[#3440](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3440)] - `modules/gke-hub`: Unified cluster configuration. The module now uses a single `clusters` variable to configure both cluster registration and feature enablement. [[#3332](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3332)] - `all modules`: Minimum supported Terraform version bumped 1.12.2 [[#3332](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3332)] - `all modules`: Minimum supported OpenTofu version bumped 1.10.0 [[#3332](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3332)] - `modules/project-factory`: the format for automation service account names has changed. [[#3345](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3345)] +- [[#3428](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3428)] gitignore update ([juliocc](https://github.com/juliocc)) - [[#3361](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3361)] Use pre-commit managed Python environment for pre-commit checks ([wiktorn](https://github.com/wiktorn)) ### FAST +- [[#3440](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3440)] Support resource-level factories config in project factory module and FAST stages ([ludoo](https://github.com/ludoo)) +- [[#3439](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3439)] compatiblity fix: Github CICD templates Terraform version bump to 1.12.2 ([ysolt](https://github.com/ysolt)) +- [[#3432](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3432)] Revert "Added audience to workflow local in 0-org-setup" ([ludoo](https://github.com/ludoo)) +- [[#3418](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3418)] Added audience to workflow local in 0-org-setup ([kovagoadam](https://github.com/kovagoadam)) +- [[#3427](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3427)] Add missing project number variable to outputs in 0-org-setup stage ([norbert-loderer](https://github.com/norbert-loderer)) - [[#3332](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3332)] Update gke-hub module to use new Policy Controller API ([juliocc](https://github.com/juliocc)) - [[#3400](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3400)] Remove unavailable service from VPC-SC stage services list ([ludoo](https://github.com/ludoo)) - [[#3385](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3385)] fix: expose missing audiences variable for gitlab workflow file ([vvision](https://github.com/vvision)) @@ -34,6 +41,10 @@ All notable changes to this project will be documented in this file. ### MODULES +- [[#3440](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3440)] Support resource-level factories config in project factory module and FAST stages ([ludoo](https://github.com/ludoo)) +- [[#3436](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3436)] Add service agent outputs to folder and organization ([juliocc](https://github.com/juliocc)) +- [[#3423](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3423)] bigquery-connection module ([lcaggio](https://github.com/lcaggio)) +- [[#3425](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3425)] bigquery-dataset: fix issues ([rosmo](https://github.com/rosmo)) - [[#3424](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3424)] Support CIDR range sets in firewall modules context ([ludoo](https://github.com/ludoo)) - [[#3421](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3421)] Adds network_id to net-vpc outputs ([sruffilli](https://github.com/sruffilli)) - [[#3420](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3420)] Add support for context to net-vpn-ha module ([ludoo](https://github.com/ludoo)) @@ -65,6 +76,7 @@ All notable changes to this project will be documented in this file. ### TOOLS +- [[#3436](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3436)] Add service agent outputs to folder and organization ([juliocc](https://github.com/juliocc)) - [[#3407](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3407)] remove tf version from matrix, to keep workflow names stable across upgrades ([wiktorn](https://github.com/wiktorn)) - [[#3332](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3332)] Update gke-hub module to use new Policy Controller API ([juliocc](https://github.com/juliocc)) - [[#3404](https://github.com/GoogleCloudPlatform/cloud-foundation-fabric/pull/3404)] Add tests for service agents iam_emails ([wiktorn](https://github.com/wiktorn)) diff --git a/fast/stages/0-org-setup/assets/workflow-github.yaml b/fast/stages/0-org-setup/assets/workflow-github.yaml index 1009cb149..465fd29b8 100644 --- a/fast/stages/0-org-setup/assets/workflow-github.yaml +++ b/fast/stages/0-org-setup/assets/workflow-github.yaml @@ -30,7 +30,7 @@ env: SSH_AUTH_SOCK: /tmp/ssh_agent.sock TF_PROVIDERS_FILE: ${tf_providers_files.apply} TF_PROVIDERS_FILE_PLAN: ${tf_providers_files.plan} - TF_VERSION: 1.11.4 + TF_VERSION: 1.12.2 jobs: fast-pr: diff --git a/fast/stages/0-org-setup/output-files.tf b/fast/stages/0-org-setup/output-files.tf index c3d9f1ba5..8d138162c 100644 --- a/fast/stages/0-org-setup/output-files.tf +++ b/fast/stages/0-org-setup/output-files.tf @@ -68,6 +68,7 @@ locals { iam_principals = local.iam_principals logging = { writer_identities = module.organization-iam.0.sink_writer_identities + project_number = module.factory.project_numbers["log-0"] } project_ids = merge( local.ctx.project_ids, diff --git a/fast/stages/0-org-setup/schemas/folder.schema.json b/fast/stages/0-org-setup/schemas/folder.schema.json deleted file mode 100644 index 0ca0be056..000000000 --- a/fast/stages/0-org-setup/schemas/folder.schema.json +++ /dev/null @@ -1,423 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Folder", - "type": "object", - "additionalProperties": false, - "properties": { - "automation": { - "type": "object", - "additionalProperties": false, - "required": [ - "project" - ], - "properties": { - "prefix": { - "type": "string" - }, - "project": { - "type": "string" - }, - "bucket": { - "$ref": "#/$defs/bucket" - }, - "service_accounts": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9-]+$": { - "type": "object", - "additionalProperties": false, - "properties": { - "description": { - "type": "string" - }, - "iam": { - "$ref": "#/$defs/iam" - }, - "iam_bindings": { - "$ref": "#/$defs/iam_bindings" - }, - "iam_bindings_additive": { - "$ref": "#/$defs/iam_bindings_additive" - }, - "iam_billing_roles": { - "$ref": "#/$defs/iam_billing_roles" - }, - "iam_folder_roles": { - "$ref": "#/$defs/iam_folder_roles" - }, - "iam_organization_roles": { - "$ref": "#/$defs/iam_organization_roles" - }, - "iam_project_roles": { - "$ref": "#/$defs/iam_project_roles" - }, - "iam_sa_roles": { - "$ref": "#/$defs/iam_sa_roles" - }, - "iam_storage_roles": { - "$ref": "#/$defs/iam_storage_roles" - } - } - } - } - } - } - }, - "iam": { - "$ref": "#/$defs/iam" - }, - "iam_bindings": { - "$ref": "#/$defs/iam_bindings" - }, - "iam_bindings_additive": { - "$ref": "#/$defs/iam_bindings_additive" - }, - "iam_by_principals": { - "$ref": "#/$defs/iam_by_principals" - }, - "name": { - "type": "string" - }, - "org_policies": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z]+\\.": { - "type": "object", - "properties": { - "inherit_from_parent": { - "type": "boolean" - }, - "reset": { - "type": "boolean" - }, - "rules": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "properties": { - "allow": { - "type": "object", - "additionalProperties": false, - "properties": { - "all": { - "type": "boolean" - }, - "values": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "deny": { - "type": "object", - "additionalProperties": false, - "properties": { - "all": { - "type": "boolean" - }, - "values": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "enforce": { - "type": "boolean" - }, - "condition": { - "type": "object", - "additionalProperties": false, - "properties": { - "description": { - "type": "string" - }, - "expression": { - "type": "string" - }, - "location": { - "type": "string" - }, - "title": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "parent": { - "type": "string", - "pattern": "^(?:folders/[0-9]+|organizations/[0-9]+|\\$folder_ids:[a-z0-9_-]+)$" - }, - "tag_bindings": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9_-]+$": { - "type": "string" - } - } - } - }, - "$defs": { - "bucket": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "description": { - "type": "string" - }, - "iam": { - "$ref": "#/$defs/iam" - }, - "iam_bindings": { - "$ref": "#/$defs/iam_bindings" - }, - "iam_bindings_additive": { - "$ref": "#/$defs/iam_bindings_additive" - }, - "force_destroy": { - "type": "boolean" - }, - "labels": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "location": { - "type": "string" - }, - "managed_folders": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-zA-Z0-9][a-zA-Z0-9_/-]+$": { - "type": "object", - "additionalProperties": false, - "properties": { - "force_destroy": { - "type": "boolean" - }, - "iam": { - "$ref": "#/$defs/iam" - }, - "iam_bindings": { - "$ref": "#/$defs/iam_bindings" - }, - "iam_bindings_additive": { - "$ref": "#/$defs/iam_bindings_additive" - } - } - } - } - }, - "prefix": { - "type": "string" - }, - "storage_class": { - "type": "string" - }, - "uniform_bucket_level_access": { - "type": "boolean" - }, - "versioning": { - "type": "boolean" - } - } - }, - "iam": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^(?:roles/|\\$custom_roles:)": { - "type": "array", - "items": { - "type": "string", - "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:)" - } - } - } - }, - "iam_bindings": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9_-]+$": { - "type": "object", - "additionalProperties": false, - "properties": { - "members": { - "type": "array", - "items": { - "type": "string", - "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:)" - } - }, - "role": { - "type": "string", - "pattern": "^(?:roles/|\\$custom_roles:)" - }, - "condition": { - "type": "object", - "additionalProperties": false, - "required": [ - "expression", - "title" - ], - "properties": { - "expression": { - "type": "string" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - } - } - } - } - } - } - }, - "iam_bindings_additive": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9_-]+$": { - "type": "object", - "additionalProperties": false, - "properties": { - "member": { - "type": "string", - "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:)" - }, - "role": { - "type": "string", - "pattern": "^(?:roles/|\\$custom_roles:)" - }, - "condition": { - "type": "object", - "additionalProperties": false, - "required": [ - "expression", - "title" - ], - "properties": { - "expression": { - "type": "string" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - } - } - } - } - } - } - }, - "iam_by_principals": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:)": { - "type": "array", - "items": { - "type": "string", - "pattern": "^(?:roles/|\\$custom_roles:)" - } - } - } - }, - "iam_billing_roles": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9-]+$": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "iam_folder_roles": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9-]+$": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "iam_organization_roles": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9-]+$": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "iam_project_roles": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9-]+$": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "iam_sa_roles": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9-]+$": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "iam_storage_roles": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9-]+$": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } -} diff --git a/fast/stages/0-org-setup/schemas/folder.schema.json b/fast/stages/0-org-setup/schemas/folder.schema.json new file mode 120000 index 000000000..d58a2759b --- /dev/null +++ b/fast/stages/0-org-setup/schemas/folder.schema.json @@ -0,0 +1 @@ +../../../../modules/project-factory/schemas/folder.schema.json \ No newline at end of file diff --git a/fast/stages/0-org-setup/schemas/folder.schema.md b/fast/stages/0-org-setup/schemas/folder.schema.md deleted file mode 100644 index cb340e2d2..000000000 --- a/fast/stages/0-org-setup/schemas/folder.schema.md +++ /dev/null @@ -1,149 +0,0 @@ -# Folder - - - -## Properties - -*additional properties: false* - -- **automation**: *object* -
*additional properties: false* - - **prefix**: *string* - - ⁺**project**: *string* - - **bucket**: *reference([bucket](#refs-bucket))* - - **service_accounts**: *object* -
*additional properties: false* - - **`^[a-z0-9-]+$`**: *object* -
*additional properties: false* - - **description**: *string* - - **iam**: *reference([iam](#refs-iam))* - - **iam_bindings**: *reference([iam_bindings](#refs-iam_bindings))* - - **iam_bindings_additive**: *reference([iam_bindings_additive](#refs-iam_bindings_additive))* - - **iam_billing_roles**: *reference([iam_billing_roles](#refs-iam_billing_roles))* - - **iam_folder_roles**: *reference([iam_folder_roles](#refs-iam_folder_roles))* - - **iam_organization_roles**: *reference([iam_organization_roles](#refs-iam_organization_roles))* - - **iam_project_roles**: *reference([iam_project_roles](#refs-iam_project_roles))* - - **iam_sa_roles**: *reference([iam_sa_roles](#refs-iam_sa_roles))* - - **iam_storage_roles**: *reference([iam_storage_roles](#refs-iam_storage_roles))* -- **iam**: *reference([iam](#refs-iam))* -- **iam_bindings**: *reference([iam_bindings](#refs-iam_bindings))* -- **iam_bindings_additive**: *reference([iam_bindings_additive](#refs-iam_bindings_additive))* -- **iam_by_principals**: *reference([iam_by_principals](#refs-iam_by_principals))* -- **name**: *string* -- **org_policies**: *object* -
*additional properties: false* - - **`^[a-z]+\.`**: *object* - - **inherit_from_parent**: *boolean* - - **reset**: *boolean* - - **rules**: *array* - - items: *object* -
*additional properties: false* - - **allow**: *object* -
*additional properties: false* - - **all**: *boolean* - - **values**: *array* - - items: *string* - - **deny**: *object* -
*additional properties: false* - - **all**: *boolean* - - **values**: *array* - - items: *string* - - **enforce**: *boolean* - - **condition**: *object* -
*additional properties: false* - - **description**: *string* - - **expression**: *string* - - **location**: *string* - - **title**: *string* -- **parent**: *string* -
*pattern: ^(?:folders/[0-9]+|organizations/[0-9]+|\$folder_ids:[a-z0-9_-]+)$* -- **tag_bindings**: *object* -
*additional properties: false* - - **`^[a-z0-9_-]+$`**: *string* - -## Definitions - -- **bucket**: *object* -
*additional properties: false* - - **name**: *string* - - **description**: *string* - - **iam**: *reference([iam](#refs-iam))* - - **iam_bindings**: *reference([iam_bindings](#refs-iam_bindings))* - - **iam_bindings_additive**: *reference([iam_bindings_additive](#refs-iam_bindings_additive))* - - **force_destroy**: *boolean* - - **labels**: *object* - *additional properties: String* - - **location**: *string* - - **managed_folders**: *object* -
*additional properties: false* - - **`^[a-zA-Z0-9][a-zA-Z0-9_/-]+$`**: *object* -
*additional properties: false* - - **force_destroy**: *boolean* - - **iam**: *reference([iam](#refs-iam))* - - **iam_bindings**: *reference([iam_bindings](#refs-iam_bindings))* - - **iam_bindings_additive**: *reference([iam_bindings_additive](#refs-iam_bindings_additive))* - - **prefix**: *string* - - **storage_class**: *string* - - **uniform_bucket_level_access**: *boolean* - - **versioning**: *boolean* -- **iam**: *object* -
*additional properties: false* - - **`^(?:roles/|\$custom_roles:)`**: *array* - - items: *string* -
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:)* -- **iam_bindings**: *object* -
*additional properties: false* - - **`^[a-z0-9_-]+$`**: *object* -
*additional properties: false* - - **members**: *array* - - items: *string* -
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:)* - - **role**: *string* -
*pattern: ^(?:roles/|\$custom_roles:)* - - **condition**: *object* -
*additional properties: false* - - ⁺**expression**: *string* - - ⁺**title**: *string* - - **description**: *string* -- **iam_bindings_additive**: *object* -
*additional properties: false* - - **`^[a-z0-9_-]+$`**: *object* -
*additional properties: false* - - **member**: *string* -
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:)* - - **role**: *string* -
*pattern: ^(?:roles/|\$custom_roles:)* - - **condition**: *object* -
*additional properties: false* - - ⁺**expression**: *string* - - ⁺**title**: *string* - - **description**: *string* -- **iam_by_principals**: *object* -
*additional properties: false* - - **`^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:)`**: *array* - - items: *string* -
*pattern: ^(?:roles/|\$custom_roles:)* -- **iam_billing_roles**: *object* -
*additional properties: false* - - **`^[a-z0-9-]+$`**: *array* - - items: *string* -- **iam_folder_roles**: *object* -
*additional properties: false* - - **`^[a-z0-9-]+$`**: *array* - - items: *string* -- **iam_organization_roles**: *object* -
*additional properties: false* - - **`^[a-z0-9-]+$`**: *array* - - items: *string* -- **iam_project_roles**: *object* -
*additional properties: false* - - **`^[a-z0-9-]+$`**: *array* - - items: *string* -- **iam_sa_roles**: *object* -
*additional properties: false* - - **`^[a-z0-9-]+$`**: *array* - - items: *string* -- **iam_storage_roles**: *object* -
*additional properties: false* - - **`^[a-z0-9-]+$`**: *array* - - items: *string* diff --git a/fast/stages/0-org-setup/schemas/folder.schema.md b/fast/stages/0-org-setup/schemas/folder.schema.md new file mode 120000 index 000000000..acf5b4bda --- /dev/null +++ b/fast/stages/0-org-setup/schemas/folder.schema.md @@ -0,0 +1 @@ +../../../../modules/project-factory/schemas/folder.schema.md \ No newline at end of file diff --git a/fast/stages/0-org-setup/schemas/project.schema.json b/fast/stages/0-org-setup/schemas/project.schema.json deleted file mode 100644 index bf454c8f8..000000000 --- a/fast/stages/0-org-setup/schemas/project.schema.json +++ /dev/null @@ -1,861 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "title": "Project", - "type": "object", - "additionalProperties": false, - "properties": { - "automation": { - "type": "object", - "additionalProperties": false, - "required": [ - "project" - ], - "properties": { - "prefix": { - "type": "string" - }, - "project": { - "type": "string" - }, - "bucket": { - "$ref": "#/$defs/bucket" - }, - "service_accounts": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9-]+$": { - "type": "object", - "additionalProperties": false, - "properties": { - "description": { - "type": "string" - }, - "iam": { - "$ref": "#/$defs/iam" - }, - "iam_bindings": { - "$ref": "#/$defs/iam_bindings" - }, - "iam_bindings_additive": { - "$ref": "#/$defs/iam_bindings_additive" - }, - "iam_billing_roles": { - "$ref": "#/$defs/iam_billing_roles" - }, - "iam_folder_roles": { - "$ref": "#/$defs/iam_folder_roles" - }, - "iam_organization_roles": { - "$ref": "#/$defs/iam_organization_roles" - }, - "iam_project_roles": { - "$ref": "#/$defs/iam_project_roles" - }, - "iam_sa_roles": { - "$ref": "#/$defs/iam_sa_roles" - }, - "iam_storage_roles": { - "$ref": "#/$defs/iam_storage_roles" - } - } - } - } - } - } - }, - "billing_account": { - "type": "string" - }, - "billing_budgets": { - "type": "array", - "items": { - "type": "string" - } - }, - "buckets": { - "$ref": "#/$defs/buckets" - }, - "contacts": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9_-]+$": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "deletion_policy": { - "type": "string", - "enum": [ - "PREVENT", - "DELETE", - "ABANDON" - ] - }, - "iam": { - "$ref": "#/$defs/iam" - }, - "iam_bindings": { - "$ref": "#/$defs/iam_bindings" - }, - "iam_bindings_additive": { - "$ref": "#/$defs/iam_bindings_additive" - }, - "iam_by_principals": { - "$ref": "#/$defs/iam_by_principals" - }, - "labels": { - "type": "object" - }, - "log_buckets": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9-]+$": { - "$ref": "#/$defs/log_bucket" - } - } - }, - "metric_scopes": { - "type": "array", - "items": { - "type": "string" - } - }, - "name": { - "type": "string" - }, - "org_policies": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z]+\\.": { - "type": "object", - "properties": { - "inherit_from_parent": { - "type": "boolean" - }, - "reset": { - "type": "boolean" - }, - "rules": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "properties": { - "allow": { - "type": "object", - "additionalProperties": false, - "properties": { - "all": { - "type": "boolean" - }, - "values": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "deny": { - "type": "object", - "additionalProperties": false, - "properties": { - "all": { - "type": "boolean" - }, - "values": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "enforce": { - "type": "boolean" - }, - "condition": { - "type": "object", - "additionalProperties": false, - "properties": { - "description": { - "type": "string" - }, - "expression": { - "type": "string" - }, - "location": { - "type": "string" - }, - "title": { - "type": "string" - } - } - } - } - } - } - } - } - } - }, - "quotas": { - "title": "Quotas", - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-zA-Z0-9_-]+$": { - "type": "object", - "additionalProperties": false, - "required": [ - "service", - "quota_id", - "preferred_value" - ], - "properties": { - "service": { - "type": "string" - }, - "quota_id": { - "type": "string" - }, - "preferred_value": { - "type": "number" - }, - "dimensions": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "justification": { - "type": "string" - }, - "contact_email": { - "type": "string" - }, - "annotations": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "ignore_safety_checks": { - "type": "string", - "enum": [ - "QUOTA_DECREASE_BELOW_USAGE", - "QUOTA_DECREASE_PERCENTAGE_TOO_HIGH", - "QUOTA_SAFETY_CHECK_UNSPECIFIED" - ] - } - } - } - } - }, - "parent": { - "type": "string" - }, - "prefix": { - "type": "string" - }, - "project_reuse": { - "type": "object", - "additionalProperties": false, - "properties": { - "use_data_source": { - "type": "boolean" - }, - "attributes": { - "type": "object", - "required": [ - "name", - "number" - ], - "properties": { - "name": { - "type": "string" - }, - "number": { - "type": "number" - }, - "services_enabled": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "project_template": { - "type": "string" - }, - "service_accounts": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9-]+$": { - "type": "object", - "additionalProperties": false, - "properties": { - "display_name": { - "type": "string" - }, - "iam": { - "$ref": "#/$defs/iam" - }, - "iam_self_roles": { - "type": "array", - "items": { - "type": "string" - } - }, - "iam_project_roles": { - "$ref": "#/$defs/iam_project_roles" - }, - "iam_sa_roles": { - "$ref": "#/$defs/iam_sa_roles" - } - } - } - } - }, - "service_encryption_key_ids": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z-]+\\.googleapis\\.com$": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "services": { - "type": "array", - "items": { - "type": "string", - "pattern": "^[a-z-]+\\.googleapis\\.com$" - } - }, - "shared_vpc_host_config": { - "type": "object", - "additionalProperties": false, - "required": [ - "enabled" - ], - "properties": { - "enabled": { - "type": "boolean" - }, - "service_projects": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "shared_vpc_service_config": { - "type": "object", - "additionalProperties": false, - "required": [ - "host_project" - ], - "properties": { - "host_project": { - "type": "string" - }, - "iam_bindings_additive": { - "$ref": "#/$defs/iam_bindings_additive" - }, - "network_users": { - "type": "array", - "items": { - "type": "string" - } - }, - "service_agent_iam": { - "type": "object", - "additionalItems": false, - "patternProperties": { - "^[a-z0-9_-]+$": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "service_agent_subnet_iam": { - "type": "object", - "additionalItems": false, - "patternProperties": { - "^[a-z0-9_-]+$": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "service_iam_grants": { - "type": "array", - "items": { - "type": "string" - } - }, - "network_subnet_users": { - "type": "object", - "additionalItems": false, - "patternProperties": { - "^[a-z0-9_-]+$": { - "type": "array", - "items": { - "type": "string" - } - } - } - } - } - }, - "tag_bindings": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9_-]+$": { - "type": "string" - } - } - }, - "tags": { - "type": "object", - "additionalProperties": { - "type": "object", - "additionalProperties": false, - "properties": { - "description": { - "type": "string" - }, - "iam": { - "$ref": "#/$defs/iam" - }, - "iam_bindings": { - "$ref": "#/$defs/iam_bindings" - }, - "iam_bindings_additive": { - "$ref": "#/$defs/iam_bindings_additive" - }, - "id": { - "type": "string" - }, - "values": { - "type": "object", - "additionalProperties": { - "type": "object", - "additionalProperties": false, - "properties": { - "description": { - "type": "string" - }, - "iam": { - "$ref": "#/$defs/iam" - }, - "iam_bindings": { - "$ref": "#/$defs/iam_bindings" - }, - "iam_bindings_additive": { - "$ref": "#/$defs/iam_bindings_additive" - }, - "id": { - "type": "string" - } - } - } - } - } - } - }, - "universe": { - "type": "object", - "additionalProperties": false, - "properties": { - "prefix": { - "type": "string" - }, - "forced_jit_service_identities": { - "type": "array", - "items": { - "type": "string" - } - }, - "unavailable_services": { - "type": "array", - "items": { - "type": "string" - } - }, - "unavailable_service_identities": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "vpc_sc": { - "type": "object", - "additionalItems": false, - "required": [ - "perimeter_name" - ], - "properties": { - "perimeter_name": { - "type": "string" - }, - "is_dry_run": { - "type": "boolean" - } - } - }, - "datasets": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9_]+$": { - "type": "object", - "additionalProperties": false, - "properties": { - "friendly_name": { - "type": "string" - }, - "location": { - "type": "string" - } - } - } - } - } - }, - "$defs": { - "bucket": { - "type": "object", - "additionalProperties": false, - "properties": { - "name": { - "type": "string" - }, - "create": { - "type": "boolean", - "default": true - }, - "description": { - "type": "string" - }, - "iam": { - "$ref": "#/$defs/iam" - }, - "iam_bindings": { - "$ref": "#/$defs/iam_bindings" - }, - "iam_bindings_additive": { - "$ref": "#/$defs/iam_bindings_additive" - }, - "force_destroy": { - "type": "boolean" - }, - "labels": { - "type": "object", - "additionalProperties": { - "type": "string" - } - }, - "location": { - "type": "string" - }, - "managed_folders": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-zA-Z0-9][a-zA-Z0-9_/-]+$": { - "type": "object", - "additionalProperties": false, - "properties": { - "force_destroy": { - "type": "boolean" - }, - "iam": { - "$ref": "#/$defs/iam" - }, - "iam_bindings": { - "$ref": "#/$defs/iam_bindings" - }, - "iam_bindings_additive": { - "$ref": "#/$defs/iam_bindings_additive" - } - } - } - } - }, - "prefix": { - "type": "string" - }, - "storage_class": { - "type": "string" - }, - "uniform_bucket_level_access": { - "type": "boolean" - }, - "versioning": { - "type": "boolean" - }, - "retention_policy": { - "type": "object", - "additionalProperties": false, - "properties": { - "retention_period": { - "type": "number" - }, - "is_locked": { - "type": "boolean" - } - } - }, - "enable_object_retention": { - "type": "boolean" - } - } - }, - "buckets": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9-]+$": { - "$ref": "#/$defs/bucket" - } - } - }, - "iam": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^(?:roles/|\\$custom_roles:)": { - "type": "array", - "items": { - "type": "string", - "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:||\\$iam_principals:[a-z0-9_-]+)" - } - } - } - }, - "iam_bindings": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9_-]+$": { - "type": "object", - "additionalProperties": false, - "properties": { - "members": { - "type": "array", - "items": { - "type": "string", - "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:[a-z0-9_-]+)" - } - }, - "role": { - "type": "string", - "pattern": "^(?:roles/|\\$custom_roles:)" - }, - "condition": { - "type": "object", - "additionalProperties": false, - "required": [ - "expression", - "title" - ], - "properties": { - "expression": { - "type": "string" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - } - } - } - } - } - } - }, - "iam_bindings_additive": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9_-]+$": { - "type": "object", - "additionalProperties": false, - "properties": { - "member": { - "type": "string", - "pattern": "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:[a-z0-9_-]+)" - }, - "role": { - "type": "string", - "pattern": "^(?:roles/|\\$custom_roles:)" - }, - "condition": { - "type": "object", - "additionalProperties": false, - "required": [ - "expression", - "title" - ], - "properties": { - "expression": { - "type": "string" - }, - "title": { - "type": "string" - }, - "description": { - "type": "string" - } - } - } - } - } - } - }, - "iam_by_principals": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\\$iam_principals:[a-z0-9_-]+)": { - "type": "array", - "items": { - "type": "string", - "pattern": "^(?:roles/|\\$custom_roles:)" - } - } - } - }, - "iam_billing_roles": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9-]+$": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "iam_folder_roles": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9-]+$": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "iam_organization_roles": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9-]+$": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "iam_project_roles": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^(?:[a-z0-9-]|\\$project_ids:[a-z0-9_-])+$": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "iam_sa_roles": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^(?:\\$service_account_ids:|projects/)": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "iam_storage_roles": { - "type": "object", - "additionalProperties": false, - "patternProperties": { - "^[a-z0-9-]+$": { - "type": "array", - "items": { - "type": "string" - } - } - } - }, - "log_bucket": { - "type": "object", - "additionalProperties": false, - "properties": { - "description": { - "type": "string" - }, - "kms_key_name": { - "type": "string" - }, - "location": { - "type": "string" - }, - "log_analytics": { - "type": "object", - "additionalProperties": false, - "properties": { - "enable": { - "type": "boolean", - "default": false - }, - "dataset_link_id": { - "type": "string" - }, - "description": { - "type": "string" - } - } - }, - "retention": { - "type": "number" - } - } - } - } -} diff --git a/fast/stages/0-org-setup/schemas/project.schema.json b/fast/stages/0-org-setup/schemas/project.schema.json new file mode 120000 index 000000000..11f161f17 --- /dev/null +++ b/fast/stages/0-org-setup/schemas/project.schema.json @@ -0,0 +1 @@ +../../../../modules/project-factory/schemas/project.schema.json \ No newline at end of file diff --git a/fast/stages/0-org-setup/schemas/project.schema.md b/fast/stages/0-org-setup/schemas/project.schema.md deleted file mode 100644 index 6915ddb0b..000000000 --- a/fast/stages/0-org-setup/schemas/project.schema.md +++ /dev/null @@ -1,257 +0,0 @@ -# Project - - - -## Properties - -*additional properties: false* - -- **automation**: *object* -
*additional properties: false* - - **prefix**: *string* - - ⁺**project**: *string* - - **bucket**: *reference([bucket](#refs-bucket))* - - **service_accounts**: *object* -
*additional properties: false* - - **`^[a-z0-9-]+$`**: *object* -
*additional properties: false* - - **description**: *string* - - **iam**: *reference([iam](#refs-iam))* - - **iam_bindings**: *reference([iam_bindings](#refs-iam_bindings))* - - **iam_bindings_additive**: *reference([iam_bindings_additive](#refs-iam_bindings_additive))* - - **iam_billing_roles**: *reference([iam_billing_roles](#refs-iam_billing_roles))* - - **iam_folder_roles**: *reference([iam_folder_roles](#refs-iam_folder_roles))* - - **iam_organization_roles**: *reference([iam_organization_roles](#refs-iam_organization_roles))* - - **iam_project_roles**: *reference([iam_project_roles](#refs-iam_project_roles))* - - **iam_sa_roles**: *reference([iam_sa_roles](#refs-iam_sa_roles))* - - **iam_storage_roles**: *reference([iam_storage_roles](#refs-iam_storage_roles))* -- **billing_account**: *string* -- **billing_budgets**: *array* - - items: *string* -- **buckets**: *reference([buckets](#refs-buckets))* -- **contacts**: *object* -
*additional properties: false* - - **`^[a-z0-9_-]+$`**: *array* - - items: *string* -- **deletion_policy**: *string* -
*enum: ['PREVENT', 'DELETE', 'ABANDON']* -- **iam**: *reference([iam](#refs-iam))* -- **iam_bindings**: *reference([iam_bindings](#refs-iam_bindings))* -- **iam_bindings_additive**: *reference([iam_bindings_additive](#refs-iam_bindings_additive))* -- **iam_by_principals**: *reference([iam_by_principals](#refs-iam_by_principals))* -- **labels**: *object* -- **log_buckets**: *object* -
*additional properties: false* - - **`^[a-z0-9-]+$`**: *reference([log_bucket](#refs-log_bucket))* -- **metric_scopes**: *array* - - items: *string* -- **name**: *string* -- **org_policies**: *object* -
*additional properties: false* - - **`^[a-z]+\.`**: *object* - - **inherit_from_parent**: *boolean* - - **reset**: *boolean* - - **rules**: *array* - - items: *object* -
*additional properties: false* - - **allow**: *object* -
*additional properties: false* - - **all**: *boolean* - - **values**: *array* - - items: *string* - - **deny**: *object* -
*additional properties: false* - - **all**: *boolean* - - **values**: *array* - - items: *string* - - **enforce**: *boolean* - - **condition**: *object* -
*additional properties: false* - - **description**: *string* - - **expression**: *string* - - **location**: *string* - - **title**: *string* -- **quotas**: *object* -
*additional properties: false* - - **`^[a-zA-Z0-9_-]+$`**: *object* -
*additional properties: false* - - ⁺**service**: *string* - - ⁺**quota_id**: *string* - - ⁺**preferred_value**: *number* - - **dimensions**: *object* - *additional properties: String* - - **justification**: *string* - - **contact_email**: *string* - - **annotations**: *object* - *additional properties: String* - - **ignore_safety_checks**: *string* -
*enum: ['QUOTA_DECREASE_BELOW_USAGE', 'QUOTA_DECREASE_PERCENTAGE_TOO_HIGH', 'QUOTA_SAFETY_CHECK_UNSPECIFIED']* -- **parent**: *string* -- **prefix**: *string* -- **project_reuse**: *object* -
*additional properties: false* - - **use_data_source**: *boolean* - - **attributes**: *object* - - ⁺**name**: *string* - - ⁺**number**: *number* - - **services_enabled**: *array* - - items: *string* -- **service_accounts**: *object* -
*additional properties: false* - - **`^[a-z0-9-]+$`**: *object* -
*additional properties: false* - - **display_name**: *string* - - **iam**: *reference([iam](#refs-iam))* - - **iam_self_roles**: *array* - - items: *string* - - **iam_project_roles**: *reference([iam_project_roles](#refs-iam_project_roles))* - - **iam_sa_roles**: *reference([iam_sa_roles](#refs-iam_sa_roles))* -- **service_encryption_key_ids**: *object* -
*additional properties: false* - - **`^[a-z-]+\.googleapis\.com$`**: *array* - - items: *string* -- **services**: *array* - - items: *string* -
*pattern: ^[a-z-]+\.googleapis\.com$* -- **shared_vpc_host_config**: *object* -
*additional properties: false* - - ⁺**enabled**: *boolean* - - **service_projects**: *array* - - items: *string* -- **shared_vpc_service_config**: *object* -
*additional properties: false* - - ⁺**host_project**: *string* - - **iam_bindings_additive**: *reference([iam_bindings_additive](#refs-iam_bindings_additive))* - - **network_users**: *array* - - items: *string* - - **service_agent_iam**: *object* - - **`^[a-z0-9_-]+$`**: *array* - - items: *string* - - **service_agent_subnet_iam**: *object* - - **`^[a-z0-9_-]+$`**: *array* - - items: *string* - - **service_iam_grants**: *array* - - items: *string* - - **network_subnet_users**: *object* - - **`^[a-z0-9_-]+$`**: *array* - - items: *string* -- **tag_bindings**: *object* -
*additional properties: false* - - **`^[a-z0-9_-]+$`**: *string* -- **tags**: *object* - *additional properties: Object* -- **vpc_sc**: *object* - - ⁺**perimeter_name**: *string* - - **is_dry_run**: *boolean* -- **datasets**: *object* -
*additional properties: false* - - **`^[a-z0-9_]+$`**: *object* -
*additional properties: false* - - **friendly_name**: *string* - - **location**: *string* - -## Definitions - -- **bucket**: *object* -
*additional properties: false* - - **name**: *string* - - **description**: *string* - - **iam**: *reference([iam](#refs-iam))* - - **iam_bindings**: *reference([iam_bindings](#refs-iam_bindings))* - - **iam_bindings_additive**: *reference([iam_bindings_additive](#refs-iam_bindings_additive))* - - **force_destroy**: *boolean* - - **labels**: *object* - *additional properties: String* - - **location**: *string* - - **managed_folders**: *object* -
*additional properties: false* - - **`^[a-zA-Z0-9][a-zA-Z0-9_/-]+$`**: *object* -
*additional properties: false* - - **force_destroy**: *boolean* - - **iam**: *reference([iam](#refs-iam))* - - **iam_bindings**: *reference([iam_bindings](#refs-iam_bindings))* - - **iam_bindings_additive**: *reference([iam_bindings_additive](#refs-iam_bindings_additive))* - - **prefix**: *string* - - **storage_class**: *string* - - **uniform_bucket_level_access**: *boolean* - - **versioning**: *boolean* - - **retention_policy**: *object* -
*additional properties: false* - - **retention_period**: *number* - - **is_locked**: *boolean* - - **enable_object_retention**: *boolean* -- **buckets**: *object* -
*additional properties: false* - - **`^[a-z0-9-]+$`**: *reference([bucket](#refs-bucket))* -- **iam**: *object* -
*additional properties: false* - - **`^(?:roles/|\$custom_roles:)`**: *array* - - items: *string* -
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:||\$iam_principals:[a-z0-9_-]+)* -- **iam_bindings**: *object* -
*additional properties: false* - - **`^[a-z0-9_-]+$`**: *object* -
*additional properties: false* - - **members**: *array* - - items: *string* -
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:[a-z0-9_-]+)* - - **role**: *string* -
*pattern: ^(?:roles/|\$custom_roles:)* - - **condition**: *object* -
*additional properties: false* - - ⁺**expression**: *string* - - ⁺**title**: *string* - - **description**: *string* -- **iam_bindings_additive**: *object* -
*additional properties: false* - - **`^[a-z0-9_-]+$`**: *object* -
*additional properties: false* - - **member**: *string* -
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:[a-z0-9_-]+)* - - **role**: *string* -
*pattern: ^(?:roles/|\$custom_roles:)* - - **condition**: *object* -
*additional properties: false* - - ⁺**expression**: *string* - - ⁺**title**: *string* - - **description**: *string* -- **iam_by_principals**: *object* -
*additional properties: false* - - **`^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:[a-z0-9_-]+)`**: *array* - - items: *string* -
*pattern: ^(?:roles/|\$custom_roles:)* -- **iam_billing_roles**: *object* -
*additional properties: false* - - **`^[a-z0-9-]+$`**: *array* - - items: *string* -- **iam_folder_roles**: *object* -
*additional properties: false* - - **`^[a-z0-9-]+$`**: *array* - - items: *string* -- **iam_organization_roles**: *object* -
*additional properties: false* - - **`^[a-z0-9-]+$`**: *array* - - items: *string* -- **iam_project_roles**: *object* -
*additional properties: false* - - **`^(?:[a-z0-9-]|\$project_ids:[a-z0-9_-])+$`**: *array* - - items: *string* -- **iam_sa_roles**: *object* -
*additional properties: false* - - **`^(?:\$service_account_ids:|projects/)`**: *array* - - items: *string* -- **iam_storage_roles**: *object* -
*additional properties: false* - - **`^[a-z0-9-]+$`**: *array* - - items: *string* -- **log_bucket**: *object* -
*additional properties: false* - - **description**: *string* - - **kms_key_name**: *string* - - **location**: *string* - - **log_analytics**: *object* -
*additional properties: false* - - **enable**: *boolean* - - **dataset_link_id**: *string* - - **description**: *string* - - **retention**: *number* diff --git a/fast/stages/0-org-setup/schemas/project.schema.md b/fast/stages/0-org-setup/schemas/project.schema.md new file mode 120000 index 000000000..1b04336aa --- /dev/null +++ b/fast/stages/0-org-setup/schemas/project.schema.md @@ -0,0 +1 @@ +../../../../modules/project-factory/schemas/project.schema.md \ No newline at end of file diff --git a/modules/apigee/recipe-apigee-swp/README.md b/modules/apigee/recipe-apigee-swp/README.md index 121d54532..c246e5df9 100644 --- a/modules/apigee/recipe-apigee-swp/README.md +++ b/modules/apigee/recipe-apigee-swp/README.md @@ -54,4 +54,4 @@ module "recipe_apigee_swp" { subnet_proxy_only_ip_cidr_range = "10.16.2.0/24" } } -# tftest modules=10 resources=43 +# tftest modules=10 resources=44 diff --git a/modules/folder/README.md b/modules/folder/README.md index 8798cb33d..a644e9af2 100644 --- a/modules/folder/README.md +++ b/modules/folder/README.md @@ -473,6 +473,7 @@ module "folder" { | [organization-policies.tf](./organization-policies.tf) | Folder-level organization policies. | google_org_policy_policy | | [outputs.tf](./outputs.tf) | Module outputs. | | | [scc-sha-custom-modules.tf](./scc-sha-custom-modules.tf) | Folder-level Custom modules with Security Health Analytics. | google_scc_management_folder_security_health_analytics_custom_module | +| [service-agents.tf](./service-agents.tf) | Service agents supporting resources. | | | [tags.tf](./tags.tf) | None | google_tags_tag_binding | | [variables-iam.tf](./variables-iam.tf) | None | | | [variables-logging.tf](./variables-logging.tf) | None | | @@ -517,5 +518,6 @@ module "folder" { | [name](outputs.tf#L38) | Folder name. | | | [organization_policies_ids](outputs.tf#L47) | Map of ORGANIZATION_POLICIES => ID in the folder. | | | [scc_custom_sha_modules_ids](outputs.tf#L52) | Map of SCC CUSTOM SHA MODULES => ID in the folder. | | -| [sink_writer_identities](outputs.tf#L57) | Writer identities created for each sink. | | +| [service_agents](outputs.tf#L57) | Identities of all folder-level service agents. | | +| [sink_writer_identities](outputs.tf#L62) | Writer identities created for each sink. | | diff --git a/modules/folder/main.tf b/modules/folder/main.tf index 75d099846..cb788fd32 100644 --- a/modules/folder/main.tf +++ b/modules/folder/main.tf @@ -30,8 +30,9 @@ locals { ) : format("folders/%s", try(google_assured_workloads_workload.folder[0].resources[0].resource_id, "")) ) + folder_number = split("/", local.folder_id)[1] aw_parent = ( - # Assured Workload only accepls folder as a parent and uses organization as a parent when no value provided. + # Assured Workload only accepts folder as a parent and uses organization as a parent when no value provided. var.parent == null ? null : ( diff --git a/modules/folder/outputs.tf b/modules/folder/outputs.tf index 58693e74f..1346077d4 100644 --- a/modules/folder/outputs.tf +++ b/modules/folder/outputs.tf @@ -1,5 +1,5 @@ /** - * Copyright 2022 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. @@ -54,6 +54,11 @@ output "scc_custom_sha_modules_ids" { value = { for k, v in google_scc_management_folder_security_health_analytics_custom_module.scc_folder_custom_module : k => v.id } } +output "service_agents" { + description = "Identities of all folder-level service agents." + value = local.service_agents +} + output "sink_writer_identities" { description = "Writer identities created for each sink." value = { diff --git a/modules/folder/service-agents.tf b/modules/folder/service-agents.tf new file mode 100644 index 000000000..a26207e50 --- /dev/null +++ b/modules/folder/service-agents.tf @@ -0,0 +1,33 @@ +/** + * 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. + */ + +# tfdoc:file:description Service agents supporting resources. + +locals { + _sa_raw = yamldecode(file("${path.module}/service-agents.yaml")) + service_agents = { + for agent in local._sa_raw : + agent.name => { + create_command = ( + "gcloud beta services identity create --service=${agent.api} --folder=${local.folder_number}" + ) + display_name = agent.display_name + identity = templatestring(agent.identity, { + folder_number = local.folder_number + }) + } + } +} diff --git a/modules/folder/service-agents.yaml b/modules/folder/service-agents.yaml new file mode 100644 index 000000000..e1e2da4aa --- /dev/null +++ b/modules/folder/service-agents.yaml @@ -0,0 +1,85 @@ +# 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 +# +# https://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. + +- name: accessapproval + display_name: Access Approval Service Agent + api: accessapproval.googleapis.com + identity: service-f${folder_number}@gcp-sa-accessapproval.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: assuredworkloads + display_name: Assured Workloads Service Agent + api: assuredworkloads.googleapis.com + identity: service-folder-${folder_number}@gcp-sa-assuredworkloads.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: audit-manager + display_name: Audit Manager Service Agent + api: auditmanager.googleapis.com + identity: service-folder-${folder_number}@gcp-sa-audit-manager.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: cloudcontrolspartner + display_name: Cloud Controls Partner Service Agent + api: cloudcontrolspartner.googleapis.com + identity: service-folder-${folder_number}@gcp-sa-cloudcontrolspartner.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: logging + display_name: Cloud Logging Service Agent + api: logging.googleapis.com + identity: service-folder-${folder_number}@gcp-sa-logging.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: observability + display_name: Cloud Observability Service Account + api: observability.googleapis.com + identity: service-folder-${folder_number}@gcp-sa-observability.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: osconfig-rollout + display_name: Google Cloud OS Config Rollout Service Agent + api: osconfig.googleapis.com + identity: service-folder-${folder_number}@gcp-sa-osconfig-rollout.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: osconfig + display_name: Google Cloud OS Config Service Agent + api: osconfig.googleapis.com + identity: service-folder-${folder_number}@gcp-sa-osconfig.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: pam + display_name: Privileged Access Manager Service Agent + api: privilegedaccessmanager.googleapis.com + identity: service-folder-${folder_number}@gcp-sa-pam.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: progrollout + display_name: Progressive Rollout Service Agent + api: progressiverollout.googleapis.com + identity: service-folder-${folder_number}@gcp-sa-progrollout.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] + diff --git a/modules/organization/README.md b/modules/organization/README.md index 2ad352edb..45bbf8796 100644 --- a/modules/organization/README.md +++ b/modules/organization/README.md @@ -655,6 +655,7 @@ values: | [organization-policies.tf](./organization-policies.tf) | Organization-level organization policies. | google_org_policy_policy | | [outputs.tf](./outputs.tf) | Module outputs. | | | [scc-sha-custom-modules.tf](./scc-sha-custom-modules.tf) | Organization-level Custom modules with Security Health Analytics. | google_scc_management_organization_security_health_analytics_custom_module | +| [service-agents.tf](./service-agents.tf) | Service agents supporting resources. | | | [tags.tf](./tags.tf) | Manages GCP Secure Tags, keys, values, and IAM. | google_tags_tag_binding · google_tags_tag_key · google_tags_tag_key_iam_binding · google_tags_tag_key_iam_member · google_tags_tag_value · google_tags_tag_value_iam_binding · google_tags_tag_value_iam_member | | [variables-iam.tf](./variables-iam.tf) | None | | | [variables-logging.tf](./variables-logging.tf) | None | | @@ -703,7 +704,8 @@ values: | [organization_id](outputs.tf#L69) | Organization id dependent on module resources. | | | [organization_policies_ids](outputs.tf#L86) | Map of ORGANIZATION_POLICIES => ID in the organization. | | | [scc_custom_sha_modules_ids](outputs.tf#L91) | Map of SCC CUSTOM SHA MODULES => ID in the organization. | | -| [sink_writer_identities](outputs.tf#L96) | Writer identities created for each sink. | | -| [tag_keys](outputs.tf#L104) | Tag key resources. | | -| [tag_values](outputs.tf#L113) | Tag value resources. | | +| [service_agents](outputs.tf#L96) | Identities of all organization-level service agents. | | +| [sink_writer_identities](outputs.tf#L101) | Writer identities created for each sink. | | +| [tag_keys](outputs.tf#L109) | Tag key resources. | | +| [tag_values](outputs.tf#L118) | Tag value resources. | | diff --git a/modules/organization/outputs.tf b/modules/organization/outputs.tf index 43c8062eb..7f5e61abe 100644 --- a/modules/organization/outputs.tf +++ b/modules/organization/outputs.tf @@ -1,5 +1,5 @@ /** - * 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. @@ -93,6 +93,11 @@ output "scc_custom_sha_modules_ids" { value = { for k, v in google_scc_management_organization_security_health_analytics_custom_module.scc_organization_custom_module : k => v.id } } +output "service_agents" { + description = "Identities of all organization-level service agents." + value = local.service_agents +} + output "sink_writer_identities" { description = "Writer identities created for each sink." value = { diff --git a/modules/organization/service-agents.tf b/modules/organization/service-agents.tf new file mode 100644 index 000000000..eca1c65df --- /dev/null +++ b/modules/organization/service-agents.tf @@ -0,0 +1,33 @@ +/** + * 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. + */ + +# tfdoc:file:description Service agents supporting resources. + +locals { + _sa_raw = yamldecode(file("${path.module}/service-agents.yaml")) + service_agents = { + for agent in local._sa_raw : + agent.name => { + create_command = ( + "gcloud beta services identity create --service=${agent.api} --organization=${local.organization_id_numeric}" + ) + display_name = agent.display_name + identity = templatestring(agent.identity, { + organization_number = local.organization_id_numeric + }) + } + } +} diff --git a/modules/organization/service-agents.yaml b/modules/organization/service-agents.yaml new file mode 100644 index 000000000..c6572248d --- /dev/null +++ b/modules/organization/service-agents.yaml @@ -0,0 +1,190 @@ +# 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 +# +# https://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. + +- name: accessapproval + display_name: Access Approval Service Agent + api: accessapproval.googleapis.com + identity: service-o${organization_number}@gcp-sa-accessapproval.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: assuredoss + display_name: Assured OSS Service Agent + api: assuredoss.googleapis.com + identity: service-org-${organization_number}@gcp-sa-assuredoss.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: asm-hpsa + display_name: Attack Surface Management Service Agent + api: securitycenter.googleapis.com + identity: service-org-${organization_number}@gcp-sa-asm-hpsa.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: audit-manager + display_name: Audit Manager Service Agent + api: auditmanager.googleapis.com + identity: service-org-${organization_number}@gcp-sa-audit-manager.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: chronicle-soar + display_name: Chronicle Soar Service Agent + api: chronicle.googleapis.com + identity: service-org-${organization_number}@gcp-sa-chronicle-soar.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: effectivepolicy + display_name: Cloud Asset Effective Policy Service Agent + api: cloudasset.googleapis.com + identity: service-org-${organization_number}@gcp-sa-effectivepolicy.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: othercloudcfg + display_name: Cloud Asset Other Cloud Config Service Agent + api: cloudasset.googleapis.com + identity: service-org-${organization_number}@gcp-sa-othercloudcfg.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: cloudkms + display_name: Cloud KMS Organization Service Agent + api: cloudkms.googleapis.com + identity: service-org-${organization_number}@gcp-sa-cloudkms.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: logging + display_name: Cloud Logging Service Agent + api: logging.googleapis.com + identity: service-org-${organization_number}@gcp-sa-logging.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: nss-hpsa + display_name: Cloud Notebook Security Scanner Service Agent + api: notebooksecurityscanner.googleapis.com + identity: service-org-${organization_number}@gcp-sa-nss-hpsa.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: observability + display_name: Cloud Observability Service Account + api: observability.googleapis.com + identity: service-org-${organization_number}@gcp-sa-observability.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: cloudresourcemanager + display_name: Cloud Resource Manager Service Agent + api: cloudresourcemanager.googleapis.com + identity: service-org-${organization_number}@gcp-sa-cloudresourcemanager.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: riskmanager + display_name: Cloud Risk Manager Service Agent + api: dlp.googleapis.com + identity: organizations-${organization_number}@gcp-sa-riskmanager.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: scc-bulk-export + display_name: Cloud Security Command Center Bulk Export Service Account + api: securitycenter.googleapis.com + identity: service-org-${organization_number}@gcp-sa-scc-bulk-export.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: scc-notification + display_name: Cloud Security Command Center Notification Service Account + api: securitycenter.googleapis.com + identity: service-org-${organization_number}@gcp-sa-scc-notification.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: security-center-api + display_name: Cloud Security Command Center Service Agent + api: securitycenter.googleapis.com + identity: service-org-${organization_number}@security-center-api.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: ktd-hpsa + display_name: Container Threat Detection Service Agent + api: containerthreatdetection.googleapis.com + identity: service-org-${organization_number}@gcp-sa-ktd-hpsa.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: dataplex-cmek + display_name: Dataplex Cmek Service Agent + api: dataplex.googleapis.com + identity: service-org-${organization_number}@gcp-sa-dataplex-cmek.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: dataplex + display_name: Dataplex Service Agent + api: dataplex.googleapis.com + identity: service-org-${organization_number}@gcp-sa-dataplex.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: osconfig-rollout + display_name: Google Cloud OS Config Rollout Service Agent + api: osconfig.googleapis.com + identity: service-org-${organization_number}@gcp-sa-osconfig-rollout.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: osconfig + display_name: Google Cloud OS Config Service Agent + api: osconfig.googleapis.com + identity: service-org-${organization_number}@gcp-sa-osconfig.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: v1-remediator + display_name: Policy Remediator Service Agent (prod) + api: policyremediator.googleapis.com + identity: service-org-${organization_number}@gcp-sa-v1-remediator.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: pam + display_name: Privileged Access Manager Service Agent + api: privilegedaccessmanager.googleapis.com + identity: service-org-${organization_number}@gcp-sa-pam.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: progrollout + display_name: Progressive Rollout Service Agent + api: progressiverollout.googleapis.com + identity: service-org-${organization_number}@gcp-sa-progrollout.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] +- name: sccspanner + display_name: SCC CMEK Spanner Service Agent (PROD) + api: securitycenter.googleapis.com + identity: service-org-${organization_number}@gcp-sa-sccspanner.iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] + diff --git a/modules/project-factory/README.md b/modules/project-factory/README.md index 906db469f..cca3410f8 100644 --- a/modules/project-factory/README.md +++ b/modules/project-factory/README.md @@ -462,7 +462,7 @@ module "project-factory" { } } } -# tftest files=t0,0,1,2,3,4,5,6,7,8,9 inventory=example.yaml +# tftest files=t0,0,1,2,3,4,5,6,7,8,9,10 inventory=example.yaml ``` A project template for GKE projects: @@ -510,6 +510,8 @@ parent: folders/5678901234 ```yaml name: App 0 +factories_config: + org_policies: data/factories/org-policies # tftest-file id=3 path=data/hierarchy/team-a/app-0/.config.yaml schema=folder.schema.json ``` @@ -520,10 +522,12 @@ tag_bindings: # tftest-file id=4 path=data/hierarchy/team-b/app-0/.config.yaml schema=folder.schema.json ``` -One project defined within the folder hierarchy: +One project defined within the folder hierarchy, using a lower level factory for org polcies: ```yaml billing_account: 012345-67890A-BCDEF0 +factories_config: + org_policies: data/factories/org-policies services: - container.googleapis.com - storage.googleapis.com @@ -682,6 +686,15 @@ service_accounts: # tftest-file id=9 path=data/projects/dev-tb-app0-1.yaml schema=project.schema.json ``` +Lower-level factory example. + +```yaml +compute.disableSerialPortAccess: + rules: + - enforce: false +# tftest-file id=10 path=data/factories/org-policies/compute.yaml +``` + ## Files @@ -708,11 +721,11 @@ service_accounts: | name | description | type | required | default | |---|---|:---:|:---:|:---:| -| [factories_config](variables.tf#L181) | Path to folder with YAML resource description data files. | object({…}) | ✓ | | +| [factories_config](variables.tf#L170) | Path to folder with YAML resource description data files. | object({…}) | ✓ | | | [context](variables.tf#L17) | Context-specific interpolations. | object({…}) | | {} | -| [data_defaults](variables.tf#L36) | Optional default values used when corresponding project or folder data from files are missing. | object({…}) | | {} | -| [data_merges](variables.tf#L112) | Optional values that will be merged with corresponding data from files. Combines with `data_defaults`, file data, and `data_overrides`. | object({…}) | | {} | -| [data_overrides](variables.tf#L131) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} | +| [data_defaults](variables.tf#L36) | Optional default values used when corresponding project or folder data from files are missing. | object({…}) | | {} | +| [data_merges](variables.tf#L107) | Optional values that will be merged with corresponding data from files. Combines with `data_defaults`, file data, and `data_overrides`. | object({…}) | | {} | +| [data_overrides](variables.tf#L126) | Optional values that override corresponding data from files. Takes precedence over file data and `data_defaults`. | object({…}) | | {} | | [folders](variables-folders.tf#L17) | Folders data merged with factory data. | map(object({…})) | | {} | | [notification_channels](variables-billing.tf#L17) | Notification channels used by budget alerts. | map(object({…})) | | {} | | [projects](variables-projects.tf#L17) | Projects data merged with factory data. | map(object({…})) | | {} | diff --git a/modules/project-factory/folders.tf b/modules/project-factory/folders.tf index 8d57ab85b..8ec80f424 100644 --- a/modules/project-factory/folders.tf +++ b/modules/project-factory/folders.tf @@ -58,6 +58,7 @@ module "folder-1" { } parent = coalesce(each.value.parent, "$folder_ids:default") name = each.value.name + factories_config = lookup(each.value, "factories_config", {}) org_policies = lookup(each.value, "org_policies", {}) tag_bindings = lookup(each.value, "tag_bindings", {}) logging_data_access = lookup(each.value, "logging_data_access", {}) @@ -89,6 +90,7 @@ module "folder-2" { each.value.parent, "$folder_ids:${each.value.parent_key}" ) name = each.value.name + factories_config = lookup(each.value, "factories_config", {}) org_policies = lookup(each.value, "org_policies", {}) tag_bindings = lookup(each.value, "tag_bindings", {}) logging_data_access = lookup(each.value, "logging_data_access", {}) @@ -128,6 +130,7 @@ module "folder-3" { each.value.parent, "$folder_ids:${each.value.parent_key}" ) name = each.value.name + factories_config = lookup(each.value, "factories_config", {}) org_policies = lookup(each.value, "org_policies", {}) tag_bindings = lookup(each.value, "tag_bindings", {}) logging_data_access = lookup(each.value, "logging_data_access", {}) diff --git a/modules/project-factory/projects-defaults.tf b/modules/project-factory/projects-defaults.tf index a12f0756f..5e7ff14f0 100644 --- a/modules/project-factory/projects-defaults.tf +++ b/modules/project-factory/projects-defaults.tf @@ -25,6 +25,103 @@ locals { defaults = try(var.data_defaults, {}) overrides = try(var.data_overrides, {}) } + data_defaults = { + defaults = merge( + { + billing_account = null + contacts = {} + deletion_policy = null + labels = {} + metric_scopes = [] + parent = null + prefix = null + project_reuse = merge( + { + use_data_source = true + attributes = null + }, + try(local._data_defaults.defaults.project_reuse, { + use_data_source = true + attributes = null + } + ) + ) + service_encryption_key_ids = {} + services = [] + shared_vpc_service_config = merge( + { + host_project = null + iam_bindings_additive = {} + network_users = [] + service_agent_iam = {} + service_agent_subnet_iam = {} + service_iam_grants = [] + network_subnet_users = {} + }, + try(local._data_defaults.defaults.shared_vpc_service_config, { + host_project = null + iam_bindings_additive = {} + network_users = [] + service_agent_iam = {} + service_agent_subnet_iam = {} + service_iam_grants = [] + network_subnet_users = {} + } + ) + ) + storage_location = null + tag_bindings = {} + service_accounts = {} + universe = null + vpc_sc = merge( + { + perimeter_name = null + is_dry_run = false + }, + try(local._data_defaults.defaults.vpc_sc, { + perimeter_name = null + is_dry_run = false + } + ) + ) + logging_data_access = {} + bigquery_location = null + }, + try( + local._data_defaults.defaults, {} + ) + ) + # data_overrides default to null's, to mark that they should not override + overrides = merge({ + billing_account = null + contacts = null + deletion_policy = null + parent = null + prefix = null + service_encryption_key_ids = null + storage_location = null + tag_bindings = null + services = null + service_accounts = null + universe = null + vpc_sc = try( + merge( + { + perimeter_name = null + is_dry_run = false + }, + local._data_defaults.overrides.vpc_sc + ), + null + ) + logging_data_access = null + bigquery_location = null + }, + try( + local._data_defaults.overrides, {} + ) + ) + } _projects_output = { # Semantics of the merges are: # - if data_overrides. is not null, use this value @@ -49,37 +146,7 @@ locals { try(v.contacts, null), local.data_defaults.defaults.contacts ) - factories_config = { # type: object - custom_roles = try( # type: string - coalesce( - local.data_defaults.overrides.factories_config.custom_roles, - try(v.factories_config.custom_roles, null), - local.data_defaults.defaults.factories_config.custom_roles - ), - null - ) - observability = try( # type: string - coalesce( - local.data_defaults.overrides.factories_config.observability, - try(v.factories_config.observability, null), - local.data_defaults.defaults.factories_config.observability - ), - null) - org_policies = try( # type: string - coalesce( - local.data_defaults.overrides.factories_config.org_policies, - try(v.factories_config.org_policies, null), - local.data_defaults.defaults.factories_config.org_policies - ), - null) - quotas = try( # type: string - coalesce( - local.data_defaults.overrides.factories_config.quotas, - try(v.factories_config.quotas, null), - local.data_defaults.defaults.factories_config.quotas - ), - null) - } + factories_config = try(v.factories_config, {}) iam = try(v.iam, {}) # type: map(list(string)) iam_bindings = try(v.iam_bindings, {}) # type: map(object({...})) iam_bindings_additive = try(v.iam_bindings_additive, {}) # type: map(object({...})) @@ -226,21 +293,6 @@ locals { billing_account = null contacts = {} deletion_policy = null - factories_config = merge( - { - custom_roles = null - observability = null - org_policies = null - quotas = null - }, - try(local._data_defaults.defaults.factories_config, { - custom_roles = null - observability = null - org_policies = null - quotas = null - } - ) - ) labels = {} locations = { bigquery = try(local._data_defaults.defaults.locations.bigquery, null) @@ -297,21 +349,6 @@ locals { billing_account = null contacts = null deletion_policy = null - factories_config = merge( - { - custom_roles = null - observability = null - org_policies = null - quotas = null - }, - try(local._data_defaults.overrides.factories_config, { - custom_roles = null - observability = null - org_policies = null - quotas = null - } - ) - ) locations = { bigquery = try(local._data_defaults.overrides.locations.bigquery, null) logging = try(local._data_defaults.overrides.locations.logging, null) diff --git a/modules/project-factory/projects.tf b/modules/project-factory/projects.tf index 4486ce1da..71b521db4 100644 --- a/modules/project-factory/projects.tf +++ b/modules/project-factory/projects.tf @@ -73,12 +73,7 @@ module "projects" { }) default_service_account = try(each.value.default_service_account, "keep") descriptive_name = try(each.value.descriptive_name, null) - factories_config = { - custom_roles = each.value.factories_config.custom_roles - observability = each.value.factories_config.observability - org_policies = each.value.factories_config.org_policies - quotas = each.value.factories_config.quotas - } + factories_config = each.value.factories_config labels = merge( each.value.labels, var.data_merges.labels ) diff --git a/modules/project-factory/schemas/folder.schema.json b/modules/project-factory/schemas/folder.schema.json index 1125a8a97..fd266920f 100644 --- a/modules/project-factory/schemas/folder.schema.json +++ b/modules/project-factory/schemas/folder.schema.json @@ -64,6 +64,18 @@ } } }, + "factories_config": { + "type": "object", + "additionalProperties": false, + "properties": { + "org_policies": { + "type": "string" + }, + "scc_sha_custom_modules": { + "type": "string" + } + } + }, "iam": { "$ref": "#/$defs/iam" }, @@ -157,7 +169,8 @@ } }, "parent": { - "type": "string" + "type": "string", + "pattern": "^(?:folders/[0-9]+|organizations/[0-9]+|\\$folder_ids:[a-z0-9_-]+)$" }, "tag_bindings": { "type": "object", @@ -269,7 +282,7 @@ }, "role": { "type": "string", - "pattern": "^roles/" + "pattern": "^(?:roles/|\\$custom_roles:)" }, "condition": { "type": "object", @@ -308,7 +321,7 @@ }, "role": { "type": "string", - "pattern": "^roles/" + "pattern": "^(?:roles/|\\$custom_roles:)" }, "condition": { "type": "object", diff --git a/modules/project-factory/schemas/folder.schema.md b/modules/project-factory/schemas/folder.schema.md index 4c5fac144..b175e3421 100644 --- a/modules/project-factory/schemas/folder.schema.md +++ b/modules/project-factory/schemas/folder.schema.md @@ -25,6 +25,10 @@ - **iam_project_roles**: *reference([iam_project_roles](#refs-iam_project_roles))* - **iam_sa_roles**: *reference([iam_sa_roles](#refs-iam_sa_roles))* - **iam_storage_roles**: *reference([iam_storage_roles](#refs-iam_storage_roles))* +- **factories_config**: *object* +
*additional properties: false* + - **org_policies**: *string* + - **scc_sha_custom_modules**: *string* - **iam**: *reference([iam](#refs-iam))* - **iam_bindings**: *reference([iam_bindings](#refs-iam_bindings))* - **iam_bindings_additive**: *reference([iam_bindings_additive](#refs-iam_bindings_additive))* @@ -99,7 +103,7 @@ - items: *string*
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:)* - **role**: *string* -
*pattern: ^roles/* +
*pattern: ^(?:roles/|\$custom_roles:)* - **condition**: *object*
*additional properties: false* - ⁺**expression**: *string* @@ -112,7 +116,7 @@ - **member**: *string*
*pattern: ^(?:domain:|group:|serviceAccount:|user:|principal:|principalSet:|\$iam_principals:)* - **role**: *string* -
*pattern: ^roles/* +
*pattern: ^(?:roles/|\$custom_roles:)* - **condition**: *object*
*additional properties: false* - ⁺**expression**: *string* diff --git a/modules/project-factory/schemas/project.schema.json b/modules/project-factory/schemas/project.schema.json index baf129a1e..0eedab517 100644 --- a/modules/project-factory/schemas/project.schema.json +++ b/modules/project-factory/schemas/project.schema.json @@ -114,6 +114,30 @@ "ABANDON" ] }, + "factories_config": { + "type": "object", + "additionalProperties": false, + "properties": { + "custom_roles": { + "type": "string" + }, + "observability": { + "type": "string" + }, + "org_policies": { + "type": "string" + }, + "quotas": { + "type": "string" + }, + "scc_sha_custom_modules": { + "type": "string" + }, + "tags": { + "type": "string" + } + } + }, "iam": { "$ref": "#/$defs/iam" }, diff --git a/modules/project-factory/schemas/project.schema.md b/modules/project-factory/schemas/project.schema.md index c013c7d02..6c908d654 100644 --- a/modules/project-factory/schemas/project.schema.md +++ b/modules/project-factory/schemas/project.schema.md @@ -35,6 +35,14 @@ - items: *string* - **deletion_policy**: *string*
*enum: ['PREVENT', 'DELETE', 'ABANDON']* +- **factories_config**: *object* +
*additional properties: false* + - **custom_roles**: *string* + - **observability**: *string* + - **org_policies**: *string* + - **quotas**: *string* + - **scc_sha_custom_modules**: *string* + - **tags**: *string* - **iam**: *reference([iam](#refs-iam))* - **iam_bindings**: *reference([iam_bindings](#refs-iam_bindings))* - **iam_bindings_additive**: *reference([iam_bindings_additive](#refs-iam_bindings_additive))* @@ -96,6 +104,7 @@ - ⁺**number**: *number* - **services_enabled**: *array* - items: *string* +- **project_template**: *string* - **service_accounts**: *object*
*additional properties: false* - **`^[a-z0-9-]+$`**: *object* @@ -143,6 +152,12 @@ - **universe**: *object*
*additional properties: false* - **prefix**: *string* + - **forced_jit_service_identities**: *array* + - items: *string* + - **unavailable_services**: *array* + - items: *string* + - **unavailable_service_identities**: *array* + - items: *string* - **vpc_sc**: *object* - ⁺**perimeter_name**: *string* - **is_dry_run**: *boolean* @@ -158,6 +173,7 @@ - **bucket**: *object*
*additional properties: false* - **name**: *string* + - **create**: *boolean* - **description**: *string* - **iam**: *reference([iam](#refs-iam))* - **iam_bindings**: *reference([iam_bindings](#refs-iam_bindings))* diff --git a/modules/project-factory/variables.tf b/modules/project-factory/variables.tf index 2e33347b3..d380247d0 100644 --- a/modules/project-factory/variables.tf +++ b/modules/project-factory/variables.tf @@ -42,18 +42,13 @@ variable "data_defaults" { }), {}) contacts = optional(map(list(string)), {}) deletion_policy = optional(string) - factories_config = optional(object({ - custom_roles = optional(string) - observability = optional(string) - org_policies = optional(string) - quotas = optional(string) - }), {}) - labels = optional(map(string), {}) + labels = optional(map(string), {}) locations = optional(object({ bigquery = optional(string) logging = optional(string) storage = optional(string) }), {}) + labels = optional(map(string), {}) logging_data_access = optional(map(object({ ADMIN_READ = optional(object({ exempted_members = optional(list(string)) })), DATA_READ = optional(object({ exempted_members = optional(list(string)) })), @@ -138,12 +133,6 @@ variable "data_overrides" { }), {}) contacts = optional(map(list(string))) deletion_policy = optional(string) - factories_config = optional(object({ - custom_roles = optional(string) - observability = optional(string) - org_policies = optional(string) - quotas = optional(string) - }), {}) locations = optional(object({ bigquery = optional(string) logging = optional(string) diff --git a/modules/project/service-agents.yaml b/modules/project/service-agents.yaml index 08967a456..1d2fea21e 100644 --- a/modules/project/service-agents.yaml +++ b/modules/project/service-agents.yaml @@ -103,6 +103,13 @@ role: roles/meshdataplane.serviceAgent is_primary: false aliases: [] +- name: accessapproval + display_name: Access Approval Service Agent + api: accessapproval.googleapis.com + identity: service-p${project_number}@gcp-sa-accessapproval.${universe_domain}iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] - name: adsdatahub display_name: Ads Data Hub Service Account api: adsdatahub.googleapis.com @@ -218,7 +225,7 @@ - name: gae-api-prod display_name: App Engine Flexible Environment Service Agent api: appengineflex.googleapis.com - identity: service-${project_number}@gae-api-prod.google.com.${universe_domain}iam.gserviceaccount.com + identity: service-${project_number}@gae-api-prod.${universe_domain}iam.gserviceaccount.com role: roles/appengineflex.serviceAgent is_primary: true aliases: @@ -293,13 +300,6 @@ role: roles/backupdr.serviceAgent is_primary: true aliases: [] -- name: backupdr-pr - display_name: Backup and DR Vault Service Agent - api: backupdr.googleapis.com - identity: vault-${project_number}-IDENTIFIER@gcp-sa-backupdr-pr.${universe_domain}iam.gserviceaccount.com - role: null - is_primary: false - aliases: [] - name: gkebackup display_name: Backup for GKE Service Account api: gkebackup.googleapis.com @@ -329,11 +329,11 @@ is_primary: false aliases: - bq -- name: biglakerestcatalog - display_name: BigLake Iceberg Rest Catalog API Service Agent - api: biglake.googleapis.com - identity: blirc-${project_number}-IDENTIFIER@gcp-sa-biglakerestcatalog.${universe_domain}iam.gserviceaccount.com - role: null +- name: connectedsheets + display_name: BigQuery Connected Sheets Service Agent + api: bigquery.googleapis.com + identity: service-${project_number}@gcp-sa-connectedsheets.${universe_domain}iam.gserviceaccount.com + role: roles/bigquery.connectedSheetsServiceAgent is_primary: false aliases: [] - name: bigqueryconnection @@ -371,13 +371,6 @@ role: null is_primary: false aliases: [] -- name: bigquery-consp - display_name: BigQuery Spark Connection Delegate Service Agent - api: bigqueryconnection.googleapis.com - identity: bqcx-${project_number}-IDENTIFIER@gcp-sa-bigquery-consp.${universe_domain}iam.gserviceaccount.com - role: null - is_primary: false - aliases: [] - name: bigqueryspark display_name: BigQuery Spark Service Agent api: bigquery.googleapis.com @@ -399,13 +392,6 @@ role: roles/blockchainnodeengine.serviceAgent is_primary: true aliases: [] -- name: bundles - display_name: Bundles Service Agent - api: integrations.googleapis.com - identity: b${project_number}-IDENTIFIER@gcp-sa-bundles.${universe_domain}iam.gserviceaccount.com - role: null - is_primary: false - aliases: [] - name: chronicle-sv display_name: Chronicle Security Validation Service Account api: chronicle.googleapis.com @@ -639,11 +625,18 @@ role: null is_primary: true aliases: [] +- name: nss-hpsa + display_name: Cloud Notebook Security Scanner Service Agent + api: notebooksecurityscanner.googleapis.com + identity: service-${project_number}@gcp-sa-nss-hpsa.${universe_domain}iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] - name: observability display_name: Cloud Observability Service Account api: observability.googleapis.com identity: service-${project_number}@gcp-sa-observability.${universe_domain}iam.gserviceaccount.com - role: null + role: roles/observability.serviceAgent is_primary: true aliases: [] - name: cloudoptim @@ -850,6 +843,13 @@ role: roles/containerthreatdetection.serviceAgent is_primary: true aliases: [] +- name: ktd-hpsa + display_name: Container Threat Detection Service Agent + api: containerthreatdetection.googleapis.com + identity: service-${project_number}@gcp-sa-ktd-hpsa.${universe_domain}iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] - name: cloud-cw display_name: Content Warehouse Service Account api: contentwarehouse.googleapis.com @@ -1096,6 +1096,13 @@ is_primary: true aliases: - fleet +- name: geminicodeassistmp + display_name: Gemini Code Assist Management Service Agent + api: geminicodeassistmanagement.googleapis.com + identity: service-${project_number}@gcp-sa-geminicodeassistmp.${universe_domain}iam.gserviceaccount.com + role: roles/geminicodeassistmanagement.serviceAgent + is_primary: true + aliases: [] - name: cloudaicompanion display_name: Gemini for Google Cloud Service Agent api: cloudaicompanion.googleapis.com @@ -1145,7 +1152,7 @@ - name: cloud-ml display_name: Google Cloud ML Engine Service Agent api: ml.googleapis.com - identity: service-${project_number}@cloud-ml.google.com.${universe_domain}iam.gserviceaccount.com + identity: service-${project_number}@cloud-ml.${universe_domain}iam.gserviceaccount.com role: roles/ml.serviceAgent is_primary: true aliases: [] @@ -1156,6 +1163,13 @@ role: null is_primary: true aliases: [] +- name: ns-authz + display_name: Google Cloud Network Security Authz Service Account + api: networksecurity.googleapis.com + identity: service-${project_number}@gcp-sa-ns-authz.${universe_domain}iam.gserviceaccount.com + role: roles/networksecurity.authzServiceAgent + is_primary: false + aliases: [] - name: osconfig-rollout display_name: Google Cloud OS Config Rollout Service Agent api: osconfig.googleapis.com @@ -1383,7 +1397,7 @@ display_name: On-Demand Scanning Service Account api: ondemandscanning.googleapis.com identity: service-${project_number}@gcp-sa-ondemandscanning.${universe_domain}iam.gserviceaccount.com - role: roles/ondemandscanning.serviceAgent + role: null is_primary: true aliases: [] - name: oci @@ -1414,6 +1428,13 @@ role: null is_primary: true aliases: [] +- name: pam + display_name: Privileged Access Manager Service Agent + api: privilegedaccessmanager.googleapis.com + identity: service-${project_number}@gcp-sa-pam.${universe_domain}iam.gserviceaccount.com + role: null + is_primary: false + aliases: [] - name: progrollout display_name: Progressive Rollout Service Agent api: progressiverollout.googleapis.com @@ -1673,6 +1694,13 @@ role: roles/aiplatform.tuningServiceAgent is_primary: false aliases: [] +- name: vertex-telemetry + display_name: Vertex AI Telemetry Service Agent + api: aiplatform.googleapis.com + identity: service-${project_number}@gcp-sa-vertex-telemetry.${universe_domain}iam.gserviceaccount.com + role: roles/aiplatform.telemetryServiceAgent + is_primary: false + aliases: [] - name: vertex-agent display_name: Vertex Agent Service Agent api: aiplatform.googleapis.com diff --git a/tests/fast/stages/s0_org_setup/not-simple.yaml b/tests/fast/stages/s0_org_setup/not-simple.yaml index 78f2f91be..3c9cec91a 100644 --- a/tests/fast/stages/s0_org_setup/not-simple.yaml +++ b/tests/fast/stages/s0_org_setup/not-simple.yaml @@ -2781,7 +2781,7 @@ counts: google_organization_iam_custom_role: 9 google_project: 3 google_project_iam_binding: 16 - google_project_iam_member: 15 + google_project_iam_member: 18 google_project_service: 33 google_project_service_identity: 9 google_service_account: 16 diff --git a/tests/fast/stages/s2_networking_a_simple/ncc.yaml b/tests/fast/stages/s2_networking_a_simple/ncc.yaml index 09d4db45c..59af96b43 100644 --- a/tests/fast/stages/s2_networking_a_simple/ncc.yaml +++ b/tests/fast/stages/s2_networking_a_simple/ncc.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. @@ -36,10 +36,10 @@ counts: google_network_connectivity_spoke: 2 google_project: 3 google_project_iam_binding: 2 - google_project_iam_member: 22 + google_project_iam_member: 24 google_project_service: 28 google_project_service_identity: 22 google_storage_bucket_object: 2 google_tags_tag_binding: 3 modules: 23 - resources: 189 + resources: 191 diff --git a/tests/fast/stages/s2_networking_a_simple/simple.yaml b/tests/fast/stages/s2_networking_a_simple/simple.yaml index add5be060..3f3b4c8ce 100644 --- a/tests/fast/stages/s2_networking_a_simple/simple.yaml +++ b/tests/fast/stages/s2_networking_a_simple/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. @@ -40,11 +40,11 @@ counts: google_monitoring_monitored_project: 2 google_project: 3 google_project_iam_binding: 2 - google_project_iam_member: 22 + google_project_iam_member: 24 google_project_service: 28 google_project_service_identity: 22 google_storage_bucket_object: 2 google_tags_tag_binding: 3 modules: 28 random_id: 3 - resources: 206 + resources: 208 diff --git a/tests/fast/stages/s2_networking_a_simple/vpn.yaml b/tests/fast/stages/s2_networking_a_simple/vpn.yaml index 8443a904d..4b711fb60 100644 --- a/tests/fast/stages/s2_networking_a_simple/vpn.yaml +++ b/tests/fast/stages/s2_networking_a_simple/vpn.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. @@ -38,11 +38,11 @@ counts: google_monitoring_monitored_project: 2 google_project: 3 google_project_iam_binding: 2 - google_project_iam_member: 22 + google_project_iam_member: 24 google_project_service: 28 google_project_service_identity: 22 google_storage_bucket_object: 2 google_tags_tag_binding: 3 modules: 30 random_id: 17 - resources: 253 + resources: 255 diff --git a/tests/fast/stages/s2_networking_b_nva/ncc-ra.yaml b/tests/fast/stages/s2_networking_b_nva/ncc-ra.yaml index e5560b5b1..28c84e930 100644 --- a/tests/fast/stages/s2_networking_b_nva/ncc-ra.yaml +++ b/tests/fast/stages/s2_networking_b_nva/ncc-ra.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. @@ -43,11 +43,11 @@ counts: google_network_connectivity_spoke: 4 google_project: 3 google_project_iam_binding: 2 - google_project_iam_member: 22 + google_project_iam_member: 24 google_project_service: 28 google_project_service_identity: 22 google_storage_bucket_object: 2 google_tags_tag_binding: 3 modules: 38 random_id: 6 - resources: 273 + resources: 275 diff --git a/tests/fast/stages/s2_networking_b_nva/regional.yaml b/tests/fast/stages/s2_networking_b_nva/regional.yaml index cee53e755..5e08d85a3 100644 --- a/tests/fast/stages/s2_networking_b_nva/regional.yaml +++ b/tests/fast/stages/s2_networking_b_nva/regional.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. @@ -45,11 +45,11 @@ counts: google_monitoring_monitored_project: 2 google_project: 3 google_project_iam_binding: 2 - google_project_iam_member: 22 + google_project_iam_member: 24 google_project_service: 28 google_project_service_identity: 22 google_storage_bucket_object: 2 google_tags_tag_binding: 3 modules: 46 random_id: 6 - resources: 283 + resources: 285 diff --git a/tests/fast/stages/s2_networking_b_nva/simple.yaml b/tests/fast/stages/s2_networking_b_nva/simple.yaml index b2c876a2b..777d7c8ac 100644 --- a/tests/fast/stages/s2_networking_b_nva/simple.yaml +++ b/tests/fast/stages/s2_networking_b_nva/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. @@ -45,11 +45,11 @@ counts: google_monitoring_monitored_project: 2 google_project: 3 google_project_iam_binding: 2 - google_project_iam_member: 22 + google_project_iam_member: 24 google_project_service: 28 google_project_service_identity: 22 google_storage_bucket_object: 2 google_tags_tag_binding: 3 modules: 42 random_id: 6 - resources: 259 + resources: 261 diff --git a/tests/fast/stages/s2_networking_c_separate_envs/simple.yaml b/tests/fast/stages/s2_networking_c_separate_envs/simple.yaml index 9b87e211d..89a29d649 100644 --- a/tests/fast/stages/s2_networking_c_separate_envs/simple.yaml +++ b/tests/fast/stages/s2_networking_c_separate_envs/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. @@ -38,11 +38,11 @@ counts: google_monitoring_dashboard: 6 google_project: 2 google_project_iam_binding: 2 - google_project_iam_member: 18 + google_project_iam_member: 20 google_project_service: 22 google_project_service_identity: 18 google_storage_bucket_object: 2 google_tags_tag_binding: 2 modules: 23 random_id: 6 - resources: 231 + resources: 233 diff --git a/tests/fast/stages/s3_data_platform_dev/simple.yaml b/tests/fast/stages/s3_data_platform_dev/simple.yaml index 7d0fc4e16..f5f9c4074 100644 --- a/tests/fast/stages/s3_data_platform_dev/simple.yaml +++ b/tests/fast/stages/s3_data_platform_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. @@ -24,7 +24,7 @@ counts: google_folder_iam_binding: 3 google_project: 3 google_project_iam_binding: 23 - google_project_iam_member: 12 + google_project_iam_member: 15 google_project_service: 18 google_project_service_identity: 6 google_service_account: 6 @@ -37,4 +37,4 @@ counts: google_tags_tag_key: 1 google_tags_tag_value: 1 modules: 19 - resources: 109 + resources: 112 diff --git a/tests/modules/cloud_run_v2/examples/service-vpc-access-connector-create-sharedvpc.yaml b/tests/modules/cloud_run_v2/examples/service-vpc-access-connector-create-sharedvpc.yaml index 16efec979..77920dad3 100644 --- a/tests/modules/cloud_run_v2/examples/service-vpc-access-connector-create-sharedvpc.yaml +++ b/tests/modules/cloud_run_v2/examples/service-vpc-access-connector-create-sharedvpc.yaml @@ -53,6 +53,6 @@ counts: google_cloud_run_v2_service: 1 google_vpc_access_connector: 1 modules: 4 - resources: 59 + resources: 60 outputs: {} diff --git a/tests/modules/net_vpc_factory/ncc.yaml b/tests/modules/net_vpc_factory/ncc.yaml index 30a070167..4b45eb9e2 100644 --- a/tests/modules/net_vpc_factory/ncc.yaml +++ b/tests/modules/net_vpc_factory/ncc.yaml @@ -1,4 +1,4 @@ -# Copyright 2023 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. @@ -32,9 +32,9 @@ counts: google_network_connectivity_hub: 1 google_network_connectivity_spoke: 3 google_project: 3 - google_project_iam_member: 21 + google_project_iam_member: 24 google_project_service: 27 google_project_service_identity: 21 modules: 17 random_id: 3 - resources: 136 + resources: 139 diff --git a/tests/modules/net_vpc_factory/only_projects.yaml b/tests/modules/net_vpc_factory/only_projects.yaml index e67e4ff6d..bbe208a05 100644 --- a/tests/modules/net_vpc_factory/only_projects.yaml +++ b/tests/modules/net_vpc_factory/only_projects.yaml @@ -1,4 +1,4 @@ -# Copyright 2023 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. @@ -14,8 +14,8 @@ counts: google_project: 3 - google_project_iam_member: 21 + google_project_iam_member: 24 google_project_service: 27 google_project_service_identity: 21 modules: 3 - resources: 72 + resources: 75 diff --git a/tests/modules/net_vpc_factory/peering.yaml b/tests/modules/net_vpc_factory/peering.yaml index fd734ffcd..cd34a4f83 100644 --- a/tests/modules/net_vpc_factory/peering.yaml +++ b/tests/modules/net_vpc_factory/peering.yaml @@ -1,4 +1,4 @@ -# Copyright 2023 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. @@ -30,9 +30,9 @@ counts: google_dns_policy: 4 google_dns_record_set: 1 google_project: 3 - google_project_iam_member: 21 + google_project_iam_member: 24 google_project_service: 27 google_project_service_identity: 21 modules: 18 random_id: 3 - resources: 139 + resources: 142 diff --git a/tests/modules/net_vpc_factory/separate_envs.yaml b/tests/modules/net_vpc_factory/separate_envs.yaml index f3b1399a0..221d45505 100644 --- a/tests/modules/net_vpc_factory/separate_envs.yaml +++ b/tests/modules/net_vpc_factory/separate_envs.yaml @@ -1,4 +1,4 @@ -# Copyright 2023 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. @@ -27,9 +27,9 @@ counts: google_compute_vpn_tunnel: 2 google_dns_policy: 2 google_project: 3 - google_project_iam_member: 21 + google_project_iam_member: 24 google_project_service: 27 google_project_service_identity: 21 modules: 11 random_id: 4 - resources: 114 + resources: 117 diff --git a/tests/modules/net_vpc_factory/vpn.yaml b/tests/modules/net_vpc_factory/vpn.yaml index 7598121b7..c8d8b574e 100644 --- a/tests/modules/net_vpc_factory/vpn.yaml +++ b/tests/modules/net_vpc_factory/vpn.yaml @@ -1,4 +1,4 @@ -# Copyright 2023 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. @@ -29,9 +29,9 @@ counts: google_dns_policy: 4 google_dns_record_set: 1 google_project: 3 - google_project_iam_member: 21 + google_project_iam_member: 24 google_project_service: 27 google_project_service_identity: 21 modules: 22 random_id: 15 - resources: 175 + resources: 178 diff --git a/tests/modules/project/examples/data.yaml b/tests/modules/project/examples/data.yaml index 065a56aa0..1962876d1 100644 --- a/tests/modules/project/examples/data.yaml +++ b/tests/modules/project/examples/data.yaml @@ -516,7 +516,7 @@ counts: google_project: 2 google_project_iam_audit_config: 2 google_project_iam_binding: 7 - google_project_iam_member: 14 + google_project_iam_member: 15 google_project_service: 7 google_project_service_identity: 3 google_pubsub_topic: 1 @@ -525,7 +525,7 @@ 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_factory/examples/example.yaml b/tests/modules/project_factory/examples/example.yaml index a69cf903d..2c487a7e4 100644 --- a/tests/modules/project_factory/examples/example.yaml +++ b/tests/modules/project_factory/examples/example.yaml @@ -145,6 +145,19 @@ values: display_name: App 0 tags: null timeouts: null + module.project-factory.module.folder-2["team-a/app-0"].google_org_policy_policy.default["compute.disableSerialPortAccess"]: + dry_run_spec: [] + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'FALSE' + parameters: null + values: [] + timeouts: null module.project-factory.module.folder-2["team-b/app-0"].google_folder.folder[0]: deletion_protection: false display_name: App 0 @@ -438,6 +451,21 @@ values: - ALL parent: projects/test-pf-teams-iac-0 timeouts: null + module.project-factory.module.projects["teams-iac-0"].google_org_policy_policy.default["compute.disableSerialPortAccess"]: + dry_run_spec: [] + name: projects/test-pf-teams-iac-0/policies/compute.disableSerialPortAccess + parent: projects/test-pf-teams-iac-0 + spec: + - inherit_from_parent: null + reset: null + rules: + - allow_all: null + condition: [] + deny_all: null + enforce: 'FALSE' + parameters: null + values: [] + timeouts: null module.project-factory.module.projects["teams-iac-0"].google_project.project[0]: auto_create_network: false billing_account: 012345-67890A-BCDEF0 @@ -587,6 +615,7 @@ counts: google_folder_iam_binding: 1 google_kms_crypto_key_iam_member: 2 google_monitoring_notification_channel: 1 + google_org_policy_policy: 2 google_project: 4 google_project_iam_binding: 6 google_project_iam_member: 21 @@ -602,5 +631,5 @@ counts: google_tags_tag_value: 2 google_tags_tag_value_iam_binding: 1 modules: 23 - resources: 86 + resources: 88 terraform_data: 1 diff --git a/tools/build_service_agents.py b/tools/build_service_agents.py index 55b4ff573..eddab41f6 100755 --- a/tools/build_service_agents.py +++ b/tools/build_service_agents.py @@ -58,6 +58,13 @@ IGNORED_AGENTS = [ 'c-PROJECT_NUMBER-IDENTIFIER@gcp-sa-alloydb.iam.gserviceaccount.com' ] +AGENT_NAME_OVERRIDE = { + # special case for Cloud Build that has two service agents: + # - %s@cloudbuild.gserviceaccount.com + # - service-%s@gcp-sa-cloudbuild.iam.gserviceaccount.com + 'PROJECT_NUMBER@cloudbuild.gserviceaccount.com': 'cloudbuild-sa', +} + E2E_SERVICES = [ "alloydb.googleapis.com", "analyticshub.googleapis.com", @@ -112,7 +119,13 @@ class Agent: @click.command() @click.option('--e2e', is_flag=True, default=False) -def main(e2e=False): +@click.option('--organization', 'mode', flag_value='organization', + default=False, help='Extract organization-level service agents') +@click.option('--folder', 'mode', flag_value='folder', default=False, + help='Extract folder-level service agents') +@click.option('--project', 'mode', flag_value='project', default=False, + help='Extract project-level service agents') +def main(mode, e2e=False): page = requests.get(SERVICE_AGENTS_URL).content soup = BeautifulSoup(page, 'html.parser') agents = [] @@ -120,32 +133,58 @@ def main(e2e=False): agent_text = content.get_text() col1, col2 = content.find_all('td') - # skip agents with more than one identity + # Extract all identities from col1 (could be in a single

or multiple in a