diff --git a/mmv1/products/chronicle/DataAccessScope.yaml b/mmv1/products/chronicle/DataAccessScope.yaml new file mode 100644 index 000000000000..8d040a95e23d --- /dev/null +++ b/mmv1/products/chronicle/DataAccessScope.yaml @@ -0,0 +1,230 @@ +# Copyright 2024 Google Inc. +# 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. + +--- +name: DataAccessScope +description: A DataAccessScope is a boolean expression of data access labels used to restrict access to data for users. +min_version: 'beta' +references: + guides: + 'Introduction to data RBAC': 'https://cloud.google.com/chronicle/docs/onboard/onboard-datarbac' + api: 'https://cloud.google.com/chronicle/docs/reference/rest/v1alpha/projects.locations.instances.dataAccessScopes' +base_url: projects/{{project}}/locations/{{location}}/instances/{{instance}}/dataAccessScopes +self_link: projects/{{project}}/locations/{{location}}/instances/{{instance}}/dataAccessScopes/{{data_access_scope_id}} +create_url: projects/{{project}}/locations/{{location}}/instances/{{instance}}/dataAccessScopes?dataAccessScopeId={{data_access_scope_id}} +id_format: projects/{{project}}/locations/{{location}}/instances/{{instance}}/dataAccessScopes/{{data_access_scope_id}} +import_format: +- projects/{{project}}/locations/{{location}}/instances/{{instance}}/dataAccessScopes/{{data_access_scope_id}} +update_verb: PATCH +update_mask: true + +examples: +- name: 'chronicle_dataaccessscope_with_logtype' + primary_resource_id: 'example' + min_version: 'beta' + vars: + name: scope-with-logtype + description: scope-description + test_env_vars: + chronicle_id: 'CHRONICLE_ID' +- name: 'chronicle_dataaccessscope_with_dataaccesslabel' + primary_resource_id: 'example' + min_version: 'beta' + vars: + name: scope-with-dataaccesslabel + description: scope-description + data_access_label_id: label-name + test_env_vars: + chronicle_id: 'CHRONICLE_ID' +- name: 'chronicle_dataaccessscope_with_asset_namespace' + primary_resource_id: 'example' + min_version: 'beta' + vars: + name: scope-with-asset-namespace + description: scope-description + test_env_vars: + chronicle_id: 'CHRONICLE_ID' +- name: 'chronicle_dataaccessscope_with_ingestion_label' + primary_resource_id: 'example' + min_version: 'beta' + vars: + name: scope-with-ingestion-label + description: scope-description + test_env_vars: + chronicle_id: 'CHRONICLE_ID' +- name: 'chronicle_dataaccessscope_with_denied_labels' + primary_resource_id: 'example' + min_version: 'beta' + vars: + name: scope-with-denied-labels + description: scope-description + data_access_label_id: label-name + test_env_vars: + chronicle_id: 'CHRONICLE_ID' + + +parameters: +- name: location + type: String + description: Resource ID segment making up resource `name`. It identifies the resource within its parent collection as described in https://google.aip.dev/122. + immutable: true + url_param_only: true + required: true +- name: instance + type: String + description: Resource ID segment making up resource `name`. It identifies the resource within its parent collection as described in https://google.aip.dev/122. + immutable: true + url_param_only: true + required: true +- name: dataAccessScopeId + type: String + description: |- + Required. The user provided scope id which will become the last part of the name + of the scope resource. + Needs to be compliant with https://google.aip.dev/122 + immutable: true + url_param_only: true + required: true +properties: +- name: deniedDataAccessLabels + type: Array + description: |- + Optional. The denied labels for the scope. + The logical operator for evaluation of the denied labels is AND. + E.g.: A customer with scope with denied labels A and B won't be able + to see data labeled with A and data labeled with B + and data with labels A and B. + item_type: + type: NestedObject + properties: + - name: displayName + type: String + description: |- + Output only. The display name of the label. + Data access label and log types's name + will match the display name of the resource. + The asset namespace will match the namespace itself. + The ingestion key value pair will match the key of the tuple. + output: true + - name: dataAccessLabel + type: String + description: The name of the data access label. + - name: logType + type: String + description: The name of the log type. + - name: assetNamespace + type: String + description: |- + The asset namespace configured in the forwarder + of the customer's events. + - name: ingestionLabel + type: NestedObject + description: Representation of an ingestion label type. + properties: + - name: ingestionLabelKey + type: String + description: Required. The key of the ingestion label. Always required. + required: true + - name: ingestionLabelValue + type: String + description: |- + Optional. The value of the ingestion label. Optional. An object + with no provided value and some key provided would match + against the given key and ANY value. +- name: displayName + type: String + description: Output only. The name to be used for display to customers of the data access scope. + output: true +- name: createTime + type: String + description: Output only. The time at which the data access scope was created. + output: true +- name: author + type: String + description: Output only. The user who created the data access scope. + output: true +- name: lastEditor + type: String + description: Output only. The user who last updated the data access scope. + output: true +- name: description + type: String + description: Optional. A description of the data access scope for a human reader. +- name: allowAll + type: Boolean + description: |- + Optional. Whether or not the scope allows all labels, allow_all and + allowed_data_access_labels are mutually exclusive and one of them must be + present. denied_data_access_labels can still be used along with allow_all. + When combined with denied_data_access_labels, access will be granted to all + data that doesn't have labels mentioned in denied_data_access_labels. E.g.: + A customer with scope with denied labels A and B and allow_all will be able + to see all data except data labeled with A and data labeled with B and data + with labels A and B. +- name: name + type: String + description: |- + Required. The unique full name of the data access scope. + The name should comply with https://google.aip.dev/122 standards. + required: true + default_from_api: true +- name: allowedDataAccessLabels + type: Array + description: |- + Required. The allowed labels for the scope. There has to be at + least one label allowed for the scope to be valid. + The logical operator for evaluation of the allowed labels is OR. + Either allow_all or allowed_data_access_labels needs to be provided. + E.g.: A customer with scope with allowed labels A and B will be able + to see data with labeled with A or B or (A and B). + item_type: + type: NestedObject + properties: + - name: dataAccessLabel + type: String + description: The name of the data access label. + - name: logType + type: String + description: The name of the log type. + - name: assetNamespace + type: String + description: |- + The asset namespace configured in the forwarder + of the customer's events. + - name: ingestionLabel + type: NestedObject + description: Representation of an ingestion label type. + properties: + - name: ingestionLabelKey + type: String + description: Required. The key of the ingestion label. Always required. + required: true + - name: ingestionLabelValue + type: String + description: |- + Optional. The value of the ingestion label. Optional. An object + with no provided value and some key provided would match + against the given key and ANY value. + - name: displayName + type: String + description: |- + Output only. The display name of the label. + Data access label and log types's name + will match the display name of the resource. + The asset namespace will match the namespace itself. + The ingestion key value pair will match the key of the tuple. + output: true +- name: updateTime + type: String + description: Output only. The time at which the data access scope was last updated. + output: true diff --git a/mmv1/products/chronicle/product.yaml b/mmv1/products/chronicle/product.yaml new file mode 100644 index 000000000000..5802b9c2c749 --- /dev/null +++ b/mmv1/products/chronicle/product.yaml @@ -0,0 +1,22 @@ +# Copyright 2024 Google Inc. +# 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. + +--- +name: Chronicle +display_name: Chronicle +scopes: +- https://www.googleapis.com/auth/cloud-platform +versions: +- base_url: https://{{location}}-chronicle.googleapis.com/v1beta/ + name: beta +caibaseurl: "" diff --git a/mmv1/templates/terraform/examples/chronicle_dataaccessscope_with_asset_namespace.tf.tmpl b/mmv1/templates/terraform/examples/chronicle_dataaccessscope_with_asset_namespace.tf.tmpl new file mode 100644 index 000000000000..89692cd83b96 --- /dev/null +++ b/mmv1/templates/terraform/examples/chronicle_dataaccessscope_with_asset_namespace.tf.tmpl @@ -0,0 +1,15 @@ +provider "google-beta" { + user_project_override = true +} + +resource "google_chronicle_data_access_scope" "{{$.PrimaryResourceId}}" { + provider = "google-beta" + location = "us" + instance = "{{index $.TestEnvVars "chronicle_id"}}" + data_access_scope_id = "{{index $.Vars "name"}}" + description = "{{index $.Vars "description"}}" + allowed_data_access_labels { + asset_namespace = "my-namespace" + } +} + diff --git a/mmv1/templates/terraform/examples/chronicle_dataaccessscope_with_dataaccesslabel.tf.tmpl b/mmv1/templates/terraform/examples/chronicle_dataaccessscope_with_dataaccesslabel.tf.tmpl new file mode 100644 index 000000000000..89c1082d4efe --- /dev/null +++ b/mmv1/templates/terraform/examples/chronicle_dataaccessscope_with_dataaccesslabel.tf.tmpl @@ -0,0 +1,25 @@ +provider "google-beta" { + user_project_override = true +} + +resource "google_chronicle_data_access_label" "custom_data_access_label" { + provider = "google-beta" + location = "us" + instance = "{{index $.TestEnvVars "chronicle_id"}}" + data_access_label_id = "{{index $.Vars "data_access_label_id"}}" + udm_query = "principal.hostname=\"google.com\"" +} + +resource "google_chronicle_data_access_scope" "{{$.PrimaryResourceId}}" { + provider = "google-beta" + location = "us" + instance = "{{index $.TestEnvVars "chronicle_id"}}" + data_access_scope_id = "{{index $.Vars "name"}}" + description = "{{index $.Vars "description"}}" + allowed_data_access_labels { + log_type = "GCP_CLOUDAUDIT" + } + allowed_data_access_labels { + data_access_label = resource.google_chronicle_data_access_label.custom_data_access_label.data_access_label_id + } +} diff --git a/mmv1/templates/terraform/examples/chronicle_dataaccessscope_with_denied_labels.tf.tmpl b/mmv1/templates/terraform/examples/chronicle_dataaccessscope_with_denied_labels.tf.tmpl new file mode 100644 index 000000000000..31e366daec7f --- /dev/null +++ b/mmv1/templates/terraform/examples/chronicle_dataaccessscope_with_denied_labels.tf.tmpl @@ -0,0 +1,38 @@ +provider "google-beta" { + user_project_override = true +} + +resource "google_chronicle_data_access_label" "custom_data_access_label" { + provider = "google-beta" + location = "us" + instance = "{{index $.TestEnvVars "chronicle_id"}}" + data_access_label_id = "{{index $.Vars "data_access_label_id"}}" + udm_query = "principal.hostname=\"google.com\"" +} + +resource "google_chronicle_data_access_scope" "{{$.PrimaryResourceId}}" { + provider = "google-beta" + location = "us" + instance = "{{index $.TestEnvVars "chronicle_id"}}" + data_access_scope_id = "{{index $.Vars "name"}}" + description = "{{index $.Vars "description"}}" + allow_all = false + allowed_data_access_labels { + log_type = "GITHUB" + } + denied_data_access_labels { + log_type = "GCP_CLOUDAUDIT" + } + denied_data_access_labels { + data_access_label = resource.google_chronicle_data_access_label.custom_data_access_label.data_access_label_id + } + denied_data_access_labels { + ingestion_label { + ingestion_label_key = "ingestion_key" + ingestion_label_value = "ingestion_value" + } + } + denied_data_access_labels { + asset_namespace = "my-namespace" + } +} diff --git a/mmv1/templates/terraform/examples/chronicle_dataaccessscope_with_ingestion_label.tf.tmpl b/mmv1/templates/terraform/examples/chronicle_dataaccessscope_with_ingestion_label.tf.tmpl new file mode 100644 index 000000000000..f8976ab3e7c0 --- /dev/null +++ b/mmv1/templates/terraform/examples/chronicle_dataaccessscope_with_ingestion_label.tf.tmpl @@ -0,0 +1,18 @@ +provider "google-beta" { + user_project_override = true +} + +resource "google_chronicle_data_access_scope" "{{$.PrimaryResourceId}}" { + provider = "google-beta" + location = "us" + instance = "{{index $.TestEnvVars "chronicle_id"}}" + data_access_scope_id = "{{index $.Vars "name"}}" + description = "{{index $.Vars "description"}}" + allowed_data_access_labels { + ingestion_label { + ingestion_label_key = "ingestion_key" + ingestion_label_value = "ingestion_value" + } + } +} + diff --git a/mmv1/templates/terraform/examples/chronicle_dataaccessscope_with_logtype.tf.tmpl b/mmv1/templates/terraform/examples/chronicle_dataaccessscope_with_logtype.tf.tmpl new file mode 100644 index 000000000000..c2cdd8e594dc --- /dev/null +++ b/mmv1/templates/terraform/examples/chronicle_dataaccessscope_with_logtype.tf.tmpl @@ -0,0 +1,17 @@ +provider "google-beta" { + user_project_override = true +} + +resource "google_chronicle_data_access_scope" "{{$.PrimaryResourceId}}" { + provider = "google-beta" + location = "us" + instance = "{{index $.TestEnvVars "chronicle_id"}}" + data_access_scope_id = "{{index $.Vars "name"}}" + description = "{{index $.Vars "description"}}" + allowed_data_access_labels { + log_type = "GCP_CLOUDAUDIT" + } + allowed_data_access_labels { + log_type = "GITHUB" + } +} diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt index be44dcb96987..24abf96b5b4f 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt @@ -141,6 +141,11 @@ var ServicesListBeta = mapOf( "displayName" to "Certificatemanager", "path" to "./google-beta/services/certificatemanager" ), + "chronicle" to mapOf( + "name" to "chronicle", + "displayName" to "Chronicle", + "path" to "./google-beta/services/chronicle" + ), "cloudasset" to mapOf( "name" to "cloudasset", "displayName" to "Cloudasset", diff --git a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt index 817c79f96f11..2c7b8722ff74 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt @@ -141,6 +141,11 @@ var ServicesListGa = mapOf( "displayName" to "Certificatemanager", "path" to "./google/services/certificatemanager" ), + "chronicle" to mapOf( + "name" to "chronicle", + "displayName" to "Chronicle", + "path" to "./google-beta/services/chronicle" + ), "cloudasset" to mapOf( "name" to "cloudasset", "displayName" to "Cloudasset", diff --git a/mmv1/third_party/terraform/services/chronicle/resource_chronicle_data_access_scope_test.go.tmpl b/mmv1/third_party/terraform/services/chronicle/resource_chronicle_data_access_scope_test.go.tmpl new file mode 100644 index 000000000000..ef64883e8425 --- /dev/null +++ b/mmv1/third_party/terraform/services/chronicle/resource_chronicle_data_access_scope_test.go.tmpl @@ -0,0 +1,133 @@ +package chronicle_test + +{{- if ne $.TargetVersionName "ga" }} + +import ( + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccChronicleDataAccessScope_chronicleDataaccessscopeBasicExample_update(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "chronicle_id": envvar.GetTestChronicleInstanceIdFromEnv(t), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderBetaFactories(t), + CheckDestroy: testAccCheckChronicleDataAccessScopeDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccChronicleDataAccessScope_chronicleDataaccessscopeBasicExample_full(context), + }, + { + ResourceName: "google_chronicle_data_access_scope.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"data_access_scope_id", "instance", "location"}, + }, + + { + Config: testAccChronicleDataAccessScope_chronicleDataaccessscopeBasicExample_update(context), + }, + { + ResourceName: "google_chronicle_data_access_scope.example", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"data_access_scope_id", "instance", "location"}, + }, + }, + }) +} + +func testAccChronicleDataAccessScope_chronicleDataaccessscopeBasicExample_full(context map[string]interface{}) string { + return acctest.Nprintf(` +provider "google-beta" { + user_project_override = true +} + +resource "google_chronicle_data_access_label" "custom_data_access_label" { + provider = "google-beta" + location = "us" + instance = "%{chronicle_id}" + data_access_label_id = "tf-test-label-name%{random_suffix}" + udm_query = "principal.hostname=\"google.com\"" +} + +resource "google_chronicle_data_access_scope" "example" { + provider = "google-beta" + location = "us" + instance = "%{chronicle_id}" + data_access_scope_id = "tf-test-scope-with-denied-labels%{random_suffix}" + description = "tf-test-scope-description%{random_suffix}" + allow_all = false + allowed_data_access_labels { + log_type = "GITHUB" + } + denied_data_access_labels { + log_type = "GCP_CLOUDAUDIT" + } + denied_data_access_labels { + data_access_label = resource.google_chronicle_data_access_label.custom_data_access_label.data_access_label_id + } + denied_data_access_labels { + ingestion_label { + ingestion_label_key = "ingestion_key" + ingestion_label_value = "ingestion_value" + } + } + denied_data_access_labels { + asset_namespace = "my-namespace" + } +} +`, context) +} + +func testAccChronicleDataAccessScope_chronicleDataaccessscopeBasicExample_update(context map[string]interface{}) string { + return acctest.Nprintf(` +provider "google-beta" { + user_project_override = true +} + +resource "google_chronicle_data_access_label" "custom_data_access_label" { + provider = "google-beta" + location = "us" + instance = "%{chronicle_id}" + data_access_label_id = "tf-test-label-name%{random_suffix}" + udm_query = "principal.hostname=\"google-updated.com\"" +} + +resource "google_chronicle_data_access_scope" "example" { + provider = "google-beta" + location = "us" + instance = "%{chronicle_id}" + data_access_scope_id = "tf-test-scope-with-denied-labels%{random_suffix}" + description = "tf-test-scope-description-updated%{random_suffix}" + allow_all = true + denied_data_access_labels { + log_type = "GITHUB" + } + denied_data_access_labels { + data_access_label = resource.google_chronicle_data_access_label.custom_data_access_label.data_access_label_id + } + denied_data_access_labels { + ingestion_label { + ingestion_label_key = "ingestion_key-updated" + ingestion_label_value = "ingestion_value-updated" + } + } + denied_data_access_labels { + asset_namespace = "my-namespace-updated" + } +} +`, context) +} + +{{- end }}