From c9b9c56fb9fb0402b15476a9caba3e1570486943 Mon Sep 17 00:00:00 2001 From: Hao Nan Li Date: Tue, 30 May 2023 10:42:21 -0700 Subject: [PATCH 01/10] Initial commit for ACM policies fine grained resources --- .../ServicePerimeterEgressPolicy.yaml | 143 +++++++++++++++ .../ServicePerimeterIngressPolicy.yaml | 167 ++++++++++++++++++ ...ger_service_perimeter_egress_policy.go.erb | 9 +- ...er_service_perimeter_ingress_policy.go.erb | 9 +- ..._context_manager_access_policy_test.go.erb | 30 ++-- ...er_service_perimeter_egress_policy_test.go | 136 ++++++++++++++ ...r_service_perimeter_ingress_policy_test.go | 154 ++++++++++++++++ 7 files changed, 621 insertions(+), 27 deletions(-) create mode 100644 mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml create mode 100644 mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml create mode 100644 mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go create mode 100644 mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml new file mode 100644 index 000000000000..951ae40f9a89 --- /dev/null +++ b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml @@ -0,0 +1,143 @@ +# Copyright 2018 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: 'ServicePerimeterEgressPolicy' +create_url: '{{perimeter}}' +base_url: '' +self_link: '{{perimeter}}' +create_verb: :PATCH +delete_verb: :PATCH +update_mask: true +identity: + - egressPolicy +nested_query: !ruby/object:Api::Resource::NestedQuery + modify_by_patch: true + is_list_of_ids: true + keys: + - status + - egressPolicies +references: !ruby/object:Api::Resource::ReferenceLinks + api: 'https://cloud.google.com/access-context-manager/docs/reference/rest/v1/accessPolicies.servicePerimeters#egresspolicy' +description: | + EgressPolicies match requests based on egressFrom and egressTo stanzas. + For an EgressPolicy to match, both egressFrom and egressTo stanzas must be matched. + If an EgressPolicy matches a request, the request is allowed to span the ServicePerimeter + boundary. For example, an EgressPolicy can be used to allow VMs on networks + within the ServicePerimeter to access a defined set of projects outside the + perimeter in certain contexts (e.g. to read data from a Cloud Storage bucket + or query against a BigQuery dataset). +autogen_async: true +exclude_validator: true +# Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter/IngressPolicy +skip_sweeper: true +id_format: '{{perimeter}}' +import_format: ['{{perimeter}}'] +custom_code: !ruby/object:Provider::Terraform::CustomCode + custom_import: templates/terraform/custom_import/access_context_manager_service_perimeter_ingress_policy.go.erb +parameters: + - !ruby/object:Api::Type::ResourceRef + name: 'perimeter' + resource: 'ServicePerimeter' + imports: 'name' + description: | + The name of the Service Perimeter to add this resource to. + required: true + immutable: true + url_param_only: true +properties: + - !ruby/object:Api::Type::NestedObject + name: 'egressPolicy' + description: | + List of EgressPolicies to apply to the perimeter. A perimeter may + have multiple EgressPolicies, each of which is evaluated separately. + Access is granted if any EgressPolicy grants it. Must be empty for + a perimeter bridge. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'egressFrom' + description: | + Defines conditions on the source of a request causing this `EgressPolicy` to apply. + properties: + - !ruby/object:Api::Type::Enum + name: 'identityType' + description: | + Specifies the type of identities that are allowed access to outside the + perimeter. If left unspecified, then members of `identities` field will + be allowed access. + values: + - :IDENTITY_TYPE_UNSPECIFIED + - :ANY_IDENTITY + - :ANY_USER_ACCOUNT + - :ANY_SERVICE_ACCOUNT + - !ruby/object:Api::Type::Array + name: 'identities' + description: | + A list of identities that are allowed access through this `EgressPolicy`. + Should be in the format of email address. The email address should + represent individual user or service account only. + item_type: Api::Type::String + - !ruby/object:Api::Type::NestedObject + name: 'egressTo' + description: | + Defines the conditions on the `ApiOperation` and destination resources that + cause this `EgressPolicy` to apply. + properties: + - !ruby/object:Api::Type::Array + name: 'resources' + item_type: Api::Type::String + description: | + A list of resources, currently only projects in the form + `projects/`, that match this to stanza. A request matches + if it contains a resource in this list. If * is specified for resources, + then this `EgressTo` rule will authorize access to all resources outside + the perimeter. + - !ruby/object:Api::Type::Array + name: 'externalResources' + item_type: Api::Type::String + description: | + A list of external resources that are allowed to be accessed. A request + matches if it contains an external resource in this list (Example: + s3://bucket/path). Currently '*' is not allowed. + - !ruby/object:Api::Type::Array + name: 'operations' + description: | + A list of `ApiOperations` that this egress rule applies to. A request matches + if it contains an operation/service in this list. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'serviceName' + description: | + The name of the API whose methods or permissions the `IngressPolicy` or + `EgressPolicy` want to allow. A single `ApiOperation` with serviceName + field set to `*` will allow all methods AND permissions for all services. + - !ruby/object:Api::Type::Array + name: 'methodSelectors' + description: | + API methods or permissions to allow. Method or permission must belong + to the service specified by `serviceName` field. A single MethodSelector + entry with `*` specified for the `method` field will allow all methods + AND permissions for the service specified in `serviceName`. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'method' + description: | + Value for `method` should be a valid method name for the corresponding + `serviceName` in `ApiOperation`. If `*` used as value for method, + then ALL methods and permissions are allowed. + - !ruby/object:Api::Type::String + name: 'permission' + description: | + Value for permission should be a valid Cloud IAM permission for the + corresponding `serviceName` in `ApiOperation`. \ No newline at end of file diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml new file mode 100644 index 000000000000..5f888f603f0b --- /dev/null +++ b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml @@ -0,0 +1,167 @@ +# Copyright 2018 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: 'ServicePerimeterIngressPolicy' +create_url: '{{perimeter}}' +base_url: '' +self_link: '{{perimeter}}' +create_verb: :PATCH +delete_verb: :PATCH +update_mask: true +identity: + - ingressPolicy +nested_query: !ruby/object:Api::Resource::NestedQuery + modify_by_patch: true + is_list_of_ids: true + keys: + - status + - ingressPolicies +references: !ruby/object:Api::Resource::ReferenceLinks + api: 'https://cloud.google.com/access-context-manager/docs/reference/rest/v1/accessPolicies.servicePerimeters#ingresspolicy' +description: | + IngressPolicies match requests based on ingressFrom and ingressTo stanzas. For an ingress policy to match, + both the ingressFrom and ingressTo stanzas must be matched. If an IngressPolicy matches a request, + the request is allowed through the perimeter boundary from outside the perimeter. + For example, access from the internet can be allowed either based on an AccessLevel or, + for traffic hosted on Google Cloud, the project of the source network. + For access from private networks, using the project of the hosting network is required. + Individual ingress policies can be limited by restricting which services and/ + or actions they match using the ingressTo field. +autogen_async: true +exclude_validator: true +# Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter/IngressPolicy +skip_sweeper: true +id_format: '{{perimeter}}' +import_format: ['{{perimeter}}'] +custom_code: !ruby/object:Provider::Terraform::CustomCode + custom_import: templates/terraform/custom_import/access_context_manager_service_perimeter_ingress_policy.go.erb +parameters: + - !ruby/object:Api::Type::ResourceRef + name: 'perimeter' + resource: 'ServicePerimeter' + imports: 'name' + description: | + The name of the Service Perimeter to add this resource to. + required: true + immutable: true + url_param_only: true +properties: + - !ruby/object:Api::Type::NestedObject + name: 'ingressPolicy' + description: | + List of `IngressPolicies` to apply to the perimeter. A perimeter may + have multiple `IngressPolicies`, each of which is evaluated + separately. Access is granted if any `Ingress Policy` grants it. + Must be empty for a perimeter bridge. + properties: + - !ruby/object:Api::Type::NestedObject + name: 'ingressFrom' + description: | + Defines the conditions on the source of a request causing this `IngressPolicy` + to apply. + properties: + - !ruby/object:Api::Type::Enum + name: 'identityType' + description: | + Specifies the type of identities that are allowed access from outside the + perimeter. If left unspecified, then members of `identities` field will be + allowed access. + values: + - :IDENTITY_TYPE_UNSPECIFIED + - :ANY_IDENTITY + - :ANY_USER_ACCOUNT + - :ANY_SERVICE_ACCOUNT + - !ruby/object:Api::Type::Array + name: 'identities' + item_type: Api::Type::String + description: | + A list of identities that are allowed access through this ingress policy. + Should be in the format of email address. The email address should represent + individual user or service account only. + - !ruby/object:Api::Type::Array + name: 'sources' + description: | + Sources that this `IngressPolicy` authorizes access from. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'accessLevel' + description: | + An `AccessLevel` resource name that allow resources within the + `ServicePerimeters` to be accessed from the internet. `AccessLevels` listed + must be in the same policy as this `ServicePerimeter`. Referencing a nonexistent + `AccessLevel` will cause an error. If no `AccessLevel` names are listed, + resources within the perimeter can only be accessed via Google Cloud calls + with request origins within the perimeter. + Example `accessPolicies/MY_POLICY/accessLevels/MY_LEVEL.` + If * is specified, then all IngressSources will be allowed. + - !ruby/object:Api::Type::String + name: 'resource' + description: | + A Google Cloud resource that is allowed to ingress the perimeter. + Requests from these resources will be allowed to access perimeter data. + Currently only projects are allowed. Format `projects/{project_number}` + The project may be in any Google Cloud organization, not just the + organization that the perimeter is defined in. `*` is not allowed, the case + of allowing all Google Cloud resources only is not supported. + - !ruby/object:Api::Type::NestedObject + name: 'ingressTo' + description: | + Defines the conditions on the `ApiOperation` and request destination that cause + this `IngressPolicy` to apply. + properties: + - !ruby/object:Api::Type::Array + name: 'resources' + item_type: Api::Type::String + description: | + A list of resources, currently only projects in the form + `projects/`, protected by this `ServicePerimeter` + that are allowed to be accessed by sources defined in the + corresponding `IngressFrom`. A request matches if it contains + a resource in this list. If `*` is specified for resources, + then this `IngressTo` rule will authorize access to all + resources inside the perimeter, provided that the request + also matches the `operations` field. + - !ruby/object:Api::Type::Array + name: 'operations' + description: | + A list of `ApiOperations` the sources specified in corresponding `IngressFrom` + are allowed to perform in this `ServicePerimeter`. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'serviceName' + description: | + The name of the API whose methods or permissions the `IngressPolicy` or + `EgressPolicy` want to allow. A single `ApiOperation` with `serviceName` + field set to `*` will allow all methods AND permissions for all services. + - !ruby/object:Api::Type::Array + name: 'methodSelectors' + description: | + API methods or permissions to allow. Method or permission must belong to + the service specified by serviceName field. A single `MethodSelector` entry + with `*` specified for the method field will allow all methods AND + permissions for the service specified in `serviceName`. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'method' + description: | + Value for method should be a valid method name for the corresponding + serviceName in `ApiOperation`. If `*` used as value for `method`, then + ALL methods and permissions are allowed. + - !ruby/object:Api::Type::String + name: 'permission' + description: | + Value for permission should be a valid Cloud IAM permission for the + corresponding `serviceName` in `ApiOperation`. \ No newline at end of file diff --git a/mmv1/templates/terraform/custom_import/access_context_manager_service_perimeter_egress_policy.go.erb b/mmv1/templates/terraform/custom_import/access_context_manager_service_perimeter_egress_policy.go.erb index b2b39af2a8b1..269d4812fbdd 100644 --- a/mmv1/templates/terraform/custom_import/access_context_manager_service_perimeter_egress_policy.go.erb +++ b/mmv1/templates/terraform/custom_import/access_context_manager_service_perimeter_egress_policy.go.erb @@ -15,15 +15,12 @@ config := meta.(*transport_tpg.Config) // current import_formats can't import fields with forward slashes in their value - parts, err := tpgresource.GetImportIdQualifiers([]string{"accessPolicies/(?P[^/]+)/servicePerimeters/(?P[^/]+)/(?P.+)"}, d, config, d.Id()) + parts, err := tpgresource.GetImportIdQualifiers([]string{"accessPolicies/(?P[^/]+)/servicePerimeters/(?P[^/]+)"}, d, config, d.Id()) if err != nil { return nil, err } - if err := d.Set("egress_policy_name", fmt.Sprintf("accessPolicies/%s/servicePerimeters/%s", parts["accessPolicy"], parts["perimeter"])); err != nil { - return nil, fmt.Errorf("Error setting egress_policy_name: %s", err) - } - if err := d.Set("resource", parts["resource"]); err != nil { - return nil, fmt.Errorf("Error setting resource: %s", err) + if err := d.Set("perimeter", fmt.Sprintf("accessPolicies/%s/servicePerimeters/%s", parts["accessPolicy"], parts["perimeter"])); err != nil { + return nil, fmt.Errorf("Error setting perimeter: %s", err) } return []*schema.ResourceData{d}, nil diff --git a/mmv1/templates/terraform/custom_import/access_context_manager_service_perimeter_ingress_policy.go.erb b/mmv1/templates/terraform/custom_import/access_context_manager_service_perimeter_ingress_policy.go.erb index e01799b4305a..269d4812fbdd 100644 --- a/mmv1/templates/terraform/custom_import/access_context_manager_service_perimeter_ingress_policy.go.erb +++ b/mmv1/templates/terraform/custom_import/access_context_manager_service_perimeter_ingress_policy.go.erb @@ -15,15 +15,12 @@ config := meta.(*transport_tpg.Config) // current import_formats can't import fields with forward slashes in their value - parts, err := tpgresource.GetImportIdQualifiers([]string{"accessPolicies/(?P[^/]+)/servicePerimeters/(?P[^/]+)/(?P.+)"}, d, config, d.Id()) + parts, err := tpgresource.GetImportIdQualifiers([]string{"accessPolicies/(?P[^/]+)/servicePerimeters/(?P[^/]+)"}, d, config, d.Id()) if err != nil { return nil, err } - if err := d.Set("ingress_policy_name", fmt.Sprintf("accessPolicies/%s/servicePerimeters/%s", parts["accessPolicy"], parts["perimeter"])); err != nil { - return nil, fmt.Errorf("Error setting ingress_policy_name: %s", err) - } - if err := d.Set("resource", parts["resource"]); err != nil { - return nil, fmt.Errorf("Error setting resource: %s", err) + if err := d.Set("perimeter", fmt.Sprintf("accessPolicies/%s/servicePerimeters/%s", parts["accessPolicy"], parts["perimeter"])); err != nil { + return nil, fmt.Errorf("Error setting perimeter: %s", err) } return []*schema.ResourceData{d}, nil diff --git a/mmv1/third_party/terraform/tests/resource_access_context_manager_access_policy_test.go.erb b/mmv1/third_party/terraform/tests/resource_access_context_manager_access_policy_test.go.erb index dcda4cefc190..6f846e77042d 100644 --- a/mmv1/third_party/terraform/tests/resource_access_context_manager_access_policy_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_access_context_manager_access_policy_test.go.erb @@ -92,21 +92,21 @@ func testSweepAccessContextManagerPolicies(region string) error { // can exist, they need to be run serially func TestAccAccessContextManager(t *testing.T) { testCases := map[string]func(t *testing.T){ - "access_policy": testAccAccessContextManagerAccessPolicy_basicTest, - "access_policy_scoped": testAccAccessContextManagerAccessPolicy_scopedTest, - "service_perimeter": testAccAccessContextManagerServicePerimeter_basicTest, - "service_perimeter_update": testAccAccessContextManagerServicePerimeter_updateTest, - "service_perimeter_resource": testAccAccessContextManagerServicePerimeterResource_basicTest, - "access_level": testAccAccessContextManagerAccessLevel_basicTest, - "access_level_full": testAccAccessContextManagerAccessLevel_fullTest, - "access_level_custom": testAccAccessContextManagerAccessLevel_customTest, - "access_levels": testAccAccessContextManagerAccessLevels_basicTest, - "access_level_condition": testAccAccessContextManagerAccessLevelCondition_basicTest, - "egress_policy": testAccAccessContextManagerEgressPolicy_basicTest, - "ingress_policy": testAccAccessContextManagerIngressPolicy_basicTest, - "service_perimeters": testAccAccessContextManagerServicePerimeters_basicTest, - "gcp_user_access_binding": testAccAccessContextManagerGcpUserAccessBinding_basicTest, - "authorized_orgs_desc": testAccAccessContextManagerAuthorizedOrgsDesc_basicTest, + "access_policy": testAccAccessContextManagerAccessPolicy_basicTest, + "access_policy_scoped": testAccAccessContextManagerAccessPolicy_scopedTest, + "service_perimeter": testAccAccessContextManagerServicePerimeter_basicTest, + "service_perimeter_update": testAccAccessContextManagerServicePerimeter_updateTest, + "service_perimeter_resource": testAccAccessContextManagerServicePerimeterResource_basicTest, + "access_level": testAccAccessContextManagerAccessLevel_basicTest, + "access_level_full": testAccAccessContextManagerAccessLevel_fullTest, + "access_level_custom": testAccAccessContextManagerAccessLevel_customTest, + "access_levels": testAccAccessContextManagerAccessLevels_basicTest, + "access_level_condition": testAccAccessContextManagerAccessLevelCondition_basicTest, + "service_perimeter_egress_policy": testAccAccessContextManagerServicePerimeterEgressPolicy_basicTest, + "service_perimeter_ingress_policy": testAccAccessContextManagerServicePerimeterIngressPolicy_basicTest, + "service_perimeters": testAccAccessContextManagerServicePerimeters_basicTest, + "gcp_user_access_binding": testAccAccessContextManagerGcpUserAccessBinding_basicTest, + "authorized_orgs_desc": testAccAccessContextManagerAuthorizedOrgsDesc_basicTest, } for name, tc := range testCases { diff --git a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go new file mode 100644 index 000000000000..f0e9391020bd --- /dev/null +++ b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go @@ -0,0 +1,136 @@ +package google + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +// Since each test here is acting on the same organization and only one AccessPolicy +// can exist, they need to be run serially. See AccessPolicy for the test runner. + +func testAccAccessContextManagerEgressPolicy_basicTest(t *testing.T) { + // Multiple fine-grained resources + acctest.SkipIfVcr(t) + org := acctest.GetTestOrgFromEnv(t) + projects := BootstrapServicePerimeterProjects(t, 1) + policyTitle := RandString(t, 10) + perimeterTitle := "perimeter" + + VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccAccessContextManagerEgressPolicy_basic(org, policyTitle, perimeterTitle, projects[0].ProjectNumber), + }, + { + ResourceName: "google_access_context_manager_egress_policy.test-access1", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAccessContextManagerEgressPolicy_destroy(org, policyTitle, perimeterTitle), + Check: testAccCheckAccessContextManagerEgressPolicyDestroyProducer(t), + }, + }, + }) +} + +func testAccCheckAccessContextManagerEgressPolicyDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "google_access_context_manager_service_perimeter_egress_policy" { + continue + } + + config := GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{AccessContextManagerBasePath}}{{perimeter}}") + if err != nil { + return err + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + RawURL: url, + UserAgent: config.UserAgent, + }) + if err != nil { + return err + } + + v, ok := res["status"] + if !ok || v == nil { + return nil + } + + res = v.(map[string]interface{}) + v, ok = res["egress_policies"] + if !ok || v == nil { + return nil + } + + resources := v.([]interface{}) + if len(resources) == 0 { + return nil + } + + return fmt.Errorf("expected 0 resources in perimeter, found %d: %v", len(resources), resources) + } + + return nil + } +} + +func testAccAccessContextManagerServicePerimeterEgressPolicy_basic(org, policyTitle, perimeterTitleName string) string { + return fmt.Sprintf(` +%s + +resource "google_access_context_manager_service_perimeter_egress_policy" "test-access1" { + perimeter = google_access_context_manager_service_perimeter.test-access.name + egress_policy { + egress_from { + identity_type = "ANY_USER_ACCOUNT" + } + egress_to { + operations { + service_name = "storage.googleapis.com" + method_selectors { + method = "*" + } + } + } + } +} + +`, testAccAccessContextManagerServicePerimeterEgressPolicy_destroy(org, policyTitle, perimeterTitleName)) +} + +func testAccAccessContextManagerServicePerimeterEgressPolicy_destroy(org, policyTitle, perimeterTitleName string) string { + return fmt.Sprintf(` +resource "google_access_context_manager_access_policy" "test-access" { + parent = "organizations/%s" + title = "%s" +} + +resource "google_access_context_manager_service_perimeter" "test-access" { + parent = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}" + name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/servicePerimeters/%s" + title = "%s" + status { + restricted_services = ["storage.googleapis.com"] + } + + lifecycle { + ignore_changes = [status[0].egress_policies] + } +} +`, org, policyTitle, perimeterTitleName, perimeterTitleName) +} diff --git a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go new file mode 100644 index 000000000000..ee9e422b6258 --- /dev/null +++ b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go @@ -0,0 +1,154 @@ +package google + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" +) + +// Since each test here is acting on the same organization and only one AccessPolicy +// can exist, they need to be run serially. See AccessPolicy for the test runner. + +func testAccAccessContextManagerIngressPolicy_basicTest(t *testing.T) { + // Multiple fine-grained resources + acctest.SkipIfVcr(t) + org := acctest.GetTestOrgFromEnv(t) + projects := BootstrapServicePerimeterProjects(t, 1) + policyTitle := RandString(t, 10) + perimeterTitle := "perimeter" + + VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccAccessContextManagerIngressPolicy_basic(org, policyTitle, perimeterTitle, projects[0].ProjectNumber), + }, + { + ResourceName: "google_access_context_manager_ingress_policy.test-access1", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAccessContextManagerIngressPolicy_destroy(org, policyTitle, perimeterTitle), + Check: testAccCheckAccessContextManagerIngressPolicyDestroyProducer(t), + }, + }, + }) +} + +func testAccCheckAccessContextManagerIngressPolicyDestroyProducer(t *testing.T) func(s *terraform.State) error { + return func(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "google_access_context_manager_service_perimeter_ingress_policy" { + continue + } + + config := GoogleProviderConfig(t) + + url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{AccessContextManagerBasePath}}{{perimeter}}") + if err != nil { + return err + } + + res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: config, + Method: "GET", + RawURL: url, + UserAgent: config.UserAgent, + }) + if err != nil { + return err + } + + v, ok := res["status"] + if !ok || v == nil { + return nil + } + + res = v.(map[string]interface{}) + v, ok = res["perimeter"] + if !ok || v == nil { + return nil + } + + resources := v.([]interface{}) + if len(resources) == 0 { + return nil + } + + return fmt.Errorf("expected 0 resources in perimeter, found %d: %v", len(resources), resources) + } + + return nil + } +} + +func testAccAccessContextManagerServicePerimeterIngressPolicy_basic(org, policyTitle, perimeterTitleName string) string { + return fmt.Sprintf(` +%s + +resource "google_access_context_manager_service_perimeter_ingress_policy" "test-access" { + perimeter = google_access_context_manager_service_perimeter.test-access.name + ingress_policy { + ingress_from { + identity_type = "ANY_IDENTITY" + } + ingress_to { + resources = [ "*" ] + operations { + service_name = "bigquery.googleapis.com" + + method_selectors { + method = "BigQueryStorage.ReadRows" + } + + method_selectors { + method = "TableService.ListTables" + } + + method_selectors { + permission = "bigquery.jobs.get" + } + } + + operations { + service_name = "storage.googleapis.com" + + method_selectors { + method = "google.storage.objects.create" + } + } + } + } +} + +`, testAccAccessContextManagerServicePerimeterIngressPolicy_destroy(org, policyTitle, perimeterTitleName)) +} + +func testAccAccessContextManagerServicePerimeterIngressPolicy_destroy(org, policyTitle, perimeterTitleName string) string { + return fmt.Sprintf(` +resource "google_access_context_manager_access_policy" "test-access" { + parent = "organizations/%s" + title = "%s" +} + +resource "google_access_context_manager_service_perimeter" "test-access" { + parent = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}" + name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/servicePerimeters/%s" + title = "%s" + status { + restricted_services = ["storage.googleapis.com"] + } + + lifecycle { + ignore_changes = [status[0].ingress_policies] + } +} +`, org, policyTitle, perimeterTitleName, perimeterTitleName) +} From 4ac178a3cf7257de0ce0f6706ce9cd642ccefe57 Mon Sep 17 00:00:00 2001 From: Hao Nan Li Date: Tue, 30 May 2023 10:45:33 -0700 Subject: [PATCH 02/10] Delete old test files --- ...cess_context_manager_egress_policy_test.go | 129 --------------- ...ess_context_manager_ingress_policy_test.go | 156 ------------------ 2 files changed, 285 deletions(-) delete mode 100644 mmv1/third_party/terraform/tests/resource_access_context_manager_egress_policy_test.go delete mode 100644 mmv1/third_party/terraform/tests/resource_access_context_manager_ingress_policy_test.go diff --git a/mmv1/third_party/terraform/tests/resource_access_context_manager_egress_policy_test.go b/mmv1/third_party/terraform/tests/resource_access_context_manager_egress_policy_test.go deleted file mode 100644 index cdc11ad7f5ab..000000000000 --- a/mmv1/third_party/terraform/tests/resource_access_context_manager_egress_policy_test.go +++ /dev/null @@ -1,129 +0,0 @@ -package google - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" - "github.com/hashicorp/terraform-provider-google/google/acctest" - "github.com/hashicorp/terraform-provider-google/google/tpgresource" - transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" -) - -// Since each test here is acting on the same organization and only one AccessPolicy -// can exist, they need to be run serially. See AccessPolicy for the test runner. - -func testAccAccessContextManagerEgressPolicy_basicTest(t *testing.T) { - // Multiple fine-grained resources - acctest.SkipIfVcr(t) - org := acctest.GetTestOrgFromEnv(t) - projects := BootstrapServicePerimeterProjects(t, 1) - policyTitle := RandString(t, 10) - perimeterTitle := "perimeter" - - VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), - Steps: []resource.TestStep{ - { - Config: testAccAccessContextManagerEgressPolicy_basic(org, policyTitle, perimeterTitle, projects[0].ProjectNumber), - }, - { - ResourceName: "google_access_context_manager_egress_policy.test-access1", - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccAccessContextManagerEgressPolicy_destroy(org, policyTitle, perimeterTitle), - Check: testAccCheckAccessContextManagerEgressPolicyDestroyProducer(t), - }, - }, - }) -} - -func testAccCheckAccessContextManagerEgressPolicyDestroyProducer(t *testing.T) func(s *terraform.State) error { - return func(s *terraform.State) error { - for _, rs := range s.RootModule().Resources { - if rs.Type != "google_access_context_manager_egress_policy" { - continue - } - - config := GoogleProviderConfig(t) - - url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{AccessContextManagerBasePath}}{{egress_policy_name}}") - if err != nil { - return err - } - - res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ - Config: config, - Method: "GET", - RawURL: url, - UserAgent: config.UserAgent, - }) - if err != nil { - return err - } - - v, ok := res["status"] - if !ok || v == nil { - return nil - } - - res = v.(map[string]interface{}) - v, ok = res["resources"] - if !ok || v == nil { - return nil - } - - resources := v.([]interface{}) - if len(resources) == 0 { - return nil - } - - return fmt.Errorf("expected 0 resources in perimeter, found %d: %v", len(resources), resources) - } - - return nil - } -} - -func testAccAccessContextManagerEgressPolicy_basic(org, policyTitle, perimeterTitleName string, projectNumber1 int64) string { - return fmt.Sprintf(` -%s - -resource "google_access_context_manager_egress_policy" "test-access1" { - egress_policy_name = google_access_context_manager_service_perimeter.test-access.name - resource = "projects/%d" -} - -`, testAccAccessContextManagerEgressPolicy_destroy(org, policyTitle, perimeterTitleName), projectNumber1) -} - -func testAccAccessContextManagerEgressPolicy_destroy(org, policyTitle, perimeterTitleName string) string { - return fmt.Sprintf(` -resource "google_access_context_manager_access_policy" "test-access" { - parent = "organizations/%s" - title = "%s" -} - -resource "google_access_context_manager_service_perimeter" "test-access" { - parent = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}" - name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/servicePerimeters/%s" - title = "%s" - status { - restricted_services = ["storage.googleapis.com"] - egress_policies { - egress_from { - identity_type = "ANY_USER_ACCOUNT" - } - } - } - - lifecycle { - ignore_changes = [status[0].resources] - } -} -`, org, policyTitle, perimeterTitleName, perimeterTitleName) -} diff --git a/mmv1/third_party/terraform/tests/resource_access_context_manager_ingress_policy_test.go b/mmv1/third_party/terraform/tests/resource_access_context_manager_ingress_policy_test.go deleted file mode 100644 index 0f14aa1bc3b4..000000000000 --- a/mmv1/third_party/terraform/tests/resource_access_context_manager_ingress_policy_test.go +++ /dev/null @@ -1,156 +0,0 @@ -package google - -import ( - "fmt" - "testing" - - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" - "github.com/hashicorp/terraform-provider-google/google/acctest" - "github.com/hashicorp/terraform-provider-google/google/tpgresource" - transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport" -) - -// Since each test here is acting on the same organization and only one AccessPolicy -// can exist, they need to be run serially. See AccessPolicy for the test runner. - -func testAccAccessContextManagerIngressPolicy_basicTest(t *testing.T) { - // Multiple fine-grained resources - acctest.SkipIfVcr(t) - org := acctest.GetTestOrgFromEnv(t) - projects := BootstrapServicePerimeterProjects(t, 1) - policyTitle := RandString(t, 10) - perimeterTitle := "perimeter" - - VcrTest(t, resource.TestCase{ - PreCheck: func() { acctest.AccTestPreCheck(t) }, - ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), - Steps: []resource.TestStep{ - { - Config: testAccAccessContextManagerIngressPolicy_basic(org, policyTitle, perimeterTitle, projects[0].ProjectNumber), - }, - { - ResourceName: "google_access_context_manager_ingress_policy.test-access1", - ImportState: true, - ImportStateVerify: true, - }, - { - Config: testAccAccessContextManagerIngressPolicy_destroy(org, policyTitle, perimeterTitle), - Check: testAccCheckAccessContextManagerIngressPolicyDestroyProducer(t), - }, - }, - }) -} - -func testAccCheckAccessContextManagerIngressPolicyDestroyProducer(t *testing.T) func(s *terraform.State) error { - return func(s *terraform.State) error { - for _, rs := range s.RootModule().Resources { - if rs.Type != "google_access_context_manager_ingress_policy" { - continue - } - - config := GoogleProviderConfig(t) - - url, err := tpgresource.ReplaceVarsForTest(config, rs, "{{AccessContextManagerBasePath}}{{ingress_policy_name}}") - if err != nil { - return err - } - - res, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ - Config: config, - Method: "GET", - RawURL: url, - UserAgent: config.UserAgent, - }) - if err != nil { - return err - } - - v, ok := res["status"] - if !ok || v == nil { - return nil - } - - res = v.(map[string]interface{}) - v, ok = res["resources"] - if !ok || v == nil { - return nil - } - - resources := v.([]interface{}) - if len(resources) == 0 { - return nil - } - - return fmt.Errorf("expected 0 resources in perimeter, found %d: %v", len(resources), resources) - } - - return nil - } -} - -func testAccAccessContextManagerIngressPolicy_basic(org, policyTitle, perimeterTitleName string, projectNumber1 int64) string { - return fmt.Sprintf(` -%s - -resource "google_access_context_manager_ingress_policy" "test-access1" { - ingress_policy_name = google_access_context_manager_service_perimeter.test-access.name - resource = "projects/%d" -} - -`, testAccAccessContextManagerIngressPolicy_destroy(org, policyTitle, perimeterTitleName), projectNumber1) -} - -func testAccAccessContextManagerIngressPolicy_destroy(org, policyTitle, perimeterTitleName string) string { - return fmt.Sprintf(` -resource "google_access_context_manager_access_policy" "test-access" { - parent = "organizations/%s" - title = "%s" -} - -resource "google_access_context_manager_service_perimeter" "test-access" { - parent = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}" - name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/servicePerimeters/%s" - title = "%s" - status { - restricted_services = ["storage.googleapis.com"] - ingress_policies { - ingress_from { - identity_type = "ANY_IDENTITY" - } - - ingress_to { - resources = [ "*" ] - operations { - service_name = "bigquery.googleapis.com" - - method_selectors { - method = "BigQueryStorage.ReadRows" - } - - method_selectors { - method = "TableService.ListTables" - } - - method_selectors { - permission = "bigquery.jobs.get" - } - } - - operations { - service_name = "storage.googleapis.com" - - method_selectors { - method = "google.storage.objects.create" - } - } - } - } - } - - lifecycle { - ignore_changes = [status[0].resources] - } -} -`, org, policyTitle, perimeterTitleName, perimeterTitleName) -} From 1f0c8d434f310517271a784a58a3953fd9b69c7d Mon Sep 17 00:00:00 2001 From: Hao Nan Li Date: Tue, 30 May 2023 15:31:55 -0700 Subject: [PATCH 03/10] Fix tests failures --- ...er_service_perimeter_egress_policy_test.go | 10 +++---- ...r_service_perimeter_ingress_policy_test.go | 26 +++++++++++++------ 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go index f0e9391020bd..575941ce7493 100644 --- a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go +++ b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go @@ -14,11 +14,11 @@ import ( // Since each test here is acting on the same organization and only one AccessPolicy // can exist, they need to be run serially. See AccessPolicy for the test runner. -func testAccAccessContextManagerEgressPolicy_basicTest(t *testing.T) { +func testAccAccessContextManagerServicePerimeterEgressPolicy_basicTest(t *testing.T) { // Multiple fine-grained resources acctest.SkipIfVcr(t) org := acctest.GetTestOrgFromEnv(t) - projects := BootstrapServicePerimeterProjects(t, 1) + //projects := BootstrapServicePerimeterProjects(t, 1) policyTitle := RandString(t, 10) perimeterTitle := "perimeter" @@ -27,7 +27,7 @@ func testAccAccessContextManagerEgressPolicy_basicTest(t *testing.T) { ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), Steps: []resource.TestStep{ { - Config: testAccAccessContextManagerEgressPolicy_basic(org, policyTitle, perimeterTitle, projects[0].ProjectNumber), + Config: testAccAccessContextManagerServicePerimeterEgressPolicy_basic(org, policyTitle, perimeterTitle), }, { ResourceName: "google_access_context_manager_egress_policy.test-access1", @@ -36,13 +36,13 @@ func testAccAccessContextManagerEgressPolicy_basicTest(t *testing.T) { }, { Config: testAccAccessContextManagerEgressPolicy_destroy(org, policyTitle, perimeterTitle), - Check: testAccCheckAccessContextManagerEgressPolicyDestroyProducer(t), + Check: testAccCheckAccessContextManagerServicePerimeterEgressPolicyDestroyProducer(t), }, }, }) } -func testAccCheckAccessContextManagerEgressPolicyDestroyProducer(t *testing.T) func(s *terraform.State) error { +func testAccCheckAccessContextManagerServicePerimeterEgressPolicyDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { for _, rs := range s.RootModule().Resources { if rs.Type != "google_access_context_manager_service_perimeter_egress_policy" { diff --git a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go index ee9e422b6258..a6868035c849 100644 --- a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go +++ b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go @@ -14,11 +14,11 @@ import ( // Since each test here is acting on the same organization and only one AccessPolicy // can exist, they need to be run serially. See AccessPolicy for the test runner. -func testAccAccessContextManagerIngressPolicy_basicTest(t *testing.T) { +func testAccAccessContextManagerServicePerimeterIngressPolicy_basicTest(t *testing.T) { // Multiple fine-grained resources acctest.SkipIfVcr(t) org := acctest.GetTestOrgFromEnv(t) - projects := BootstrapServicePerimeterProjects(t, 1) + //projects := BootstrapServicePerimeterProjects(t, 1) policyTitle := RandString(t, 10) perimeterTitle := "perimeter" @@ -27,22 +27,27 @@ func testAccAccessContextManagerIngressPolicy_basicTest(t *testing.T) { ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), Steps: []resource.TestStep{ { - Config: testAccAccessContextManagerIngressPolicy_basic(org, policyTitle, perimeterTitle, projects[0].ProjectNumber), + Config: testAccAccessContextManagerServicePerimeterIngressPolicy_basic(org, policyTitle, perimeterTitle), }, { - ResourceName: "google_access_context_manager_ingress_policy.test-access1", + ResourceName: "google_access_context_manager_service_perimeter_ingress_policy.test-access1", ImportState: true, ImportStateVerify: true, }, { - Config: testAccAccessContextManagerIngressPolicy_destroy(org, policyTitle, perimeterTitle), - Check: testAccCheckAccessContextManagerIngressPolicyDestroyProducer(t), + ResourceName: "google_access_context_manager_service_perimeter_ingress_policy.test-access2", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAccessContextManagerServicePerimeterIngressPolicy_destroy(org, policyTitle, perimeterTitle), + Check: testAccCheckAccessContextManagerServicePerimeterIngressPolicyDestroyProducer(t), }, }, }) } -func testAccCheckAccessContextManagerIngressPolicyDestroyProducer(t *testing.T) func(s *terraform.State) error { +func testAccCheckAccessContextManagerServicePerimeterIngressPolicyDestroyProducer(t *testing.T) func(s *terraform.State) error { return func(s *terraform.State) error { for _, rs := range s.RootModule().Resources { if rs.Type != "google_access_context_manager_service_perimeter_ingress_policy" { @@ -93,7 +98,7 @@ func testAccAccessContextManagerServicePerimeterIngressPolicy_basic(org, policyT return fmt.Sprintf(` %s -resource "google_access_context_manager_service_perimeter_ingress_policy" "test-access" { +resource "google_access_context_manager_service_perimeter_ingress_policy" "test-access1" { perimeter = google_access_context_manager_service_perimeter.test-access.name ingress_policy { ingress_from { @@ -127,6 +132,11 @@ resource "google_access_context_manager_service_perimeter_ingress_policy" "test- } } } +resource "google_access_context_manager_service_perimeter_ingress_policy" "test-access2" { + perimeter = google_access_context_manager_service_perimeter.test-access.name + ingress_policy { + } +} `, testAccAccessContextManagerServicePerimeterIngressPolicy_destroy(org, policyTitle, perimeterTitleName)) } From 1d9d0aedb710b9d294a089fb13ee51209428ff59 Mon Sep 17 00:00:00 2001 From: Hao Nan Li Date: Tue, 30 May 2023 16:24:02 -0700 Subject: [PATCH 04/10] Fix tests --- ...ntext_manager_service_perimeter_egress_policy_test.go | 2 +- ...text_manager_service_perimeter_ingress_policy_test.go | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go index 575941ce7493..b5be6c118420 100644 --- a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go +++ b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go @@ -35,7 +35,7 @@ func testAccAccessContextManagerServicePerimeterEgressPolicy_basicTest(t *testin ImportStateVerify: true, }, { - Config: testAccAccessContextManagerEgressPolicy_destroy(org, policyTitle, perimeterTitle), + Config: testAccAccessContextManagerServicePerimeterEgressPolicy_destroy(org, policyTitle, perimeterTitle), Check: testAccCheckAccessContextManagerServicePerimeterEgressPolicyDestroyProducer(t), }, }, diff --git a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go index a6868035c849..1a48863b744c 100644 --- a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go +++ b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go @@ -34,11 +34,6 @@ func testAccAccessContextManagerServicePerimeterIngressPolicy_basicTest(t *testi ImportState: true, ImportStateVerify: true, }, - { - ResourceName: "google_access_context_manager_service_perimeter_ingress_policy.test-access2", - ImportState: true, - ImportStateVerify: true, - }, { Config: testAccAccessContextManagerServicePerimeterIngressPolicy_destroy(org, policyTitle, perimeterTitle), Check: testAccCheckAccessContextManagerServicePerimeterIngressPolicyDestroyProducer(t), @@ -134,7 +129,11 @@ resource "google_access_context_manager_service_perimeter_ingress_policy" "test- } resource "google_access_context_manager_service_perimeter_ingress_policy" "test-access2" { perimeter = google_access_context_manager_service_perimeter.test-access.name + depends_on = [google_access_context_manager_service_perimeter_ingress_policy.test-access1] ingress_policy { + ingress_from { + identity_type = "IDENTITY_TYPE_UNSPECIFIED" + } } } From 1821afb38f93e5636f38947be5a111fa1a90fb35 Mon Sep 17 00:00:00 2001 From: Hao Nan Li Date: Thu, 1 Jun 2023 11:02:47 -0700 Subject: [PATCH 05/10] Make ingress_policy an array --- .../ServicePerimeterIngressPolicy.yaml | 207 +++++++++--------- ..._context_manager_access_policy_test.go.erb | 2 +- ...er_service_perimeter_egress_policy_test.go | 2 +- ...r_service_perimeter_ingress_policy_test.go | 20 +- 4 files changed, 114 insertions(+), 117 deletions(-) diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml index 5f888f603f0b..da169cf18d27 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml @@ -56,112 +56,113 @@ parameters: immutable: true url_param_only: true properties: - - !ruby/object:Api::Type::NestedObject + - !ruby/object:Api::Type::Array name: 'ingressPolicy' description: | List of `IngressPolicies` to apply to the perimeter. A perimeter may have multiple `IngressPolicies`, each of which is evaluated separately. Access is granted if any `Ingress Policy` grants it. Must be empty for a perimeter bridge. - properties: - - !ruby/object:Api::Type::NestedObject - name: 'ingressFrom' - description: | - Defines the conditions on the source of a request causing this `IngressPolicy` - to apply. - properties: - - !ruby/object:Api::Type::Enum - name: 'identityType' - description: | - Specifies the type of identities that are allowed access from outside the - perimeter. If left unspecified, then members of `identities` field will be - allowed access. - values: - - :IDENTITY_TYPE_UNSPECIFIED - - :ANY_IDENTITY - - :ANY_USER_ACCOUNT - - :ANY_SERVICE_ACCOUNT - - !ruby/object:Api::Type::Array - name: 'identities' - item_type: Api::Type::String - description: | - A list of identities that are allowed access through this ingress policy. - Should be in the format of email address. The email address should represent - individual user or service account only. - - !ruby/object:Api::Type::Array - name: 'sources' - description: | - Sources that this `IngressPolicy` authorizes access from. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: 'accessLevel' - description: | - An `AccessLevel` resource name that allow resources within the - `ServicePerimeters` to be accessed from the internet. `AccessLevels` listed - must be in the same policy as this `ServicePerimeter`. Referencing a nonexistent - `AccessLevel` will cause an error. If no `AccessLevel` names are listed, - resources within the perimeter can only be accessed via Google Cloud calls - with request origins within the perimeter. - Example `accessPolicies/MY_POLICY/accessLevels/MY_LEVEL.` - If * is specified, then all IngressSources will be allowed. - - !ruby/object:Api::Type::String - name: 'resource' - description: | - A Google Cloud resource that is allowed to ingress the perimeter. - Requests from these resources will be allowed to access perimeter data. - Currently only projects are allowed. Format `projects/{project_number}` - The project may be in any Google Cloud organization, not just the - organization that the perimeter is defined in. `*` is not allowed, the case - of allowing all Google Cloud resources only is not supported. - - !ruby/object:Api::Type::NestedObject - name: 'ingressTo' - description: | - Defines the conditions on the `ApiOperation` and request destination that cause - this `IngressPolicy` to apply. - properties: - - !ruby/object:Api::Type::Array - name: 'resources' - item_type: Api::Type::String - description: | - A list of resources, currently only projects in the form - `projects/`, protected by this `ServicePerimeter` - that are allowed to be accessed by sources defined in the - corresponding `IngressFrom`. A request matches if it contains - a resource in this list. If `*` is specified for resources, - then this `IngressTo` rule will authorize access to all - resources inside the perimeter, provided that the request - also matches the `operations` field. - - !ruby/object:Api::Type::Array - name: 'operations' - description: | - A list of `ApiOperations` the sources specified in corresponding `IngressFrom` - are allowed to perform in this `ServicePerimeter`. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: 'serviceName' - description: | - The name of the API whose methods or permissions the `IngressPolicy` or - `EgressPolicy` want to allow. A single `ApiOperation` with `serviceName` - field set to `*` will allow all methods AND permissions for all services. - - !ruby/object:Api::Type::Array - name: 'methodSelectors' - description: | - API methods or permissions to allow. Method or permission must belong to - the service specified by serviceName field. A single `MethodSelector` entry - with `*` specified for the method field will allow all methods AND - permissions for the service specified in `serviceName`. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: 'method' - description: | - Value for method should be a valid method name for the corresponding - serviceName in `ApiOperation`. If `*` used as value for `method`, then - ALL methods and permissions are allowed. - - !ruby/object:Api::Type::String - name: 'permission' - description: | - Value for permission should be a valid Cloud IAM permission for the - corresponding `serviceName` in `ApiOperation`. \ No newline at end of file + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::NestedObject + name: 'ingressFrom' + description: | + Defines the conditions on the source of a request causing this `IngressPolicy` + to apply. + properties: + - !ruby/object:Api::Type::Enum + name: 'identityType' + description: | + Specifies the type of identities that are allowed access from outside the + perimeter. If left unspecified, then members of `identities` field will be + allowed access. + values: + - :IDENTITY_TYPE_UNSPECIFIED + - :ANY_IDENTITY + - :ANY_USER_ACCOUNT + - :ANY_SERVICE_ACCOUNT + - !ruby/object:Api::Type::Array + name: 'identities' + item_type: Api::Type::String + description: | + A list of identities that are allowed access through this ingress policy. + Should be in the format of email address. The email address should represent + individual user or service account only. + - !ruby/object:Api::Type::Array + name: 'sources' + description: | + Sources that this `IngressPolicy` authorizes access from. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'accessLevel' + description: | + An `AccessLevel` resource name that allow resources within the + `ServicePerimeters` to be accessed from the internet. `AccessLevels` listed + must be in the same policy as this `ServicePerimeter`. Referencing a nonexistent + `AccessLevel` will cause an error. If no `AccessLevel` names are listed, + resources within the perimeter can only be accessed via Google Cloud calls + with request origins within the perimeter. + Example `accessPolicies/MY_POLICY/accessLevels/MY_LEVEL.` + If * is specified, then all IngressSources will be allowed. + - !ruby/object:Api::Type::String + name: 'resource' + description: | + A Google Cloud resource that is allowed to ingress the perimeter. + Requests from these resources will be allowed to access perimeter data. + Currently only projects are allowed. Format `projects/{project_number}` + The project may be in any Google Cloud organization, not just the + organization that the perimeter is defined in. `*` is not allowed, the case + of allowing all Google Cloud resources only is not supported. + - !ruby/object:Api::Type::NestedObject + name: 'ingressTo' + description: | + Defines the conditions on the `ApiOperation` and request destination that cause + this `IngressPolicy` to apply. + properties: + - !ruby/object:Api::Type::Array + name: 'resources' + item_type: Api::Type::String + description: | + A list of resources, currently only projects in the form + `projects/`, protected by this `ServicePerimeter` + that are allowed to be accessed by sources defined in the + corresponding `IngressFrom`. A request matches if it contains + a resource in this list. If `*` is specified for resources, + then this `IngressTo` rule will authorize access to all + resources inside the perimeter, provided that the request + also matches the `operations` field. + - !ruby/object:Api::Type::Array + name: 'operations' + description: | + A list of `ApiOperations` the sources specified in corresponding `IngressFrom` + are allowed to perform in this `ServicePerimeter`. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'serviceName' + description: | + The name of the API whose methods or permissions the `IngressPolicy` or + `EgressPolicy` want to allow. A single `ApiOperation` with `serviceName` + field set to `*` will allow all methods AND permissions for all services. + - !ruby/object:Api::Type::Array + name: 'methodSelectors' + description: | + API methods or permissions to allow. Method or permission must belong to + the service specified by serviceName field. A single `MethodSelector` entry + with `*` specified for the method field will allow all methods AND + permissions for the service specified in `serviceName`. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'method' + description: | + Value for method should be a valid method name for the corresponding + serviceName in `ApiOperation`. If `*` used as value for `method`, then + ALL methods and permissions are allowed. + - !ruby/object:Api::Type::String + name: 'permission' + description: | + Value for permission should be a valid Cloud IAM permission for the + corresponding `serviceName` in `ApiOperation`. \ No newline at end of file diff --git a/mmv1/third_party/terraform/tests/resource_access_context_manager_access_policy_test.go.erb b/mmv1/third_party/terraform/tests/resource_access_context_manager_access_policy_test.go.erb index 6f846e77042d..787dc01b56a5 100644 --- a/mmv1/third_party/terraform/tests/resource_access_context_manager_access_policy_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_access_context_manager_access_policy_test.go.erb @@ -103,7 +103,7 @@ func TestAccAccessContextManager(t *testing.T) { "access_levels": testAccAccessContextManagerAccessLevels_basicTest, "access_level_condition": testAccAccessContextManagerAccessLevelCondition_basicTest, "service_perimeter_egress_policy": testAccAccessContextManagerServicePerimeterEgressPolicy_basicTest, - "service_perimeter_ingress_policy": testAccAccessContextManagerServicePerimeterIngressPolicy_basicTest, + "service_perimeter_ingress_policy": TestAccAccessContextManagerServicePerimeterIngressPolicy_basicTest, "service_perimeters": testAccAccessContextManagerServicePerimeters_basicTest, "gcp_user_access_binding": testAccAccessContextManagerGcpUserAccessBinding_basicTest, "authorized_orgs_desc": testAccAccessContextManagerAuthorizedOrgsDesc_basicTest, diff --git a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go index b5be6c118420..968872e8a265 100644 --- a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go +++ b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go @@ -30,7 +30,7 @@ func testAccAccessContextManagerServicePerimeterEgressPolicy_basicTest(t *testin Config: testAccAccessContextManagerServicePerimeterEgressPolicy_basic(org, policyTitle, perimeterTitle), }, { - ResourceName: "google_access_context_manager_egress_policy.test-access1", + ResourceName: "google_access_context_manager_service_perimeter.test-access", ImportState: true, ImportStateVerify: true, }, diff --git a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go index 1a48863b744c..ce9dee38af25 100644 --- a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go +++ b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go @@ -14,7 +14,7 @@ import ( // Since each test here is acting on the same organization and only one AccessPolicy // can exist, they need to be run serially. See AccessPolicy for the test runner. -func testAccAccessContextManagerServicePerimeterIngressPolicy_basicTest(t *testing.T) { +func TestAccAccessContextManagerServicePerimeterIngressPolicy_basicTest(t *testing.T) { // Multiple fine-grained resources acctest.SkipIfVcr(t) org := acctest.GetTestOrgFromEnv(t) @@ -30,7 +30,7 @@ func testAccAccessContextManagerServicePerimeterIngressPolicy_basicTest(t *testi Config: testAccAccessContextManagerServicePerimeterIngressPolicy_basic(org, policyTitle, perimeterTitle), }, { - ResourceName: "google_access_context_manager_service_perimeter_ingress_policy.test-access1", + ResourceName: "google_access_context_manager_service_perimeter.test-access", ImportState: true, ImportStateVerify: true, }, @@ -98,8 +98,8 @@ resource "google_access_context_manager_service_perimeter_ingress_policy" "test- ingress_policy { ingress_from { identity_type = "ANY_IDENTITY" - } - ingress_to { + } + ingress_to { resources = [ "*" ] operations { service_name = "bigquery.googleapis.com" @@ -126,15 +126,11 @@ resource "google_access_context_manager_service_perimeter_ingress_policy" "test- } } } -} -resource "google_access_context_manager_service_perimeter_ingress_policy" "test-access2" { - perimeter = google_access_context_manager_service_perimeter.test-access.name - depends_on = [google_access_context_manager_service_perimeter_ingress_policy.test-access1] - ingress_policy { - ingress_from { - identity_type = "IDENTITY_TYPE_UNSPECIFIED" - } + ingress_policy { + ingress_from { + identity_type = "IDENTITY_TYPE_UNSPECIFIED" } + } } `, testAccAccessContextManagerServicePerimeterIngressPolicy_destroy(org, policyTitle, perimeterTitleName)) From aeffb2c4f1c98d78879408aede5f5f04b8257a38 Mon Sep 17 00:00:00 2001 From: Hao Nan Li Date: Fri, 2 Jun 2023 11:08:27 -0700 Subject: [PATCH 06/10] Change the top level field to be ingressFrom and ingressTo --- .../ServicePerimeterIngressPolicy.yaml | 190 +++++++++--------- ...r_service_perimeter_ingress_policy_test.go | 8 +- 2 files changed, 95 insertions(+), 103 deletions(-) diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml index da169cf18d27..7cbbfed395de 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml @@ -19,10 +19,11 @@ create_verb: :PATCH delete_verb: :PATCH update_mask: true identity: - - ingressPolicy + - ingressFrom + - ingressTo nested_query: !ruby/object:Api::Resource::NestedQuery modify_by_patch: true - is_list_of_ids: true + is_list_of_ids: false keys: - status - ingressPolicies @@ -56,113 +57,104 @@ parameters: immutable: true url_param_only: true properties: - - !ruby/object:Api::Type::Array - name: 'ingressPolicy' + - !ruby/object:Api::Type::NestedObject + name: 'ingressFrom' description: | - List of `IngressPolicies` to apply to the perimeter. A perimeter may - have multiple `IngressPolicies`, each of which is evaluated - separately. Access is granted if any `Ingress Policy` grants it. - Must be empty for a perimeter bridge. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::NestedObject - name: 'ingressFrom' - description: | - Defines the conditions on the source of a request causing this `IngressPolicy` - to apply. + Defines the conditions on the source of a request causing this `IngressPolicy` + to apply. + properties: + - !ruby/object:Api::Type::Enum + name: 'identityType' + description: | + Specifies the type of identities that are allowed access from outside the + perimeter. If left unspecified, then members of `identities` field will be + allowed access. + values: + - :IDENTITY_TYPE_UNSPECIFIED + - :ANY_IDENTITY + - :ANY_USER_ACCOUNT + - :ANY_SERVICE_ACCOUNT + - !ruby/object:Api::Type::Array + name: 'identities' + item_type: Api::Type::String + description: | + A list of identities that are allowed access through this ingress policy. + Should be in the format of email address. The email address should represent + individual user or service account only. + - !ruby/object:Api::Type::Array + name: 'sources' + description: | + Sources that this `IngressPolicy` authorizes access from. + item_type: !ruby/object:Api::Type::NestedObject properties: - - !ruby/object:Api::Type::Enum - name: 'identityType' + - !ruby/object:Api::Type::String + name: 'accessLevel' description: | - Specifies the type of identities that are allowed access from outside the - perimeter. If left unspecified, then members of `identities` field will be - allowed access. - values: - - :IDENTITY_TYPE_UNSPECIFIED - - :ANY_IDENTITY - - :ANY_USER_ACCOUNT - - :ANY_SERVICE_ACCOUNT - - !ruby/object:Api::Type::Array - name: 'identities' - item_type: Api::Type::String - description: | - A list of identities that are allowed access through this ingress policy. - Should be in the format of email address. The email address should represent - individual user or service account only. - - !ruby/object:Api::Type::Array - name: 'sources' + An `AccessLevel` resource name that allow resources within the + `ServicePerimeters` to be accessed from the internet. `AccessLevels` listed + must be in the same policy as this `ServicePerimeter`. Referencing a nonexistent + `AccessLevel` will cause an error. If no `AccessLevel` names are listed, + resources within the perimeter can only be accessed via Google Cloud calls + with request origins within the perimeter. + Example `accessPolicies/MY_POLICY/accessLevels/MY_LEVEL.` + If * is specified, then all IngressSources will be allowed. + - !ruby/object:Api::Type::String + name: 'resource' description: | - Sources that this `IngressPolicy` authorizes access from. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: 'accessLevel' - description: | - An `AccessLevel` resource name that allow resources within the - `ServicePerimeters` to be accessed from the internet. `AccessLevels` listed - must be in the same policy as this `ServicePerimeter`. Referencing a nonexistent - `AccessLevel` will cause an error. If no `AccessLevel` names are listed, - resources within the perimeter can only be accessed via Google Cloud calls - with request origins within the perimeter. - Example `accessPolicies/MY_POLICY/accessLevels/MY_LEVEL.` - If * is specified, then all IngressSources will be allowed. - - !ruby/object:Api::Type::String - name: 'resource' - description: | - A Google Cloud resource that is allowed to ingress the perimeter. - Requests from these resources will be allowed to access perimeter data. - Currently only projects are allowed. Format `projects/{project_number}` - The project may be in any Google Cloud organization, not just the - organization that the perimeter is defined in. `*` is not allowed, the case - of allowing all Google Cloud resources only is not supported. - - !ruby/object:Api::Type::NestedObject - name: 'ingressTo' - description: | - Defines the conditions on the `ApiOperation` and request destination that cause - this `IngressPolicy` to apply. + A Google Cloud resource that is allowed to ingress the perimeter. + Requests from these resources will be allowed to access perimeter data. + Currently only projects are allowed. Format `projects/{project_number}` + The project may be in any Google Cloud organization, not just the + organization that the perimeter is defined in. `*` is not allowed, the case + of allowing all Google Cloud resources only is not supported. + - !ruby/object:Api::Type::NestedObject + name: 'ingressTo' + description: | + Defines the conditions on the `ApiOperation` and request destination that cause + this `IngressPolicy` to apply. + properties: + - !ruby/object:Api::Type::Array + name: 'resources' + item_type: Api::Type::String + description: | + A list of resources, currently only projects in the form + `projects/`, protected by this `ServicePerimeter` + that are allowed to be accessed by sources defined in the + corresponding `IngressFrom`. A request matches if it contains + a resource in this list. If `*` is specified for resources, + then this `IngressTo` rule will authorize access to all + resources inside the perimeter, provided that the request + also matches the `operations` field. + - !ruby/object:Api::Type::Array + name: 'operations' + description: | + A list of `ApiOperations` the sources specified in corresponding `IngressFrom` + are allowed to perform in this `ServicePerimeter`. + item_type: !ruby/object:Api::Type::NestedObject properties: - - !ruby/object:Api::Type::Array - name: 'resources' - item_type: Api::Type::String + - !ruby/object:Api::Type::String + name: 'serviceName' description: | - A list of resources, currently only projects in the form - `projects/`, protected by this `ServicePerimeter` - that are allowed to be accessed by sources defined in the - corresponding `IngressFrom`. A request matches if it contains - a resource in this list. If `*` is specified for resources, - then this `IngressTo` rule will authorize access to all - resources inside the perimeter, provided that the request - also matches the `operations` field. + The name of the API whose methods or permissions the `IngressPolicy` or + `EgressPolicy` want to allow. A single `ApiOperation` with `serviceName` + field set to `*` will allow all methods AND permissions for all services. - !ruby/object:Api::Type::Array - name: 'operations' + name: 'methodSelectors' description: | - A list of `ApiOperations` the sources specified in corresponding `IngressFrom` - are allowed to perform in this `ServicePerimeter`. + API methods or permissions to allow. Method or permission must belong to + the service specified by serviceName field. A single `MethodSelector` entry + with `*` specified for the method field will allow all methods AND + permissions for the service specified in `serviceName`. item_type: !ruby/object:Api::Type::NestedObject properties: - !ruby/object:Api::Type::String - name: 'serviceName' + name: 'method' description: | - The name of the API whose methods or permissions the `IngressPolicy` or - `EgressPolicy` want to allow. A single `ApiOperation` with `serviceName` - field set to `*` will allow all methods AND permissions for all services. - - !ruby/object:Api::Type::Array - name: 'methodSelectors' + Value for method should be a valid method name for the corresponding + serviceName in `ApiOperation`. If `*` used as value for `method`, then + ALL methods and permissions are allowed. + - !ruby/object:Api::Type::String + name: 'permission' description: | - API methods or permissions to allow. Method or permission must belong to - the service specified by serviceName field. A single `MethodSelector` entry - with `*` specified for the method field will allow all methods AND - permissions for the service specified in `serviceName`. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: 'method' - description: | - Value for method should be a valid method name for the corresponding - serviceName in `ApiOperation`. If `*` used as value for `method`, then - ALL methods and permissions are allowed. - - !ruby/object:Api::Type::String - name: 'permission' - description: | - Value for permission should be a valid Cloud IAM permission for the - corresponding `serviceName` in `ApiOperation`. \ No newline at end of file + Value for permission should be a valid Cloud IAM permission for the + corresponding `serviceName` in `ApiOperation`. \ No newline at end of file diff --git a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go index ce9dee38af25..6986fd0133a5 100644 --- a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go +++ b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go @@ -95,7 +95,6 @@ func testAccAccessContextManagerServicePerimeterIngressPolicy_basic(org, policyT resource "google_access_context_manager_service_perimeter_ingress_policy" "test-access1" { perimeter = google_access_context_manager_service_perimeter.test-access.name - ingress_policy { ingress_from { identity_type = "ANY_IDENTITY" } @@ -125,12 +124,13 @@ resource "google_access_context_manager_service_perimeter_ingress_policy" "test- } } } - } - ingress_policy { +} + +resource "google_access_context_manager_service_perimeter_ingress_policy" "test-access2" { + perimeter = google_access_context_manager_service_perimeter.test-access.name ingress_from { identity_type = "IDENTITY_TYPE_UNSPECIFIED" } - } } `, testAccAccessContextManagerServicePerimeterIngressPolicy_destroy(org, policyTitle, perimeterTitleName)) From 872fc0e4573472a0c9d950bf7708ec004bc5dec7 Mon Sep 17 00:00:00 2001 From: Hao Nan Li Date: Fri, 2 Jun 2023 12:44:54 -0700 Subject: [PATCH 07/10] Support creation for multiple ingress/egress policies --- .../ServicePerimeterEgressPolicy.yaml | 160 +++++++++--------- .../ServicePerimeterIngressPolicy.yaml | 1 + ..._context_manager_access_policy_test.go.erb | 2 +- ...er_service_perimeter_egress_policy_test.go | 10 +- ...r_service_perimeter_ingress_policy_test.go | 4 +- 5 files changed, 89 insertions(+), 88 deletions(-) diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml index 951ae40f9a89..8b152494a7d2 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml @@ -19,10 +19,11 @@ create_verb: :PATCH delete_verb: :PATCH update_mask: true identity: - - egressPolicy + - egressFrom + - egressTo nested_query: !ruby/object:Api::Resource::NestedQuery modify_by_patch: true - is_list_of_ids: true + is_list_of_ids: false keys: - status - egressPolicies @@ -42,6 +43,7 @@ exclude_validator: true skip_sweeper: true id_format: '{{perimeter}}' import_format: ['{{perimeter}}'] +mutex: '{{perimeter}}' custom_code: !ruby/object:Provider::Terraform::CustomCode custom_import: templates/terraform/custom_import/access_context_manager_service_perimeter_ingress_policy.go.erb parameters: @@ -56,88 +58,80 @@ parameters: url_param_only: true properties: - !ruby/object:Api::Type::NestedObject - name: 'egressPolicy' + name: 'egressFrom' description: | - List of EgressPolicies to apply to the perimeter. A perimeter may - have multiple EgressPolicies, each of which is evaluated separately. - Access is granted if any EgressPolicy grants it. Must be empty for - a perimeter bridge. + Defines conditions on the source of a request causing this `EgressPolicy` to apply. properties: - - !ruby/object:Api::Type::NestedObject - name: 'egressFrom' + - !ruby/object:Api::Type::Enum + name: 'identityType' description: | - Defines conditions on the source of a request causing this `EgressPolicy` to apply. - properties: - - !ruby/object:Api::Type::Enum - name: 'identityType' - description: | - Specifies the type of identities that are allowed access to outside the - perimeter. If left unspecified, then members of `identities` field will - be allowed access. - values: - - :IDENTITY_TYPE_UNSPECIFIED - - :ANY_IDENTITY - - :ANY_USER_ACCOUNT - - :ANY_SERVICE_ACCOUNT - - !ruby/object:Api::Type::Array - name: 'identities' - description: | - A list of identities that are allowed access through this `EgressPolicy`. - Should be in the format of email address. The email address should - represent individual user or service account only. - item_type: Api::Type::String - - !ruby/object:Api::Type::NestedObject - name: 'egressTo' + Specifies the type of identities that are allowed access to outside the + perimeter. If left unspecified, then members of `identities` field will + be allowed access. + values: + - :IDENTITY_TYPE_UNSPECIFIED + - :ANY_IDENTITY + - :ANY_USER_ACCOUNT + - :ANY_SERVICE_ACCOUNT + - !ruby/object:Api::Type::Array + name: 'identities' description: | - Defines the conditions on the `ApiOperation` and destination resources that - cause this `EgressPolicy` to apply. - properties: - - !ruby/object:Api::Type::Array - name: 'resources' - item_type: Api::Type::String - description: | - A list of resources, currently only projects in the form - `projects/`, that match this to stanza. A request matches - if it contains a resource in this list. If * is specified for resources, - then this `EgressTo` rule will authorize access to all resources outside - the perimeter. - - !ruby/object:Api::Type::Array - name: 'externalResources' - item_type: Api::Type::String - description: | - A list of external resources that are allowed to be accessed. A request - matches if it contains an external resource in this list (Example: - s3://bucket/path). Currently '*' is not allowed. - - !ruby/object:Api::Type::Array - name: 'operations' - description: | - A list of `ApiOperations` that this egress rule applies to. A request matches - if it contains an operation/service in this list. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: 'serviceName' - description: | - The name of the API whose methods or permissions the `IngressPolicy` or - `EgressPolicy` want to allow. A single `ApiOperation` with serviceName - field set to `*` will allow all methods AND permissions for all services. - - !ruby/object:Api::Type::Array - name: 'methodSelectors' - description: | - API methods or permissions to allow. Method or permission must belong - to the service specified by `serviceName` field. A single MethodSelector - entry with `*` specified for the `method` field will allow all methods - AND permissions for the service specified in `serviceName`. - item_type: !ruby/object:Api::Type::NestedObject - properties: - - !ruby/object:Api::Type::String - name: 'method' - description: | - Value for `method` should be a valid method name for the corresponding - `serviceName` in `ApiOperation`. If `*` used as value for method, - then ALL methods and permissions are allowed. - - !ruby/object:Api::Type::String - name: 'permission' - description: | - Value for permission should be a valid Cloud IAM permission for the - corresponding `serviceName` in `ApiOperation`. \ No newline at end of file + A list of identities that are allowed access through this `EgressPolicy`. + Should be in the format of email address. The email address should + represent individual user or service account only. + item_type: Api::Type::String + - !ruby/object:Api::Type::NestedObject + name: 'egressTo' + description: | + Defines the conditions on the `ApiOperation` and destination resources that + cause this `EgressPolicy` to apply. + properties: + - !ruby/object:Api::Type::Array + name: 'resources' + item_type: Api::Type::String + description: | + A list of resources, currently only projects in the form + `projects/`, that match this to stanza. A request matches + if it contains a resource in this list. If * is specified for resources, + then this `EgressTo` rule will authorize access to all resources outside + the perimeter. + - !ruby/object:Api::Type::Array + name: 'externalResources' + item_type: Api::Type::String + description: | + A list of external resources that are allowed to be accessed. A request + matches if it contains an external resource in this list (Example: + s3://bucket/path). Currently '*' is not allowed. + - !ruby/object:Api::Type::Array + name: 'operations' + description: | + A list of `ApiOperations` that this egress rule applies to. A request matches + if it contains an operation/service in this list. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'serviceName' + description: | + The name of the API whose methods or permissions the `IngressPolicy` or + `EgressPolicy` want to allow. A single `ApiOperation` with serviceName + field set to `*` will allow all methods AND permissions for all services. + - !ruby/object:Api::Type::Array + name: 'methodSelectors' + description: | + API methods or permissions to allow. Method or permission must belong + to the service specified by `serviceName` field. A single MethodSelector + entry with `*` specified for the `method` field will allow all methods + AND permissions for the service specified in `serviceName`. + item_type: !ruby/object:Api::Type::NestedObject + properties: + - !ruby/object:Api::Type::String + name: 'method' + description: | + Value for `method` should be a valid method name for the corresponding + `serviceName` in `ApiOperation`. If `*` used as value for method, + then ALL methods and permissions are allowed. + - !ruby/object:Api::Type::String + name: 'permission' + description: | + Value for permission should be a valid Cloud IAM permission for the + corresponding `serviceName` in `ApiOperation`. \ No newline at end of file diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml index 7cbbfed395de..346fa427bd8c 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml @@ -44,6 +44,7 @@ exclude_validator: true skip_sweeper: true id_format: '{{perimeter}}' import_format: ['{{perimeter}}'] +mutex: '{{perimeter}}' custom_code: !ruby/object:Provider::Terraform::CustomCode custom_import: templates/terraform/custom_import/access_context_manager_service_perimeter_ingress_policy.go.erb parameters: diff --git a/mmv1/third_party/terraform/tests/resource_access_context_manager_access_policy_test.go.erb b/mmv1/third_party/terraform/tests/resource_access_context_manager_access_policy_test.go.erb index 787dc01b56a5..6f846e77042d 100644 --- a/mmv1/third_party/terraform/tests/resource_access_context_manager_access_policy_test.go.erb +++ b/mmv1/third_party/terraform/tests/resource_access_context_manager_access_policy_test.go.erb @@ -103,7 +103,7 @@ func TestAccAccessContextManager(t *testing.T) { "access_levels": testAccAccessContextManagerAccessLevels_basicTest, "access_level_condition": testAccAccessContextManagerAccessLevelCondition_basicTest, "service_perimeter_egress_policy": testAccAccessContextManagerServicePerimeterEgressPolicy_basicTest, - "service_perimeter_ingress_policy": TestAccAccessContextManagerServicePerimeterIngressPolicy_basicTest, + "service_perimeter_ingress_policy": testAccAccessContextManagerServicePerimeterIngressPolicy_basicTest, "service_perimeters": testAccAccessContextManagerServicePerimeters_basicTest, "gcp_user_access_binding": testAccAccessContextManagerGcpUserAccessBinding_basicTest, "authorized_orgs_desc": testAccAccessContextManagerAuthorizedOrgsDesc_basicTest, diff --git a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go index 968872e8a265..9611d4e4e09a 100644 --- a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go +++ b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_egress_policy_test.go @@ -95,7 +95,6 @@ func testAccAccessContextManagerServicePerimeterEgressPolicy_basic(org, policyTi resource "google_access_context_manager_service_perimeter_egress_policy" "test-access1" { perimeter = google_access_context_manager_service_perimeter.test-access.name - egress_policy { egress_from { identity_type = "ANY_USER_ACCOUNT" } @@ -107,7 +106,14 @@ resource "google_access_context_manager_service_perimeter_egress_policy" "test-a } } } - } + +} + +resource "google_access_context_manager_service_perimeter_egress_policy" "test-access2" { + perimeter = google_access_context_manager_service_perimeter.test-access.name + egress_from { + identity_type = "ANY_USER_ACCOUNT" + } } `, testAccAccessContextManagerServicePerimeterEgressPolicy_destroy(org, policyTitle, perimeterTitleName)) diff --git a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go index 6986fd0133a5..411f640ac9c7 100644 --- a/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go +++ b/mmv1/third_party/terraform/tests/resource_access_context_manager_service_perimeter_ingress_policy_test.go @@ -14,7 +14,7 @@ import ( // Since each test here is acting on the same organization and only one AccessPolicy // can exist, they need to be run serially. See AccessPolicy for the test runner. -func TestAccAccessContextManagerServicePerimeterIngressPolicy_basicTest(t *testing.T) { +func testAccAccessContextManagerServicePerimeterIngressPolicy_basicTest(t *testing.T) { // Multiple fine-grained resources acctest.SkipIfVcr(t) org := acctest.GetTestOrgFromEnv(t) @@ -129,7 +129,7 @@ resource "google_access_context_manager_service_perimeter_ingress_policy" "test- resource "google_access_context_manager_service_perimeter_ingress_policy" "test-access2" { perimeter = google_access_context_manager_service_perimeter.test-access.name ingress_from { - identity_type = "IDENTITY_TYPE_UNSPECIFIED" + identity_type = "ANY_IDENTITY" } } From fe3e5d6d3ac334f78f1f60986c5d0ea49db21313 Mon Sep 17 00:00:00 2001 From: Hao Nan Li Date: Mon, 5 Jun 2023 11:11:20 -0700 Subject: [PATCH 08/10] Remove Wrong values in ingress_from/egress_from fields --- mmv1/products/accesscontextmanager/EgressPolicy.yaml | 1 + mmv1/products/accesscontextmanager/IngressPolicy.yaml | 1 + .../accesscontextmanager/ServicePerimeterEgressPolicy.yaml | 3 +-- .../accesscontextmanager/ServicePerimeterIngressPolicy.yaml | 3 +-- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/mmv1/products/accesscontextmanager/EgressPolicy.yaml b/mmv1/products/accesscontextmanager/EgressPolicy.yaml index b26535edbbde..0d506656f905 100644 --- a/mmv1/products/accesscontextmanager/EgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/EgressPolicy.yaml @@ -11,6 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +# This resource has been deprecated, please refer to ServicePerimeterEgressPolicy. --- !ruby/object:Api::Resource name: 'EgressPolicy' create_url: '{{egress_policy_name}}' diff --git a/mmv1/products/accesscontextmanager/IngressPolicy.yaml b/mmv1/products/accesscontextmanager/IngressPolicy.yaml index a67a40ca30b8..28853679582b 100644 --- a/mmv1/products/accesscontextmanager/IngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/IngressPolicy.yaml @@ -11,6 +11,7 @@ # See the License for the specific language governing permissions and # limitations under the License. +# This resource has been deprecated, please refer to ServicePerimeterIngressPolicy. --- !ruby/object:Api::Resource name: 'IngressPolicy' create_url: '{{ingress_policy_name}}' diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml index 8b152494a7d2..81afd311c59c 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml @@ -39,7 +39,7 @@ description: | or query against a BigQuery dataset). autogen_async: true exclude_validator: true -# Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter/IngressPolicy +# Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter skip_sweeper: true id_format: '{{perimeter}}' import_format: ['{{perimeter}}'] @@ -69,7 +69,6 @@ properties: perimeter. If left unspecified, then members of `identities` field will be allowed access. values: - - :IDENTITY_TYPE_UNSPECIFIED - :ANY_IDENTITY - :ANY_USER_ACCOUNT - :ANY_SERVICE_ACCOUNT diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml index 346fa427bd8c..0648ef370ec0 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml @@ -40,7 +40,7 @@ description: | or actions they match using the ingressTo field. autogen_async: true exclude_validator: true -# Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter/IngressPolicy +# Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter skip_sweeper: true id_format: '{{perimeter}}' import_format: ['{{perimeter}}'] @@ -71,7 +71,6 @@ properties: perimeter. If left unspecified, then members of `identities` field will be allowed access. values: - - :IDENTITY_TYPE_UNSPECIFIED - :ANY_IDENTITY - :ANY_USER_ACCOUNT - :ANY_SERVICE_ACCOUNT From f788a56c955fd049aa9ecb3ca992698ab9e679fe Mon Sep 17 00:00:00 2001 From: Hao Nan Li Date: Mon, 5 Jun 2023 11:22:33 -0700 Subject: [PATCH 09/10] Fix Lint --- .../ServicePerimeterEgressPolicy.yaml | 14 +++++++------- .../ServicePerimeterIngressPolicy.yaml | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml index 81afd311c59c..337d6ca3932e 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterEgressPolicy.yaml @@ -30,12 +30,12 @@ nested_query: !ruby/object:Api::Resource::NestedQuery references: !ruby/object:Api::Resource::ReferenceLinks api: 'https://cloud.google.com/access-context-manager/docs/reference/rest/v1/accessPolicies.servicePerimeters#egresspolicy' description: | - EgressPolicies match requests based on egressFrom and egressTo stanzas. - For an EgressPolicy to match, both egressFrom and egressTo stanzas must be matched. - If an EgressPolicy matches a request, the request is allowed to span the ServicePerimeter - boundary. For example, an EgressPolicy can be used to allow VMs on networks - within the ServicePerimeter to access a defined set of projects outside the - perimeter in certain contexts (e.g. to read data from a Cloud Storage bucket + EgressPolicies match requests based on egressFrom and egressTo stanzas. + For an EgressPolicy to match, both egressFrom and egressTo stanzas must be matched. + If an EgressPolicy matches a request, the request is allowed to span the ServicePerimeter + boundary. For example, an EgressPolicy can be used to allow VMs on networks + within the ServicePerimeter to access a defined set of projects outside the + perimeter in certain contexts (e.g. to read data from a Cloud Storage bucket or query against a BigQuery dataset). autogen_async: true exclude_validator: true @@ -133,4 +133,4 @@ properties: name: 'permission' description: | Value for permission should be a valid Cloud IAM permission for the - corresponding `serviceName` in `ApiOperation`. \ No newline at end of file + corresponding `serviceName` in `ApiOperation`. diff --git a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml index 0648ef370ec0..f292102fbdf4 100644 --- a/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/ServicePerimeterIngressPolicy.yaml @@ -157,4 +157,4 @@ properties: name: 'permission' description: | Value for permission should be a valid Cloud IAM permission for the - corresponding `serviceName` in `ApiOperation`. \ No newline at end of file + corresponding `serviceName` in `ApiOperation`. From 46943a52fc4b8054898db917bf023936a62f4d73 Mon Sep 17 00:00:00 2001 From: Hao Nan Li Date: Mon, 5 Jun 2023 14:37:31 -0700 Subject: [PATCH 10/10] Change description for deprecated resources --- mmv1/products/accesscontextmanager/EgressPolicy.yaml | 9 +-------- mmv1/products/accesscontextmanager/IngressPolicy.yaml | 10 +--------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/mmv1/products/accesscontextmanager/EgressPolicy.yaml b/mmv1/products/accesscontextmanager/EgressPolicy.yaml index 0d506656f905..2c5389d903db 100644 --- a/mmv1/products/accesscontextmanager/EgressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/EgressPolicy.yaml @@ -11,7 +11,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This resource has been deprecated, please refer to ServicePerimeterEgressPolicy. --- !ruby/object:Api::Resource name: 'EgressPolicy' create_url: '{{egress_policy_name}}' @@ -32,13 +31,7 @@ nested_query: !ruby/object:Api::Resource::NestedQuery references: !ruby/object:Api::Resource::ReferenceLinks api: 'https://cloud.google.com/access-context-manager/docs/reference/rest/v1/accessPolicies.servicePerimeters#egresspolicy' description: | - EgressPolicies match requests based on egressFrom and egressTo stanzas. - For an EgressPolicy to match, both egressFrom and egressTo stanzas must be matched. - If an EgressPolicy matches a request, the request is allowed to span the ServicePerimeter - boundary. For example, an EgressPolicy can be used to allow VMs on networks - within the ServicePerimeter to access a defined set of projects outside the - perimeter in certain contexts (e.g. to read data from a Cloud Storage bucket - or query against a BigQuery dataset). + This resource has been deprecated, please refer to ServicePerimeterEgressPolicy. autogen_async: true exclude_validator: true # Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter/IngressPolicy diff --git a/mmv1/products/accesscontextmanager/IngressPolicy.yaml b/mmv1/products/accesscontextmanager/IngressPolicy.yaml index 28853679582b..901b11b4632f 100644 --- a/mmv1/products/accesscontextmanager/IngressPolicy.yaml +++ b/mmv1/products/accesscontextmanager/IngressPolicy.yaml @@ -11,7 +11,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# This resource has been deprecated, please refer to ServicePerimeterIngressPolicy. --- !ruby/object:Api::Resource name: 'IngressPolicy' create_url: '{{ingress_policy_name}}' @@ -32,14 +31,7 @@ nested_query: !ruby/object:Api::Resource::NestedQuery references: !ruby/object:Api::Resource::ReferenceLinks api: 'https://cloud.google.com/access-context-manager/docs/reference/rest/v1/accessPolicies.servicePerimeters#ingresspolicy' description: | - IngressPolicies match requests based on ingressFrom and ingressTo stanzas. For an ingress policy to match, - both the ingressFrom and ingressTo stanzas must be matched. If an IngressPolicy matches a request, - the request is allowed through the perimeter boundary from outside the perimeter. - For example, access from the internet can be allowed either based on an AccessLevel or, - for traffic hosted on Google Cloud, the project of the source network. - For access from private networks, using the project of the hosting network is required. - Individual ingress policies can be limited by restricting which services and/ - or actions they match using the ingressTo field. + This resource has been deprecated, please refer to ServicePerimeterIngressPolicy. autogen_async: true exclude_validator: true # Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter/IngressPolicy