Skip to content

Commit

Permalink
AccessContextManager - Add dry run version of Ingress / Egress policy…
Browse files Browse the repository at this point in the history
… resources. (#10990)

Co-authored-by: Charlesleonius <[email protected]>
Charlesleonius and Charlesleonius authored Aug 5, 2024
1 parent 05e0a2e commit c3ebf61
Showing 13 changed files with 894 additions and 13 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
# Copyright 2024 Google Inc.
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
--- !ruby/object:Api::Resource
name: 'ServicePerimeterDryRunIngressPolicy'
create_url: '{{perimeter}}'
base_url: ''
self_link: '{{perimeter}}'
create_verb: :PATCH
delete_verb: :PATCH
update_mask: true
immutable: true
identity:
- ingressFrom
- ingressTo
nested_query: !ruby/object:Api::Resource::NestedQuery
modify_by_patch: true
is_list_of_ids: false
keys:
- spec
- ingressPolicies
references: !ruby/object:Api::Resource::ReferenceLinks
api: 'https://cloud.google.com/access-context-manager/docs/reference/rest/v1/accessPolicies.servicePerimeters#ingresspolicy'
description: |
Manage a single IngressPolicy in the spec (dry-run) configuration for a service perimeter.
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.
~> **Note:** By default, updates to this resource will remove the IngressPolicy from the
from the perimeter and add it back in a non-atomic manner. To ensure that the new IngressPolicy
is added before the old one is removed, add a `lifecycle` block with `create_before_destroy = true` to this resource.
examples:
- !ruby/object:Provider::Terraform::Examples
name: 'access_context_manager_service_perimeter_dry_run_ingress_policy'
skip_test: true
autogen_async: true
exclude_tgc: true
# Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter
skip_sweeper: true
exclude_import: 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
pre_update: templates/terraform/pre_create/access_context_manager_dry_run_resource.go.erb
pre_create: templates/terraform/pre_create/access_context_manager_dry_run_resource.go.erb
pre_delete: templates/terraform/pre_create/access_context_manager_dry_run_resource.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
url_param_only: true
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:
- :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/<projectnumber>`, 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`.
Original file line number Diff line number Diff line change
@@ -65,9 +65,9 @@ examples:
service_perimeter_name: 'restrict_all'
custom_code: !ruby/object:Provider::Terraform::CustomCode
custom_import: templates/terraform/custom_import/access_context_manager_service_perimeter_resource.go.erb
pre_update: templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb
pre_create: templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb
pre_delete: templates/terraform/pre_create/access_context_manager_service_perimeter_dry_run_resource.go.erb
pre_update: templates/terraform/pre_create/access_context_manager_dry_run_resource.go.erb
pre_create: templates/terraform/pre_create/access_context_manager_dry_run_resource.go.erb
pre_delete: templates/terraform/pre_create/access_context_manager_dry_run_resource.go.erb
parameters:
- !ruby/object:Api::Type::ResourceRef
name: 'perimeterName'
Original file line number Diff line number Diff line change
@@ -31,6 +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: |
Manage a single EgressPolicy in the status (enforced) configuration for a service perimeter.
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
@@ -50,6 +51,7 @@ autogen_async: true
exclude_tgc: true
# Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter
skip_sweeper: true
exclude_import: true
id_format: '{{perimeter}}'
import_format: ['{{perimeter}}']
mutex: '{{perimeter}}'
Original file line number Diff line number Diff line change
@@ -31,6 +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: |
Manage a single IngressPolicy in the status (enforced) configuration for a service perimeter.
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.
@@ -51,6 +52,7 @@ autogen_async: true
exclude_tgc: true
# Skipping the sweeper due to the non-standard base_url and because this is fine-grained under ServicePerimeter
skip_sweeper: true
exclude_import: true
id_format: '{{perimeter}}'
import_format: ['{{perimeter}}']
mutex: '{{perimeter}}'
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
resource "google_access_context_manager_service_perimeter" "storage-perimeter" {
parent = "accesspolicies/${google_access_context_manager_access_policy.access-policy.name}"
name = "accesspolicies/${google_access_context_manager_access_policy.access-policy.name}/serviceperimeters/storage-perimeter"
title = "Storage Perimeter"
spec {
restricted_services = ["storage.googleapis.com"]
}
lifecycle {
ignore_changes = [status[0].resources]
}
}

resource "google_access_context_manager_service_perimeter_dry_run_egress_policy" "egress_policy" {
perimeter = "${google_access_context_manager_service_perimeter.storage-perimeter.name}"
egress_from {
identity_type = "ANY_IDENTITY"
}
egress_to {
resources = ["*"]
operations {
service_name = "bigquery.googleapis.com"
method_selectors {
method = "*"
}
}
}
lifecycle {
create_before_destroy = true
}
}


resource "google_access_context_manager_access_policy" "access-policy" {
parent = "organizations/123456789"
title = "Storage Policy"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
resource "google_access_context_manager_service_perimeter" "storage-perimeter" {
parent = "accesspolicies/${google_access_context_manager_access_policy.access-policy.name}"
name = "accesspolicies/${google_access_context_manager_access_policy.access-policy.name}/serviceperimeters/storage-perimeter"
title = "Storage Perimeter"
status {
restricted_services = ["storage.googleapis.com"]
}
lifecycle {
ignore_changes = [status[0].resources]
}
}

resource "google_access_context_manager_service_perimeter_dry_run_ingress_policy" "ingress_policy" {
perimeter = "${google_access_context_manager_service_perimeter.storage-perimeter.name}"
ingress_from {
identity_type = "any_identity"
sources {
access_level = "*"
}
}
ingress_to {
resources = ["*"]
operations {
service_name = "bigquery.googleapis.com"
method_selectors {
method = "*"
}
}
}
lifecycle {
create_before_destroy = true
}
}


resource "google_access_context_manager_access_policy" "access-policy" {
parent = "organizations/123456789"
title = "Storage Policy"
}
Original file line number Diff line number Diff line change
@@ -29,7 +29,9 @@ func TestAccAccessContextManager(t *testing.T) {
"access_levels": testAccAccessContextManagerAccessLevels_basicTest,
"access_level_condition": testAccAccessContextManagerAccessLevelCondition_basicTest,
"service_perimeter_egress_policy": testAccAccessContextManagerServicePerimeterEgressPolicy_basicTest,
"service_perimeter_dry_run_egress_policy": testAccAccessContextManagerServicePerimeterDryRunEgressPolicy_basicTest,
"service_perimeter_ingress_policy": testAccAccessContextManagerServicePerimeterIngressPolicy_basicTest,
"service_perimeter_dry_run_ingress_policy": testAccAccessContextManagerServicePerimeterDryRunIngressPolicy_basicTest,
"service_perimeters": testAccAccessContextManagerServicePerimeters_basicTest,
"gcp_user_access_binding": testAccAccessContextManagerGcpUserAccessBinding_basicTest,
"authorized_orgs_desc": testAccAccessContextManagerAuthorizedOrgsDesc_basicTest,
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
package accesscontextmanager_test

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-provider-google/google/acctest"
"github.com/hashicorp/terraform-provider-google/google/envvar"
"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 testAccAccessContextManagerServicePerimeterDryRunEgressPolicy_basicTest(t *testing.T) {
org := envvar.GetTestOrgFromEnv(t)
//projects := acctest.BootstrapServicePerimeterProjects(t, 1)
policyTitle := acctest.RandString(t, 10)
perimeterTitle := "perimeter"

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
Steps: []resource.TestStep{
{
Config: testAccAccessContextManagerServicePerimeterDryRunEgressPolicy_basic(org, policyTitle, perimeterTitle),
},
{
Config: testAccAccessContextManagerServicePerimeterDryRunEgressPolicy_destroy(org, policyTitle, perimeterTitle),
Check: testAccCheckAccessContextManagerServicePerimeterDryRunEgressPolicyDestroyProducer(t),
},
},
})
}

func testAccCheckAccessContextManagerServicePerimeterDryRunEgressPolicyDestroyProducer(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_dry_run_egress_policy" {
continue
}

config := acctest.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["spec"]
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 testAccAccessContextManagerServicePerimeterDryRunEgressPolicy_basic(org, policyTitle, perimeterTitleName string) string {
return fmt.Sprintf(`
%s
resource "google_access_context_manager_access_level" "test-access" {
parent = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}"
name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/accessLevels/level"
title = "level"
description = "hello"
basic {
combining_function = "AND"
conditions {
ip_subnetworks = ["192.0.4.0/24"]
}
}
}
resource "google_access_context_manager_service_perimeter_dry_run_egress_policy" "test-access1" {
perimeter = google_access_context_manager_service_perimeter.test-access.name
egress_from {
identity_type = "ANY_USER_ACCOUNT"
}
egress_to {
operations {
service_name = "storage.googleapis.com"
method_selectors {
method = "*"
}
}
}
}
resource "google_access_context_manager_service_perimeter_dry_run_egress_policy" "test-access2" {
perimeter = google_access_context_manager_service_perimeter.test-access.name
egress_from {
identity_type = "ANY_USER_ACCOUNT"
sources {
access_level = google_access_context_manager_access_level.test-access.name
}
source_restriction = "SOURCE_RESTRICTION_ENABLED"
}
depends_on = [google_access_context_manager_service_perimeter_dry_run_egress_policy.test-access1]
}
`, testAccAccessContextManagerServicePerimeterDryRunEgressPolicy_destroy(org, policyTitle, perimeterTitleName))
}

func testAccAccessContextManagerServicePerimeterDryRunEgressPolicy_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"
spec {
restricted_services = ["storage.googleapis.com"]
}
use_explicit_dry_run_spec = true
lifecycle {
ignore_changes = [spec[0].egress_policies]
}
}
`, org, policyTitle, perimeterTitleName, perimeterTitleName)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
package accesscontextmanager_test

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
"github.com/hashicorp/terraform-provider-google/google/acctest"
"github.com/hashicorp/terraform-provider-google/google/envvar"
"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 testAccAccessContextManagerServicePerimeterDryRunIngressPolicy_basicTest(t *testing.T) {
org := envvar.GetTestOrgFromEnv(t)
//projects := acctest.BootstrapServicePerimeterProjects(t, 1)
policyTitle := acctest.RandString(t, 10)
perimeterTitle := "perimeter"

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
Steps: []resource.TestStep{
{
Config: testAccAccessContextManagerServicePerimeterDryRunIngressPolicy_basic(org, policyTitle, perimeterTitle),
},
{
Config: testAccAccessContextManagerServicePerimeterDryRunIngressPolicy_destroy(org, policyTitle, perimeterTitle),
Check: testAccCheckAccessContextManagerServicePerimeterDryRunIngressPolicyDestroyProducer(t),
},
},
})
}

func testAccCheckAccessContextManagerServicePerimeterDryRunIngressPolicyDestroyProducer(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_dry_run_ingress_policy" {
continue
}

config := acctest.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["spec"]
if !ok || v == nil {
return nil
}

res = v.(map[string]interface{})
v, ok = res["ingress_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 testAccAccessContextManagerServicePerimeterDryRunIngressPolicy_basic(org, policyTitle, perimeterTitleName string) string {
return fmt.Sprintf(`
%s
resource "google_access_context_manager_access_level" "test-access" {
parent = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}"
name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/accessLevels/level"
title = "level"
description = "hello"
basic {
combining_function = "AND"
conditions {
ip_subnetworks = ["192.0.4.0/24"]
}
}
}
resource "google_access_context_manager_service_perimeter_dry_run_ingress_policy" "test-access1" {
perimeter = google_access_context_manager_service_perimeter.test-access.name
ingress_from {
identity_type = "ANY_USER_ACCOUNT"
sources {
access_level = google_access_context_manager_access_level.test-access.name
}
}
ingress_to {
operations {
service_name = "storage.googleapis.com"
method_selectors {
method = "*"
}
}
}
}
resource "google_access_context_manager_service_perimeter_dry_run_ingress_policy" "test-access2" {
perimeter = google_access_context_manager_service_perimeter.test-access.name
ingress_from {
identity_type = "ANY_USER_ACCOUNT"
sources {
access_level = google_access_context_manager_access_level.test-access.name
}
}
depends_on = [google_access_context_manager_service_perimeter_dry_run_ingress_policy.test-access1]
}
`, testAccAccessContextManagerServicePerimeterDryRunIngressPolicy_destroy(org, policyTitle, perimeterTitleName))
}

func testAccAccessContextManagerServicePerimeterDryRunIngressPolicy_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"
spec {
restricted_services = ["storage.googleapis.com"]
}
use_explicit_dry_run_spec = true
lifecycle {
ignore_changes = [spec[0].ingress_policies]
}
}
`, org, policyTitle, perimeterTitleName, perimeterTitleName)
}
Original file line number Diff line number Diff line change
@@ -30,11 +30,6 @@ func testAccAccessContextManagerServicePerimeterEgressPolicy_basicTest(t *testin
{
Config: testAccAccessContextManagerServicePerimeterEgressPolicy_basic(org, policyTitle, perimeterTitle),
},
{
ResourceName: "google_access_context_manager_service_perimeter.test-access",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccAccessContextManagerServicePerimeterEgressPolicy_destroy(org, policyTitle, perimeterTitle),
Check: testAccCheckAccessContextManagerServicePerimeterEgressPolicyDestroyProducer(t),
Original file line number Diff line number Diff line change
@@ -30,11 +30,6 @@ func testAccAccessContextManagerServicePerimeterIngressPolicy_basicTest(t *testi
{
Config: testAccAccessContextManagerServicePerimeterIngressPolicy_basic(org, policyTitle, perimeterTitle),
},
{
ResourceName: "google_access_context_manager_service_perimeter.test-access",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testAccAccessContextManagerServicePerimeterIngressPolicy_destroy(org, policyTitle, perimeterTitle),
Check: testAccCheckAccessContextManagerServicePerimeterIngressPolicyDestroyProducer(t),

0 comments on commit c3ebf61

Please sign in to comment.