diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 70a13b03863d..aa9548a21d56 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -45293,6 +45293,13 @@ components: description: When enabled, Datadog collects metrics where location is explicitly stated as "global" or where location information cannot be deduced from GCP labels. example: true type: boolean + is_org_folder_resource_collection_enabled: + default: false + description: |- + When enabled, Datadog scans for organization and folder-level resources + under the organization the service account belongs to. + example: false + type: boolean is_per_project_quota_enabled: default: false description: |- @@ -45332,7 +45339,7 @@ components: type: array resource_collection_enabled: description: |- - When enabled, Datadog scans for all resources in your GCP environment. + When enabled, Datadog scans for all project-level resources in your GCP environment. type: boolean type: object GCPSTSServiceAccountCreateRequest: diff --git a/features/generated-test/test-runner-data/manifest.json b/features/generated-test/test-runner-data/manifest.json index 89208fac7962..ce6d24896126 100644 --- a/features/generated-test/test-runner-data/manifest.json +++ b/features/generated-test/test-runner-data/manifest.json @@ -5705,6 +5705,13 @@ "scenario": "Create a new entry for your service account with cspm enabled returns \"OK\" response", "version": "v2" }, + { + "feature": "GCP Integration", + "feature_file": "../../v2/gcp_integration.feature", + "file": "v2/gcp-integration/create-a-new-entry-for-your-service-account-with-org-folder-resource-collection-enabled-returns-ok-response.json", + "scenario": "Create a new entry for your service account with org folder resource collection enabled returns \"OK\" response", + "version": "v2" + }, { "feature": "GCP Integration", "feature_file": "../../v2/gcp_integration.feature", @@ -5761,6 +5768,13 @@ "scenario": "Update STS Service Account returns \"OK\" response with enable resource collection turned on", "version": "v2" }, + { + "feature": "GCP Integration", + "feature_file": "../../v2/gcp_integration.feature", + "file": "v2/gcp-integration/update-sts-service-account-returns-ok-response-with-org-folder-resource-collection-enabled.json", + "scenario": "Update STS Service Account returns \"OK\" response with org folder resource collection enabled", + "version": "v2" + }, { "feature": "Google Chat Integration", "feature_file": "../../v2/google_chat_integration.feature", diff --git a/features/generated-test/test-runner-data/v2/gcp-integration/create-a-new-entry-for-your-service-account-with-org-folder-resource-collection-enabled-returns-ok-response.json b/features/generated-test/test-runner-data/v2/gcp-integration/create-a-new-entry-for-your-service-account-with-org-folder-resource-collection-enabled-returns-ok-response.json new file mode 100644 index 000000000000..16776f105ee0 --- /dev/null +++ b/features/generated-test/test-runner-data/v2/gcp-integration/create-a-new-entry-for-your-service-account-with-org-folder-resource-collection-enabled-returns-ok-response.json @@ -0,0 +1,35 @@ +{ + "api": "GCPIntegration", + "expected_status": 201, + "feature": "GCP Integration", + "id": "v2/GCP Integration/Create a new entry for your service account with org folder resource collection enabled returns \"OK\" response", + "operation_id": "CreateGCPSTSAccount", + "request": { + "body": { + "schema": { + "format": null, + "ref": "GCPSTSServiceAccountCreateRequest", + "type": "object" + }, + "source": "inline", + "value": { + "data": { + "attributes": { + "client_email": "Test-{{ unique_hash }}@test-project.iam.gserviceaccount.com", + "host_filters": [], + "is_org_folder_resource_collection_enabled": true + }, + "type": "gcp_service_account" + } + } + }, + "content_type": "application/json", + "method": "POST", + "pagination": false, + "parameters": [], + "path": "/api/v2/integration/gcp/accounts" + }, + "scenario": "Create a new entry for your service account with org folder resource collection enabled returns \"OK\" response", + "schema_version": 1, + "version": "v2" +} diff --git a/features/generated-test/test-runner-data/v2/gcp-integration/update-sts-service-account-returns-ok-response-with-org-folder-resource-collection-enabled.json b/features/generated-test/test-runner-data/v2/gcp-integration/update-sts-service-account-returns-ok-response-with-org-folder-resource-collection-enabled.json new file mode 100644 index 000000000000..1d5ef5a708e6 --- /dev/null +++ b/features/generated-test/test-runner-data/v2/gcp-integration/update-sts-service-account-returns-ok-response-with-org-folder-resource-collection-enabled.json @@ -0,0 +1,52 @@ +{ + "api": "GCPIntegration", + "expected_status": 201, + "feature": "GCP Integration", + "id": "v2/GCP Integration/Update STS Service Account returns \"OK\" response with org folder resource collection enabled", + "operation_id": "UpdateGCPSTSAccount", + "request": { + "body": { + "schema": { + "format": null, + "ref": "GCPSTSServiceAccountUpdateRequest", + "type": "object" + }, + "source": "inline", + "value": { + "data": { + "attributes": { + "client_email": "Test-{{ unique_hash }}@example.com", + "is_org_folder_resource_collection_enabled": true + }, + "id": "{{ gcp_sts_account.data.id }}", + "type": "gcp_service_account" + } + } + }, + "content_type": "application/json", + "method": "PATCH", + "pagination": false, + "parameters": [ + { + "explode": null, + "in": "path", + "name": "account_id", + "required": true, + "schema": { + "format": null, + "ref": null, + "type": "string" + }, + "source": { + "path": "gcp_sts_account.data.id", + "type": "fixture" + }, + "style": null + } + ], + "path": "/api/v2/integration/gcp/accounts/{account_id}" + }, + "scenario": "Update STS Service Account returns \"OK\" response with org folder resource collection enabled", + "schema_version": 1, + "version": "v2" +} diff --git a/features/generated-test/test-server-data/v2/gcp-integration.json b/features/generated-test/test-server-data/v2/gcp-integration.json index d3a73b3052a1..636324b08cd0 100644 --- a/features/generated-test/test-server-data/v2/gcp-integration.json +++ b/features/generated-test/test-server-data/v2/gcp-integration.json @@ -320,6 +320,67 @@ "scenario": "Create a new entry for your service account with cspm enabled returns \"OK\" response", "version": "v2" }, + { + "feature": "GCP Integration", + "frozen_at": "2026-09-21T12:55:57.467Z", + "interactions": [ + { + "request": { + "body": { + "type": "json", + "value": { + "data": { + "attributes": { + "client_email": "Test-adf02e78612f5af0@test-project.iam.gserviceaccount.com", + "host_filters": [], + "is_org_folder_resource_collection_enabled": true + }, + "type": "gcp_service_account" + } + } + }, + "content_type": "application/json", + "method": "POST", + "path": "/api/v2/integration/gcp/accounts", + "query": [] + }, + "response": { + "body": { + "encoding": "text", + "value": "{\"data\":{\"id\":\"9f54448b-f2db-4b40-a311-db7bf0eba7f8\",\"type\":\"gcp_service_account\",\"attributes\":{\"account_tags\":[],\"automute\":false,\"client_email\":\"Test-adf02e78612f5af0@test-project.iam.gserviceaccount.com\",\"cloud_run_revision_filters\":[],\"host_filters\":[],\"is_cspm_enabled\":false,\"is_global_location_enabled\":true,\"is_org_folder_resource_collection_enabled\":true,\"is_per_project_quota_enabled\":false,\"is_resource_change_collection_enabled\":false,\"is_security_command_center_enabled\":false,\"metric_namespace_configs\":[{\"id\":\"prometheus\",\"disabled\":true,\"filters\":[]}],\"monitored_resource_configs\":[],\"region_filter_configs\":[],\"resource_collection_enabled\":true}}}" + }, + "headers": { + "content-type": "application/vnd.api+json" + }, + "reason": "Created", + "status": 201 + } + }, + { + "request": { + "body": { + "type": "empty", + "value": null + }, + "content_type": "", + "method": "DELETE", + "path": "/api/v2/integration/gcp/accounts/9f54448b-f2db-4b40-a311-db7bf0eba7f8", + "query": [] + }, + "response": { + "body": { + "encoding": "text", + "value": "" + }, + "headers": {}, + "reason": "No Content", + "status": 204 + } + } + ], + "scenario": "Create a new entry for your service account with org folder resource collection enabled returns \"OK\" response", + "version": "v2" + }, { "feature": "GCP Integration", "frozen_at": "2024-03-11T19:47:24.676Z", @@ -889,6 +950,98 @@ ], "scenario": "Update STS Service Account returns \"OK\" response with enable resource collection turned on", "version": "v2" + }, + { + "feature": "GCP Integration", + "frozen_at": "2026-09-21T12:55:59.538Z", + "interactions": [ + { + "request": { + "body": { + "type": "json", + "value": { + "data": { + "attributes": { + "client_email": "Test-746106a10e59cd21@example.com", + "host_filters": [] + }, + "type": "gcp_service_account" + } + } + }, + "content_type": "application/json", + "method": "POST", + "path": "/api/v2/integration/gcp/accounts", + "query": [] + }, + "response": { + "body": { + "encoding": "text", + "value": "{\"data\":{\"id\":\"fcf23df5-89e0-40af-b19c-f7dfa93c063c\",\"type\":\"gcp_service_account\",\"attributes\":{\"account_tags\":[],\"automute\":false,\"client_email\":\"Test-746106a10e59cd21@example.com\",\"cloud_run_revision_filters\":[],\"host_filters\":[],\"is_cspm_enabled\":false,\"is_global_location_enabled\":true,\"is_org_folder_resource_collection_enabled\":false,\"is_per_project_quota_enabled\":false,\"is_resource_change_collection_enabled\":false,\"is_security_command_center_enabled\":false,\"metric_namespace_configs\":[{\"id\":\"prometheus\",\"disabled\":true,\"filters\":[]}],\"monitored_resource_configs\":[],\"region_filter_configs\":[],\"resource_collection_enabled\":true}}}" + }, + "headers": { + "content-type": "application/vnd.api+json" + }, + "reason": "Created", + "status": 201 + } + }, + { + "request": { + "body": { + "type": "json", + "value": { + "data": { + "attributes": { + "client_email": "Test-746106a10e59cd21@example.com", + "is_org_folder_resource_collection_enabled": true + }, + "id": "fcf23df5-89e0-40af-b19c-f7dfa93c063c", + "type": "gcp_service_account" + } + } + }, + "content_type": "application/json", + "method": "PATCH", + "path": "/api/v2/integration/gcp/accounts/fcf23df5-89e0-40af-b19c-f7dfa93c063c", + "query": [] + }, + "response": { + "body": { + "encoding": "text", + "value": "{\"data\":{\"id\":\"fcf23df5-89e0-40af-b19c-f7dfa93c063c\",\"type\":\"gcp_service_account\",\"attributes\":{\"account_tags\":[],\"automute\":false,\"client_email\":\"Test-746106a10e59cd21@example.com\",\"cloud_run_revision_filters\":[],\"host_filters\":[],\"is_cspm_enabled\":false,\"is_global_location_enabled\":true,\"is_org_folder_resource_collection_enabled\":true,\"is_per_project_quota_enabled\":false,\"is_resource_change_collection_enabled\":false,\"is_security_command_center_enabled\":false,\"metric_namespace_configs\":[{\"id\":\"prometheus\",\"disabled\":true,\"filters\":[]}],\"monitored_resource_configs\":[],\"region_filter_configs\":[],\"resource_collection_enabled\":true}}}" + }, + "headers": { + "content-type": "application/vnd.api+json" + }, + "reason": "Created", + "status": 201 + } + }, + { + "request": { + "body": { + "type": "empty", + "value": null + }, + "content_type": "", + "method": "DELETE", + "path": "/api/v2/integration/gcp/accounts/fcf23df5-89e0-40af-b19c-f7dfa93c063c", + "query": [] + }, + "response": { + "body": { + "encoding": "text", + "value": "" + }, + "headers": {}, + "reason": "No Content", + "status": 204 + } + } + ], + "scenario": "Update STS Service Account returns \"OK\" response with org folder resource collection enabled", + "version": "v2" } ], "schema_version": 1, diff --git a/features/v2/gcp_integration.feature b/features/v2/gcp_integration.feature index 6dcb271ec177..11a97ee5b3b6 100644 --- a/features/v2/gcp_integration.feature +++ b/features/v2/gcp_integration.feature @@ -34,14 +34,14 @@ Feature: GCP Integration @generated @skip @team:DataDog/gcp-integrations Scenario: Create a new entry for your service account returns "Bad Request" response Given new "CreateGCPSTSAccount" request - And body with value {"data": {"attributes": {"account_tags": [], "client_email": "datadog-service-account@test-project.iam.gserviceaccount.com", "cloud_run_revision_filters": ["$KEY:$VALUE"], "host_filters": ["$KEY:$VALUE"], "is_global_location_enabled": true, "is_per_project_quota_enabled": true, "is_resource_change_collection_enabled": true, "is_security_command_center_enabled": true, "metric_namespace_configs": [{"disabled": true, "id": "aiplatform"}, {"filters": ["snapshot.*", "!*_by_region"], "id": "pubsub"}], "monitored_resource_configs": [{"filters": ["$KEY:$VALUE"], "type": "gce_instance"}], "region_filter_configs": ["nam4", "europe-north1"]}, "type": "gcp_service_account"}} + And body with value {"data": {"attributes": {"account_tags": [], "client_email": "datadog-service-account@test-project.iam.gserviceaccount.com", "cloud_run_revision_filters": ["$KEY:$VALUE"], "host_filters": ["$KEY:$VALUE"], "is_global_location_enabled": true, "is_org_folder_resource_collection_enabled": false, "is_per_project_quota_enabled": true, "is_resource_change_collection_enabled": true, "is_security_command_center_enabled": true, "metric_namespace_configs": [{"disabled": true, "id": "aiplatform"}, {"filters": ["snapshot.*", "!*_by_region"], "id": "pubsub"}], "monitored_resource_configs": [{"filters": ["$KEY:$VALUE"], "type": "gce_instance"}], "region_filter_configs": ["nam4", "europe-north1"]}, "type": "gcp_service_account"}} When the request is sent Then the response status is 400 Bad Request @generated @skip @team:DataDog/gcp-integrations Scenario: Create a new entry for your service account returns "Conflict" response Given new "CreateGCPSTSAccount" request - And body with value {"data": {"attributes": {"account_tags": [], "client_email": "datadog-service-account@test-project.iam.gserviceaccount.com", "cloud_run_revision_filters": ["$KEY:$VALUE"], "host_filters": ["$KEY:$VALUE"], "is_global_location_enabled": true, "is_per_project_quota_enabled": true, "is_resource_change_collection_enabled": true, "is_security_command_center_enabled": true, "metric_namespace_configs": [{"disabled": true, "id": "aiplatform"}, {"filters": ["snapshot.*", "!*_by_region"], "id": "pubsub"}], "monitored_resource_configs": [{"filters": ["$KEY:$VALUE"], "type": "gce_instance"}], "region_filter_configs": ["nam4", "europe-north1"]}, "type": "gcp_service_account"}} + And body with value {"data": {"attributes": {"account_tags": [], "client_email": "datadog-service-account@test-project.iam.gserviceaccount.com", "cloud_run_revision_filters": ["$KEY:$VALUE"], "host_filters": ["$KEY:$VALUE"], "is_global_location_enabled": true, "is_org_folder_resource_collection_enabled": false, "is_per_project_quota_enabled": true, "is_resource_change_collection_enabled": true, "is_security_command_center_enabled": true, "metric_namespace_configs": [{"disabled": true, "id": "aiplatform"}, {"filters": ["snapshot.*", "!*_by_region"], "id": "pubsub"}], "monitored_resource_configs": [{"filters": ["$KEY:$VALUE"], "type": "gce_instance"}], "region_filter_configs": ["nam4", "europe-north1"]}, "type": "gcp_service_account"}} When the request is sent Then the response status is 409 Conflict @@ -84,6 +84,16 @@ Feature: GCP Integration And the response "data.attributes.client_email" is equal to "Test-{{ unique_hash }}@test-project.iam.gserviceaccount.com" And the response "data.attributes.is_cspm_enabled" is equal to true + @team:DataDog/gcp-integrations + Scenario: Create a new entry for your service account with org folder resource collection enabled returns "OK" response + Given new "CreateGCPSTSAccount" request + And body with value {"data": {"attributes": {"is_org_folder_resource_collection_enabled": true, "client_email": "Test-{{ unique_hash }}@test-project.iam.gserviceaccount.com", "host_filters": []}, "type": "gcp_service_account"}} + When the request is sent + Then the response status is 201 OK + And the response "data.type" is equal to "gcp_service_account" + And the response "data.attributes.client_email" is equal to "Test-{{ unique_hash }}@test-project.iam.gserviceaccount.com" + And the response "data.attributes.is_org_folder_resource_collection_enabled" is equal to true + @team:DataDog/gcp-integrations Scenario: Create a new entry for your service account with resource collection enabled disabled and cspm enabled returns "Bad Request" response Given new "CreateGCPSTSAccount" request @@ -151,7 +161,7 @@ Feature: GCP Integration Scenario: Update STS Service Account returns "Bad Request" response Given new "UpdateGCPSTSAccount" request And request contains "account_id" parameter from "REPLACE.ME" - And body with value {"data": {"attributes": {"account_tags": [], "client_email": "datadog-service-account@test-project.iam.gserviceaccount.com", "cloud_run_revision_filters": ["$KEY:$VALUE"], "host_filters": ["$KEY:$VALUE"], "is_global_location_enabled": true, "is_per_project_quota_enabled": true, "is_resource_change_collection_enabled": true, "is_security_command_center_enabled": true, "metric_namespace_configs": [{"disabled": true, "id": "aiplatform"}, {"filters": ["snapshot.*", "!*_by_region"], "id": "pubsub"}], "monitored_resource_configs": [{"filters": ["$KEY:$VALUE"], "type": "gce_instance"}], "region_filter_configs": ["nam4", "europe-north1"]}, "id": "d291291f-12c2-22g4-j290-123456678897", "type": "gcp_service_account"}} + And body with value {"data": {"attributes": {"account_tags": [], "client_email": "datadog-service-account@test-project.iam.gserviceaccount.com", "cloud_run_revision_filters": ["$KEY:$VALUE"], "host_filters": ["$KEY:$VALUE"], "is_global_location_enabled": true, "is_org_folder_resource_collection_enabled": false, "is_per_project_quota_enabled": true, "is_resource_change_collection_enabled": true, "is_security_command_center_enabled": true, "metric_namespace_configs": [{"disabled": true, "id": "aiplatform"}, {"filters": ["snapshot.*", "!*_by_region"], "id": "pubsub"}], "monitored_resource_configs": [{"filters": ["$KEY:$VALUE"], "type": "gce_instance"}], "region_filter_configs": ["nam4", "europe-north1"]}, "id": "d291291f-12c2-22g4-j290-123456678897", "type": "gcp_service_account"}} When the request is sent Then the response status is 400 Bad Request @@ -159,7 +169,7 @@ Feature: GCP Integration Scenario: Update STS Service Account returns "Not Found" response Given new "UpdateGCPSTSAccount" request And request contains "account_id" parameter from "REPLACE.ME" - And body with value {"data": {"attributes": {"account_tags": [], "client_email": "datadog-service-account@test-project.iam.gserviceaccount.com", "cloud_run_revision_filters": ["$KEY:$VALUE"], "host_filters": ["$KEY:$VALUE"], "is_global_location_enabled": true, "is_per_project_quota_enabled": true, "is_resource_change_collection_enabled": true, "is_security_command_center_enabled": true, "metric_namespace_configs": [{"disabled": true, "id": "aiplatform"}, {"filters": ["snapshot.*", "!*_by_region"], "id": "pubsub"}], "monitored_resource_configs": [{"filters": ["$KEY:$VALUE"], "type": "gce_instance"}], "region_filter_configs": ["nam4", "europe-north1"]}, "id": "d291291f-12c2-22g4-j290-123456678897", "type": "gcp_service_account"}} + And body with value {"data": {"attributes": {"account_tags": [], "client_email": "datadog-service-account@test-project.iam.gserviceaccount.com", "cloud_run_revision_filters": ["$KEY:$VALUE"], "host_filters": ["$KEY:$VALUE"], "is_global_location_enabled": true, "is_org_folder_resource_collection_enabled": false, "is_per_project_quota_enabled": true, "is_resource_change_collection_enabled": true, "is_security_command_center_enabled": true, "metric_namespace_configs": [{"disabled": true, "id": "aiplatform"}, {"filters": ["snapshot.*", "!*_by_region"], "id": "pubsub"}], "monitored_resource_configs": [{"filters": ["$KEY:$VALUE"], "type": "gce_instance"}], "region_filter_configs": ["nam4", "europe-north1"]}, "id": "d291291f-12c2-22g4-j290-123456678897", "type": "gcp_service_account"}} When the request is sent Then the response status is 404 Not Found @@ -189,3 +199,12 @@ Feature: GCP Integration And body with value {"data": {"attributes": {"client_email": "Test-{{ unique_hash }}@example.com", "resource_collection_enabled": true}, "id": "{{ gcp_sts_account.data.id }}", "type": "gcp_service_account"}} When the request is sent Then the response status is 201 OK + + @team:DataDog/gcp-integrations + Scenario: Update STS Service Account returns "OK" response with org folder resource collection enabled + Given there is a valid "gcp_sts_account" in the system + And new "UpdateGCPSTSAccount" request + And request contains "account_id" parameter from "gcp_sts_account.data.id" + And body with value {"data": {"attributes": {"client_email": "Test-{{ unique_hash }}@example.com", "is_org_folder_resource_collection_enabled": true}, "id": "{{ gcp_sts_account.data.id }}", "type": "gcp_service_account"}} + When the request is sent + Then the response status is 201 OK diff --git a/services/gcp_integration/src/v2/models/GCPSTSServiceAccountAttributes.ts b/services/gcp_integration/src/v2/models/GCPSTSServiceAccountAttributes.ts index 718ff8b8d99e..cb6977e08246 100644 --- a/services/gcp_integration/src/v2/models/GCPSTSServiceAccountAttributes.ts +++ b/services/gcp_integration/src/v2/models/GCPSTSServiceAccountAttributes.ts @@ -39,6 +39,11 @@ export class GCPSTSServiceAccountAttributes { * When enabled, Datadog collects metrics where location is explicitly stated as "global" or where location information cannot be deduced from GCP labels. */ "isGlobalLocationEnabled"?: boolean; + /** + * When enabled, Datadog scans for organization and folder-level resources + * under the organization the service account belongs to. + */ + "isOrgFolderResourceCollectionEnabled"?: boolean; /** * When enabled, Datadog applies the `X-Goog-User-Project` header, attributing Google Cloud billing and quota usage to the project being monitored rather than the default service account project. */ @@ -64,7 +69,7 @@ export class GCPSTSServiceAccountAttributes { */ "regionFilterConfigs"?: Array; /** - * When enabled, Datadog scans for all resources in your GCP environment. + * When enabled, Datadog scans for all project-level resources in your GCP environment. */ "resourceCollectionEnabled"?: boolean; /** @@ -110,6 +115,10 @@ export class GCPSTSServiceAccountAttributes { baseName: "is_global_location_enabled", type: "boolean", }, + isOrgFolderResourceCollectionEnabled: { + baseName: "is_org_folder_resource_collection_enabled", + type: "boolean", + }, isPerProjectQuotaEnabled: { baseName: "is_per_project_quota_enabled", type: "boolean",