diff --git a/mmv1/products/securitycenterv2/OrganizationSource.yaml b/mmv1/products/securitycenterv2/OrganizationSource.yaml new file mode 100644 index 000000000000..18640c3c0db2 --- /dev/null +++ b/mmv1/products/securitycenterv2/OrganizationSource.yaml @@ -0,0 +1,83 @@ +# 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. + +--- !ruby/object:Api::Resource +name: 'OrganizationSource' +base_url: organizations/{{organization}}/sources +self_link: '{{name}}' +update_verb: :PATCH +update_mask: true +description: | + A Cloud Security Command Center's (Cloud SCC) finding source. A finding + source is an entity or a mechanism that can produce a finding. A source is + like a container of findings that come from the same scanner, logger, + monitor, etc. +references: !ruby/object:Api::Resource::ReferenceLinks + guides: + 'Official Documentation': 'https://cloud.google.com/security-command-center/docs' + api: 'https://cloud.google.com/security-command-center/docs/reference/rest/v2/organizations.sources' +iam_policy: !ruby/object:Api::Resource::IamPolicy + method_name_separator: ':' + fetch_iam_policy_verb: :POST + parent_resource_attribute: 'source' + base_url: organizations/{{organization}}/sources/{{source}} + import_format: + ['organizations/{{organization}}/sources/{{source}}', '{{source}}'] +skip_delete: true +examples: + - !ruby/object:Provider::Terraform::Examples + name: + 'scc_source_basic' + # resource can't be destroyed, so checkdestroy fails unnecessarily + skip_test: true + primary_resource_id: 'custom_source' + vars: + source_display_name: 'My Source' + test_env_vars: + org_id: :ORG_ID +custom_code: !ruby/object:Provider::Terraform::CustomCode + custom_import: templates/terraform/custom_import/scc_source_self_link_as_name_set_organization.go.erb + post_create: templates/terraform/post_create/set_computed_name.erb +parameters: + - !ruby/object:Api::Type::String + name: organization + required: true + immutable: true + url_param_only: true + description: | + The organization whose Cloud Security Command Center the Source + lives in. +properties: + - !ruby/object:Api::Type::String + name: name + output: true + description: | + The resource name of this source, in the format + `organizations/{{organization}}/sources/{{source}}`. + - !ruby/object:Api::Type::String + name: description + description: | + The description of the source (max of 1024 characters). + validation: !ruby/object:Provider::Terraform::Validation + function: 'validation.StringLenBetween(0, 1024)' + - !ruby/object:Api::Type::String + name: displayName + required: true + description: | + The source’s display name. A source’s display name must be unique + amongst its siblings, for example, two sources with the same parent + can't share the same display name. The display name must start and end + with a letter or digit, may contain letters, digits, spaces, hyphens, + and underscores, and can be no longer than 32 characters. + validation: !ruby/object:Provider::Terraform::Validation + regex: '[\p{L}\p{N}]({\p{L}\p{N}_- ]{0,30}[\p{L}\p{N}])?' diff --git a/mmv1/templates/terraform/examples/scc_v2_organization_source_basic.tf.erb b/mmv1/templates/terraform/examples/scc_v2_organization_source_basic.tf.erb new file mode 100644 index 000000000000..556dab9523a9 --- /dev/null +++ b/mmv1/templates/terraform/examples/scc_v2_organization_source_basic.tf.erb @@ -0,0 +1,5 @@ +resource "google_scc_v2_organization_source" "<%= ctx[:primary_resource_id] %>" { + display_name = "<%= ctx[:vars]['source_display_name'] %>" + organization = "<%= ctx[:test_env_vars]['org_id'] %>" + description = "My custom Cloud Security Command Center Finding Source" +} 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 910bb42678f5..ee60651e6d2b 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_beta.kt @@ -621,6 +621,11 @@ var ServicesListBeta = mapOf( "displayName" to "Securitycenter", "path" to "./google-beta/services/securitycenter" ), + "securitycenterv2" to mapOf( + "name" to "securitycenterv2", + "displayName" to "securitycenterv2", + "path" to "./google-beta/services/securitycenterv2" + ), "securitycentermanagement" to mapOf( "name" to "securitycentermanagement", "displayName" to "Securitycentermanagement", 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 90e903cd0702..b5fb09937ed4 100644 --- a/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt +++ b/mmv1/third_party/terraform/.teamcity/components/inputs/services_ga.kt @@ -616,6 +616,11 @@ var ServicesListGa = mapOf( "displayName" to "Securitycenter", "path" to "./google/services/securitycenter" ), + "securitycenterv2" to mapOf( + "name" to "securitycenterv2", + "displayName" to "securitycenterv2", + "path" to "./google-beta/services/securitycenterv2" + ), "securitycentermanagement" to mapOf( "name" to "securitycentermanagement", "displayName" to "Securitycentermanagement", diff --git a/mmv1/third_party/terraform/services/securitycenterv2/iam_scc_v2_organization_source_test.go b/mmv1/third_party/terraform/services/securitycenterv2/iam_scc_v2_organization_source_test.go new file mode 100644 index 000000000000..34fbde296651 --- /dev/null +++ b/mmv1/third_party/terraform/services/securitycenterv2/iam_scc_v2_organization_source_test.go @@ -0,0 +1,217 @@ +package securitycenterv2_test + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + "github.com/hashicorp/terraform-plugin-testing/terraform" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccSecurityCenterV2OrganizationSourceIamBinding(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/securitycenter.sourcesViewer", + "org_id": envvar.GetTestOrgFromEnv(t), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccSecurityCenterSourceIamBinding_basic(context), + }, + { + ResourceName: "google_scc_v2_organization_source_iam_binding.foo", + ImportStateIdFunc: func(state *terraform.State) (string, error) { + id := state.RootModule().Resources["google_scc_v2_organization_source.custom_source"].Primary.Attributes["id"] + return fmt.Sprintf("%s %s", + id, + context["role"], + ), nil + }, + ImportState: true, + ImportStateVerify: true, + }, + { + // Test Iam Binding update + Config: testAccSecurityCenterSourceIamBinding_update(context), + }, + { + ResourceName: "google_scc_v2_organization_source_iam_binding.foo", + ImportStateIdFunc: func(state *terraform.State) (string, error) { + id := state.RootModule().Resources["google_scc_v2_organization_source.custom_source"].Primary.Attributes["id"] + return fmt.Sprintf("%s %s", + id, + context["role"], + ), nil + }, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSecurityCenterV2OrganizationSourceIamMember(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/securitycenter.sourcesViewer", + "org_id": envvar.GetTestOrgFromEnv(t), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccSecurityCenterSourceIamMember_basic(context), + }, + { + ResourceName: "google_scc_v2_organization_source_iam_member.foo", + ImportStateIdFunc: func(state *terraform.State) (string, error) { + id := state.RootModule().Resources["google_scc_v2_organization_source.custom_source"].Primary.Attributes["id"] + return fmt.Sprintf("%s %s user:admin@hashicorptest.com", + id, + context["role"], + ), nil + }, + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccSecurityCenterV2OrganizationSourceIamPolicy(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/securitycenter.sourcesViewer", + "org_id": envvar.GetTestOrgFromEnv(t), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccSecurityCenterSourceIamPolicy_basic(context), + }, + { + ResourceName: "google_scc_v2_organization_source_iam_policy.foo", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccSecurityCenterSourceIamPolicy_emptyBinding(context), + }, + { + ResourceName: "google_scc_v2_organization_source_iam_policy.foo", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccSecurityCenterSourceIamMember_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_scc_v2_organization_source" "custom_source" { + display_name = "tf-test-source%{random_suffix}" + organization = "%{org_id}" + description = "My custom Cloud Security Command Center Finding Source" +} + +resource "google_scc_v2_organization_source_iam_member" "foo" { + source = google_scc_v2_organization_source.custom_source.id + organization = "%{org_id}" + role = "%{role}" + member = "user:admin@hashicorptest.com" +} +`, context) +} + +func testAccSecurityCenterSourceIamPolicy_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_scc_v2_organization_source" "custom_source" { + display_name = "tf-test-source%{random_suffix}" + organization = "%{org_id}" + description = "My custom Cloud Security Command Center Finding Source" +} + +data "google_iam_policy" "foo" { + binding { + role = "%{role}" + members = ["user:admin@hashicorptest.com"] + } +} + +resource "google_scc_v2_organization_source_iam_policy" "foo" { + source = google_scc_v2_organization_source.custom_source.id + organization = "%{org_id}" + policy_data = data.google_iam_policy.foo.policy_data +} +`, context) +} + +func testAccSecurityCenterSourceIamPolicy_emptyBinding(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_scc_v2_organization_source" "custom_source" { + display_name = "tf-test-source%{random_suffix}" + organization = "%{org_id}" + description = "My custom Cloud Security Command Center Finding Source" +} + +data "google_iam_policy" "foo" { +} + +resource "google_scc_v2_organization_source_iam_policy" "foo" { + source = google_scc_v2_organization_source.custom_source.id + organization = "%{org_id}" + policy_data = data.google_iam_policy.foo.policy_data +} +`, context) +} + +func testAccSecurityCenterSourceIamBinding_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_scc_v2_organization_source" "custom_source" { + display_name = "tf-test-source%{random_suffix}" + organization = "%{org_id}" + description = "My custom Cloud Security Command Center Finding Source" +} + +resource "google_scc_v2_organization_source_iam_binding" "foo" { + source = google_scc_v2_organization_source.custom_source.id + organization = "%{org_id}" + role = "%{role}" + members = ["user:admin@hashicorptest.com"] +} +`, context) +} + +func testAccSecurityCenterSourceIamBinding_update(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_scc_v2_organization_source" "custom_source" { + display_name = "tf-test-source%{random_suffix}" + organization = "%{org_id}" + description = "My custom Cloud Security Command Center Finding Source" +} + +resource "google_scc_v2_organization_source_iam_binding" "foo" { + source = google_scc_v2_organization_source.custom_source.id + organization = "%{org_id}" + role = "%{role}" + members = ["user:admin@hashicorptest.com", "user:gterraformtest1@gmail.com"] +} +`, context) +} diff --git a/mmv1/third_party/terraform/services/securitycenterv2/resource_scc_v2_organization_source_test.go b/mmv1/third_party/terraform/services/securitycenterv2/resource_scc_v2_organization_source_test.go new file mode 100644 index 000000000000..35cdeacaebfc --- /dev/null +++ b/mmv1/third_party/terraform/services/securitycenterv2/resource_scc_v2_organization_source_test.go @@ -0,0 +1,50 @@ +package securitycenterv2_test + +import ( + "fmt" + "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 TestAccSecurityCenterV2OrganizationSource_basic(t *testing.T) { + t.Parallel() + + orgId := envvar.GetTestOrgFromEnv(t) + suffix := acctest.RandString(t, 10) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccSecurityCenterSource_sccSourceBasicExample(orgId, suffix, "My description"), + }, + { + ResourceName: "google_scc_v2_organization_source.custom_source", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccSecurityCenterSource_sccSourceBasicExample(orgId, suffix, ""), + }, + { + ResourceName: "google_scc_v2_organization_source.custom_source", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccSecurityCenterSource_sccSourceBasicExample(orgId, suffix, description string) string { + return fmt.Sprintf(` +resource "google_scc_v2_organization_source" "custom_source" { + display_name = "TFSrc %s" + organization = "%s" + description = "%s" +} +`, suffix, orgId, description) +}