From 2797fb0d3fe4a2bbe43d984f1a3a2580316f36bb Mon Sep 17 00:00:00 2001 From: Modular Magician Date: Fri, 20 Oct 2023 22:13:03 +0000 Subject: [PATCH] Vgm vpc subseg (#9298) * First commit for VPC sub-segmentation feature. All relevant resources and tests updated. * Adding access levels instead of using a fake access level name. Also moving a VPC network to the top level instead of (incorrectly) inside another resource. * Fixing conflict between ip_subnetworks and vpc_ip_subnetworks * Undoing changes to access level condition test * Undoing changes to access level condition test * Ran gofmt * Re-adding access level conditions tests * Changing resource names to camel case to match what the HTTP response from the API returns. Also removing the 'resource' field because it's behind an allowlist. * Parameterizing the names of VPC networks created in tests * Fixing access level condition test * Fixed formatting with gofmt * Added missing fields in egress_from for service perimeter test. * Added "required: true" for AccessLevel.VpcNetworkSource.network field to match description. * Added egress source changes to test data in: example_access_context_manager_service_perimeter.tfplan.json * Add Egress Source/source restriction changes to example_access_context_manager_service_perimeter.tf * Attempt to fix example_access_context_manager_service_perimeter.tfplan.json to make it parse correctly * Add Egress Source to expected tcg test result data * Fixing expected output format in example_access_context_manager_service_perimeter.json * Fix Access Level format in expected output in example_access_context_manager_service_perimeter.json --------- Co-authored-by: vgm Co-authored-by: Viktor Moros [upstream:d30384c9aa2002c56102ce4c8f0c76c77706b923] Signed-off-by: Modular Magician --- .changelog/9298.txt | 3 + ...rce_access_context_manager_access_level.go | 137 +++++++++++++ ..._context_manager_access_level_condition.go | 142 +++++++++++++ ...ext_manager_access_level_condition_test.go | 34 +++- ...ccess_context_manager_access_level_test.go | 30 ++- ...ce_access_context_manager_access_levels.go | 137 +++++++++++++ ...cess_context_manager_access_levels_test.go | 30 ++- ...ccess_context_manager_service_perimeter.go | 188 ++++++++++++++++++ ...manager_service_perimeter_egress_policy.go | 94 +++++++++ ...er_service_perimeter_egress_policy_test.go | 17 ++ ..._context_manager_service_perimeter_test.go | 8 + ...cess_context_manager_service_perimeters.go | 188 ++++++++++++++++++ ...ontext_manager_services_perimeters_test.go | 7 + ...context_manager_access_level.html.markdown | 23 +++ ...nager_access_level_condition.html.markdown | 23 +++ ...ontext_manager_access_levels.html.markdown | 23 +++ ...xt_manager_service_perimeter.html.markdown | 34 ++++ ...vice_perimeter_egress_policy.html.markdown | 17 ++ ...t_manager_service_perimeters.html.markdown | 34 ++++ 19 files changed, 1146 insertions(+), 23 deletions(-) create mode 100644 .changelog/9298.txt diff --git a/.changelog/9298.txt b/.changelog/9298.txt new file mode 100644 index 00000000000..3d28511bf12 --- /dev/null +++ b/.changelog/9298.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +accesscontextmanager: added support for Access Context Manager's VPC Sub-segmentation feature +``` diff --git a/google/services/accesscontextmanager/resource_access_context_manager_access_level.go b/google/services/accesscontextmanager/resource_access_context_manager_access_level.go index 9aa2f2948b4..7a7d039508c 100644 --- a/google/services/accesscontextmanager/resource_access_context_manager_access_level.go +++ b/google/services/accesscontextmanager/resource_access_context_manager_access_level.go @@ -220,6 +220,38 @@ Format: accessPolicies/{policy_id}/accessLevels/{short_name}`, Type: schema.TypeString, }, }, + "vpc_network_sources": { + Type: schema.TypeList, + Optional: true, + Description: `The request must originate from one of the provided VPC networks in Google Cloud. Cannot specify this field together with 'ip_subnetworks'.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "vpc_subnetwork": { + Type: schema.TypeList, + Optional: true, + Description: `Sub networks within a VPC network.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "network": { + Type: schema.TypeString, + Required: true, + Description: `Required. Network name to be allowed by this Access Level. Networks of foreign organizations requires 'compute.network.get' permission to be granted to caller.`, + }, + "vpc_ip_subnetworks": { + Type: schema.TypeList, + Optional: true, + Description: `CIDR block IP subnetwork specification. Must be IPv4.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, }, }, }, @@ -672,6 +704,7 @@ func flattenAccessContextManagerAccessLevelBasicConditions(v interface{}, d *sch "negate": flattenAccessContextManagerAccessLevelBasicConditionsNegate(original["negate"], d, config), "device_policy": flattenAccessContextManagerAccessLevelBasicConditionsDevicePolicy(original["devicePolicy"], d, config), "regions": flattenAccessContextManagerAccessLevelBasicConditionsRegions(original["regions"], d, config), + "vpc_network_sources": flattenAccessContextManagerAccessLevelBasicConditionsVpcNetworkSources(original["vpcNetworkSources"], d, config), }) } return transformed @@ -771,6 +804,47 @@ func flattenAccessContextManagerAccessLevelBasicConditionsRegions(v interface{}, return v } +func flattenAccessContextManagerAccessLevelBasicConditionsVpcNetworkSources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "vpc_subnetwork": flattenAccessContextManagerAccessLevelBasicConditionsVpcNetworkSourcesVpcSubnetwork(original["vpcSubnetwork"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerAccessLevelBasicConditionsVpcNetworkSourcesVpcSubnetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["network"] = + flattenAccessContextManagerAccessLevelBasicConditionsVpcNetworkSourcesVpcSubnetworkNetwork(original["network"], d, config) + transformed["vpc_ip_subnetworks"] = + flattenAccessContextManagerAccessLevelBasicConditionsVpcNetworkSourcesVpcSubnetworkVpcIpSubnetworks(original["vpcIpSubnetworks"], d, config) + return []interface{}{transformed} +} +func flattenAccessContextManagerAccessLevelBasicConditionsVpcNetworkSourcesVpcSubnetworkNetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerAccessLevelBasicConditionsVpcNetworkSourcesVpcSubnetworkVpcIpSubnetworks(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenAccessContextManagerAccessLevelCustom(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { if v == nil { return nil @@ -913,6 +987,13 @@ func expandAccessContextManagerAccessLevelBasicConditions(v interface{}, d tpgre transformed["regions"] = transformedRegions } + transformedVpcNetworkSources, err := expandAccessContextManagerAccessLevelBasicConditionsVpcNetworkSources(original["vpc_network_sources"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedVpcNetworkSources); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["vpcNetworkSources"] = transformedVpcNetworkSources + } + req = append(req, transformed) } return req, nil @@ -1060,6 +1141,62 @@ func expandAccessContextManagerAccessLevelBasicConditionsRegions(v interface{}, return v, nil } +func expandAccessContextManagerAccessLevelBasicConditionsVpcNetworkSources(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedVpcSubnetwork, err := expandAccessContextManagerAccessLevelBasicConditionsVpcNetworkSourcesVpcSubnetwork(original["vpc_subnetwork"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedVpcSubnetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["vpcSubnetwork"] = transformedVpcSubnetwork + } + + req = append(req, transformed) + } + return req, nil +} + +func expandAccessContextManagerAccessLevelBasicConditionsVpcNetworkSourcesVpcSubnetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedNetwork, err := expandAccessContextManagerAccessLevelBasicConditionsVpcNetworkSourcesVpcSubnetworkNetwork(original["network"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["network"] = transformedNetwork + } + + transformedVpcIpSubnetworks, err := expandAccessContextManagerAccessLevelBasicConditionsVpcNetworkSourcesVpcSubnetworkVpcIpSubnetworks(original["vpc_ip_subnetworks"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedVpcIpSubnetworks); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["vpcIpSubnetworks"] = transformedVpcIpSubnetworks + } + + return transformed, nil +} + +func expandAccessContextManagerAccessLevelBasicConditionsVpcNetworkSourcesVpcSubnetworkNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerAccessLevelBasicConditionsVpcNetworkSourcesVpcSubnetworkVpcIpSubnetworks(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandAccessContextManagerAccessLevelCustom(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { l := v.([]interface{}) if len(l) == 0 || l[0] == nil { diff --git a/google/services/accesscontextmanager/resource_access_context_manager_access_level_condition.go b/google/services/accesscontextmanager/resource_access_context_manager_access_level_condition.go index 34e0c4a8fd7..1817bfd1eae 100644 --- a/google/services/accesscontextmanager/resource_access_context_manager_access_level_condition.go +++ b/google/services/accesscontextmanager/resource_access_context_manager_access_level_condition.go @@ -195,6 +195,42 @@ Format: accessPolicies/{policy_id}/accessLevels/{short_name}`, Type: schema.TypeString, }, }, + "vpc_network_sources": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `The request must originate from one of the provided VPC networks in Google Cloud. Cannot specify this field together with 'ip_subnetworks'.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "vpc_subnetwork": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `Sub networks within a VPC network.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "network": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + Description: `Required. Network name to be allowed by this Access Level. Networks of foreign organizations requires 'compute.network.get' permission to be granted to caller.`, + }, + "vpc_ip_subnetworks": { + Type: schema.TypeList, + Optional: true, + ForceNew: true, + Description: `CIDR block IP subnetwork specification. Must be IPv4.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, }, UseJSONNumber: true, } @@ -244,6 +280,12 @@ func resourceAccessContextManagerAccessLevelConditionCreate(d *schema.ResourceDa } else if v, ok := d.GetOkExists("regions"); !tpgresource.IsEmptyValue(reflect.ValueOf(regionsProp)) && (ok || !reflect.DeepEqual(v, regionsProp)) { obj["regions"] = regionsProp } + vpcNetworkSourcesProp, err := expandNestedAccessContextManagerAccessLevelConditionVpcNetworkSources(d.Get("vpc_network_sources"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("vpc_network_sources"); !tpgresource.IsEmptyValue(reflect.ValueOf(vpcNetworkSourcesProp)) && (ok || !reflect.DeepEqual(v, vpcNetworkSourcesProp)) { + obj["vpcNetworkSources"] = vpcNetworkSourcesProp + } lockName, err := tpgresource.ReplaceVars(d, config, "{{access_level}}") if err != nil { @@ -408,6 +450,9 @@ func resourceAccessContextManagerAccessLevelConditionRead(d *schema.ResourceData if err := d.Set("regions", flattenNestedAccessContextManagerAccessLevelConditionRegions(res["regions"], d, config)); err != nil { return fmt.Errorf("Error reading AccessLevelCondition: %s", err) } + if err := d.Set("vpc_network_sources", flattenNestedAccessContextManagerAccessLevelConditionVpcNetworkSources(res["vpcNetworkSources"], d, config)); err != nil { + return fmt.Errorf("Error reading AccessLevelCondition: %s", err) + } return nil } @@ -557,6 +602,47 @@ func flattenNestedAccessContextManagerAccessLevelConditionRegions(v interface{}, return v } +func flattenNestedAccessContextManagerAccessLevelConditionVpcNetworkSources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "vpc_subnetwork": flattenNestedAccessContextManagerAccessLevelConditionVpcNetworkSourcesVpcSubnetwork(original["vpcSubnetwork"], d, config), + }) + } + return transformed +} +func flattenNestedAccessContextManagerAccessLevelConditionVpcNetworkSourcesVpcSubnetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["network"] = + flattenNestedAccessContextManagerAccessLevelConditionVpcNetworkSourcesVpcSubnetworkNetwork(original["network"], d, config) + transformed["vpc_ip_subnetworks"] = + flattenNestedAccessContextManagerAccessLevelConditionVpcNetworkSourcesVpcSubnetworkVpcIpSubnetworks(original["vpcIpSubnetworks"], d, config) + return []interface{}{transformed} +} +func flattenNestedAccessContextManagerAccessLevelConditionVpcNetworkSourcesVpcSubnetworkNetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNestedAccessContextManagerAccessLevelConditionVpcNetworkSourcesVpcSubnetworkVpcIpSubnetworks(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func expandNestedAccessContextManagerAccessLevelConditionIpSubnetworks(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { return v, nil } @@ -688,6 +774,62 @@ func expandNestedAccessContextManagerAccessLevelConditionRegions(v interface{}, return v, nil } +func expandNestedAccessContextManagerAccessLevelConditionVpcNetworkSources(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedVpcSubnetwork, err := expandNestedAccessContextManagerAccessLevelConditionVpcNetworkSourcesVpcSubnetwork(original["vpc_subnetwork"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedVpcSubnetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["vpcSubnetwork"] = transformedVpcSubnetwork + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNestedAccessContextManagerAccessLevelConditionVpcNetworkSourcesVpcSubnetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedNetwork, err := expandNestedAccessContextManagerAccessLevelConditionVpcNetworkSourcesVpcSubnetworkNetwork(original["network"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["network"] = transformedNetwork + } + + transformedVpcIpSubnetworks, err := expandNestedAccessContextManagerAccessLevelConditionVpcNetworkSourcesVpcSubnetworkVpcIpSubnetworks(original["vpc_ip_subnetworks"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedVpcIpSubnetworks); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["vpcIpSubnetworks"] = transformedVpcIpSubnetworks + } + + return transformed, nil +} + +func expandNestedAccessContextManagerAccessLevelConditionVpcNetworkSourcesVpcSubnetworkNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedAccessContextManagerAccessLevelConditionVpcNetworkSourcesVpcSubnetworkVpcIpSubnetworks(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func flattenNestedAccessContextManagerAccessLevelCondition(d *schema.ResourceData, meta interface{}, res map[string]interface{}) (map[string]interface{}, error) { var v interface{} var ok bool diff --git a/google/services/accesscontextmanager/resource_access_context_manager_access_level_condition_test.go b/google/services/accesscontextmanager/resource_access_context_manager_access_level_condition_test.go index df0491ecdf6..2d4196f0d62 100644 --- a/google/services/accesscontextmanager/resource_access_context_manager_access_level_condition_test.go +++ b/google/services/accesscontextmanager/resource_access_context_manager_access_level_condition_test.go @@ -24,10 +24,10 @@ func testAccAccessContextManagerAccessLevelCondition_basicTest(t *testing.T) { project := envvar.GetTestProjectFromEnv() serviceAccountName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10)) + vpcName := fmt.Sprintf("test-vpc-%s", acctest.RandString(t, 10)) expected := map[string]interface{}{ - "ipSubnetworks": []interface{}{"192.0.4.0/24"}, - "members": []interface{}{"user:test@google.com", "user:test2@google.com", fmt.Sprintf("serviceAccount:%s@%s.iam.gserviceaccount.com", serviceAccountName, project)}, + "members": []interface{}{"user:test@google.com", "user:test2@google.com", fmt.Sprintf("serviceAccount:%s@%s.iam.gserviceaccount.com", serviceAccountName, project)}, "devicePolicy": map[string]interface{}{ "requireCorpOwned": true, "osConstraints": []interface{}{ @@ -37,6 +37,14 @@ func testAccAccessContextManagerAccessLevelCondition_basicTest(t *testing.T) { }, }, "regions": []interface{}{"IT", "US"}, + "vpcNetworkSources": []interface{}{ + map[string]interface{}{ + "vpcSubnetwork": map[string]interface{}{ + "network": fmt.Sprintf("//compute.googleapis.com/projects/%s/global/networks/%s", project, vpcName), + "vpcIpSubnetworks": []interface{}{"20.0.5.0/24"}, + }, + }, + }, } acctest.VcrTest(t, resource.TestCase{ @@ -45,7 +53,7 @@ func testAccAccessContextManagerAccessLevelCondition_basicTest(t *testing.T) { CheckDestroy: testAccCheckAccessContextManagerAccessLevelConditionDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccAccessContextManagerAccessLevelCondition_basic(org, "my policy", "level", serviceAccountName), + Config: testAccAccessContextManagerAccessLevelCondition_basic(org, "my policy", "level", serviceAccountName, vpcName), Check: testAccCheckAccessContextManagerAccessLevelConditionPresent(t, "google_access_context_manager_access_level_condition.access-level-condition", expected), }, }, @@ -113,7 +121,7 @@ func testAccCheckAccessContextManagerAccessLevelConditionDestroyProducer(t *test } } -func testAccAccessContextManagerAccessLevelCondition_basic(org, policyTitle, levelTitleName, saName string) string { +func testAccAccessContextManagerAccessLevelCondition_basic(org, policyTitle, levelTitleName, saName, vpcName string) string { return fmt.Sprintf(` resource "google_access_context_manager_access_policy" "test-access" { parent = "organizations/%s" @@ -141,10 +149,6 @@ resource "google_access_context_manager_access_level" "test-access" { "US", ] } - - conditions { - ip_subnetworks = ["176.0.4.0/24"] - } } lifecycle { @@ -156,9 +160,12 @@ resource "google_service_account" "created-later" { account_id = "%s" } +resource "google_compute_network" "vpc_network" { + name = "%s" +} + resource "google_access_context_manager_access_level_condition" "access-level-condition" { access_level = google_access_context_manager_access_level.test-access.name - ip_subnetworks = ["192.0.4.0/24"] members = ["user:test@google.com", "user:test2@google.com", "serviceAccount:${google_service_account.created-later.email}"] negate = false device_policy { @@ -173,6 +180,13 @@ resource "google_access_context_manager_access_level_condition" "access-level-co "IT", "US", ] + + vpc_network_sources { + vpc_subnetwork { + network = "//compute.googleapis.com/${google_compute_network.vpc_network.id}" + vpc_ip_subnetworks = ["20.0.5.0/24"] + } + } } -`, org, policyTitle, levelTitleName, levelTitleName, saName) +`, org, policyTitle, levelTitleName, levelTitleName, saName, vpcName) } diff --git a/google/services/accesscontextmanager/resource_access_context_manager_access_level_test.go b/google/services/accesscontextmanager/resource_access_context_manager_access_level_test.go index a1327dc5dd2..94e3d59b159 100644 --- a/google/services/accesscontextmanager/resource_access_context_manager_access_level_test.go +++ b/google/services/accesscontextmanager/resource_access_context_manager_access_level_test.go @@ -20,6 +20,7 @@ import ( func testAccAccessContextManagerAccessLevel_basicTest(t *testing.T) { org := envvar.GetTestOrgFromEnv(t) + vpcName := fmt.Sprintf("test-vpc-%s", acctest.RandString(t, 10)) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -27,7 +28,7 @@ func testAccAccessContextManagerAccessLevel_basicTest(t *testing.T) { CheckDestroy: testAccCheckAccessContextManagerAccessLevelDestroyProducer(t), Steps: []resource.TestStep{ { - Config: testAccAccessContextManagerAccessLevel_basic(org, "my policy", "level"), + Config: testAccAccessContextManagerAccessLevel_basic(org, "my policy", "level", vpcName), }, { ResourceName: "google_access_context_manager_access_level.test-access", @@ -115,7 +116,7 @@ func testAccAccessContextManagerAccessLevel_customTest(t *testing.T) { }) } -func testAccAccessContextManagerAccessLevel_basic(org, policyTitle, levelTitleName string) string { +func testAccAccessContextManagerAccessLevel_basic(org, policyTitle, levelTitleName, vpcName string) string { return fmt.Sprintf(` resource "google_access_context_manager_access_policy" "test-access" { parent = "organizations/%s" @@ -134,7 +135,30 @@ resource "google_access_context_manager_access_level" "test-access" { } } } -`, org, policyTitle, levelTitleName, levelTitleName) + +resource "google_compute_network" "vpc_network" { + name = "%s" +} + +resource "google_access_context_manager_access_level" "test-access2" { + parent = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}" + name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/accessLevels/%s2" + title = "%s2" + description = "hello2" + basic { + combining_function = "AND" + conditions { + vpc_network_sources { + vpc_subnetwork { + network = "//compute.googleapis.com/${google_compute_network.vpc_network.id}" + vpc_ip_subnetworks = ["20.0.5.0/24"] + } + } + } + } +} + +`, org, policyTitle, levelTitleName, levelTitleName, vpcName, levelTitleName, levelTitleName) } func testAccAccessContextManagerAccessLevel_custom(org, policyTitle, levelTitleName string) string { diff --git a/google/services/accesscontextmanager/resource_access_context_manager_access_levels.go b/google/services/accesscontextmanager/resource_access_context_manager_access_levels.go index fa47844873c..7713bcc780f 100644 --- a/google/services/accesscontextmanager/resource_access_context_manager_access_levels.go +++ b/google/services/accesscontextmanager/resource_access_context_manager_access_levels.go @@ -229,6 +229,38 @@ Format: accessPolicies/{policy_id}/accessLevels/{short_name}`, Type: schema.TypeString, }, }, + "vpc_network_sources": { + Type: schema.TypeList, + Optional: true, + Description: `The request must originate from one of the provided VPC networks in Google Cloud. Cannot specify this field together with 'ip_subnetworks'.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "vpc_subnetwork": { + Type: schema.TypeList, + Optional: true, + Description: `Sub networks within a VPC network.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "network": { + Type: schema.TypeString, + Required: true, + Description: `Required. Network name to be allowed by this Access Level. Networks of foreign organizations requires 'compute.network.get' permission to be granted to caller.`, + }, + "vpc_ip_subnetworks": { + Type: schema.TypeList, + Optional: true, + Description: `CIDR block IP subnetwork specification. Must be IPv4.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + }, + }, + }, }, }, }, @@ -587,6 +619,7 @@ func flattenAccessContextManagerAccessLevelsAccessLevelsBasicConditions(v interf "negate": flattenAccessContextManagerAccessLevelsAccessLevelsBasicConditionsNegate(original["negate"], d, config), "device_policy": flattenAccessContextManagerAccessLevelsAccessLevelsBasicConditionsDevicePolicy(original["devicePolicy"], d, config), "regions": flattenAccessContextManagerAccessLevelsAccessLevelsBasicConditionsRegions(original["regions"], d, config), + "vpc_network_sources": flattenAccessContextManagerAccessLevelsAccessLevelsBasicConditionsVpcNetworkSources(original["vpcNetworkSources"], d, config), }) } return transformed @@ -681,6 +714,47 @@ func flattenAccessContextManagerAccessLevelsAccessLevelsBasicConditionsRegions(v return v } +func flattenAccessContextManagerAccessLevelsAccessLevelsBasicConditionsVpcNetworkSources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "vpc_subnetwork": flattenAccessContextManagerAccessLevelsAccessLevelsBasicConditionsVpcNetworkSourcesVpcSubnetwork(original["vpcSubnetwork"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerAccessLevelsAccessLevelsBasicConditionsVpcNetworkSourcesVpcSubnetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["network"] = + flattenAccessContextManagerAccessLevelsAccessLevelsBasicConditionsVpcNetworkSourcesVpcSubnetworkNetwork(original["network"], d, config) + transformed["vpc_ip_subnetworks"] = + flattenAccessContextManagerAccessLevelsAccessLevelsBasicConditionsVpcNetworkSourcesVpcSubnetworkVpcIpSubnetworks(original["vpcIpSubnetworks"], d, config) + return []interface{}{transformed} +} +func flattenAccessContextManagerAccessLevelsAccessLevelsBasicConditionsVpcNetworkSourcesVpcSubnetworkNetwork(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerAccessLevelsAccessLevelsBasicConditionsVpcNetworkSourcesVpcSubnetworkVpcIpSubnetworks(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenAccessContextManagerAccessLevelsAccessLevelsCustom(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { if v == nil { return nil @@ -874,6 +948,13 @@ func expandAccessContextManagerAccessLevelsAccessLevelsBasicConditions(v interfa transformed["regions"] = transformedRegions } + transformedVpcNetworkSources, err := expandAccessContextManagerAccessLevelsAccessLevelsBasicConditionsVpcNetworkSources(original["vpc_network_sources"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedVpcNetworkSources); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["vpcNetworkSources"] = transformedVpcNetworkSources + } + req = append(req, transformed) } return req, nil @@ -1010,6 +1091,62 @@ func expandAccessContextManagerAccessLevelsAccessLevelsBasicConditionsRegions(v return v, nil } +func expandAccessContextManagerAccessLevelsAccessLevelsBasicConditionsVpcNetworkSources(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedVpcSubnetwork, err := expandAccessContextManagerAccessLevelsAccessLevelsBasicConditionsVpcNetworkSourcesVpcSubnetwork(original["vpc_subnetwork"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedVpcSubnetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["vpcSubnetwork"] = transformedVpcSubnetwork + } + + req = append(req, transformed) + } + return req, nil +} + +func expandAccessContextManagerAccessLevelsAccessLevelsBasicConditionsVpcNetworkSourcesVpcSubnetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedNetwork, err := expandAccessContextManagerAccessLevelsAccessLevelsBasicConditionsVpcNetworkSourcesVpcSubnetworkNetwork(original["network"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNetwork); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["network"] = transformedNetwork + } + + transformedVpcIpSubnetworks, err := expandAccessContextManagerAccessLevelsAccessLevelsBasicConditionsVpcNetworkSourcesVpcSubnetworkVpcIpSubnetworks(original["vpc_ip_subnetworks"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedVpcIpSubnetworks); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["vpcIpSubnetworks"] = transformedVpcIpSubnetworks + } + + return transformed, nil +} + +func expandAccessContextManagerAccessLevelsAccessLevelsBasicConditionsVpcNetworkSourcesVpcSubnetworkNetwork(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerAccessLevelsAccessLevelsBasicConditionsVpcNetworkSourcesVpcSubnetworkVpcIpSubnetworks(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandAccessContextManagerAccessLevelsAccessLevelsCustom(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { l := v.([]interface{}) if len(l) == 0 || l[0] == nil { diff --git a/google/services/accesscontextmanager/resource_access_context_manager_access_levels_test.go b/google/services/accesscontextmanager/resource_access_context_manager_access_levels_test.go index aa8dd9dbb66..006e2efa7d7 100644 --- a/google/services/accesscontextmanager/resource_access_context_manager_access_levels_test.go +++ b/google/services/accesscontextmanager/resource_access_context_manager_access_levels_test.go @@ -19,6 +19,7 @@ import ( func testAccAccessContextManagerAccessLevels_basicTest(t *testing.T) { org := envvar.GetTestOrgFromEnv(t) + vpcName := fmt.Sprintf("test-vpc-%s", acctest.RandString(t, 10)) acctest.VcrTest(t, resource.TestCase{ PreCheck: func() { acctest.AccTestPreCheck(t) }, @@ -34,7 +35,7 @@ func testAccAccessContextManagerAccessLevels_basicTest(t *testing.T) { ImportStateVerify: true, }, { - Config: testAccAccessContextManagerAccessLevels_basicUpdated(org, "my new policy", "corpnet_access", "prodnet_access"), + Config: testAccAccessContextManagerAccessLevels_basicUpdated(org, "my new policy", "corpnet_access", "prodnet_access", vpcName), }, { ResourceName: "google_access_context_manager_access_levels.test-access", @@ -118,13 +119,17 @@ resource "google_access_context_manager_access_levels" "test-access" { `, org, policyTitle, levelTitleName1, levelTitleName1, levelTitleName2, levelTitleName2) } -func testAccAccessContextManagerAccessLevels_basicUpdated(org, policyTitle, levelTitleName1, levelTitleName2 string) string { +func testAccAccessContextManagerAccessLevels_basicUpdated(org, policyTitle, levelTitleName1, levelTitleName2, vpcName string) string { return fmt.Sprintf(` resource "google_access_context_manager_access_policy" "test-access" { parent = "organizations/%s" title = "%s" } +resource "google_compute_network" "vpc_network" { + name = "%s" +} + resource "google_access_context_manager_access_levels" "test-access" { parent = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}" @@ -141,17 +146,22 @@ resource "google_access_context_manager_access_levels" "test-access" { } access_levels { - name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/accessLevels/%s" - title = "%s" - description = "hello again" - basic { - conditions { - ip_subnetworks = ["176.0.4.0/24"] - } + name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/accessLevels/%s" + title = "%s" + description = "hello again" + basic { + conditions { + vpc_network_sources { + vpc_subnetwork { + network = "//compute.googleapis.com/${google_compute_network.vpc_network.id}" + vpc_ip_subnetworks = ["20.0.5.0/24"] + } + } + } } } } -`, org, policyTitle, levelTitleName1, levelTitleName1, levelTitleName2, levelTitleName2) +`, org, policyTitle, vpcName, levelTitleName1, levelTitleName1, levelTitleName2, levelTitleName2) } func testAccAccessContextManagerAccessLevel_empty(org, policyTitle string) string { diff --git a/google/services/accesscontextmanager/resource_access_context_manager_service_perimeter.go b/google/services/accesscontextmanager/resource_access_context_manager_service_perimeter.go index 47502d91ad1..c7a1dc1b5e0 100644 --- a/google/services/accesscontextmanager/resource_access_context_manager_service_perimeter.go +++ b/google/services/accesscontextmanager/resource_access_context_manager_service_perimeter.go @@ -162,6 +162,26 @@ represent individual user or service account only.`, perimeter. If left unspecified, then members of 'identities' field will be allowed access. Possible values: ["IDENTITY_TYPE_UNSPECIFIED", "ANY_IDENTITY", "ANY_USER_ACCOUNT", "ANY_SERVICE_ACCOUNT"]`, }, + "source_restriction": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidateEnum([]string{"SOURCE_RESTRICTION_UNSPECIFIED", "SOURCE_RESTRICTION_ENABLED", "SOURCE_RESTRICTION_DISABLED", ""}), + Description: `Whether to enforce traffic restrictions based on 'sources' field. If the 'sources' field is non-empty, then this field must be set to 'SOURCE_RESTRICTION_ENABLED'. Possible values: ["SOURCE_RESTRICTION_UNSPECIFIED", "SOURCE_RESTRICTION_ENABLED", "SOURCE_RESTRICTION_DISABLED"]`, + }, + "sources": { + Type: schema.TypeList, + Optional: true, + Description: `Sources that this EgressPolicy authorizes access from.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "access_level": { + Type: schema.TypeString, + Optional: true, + Description: `An AccessLevel resource name that allows resources outside the ServicePerimeter to be accessed from the inside.`, + }, + }, + }, + }, }, }, }, @@ -506,6 +526,26 @@ represent individual user or service account only.`, perimeter. If left unspecified, then members of 'identities' field will be allowed access. Possible values: ["IDENTITY_TYPE_UNSPECIFIED", "ANY_IDENTITY", "ANY_USER_ACCOUNT", "ANY_SERVICE_ACCOUNT"]`, }, + "source_restriction": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidateEnum([]string{"SOURCE_RESTRICTION_UNSPECIFIED", "SOURCE_RESTRICTION_ENABLED", "SOURCE_RESTRICTION_DISABLED", ""}), + Description: `Whether to enforce traffic restrictions based on 'sources' field. If the 'sources' field is non-empty, then this field must be set to 'SOURCE_RESTRICTION_ENABLED'. Possible values: ["SOURCE_RESTRICTION_UNSPECIFIED", "SOURCE_RESTRICTION_ENABLED", "SOURCE_RESTRICTION_DISABLED"]`, + }, + "sources": { + Type: schema.TypeList, + Optional: true, + Description: `Sources that this EgressPolicy authorizes access from.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "access_level": { + Type: schema.TypeString, + Optional: true, + Description: `An AccessLevel resource name that allows resources outside the ServicePerimeter to be accessed from the inside.`, + }, + }, + }, + }, }, }, }, @@ -1470,6 +1510,10 @@ func flattenAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFrom(v transformed := make(map[string]interface{}) transformed["identity_type"] = flattenAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromIdentityType(original["identityType"], d, config) + transformed["sources"] = + flattenAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromSources(original["sources"], d, config) + transformed["source_restriction"] = + flattenAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromSourceRestriction(original["sourceRestriction"], d, config) transformed["identities"] = flattenAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromIdentities(original["identities"], d, config) return []interface{}{transformed} @@ -1478,6 +1522,32 @@ func flattenAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromId return v } +func flattenAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromSources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "access_level": flattenAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromSourcesAccessLevel(original["accessLevel"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromSourcesAccessLevel(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromSourceRestriction(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromIdentities(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { if v == nil { return v @@ -1812,6 +1882,10 @@ func flattenAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFrom(v i transformed := make(map[string]interface{}) transformed["identity_type"] = flattenAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromIdentityType(original["identityType"], d, config) + transformed["sources"] = + flattenAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromSources(original["sources"], d, config) + transformed["source_restriction"] = + flattenAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromSourceRestriction(original["sourceRestriction"], d, config) transformed["identities"] = flattenAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromIdentities(original["identities"], d, config) return []interface{}{transformed} @@ -1820,6 +1894,32 @@ func flattenAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromIden return v } +func flattenAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromSources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "access_level": flattenAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromSourcesAccessLevel(original["accessLevel"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromSourcesAccessLevel(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromSourceRestriction(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromIdentities(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { if v == nil { return v @@ -2286,6 +2386,20 @@ func expandAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFrom(v transformed["identityType"] = transformedIdentityType } + transformedSources, err := expandAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromSources(original["sources"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSources); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["sources"] = transformedSources + } + + transformedSourceRestriction, err := expandAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromSourceRestriction(original["source_restriction"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSourceRestriction); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["sourceRestriction"] = transformedSourceRestriction + } + transformedIdentities, err := expandAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromIdentities(original["identities"], d, config) if err != nil { return nil, err @@ -2300,6 +2414,36 @@ func expandAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromIde return v, nil } +func expandAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromSources(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedAccessLevel, err := expandAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromSourcesAccessLevel(original["access_level"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAccessLevel); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["accessLevel"] = transformedAccessLevel + } + + req = append(req, transformed) + } + return req, nil +} + +func expandAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromSourcesAccessLevel(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromSourceRestriction(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandAccessContextManagerServicePerimeterStatusEgressPoliciesEgressFromIdentities(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { v = v.(*schema.Set).List() return v, nil @@ -2776,6 +2920,20 @@ func expandAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFrom(v in transformed["identityType"] = transformedIdentityType } + transformedSources, err := expandAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromSources(original["sources"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSources); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["sources"] = transformedSources + } + + transformedSourceRestriction, err := expandAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromSourceRestriction(original["source_restriction"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSourceRestriction); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["sourceRestriction"] = transformedSourceRestriction + } + transformedIdentities, err := expandAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromIdentities(original["identities"], d, config) if err != nil { return nil, err @@ -2790,6 +2948,36 @@ func expandAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromIdent return v, nil } +func expandAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromSources(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedAccessLevel, err := expandAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromSourcesAccessLevel(original["access_level"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAccessLevel); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["accessLevel"] = transformedAccessLevel + } + + req = append(req, transformed) + } + return req, nil +} + +func expandAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromSourcesAccessLevel(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromSourceRestriction(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandAccessContextManagerServicePerimeterSpecEgressPoliciesEgressFromIdentities(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { v = v.(*schema.Set).List() return v, nil diff --git a/google/services/accesscontextmanager/resource_access_context_manager_service_perimeter_egress_policy.go b/google/services/accesscontextmanager/resource_access_context_manager_service_perimeter_egress_policy.go index 43d6cacc93d..031789c5643 100644 --- a/google/services/accesscontextmanager/resource_access_context_manager_service_perimeter_egress_policy.go +++ b/google/services/accesscontextmanager/resource_access_context_manager_service_perimeter_egress_policy.go @@ -81,6 +81,26 @@ represent individual user or service account only.`, perimeter. If left unspecified, then members of 'identities' field will be allowed access. Possible values: ["ANY_IDENTITY", "ANY_USER_ACCOUNT", "ANY_SERVICE_ACCOUNT"]`, }, + "source_restriction": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidateEnum([]string{"SOURCE_RESTRICTION_UNSPECIFIED", "SOURCE_RESTRICTION_ENABLED", "SOURCE_RESTRICTION_DISABLED", ""}), + Description: `Whether to enforce traffic restrictions based on 'sources' field. If the 'sources' field is non-empty, then this field must be set to 'SOURCE_RESTRICTION_ENABLED'. Possible values: ["SOURCE_RESTRICTION_UNSPECIFIED", "SOURCE_RESTRICTION_ENABLED", "SOURCE_RESTRICTION_DISABLED"]`, + }, + "sources": { + Type: schema.TypeList, + Optional: true, + Description: `Sources that this EgressPolicy authorizes access from.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "access_level": { + Type: schema.TypeString, + Optional: true, + Description: `An AccessLevel resource name that allows resources outside the ServicePerimeter to be accessed from the inside.`, + }, + }, + }, + }, }, }, }, @@ -511,6 +531,10 @@ func flattenNestedAccessContextManagerServicePerimeterEgressPolicyEgressFrom(v i flattenNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromIdentityType(original["identityType"], d, config) transformed["identities"] = flattenNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromIdentities(original["identities"], d, config) + transformed["sources"] = + flattenNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromSources(original["sources"], d, config) + transformed["source_restriction"] = + flattenNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromSourceRestriction(original["sourceRestriction"], d, config) return []interface{}{transformed} } func flattenNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromIdentityType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { @@ -521,6 +545,32 @@ func flattenNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromIden return v } +func flattenNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromSources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "access_level": flattenNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromSourcesAccessLevel(original["accessLevel"], d, config), + }) + } + return transformed +} +func flattenNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromSourcesAccessLevel(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromSourceRestriction(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenNestedAccessContextManagerServicePerimeterEgressPolicyEgressTo(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { if v == nil { return nil @@ -619,6 +669,20 @@ func expandNestedAccessContextManagerServicePerimeterEgressPolicyEgressFrom(v in transformed["identities"] = transformedIdentities } + transformedSources, err := expandNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromSources(original["sources"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSources); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["sources"] = transformedSources + } + + transformedSourceRestriction, err := expandNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromSourceRestriction(original["source_restriction"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSourceRestriction); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["sourceRestriction"] = transformedSourceRestriction + } + return transformed, nil } @@ -630,6 +694,36 @@ func expandNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromIdent return v, nil } +func expandNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromSources(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedAccessLevel, err := expandNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromSourcesAccessLevel(original["access_level"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAccessLevel); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["accessLevel"] = transformedAccessLevel + } + + req = append(req, transformed) + } + return req, nil +} + +func expandNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromSourcesAccessLevel(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandNestedAccessContextManagerServicePerimeterEgressPolicyEgressFromSourceRestriction(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandNestedAccessContextManagerServicePerimeterEgressPolicyEgressTo(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { l := v.([]interface{}) if len(l) == 0 || l[0] == nil { diff --git a/google/services/accesscontextmanager/resource_access_context_manager_service_perimeter_egress_policy_test.go b/google/services/accesscontextmanager/resource_access_context_manager_service_perimeter_egress_policy_test.go index a68fa6a4451..2cff05d2e6e 100644 --- a/google/services/accesscontextmanager/resource_access_context_manager_service_perimeter_egress_policy_test.go +++ b/google/services/accesscontextmanager/resource_access_context_manager_service_perimeter_egress_policy_test.go @@ -112,10 +112,27 @@ resource "google_access_context_manager_service_perimeter_egress_policy" "test-a } +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_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" } } diff --git a/google/services/accesscontextmanager/resource_access_context_manager_service_perimeter_test.go b/google/services/accesscontextmanager/resource_access_context_manager_service_perimeter_test.go index b33252b7d5d..205687fd7bc 100644 --- a/google/services/accesscontextmanager/resource_access_context_manager_service_perimeter_test.go +++ b/google/services/accesscontextmanager/resource_access_context_manager_service_perimeter_test.go @@ -265,6 +265,10 @@ resource "google_access_context_manager_service_perimeter" "test-access" { egress_policies { egress_from { identity_type = "ANY_USER_ACCOUNT" + sources { + access_level = google_access_context_manager_access_level.test-access.name + } + source_restriction = "SOURCE_RESTRICTION_ENABLED" } egress_to { operations { @@ -341,6 +345,10 @@ resource "google_access_context_manager_service_perimeter" "test-access" { egress_policies { egress_from { identity_type = "ANY_USER_ACCOUNT" + sources { + access_level = google_access_context_manager_access_level.test-access.name + } + source_restriction = "SOURCE_RESTRICTION_ENABLED" } egress_to { operations { diff --git a/google/services/accesscontextmanager/resource_access_context_manager_service_perimeters.go b/google/services/accesscontextmanager/resource_access_context_manager_service_perimeters.go index 9b1eec05069..3753557a9f6 100644 --- a/google/services/accesscontextmanager/resource_access_context_manager_service_perimeters.go +++ b/google/services/accesscontextmanager/resource_access_context_manager_service_perimeters.go @@ -166,6 +166,26 @@ represent individual user or service account only.`, perimeter. If left unspecified, then members of 'identities' field will be allowed access. Possible values: ["IDENTITY_TYPE_UNSPECIFIED", "ANY_IDENTITY", "ANY_USER_ACCOUNT", "ANY_SERVICE_ACCOUNT"]`, }, + "source_restriction": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidateEnum([]string{"SOURCE_RESTRICTION_UNSPECIFIED", "SOURCE_RESTRICTION_ENABLED", "SOURCE_RESTRICTION_DISABLED", ""}), + Description: `Whether to enforce traffic restrictions based on 'sources' field. If the 'sources' field is non-empty, then this field must be set to 'SOURCE_RESTRICTION_ENABLED'. Possible values: ["SOURCE_RESTRICTION_UNSPECIFIED", "SOURCE_RESTRICTION_ENABLED", "SOURCE_RESTRICTION_DISABLED"]`, + }, + "sources": { + Type: schema.TypeList, + Optional: true, + Description: `Sources that this EgressPolicy authorizes access from.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "access_level": { + Type: schema.TypeString, + Optional: true, + Description: `An AccessLevel resource name that allows resources outside the ServicePerimeter to be accessed from the inside.`, + }, + }, + }, + }, }, }, }, @@ -507,6 +527,26 @@ represent individual user or service account only.`, perimeter. If left unspecified, then members of 'identities' field will be allowed access. Possible values: ["IDENTITY_TYPE_UNSPECIFIED", "ANY_IDENTITY", "ANY_USER_ACCOUNT", "ANY_SERVICE_ACCOUNT"]`, }, + "source_restriction": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: verify.ValidateEnum([]string{"SOURCE_RESTRICTION_UNSPECIFIED", "SOURCE_RESTRICTION_ENABLED", "SOURCE_RESTRICTION_DISABLED", ""}), + Description: `Whether to enforce traffic restrictions based on 'sources' field. If the 'sources' field is non-empty, then this field must be set to 'SOURCE_RESTRICTION_ENABLED'. Possible values: ["SOURCE_RESTRICTION_UNSPECIFIED", "SOURCE_RESTRICTION_ENABLED", "SOURCE_RESTRICTION_DISABLED"]`, + }, + "sources": { + Type: schema.TypeList, + Optional: true, + Description: `Sources that this EgressPolicy authorizes access from.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "access_level": { + Type: schema.TypeString, + Optional: true, + Description: `An AccessLevel resource name that allows resources outside the ServicePerimeter to be accessed from the inside.`, + }, + }, + }, + }, }, }, }, @@ -1349,6 +1389,10 @@ func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPo flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromIdentityType(original["identityType"], d, config) transformed["identities"] = flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromIdentities(original["identities"], d, config) + transformed["sources"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSources(original["sources"], d, config) + transformed["source_restriction"] = + flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSourceRestriction(original["sourceRestriction"], d, config) return []interface{}{transformed} } func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromIdentityType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { @@ -1362,6 +1406,32 @@ func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPo return schema.NewSet(schema.HashString, v.([]interface{})) } +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "access_level": flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSourcesAccessLevel(original["accessLevel"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSourcesAccessLevel(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSourceRestriction(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressTo(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { if v == nil { return nil @@ -1691,6 +1761,10 @@ func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoli flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromIdentityType(original["identityType"], d, config) transformed["identities"] = flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromIdentities(original["identities"], d, config) + transformed["sources"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSources(original["sources"], d, config) + transformed["source_restriction"] = + flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSourceRestriction(original["sourceRestriction"], d, config) return []interface{}{transformed} } func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromIdentityType(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { @@ -1704,6 +1778,32 @@ func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoli return schema.NewSet(schema.HashString, v.([]interface{})) } +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSources(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return v + } + l := v.([]interface{}) + transformed := make([]interface{}, 0, len(l)) + for _, raw := range l { + original := raw.(map[string]interface{}) + if len(original) < 1 { + // Do not include empty json objects coming back from the api + continue + } + transformed = append(transformed, map[string]interface{}{ + "access_level": flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSourcesAccessLevel(original["accessLevel"], d, config), + }) + } + return transformed +} +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSourcesAccessLevel(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSourceRestriction(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + func flattenAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressTo(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { if v == nil { return nil @@ -2257,6 +2357,20 @@ func expandAccessContextManagerServicePerimetersServicePerimetersStatusEgressPol transformed["identities"] = transformedIdentities } + transformedSources, err := expandAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSources(original["sources"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSources); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["sources"] = transformedSources + } + + transformedSourceRestriction, err := expandAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSourceRestriction(original["source_restriction"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSourceRestriction); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["sourceRestriction"] = transformedSourceRestriction + } + return transformed, nil } @@ -2269,6 +2383,36 @@ func expandAccessContextManagerServicePerimetersServicePerimetersStatusEgressPol return v, nil } +func expandAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSources(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedAccessLevel, err := expandAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSourcesAccessLevel(original["access_level"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAccessLevel); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["accessLevel"] = transformedAccessLevel + } + + req = append(req, transformed) + } + return req, nil +} + +func expandAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSourcesAccessLevel(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressFromSourceRestriction(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandAccessContextManagerServicePerimetersServicePerimetersStatusEgressPoliciesEgressTo(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { l := v.([]interface{}) if len(l) == 0 || l[0] == nil { @@ -2747,6 +2891,20 @@ func expandAccessContextManagerServicePerimetersServicePerimetersSpecEgressPolic transformed["identities"] = transformedIdentities } + transformedSources, err := expandAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSources(original["sources"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSources); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["sources"] = transformedSources + } + + transformedSourceRestriction, err := expandAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSourceRestriction(original["source_restriction"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSourceRestriction); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["sourceRestriction"] = transformedSourceRestriction + } + return transformed, nil } @@ -2759,6 +2917,36 @@ func expandAccessContextManagerServicePerimetersServicePerimetersSpecEgressPolic return v, nil } +func expandAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSources(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + req := make([]interface{}, 0, len(l)) + for _, raw := range l { + if raw == nil { + continue + } + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedAccessLevel, err := expandAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSourcesAccessLevel(original["access_level"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAccessLevel); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["accessLevel"] = transformedAccessLevel + } + + req = append(req, transformed) + } + return req, nil +} + +func expandAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSourcesAccessLevel(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressFromSourceRestriction(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandAccessContextManagerServicePerimetersServicePerimetersSpecEgressPoliciesEgressTo(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { l := v.([]interface{}) if len(l) == 0 || l[0] == nil { diff --git a/google/services/accesscontextmanager/resource_access_context_manager_services_perimeters_test.go b/google/services/accesscontextmanager/resource_access_context_manager_services_perimeters_test.go index 4bc553412ff..54013a39a1f 100644 --- a/google/services/accesscontextmanager/resource_access_context_manager_services_perimeters_test.go +++ b/google/services/accesscontextmanager/resource_access_context_manager_services_perimeters_test.go @@ -138,6 +138,13 @@ resource "google_access_context_manager_service_perimeters" "test-access" { } } } + egress_from { + identity_type = "ANY_USER_ACCOUNT" + sources { + access_level = google_access_context_manager_access_level.test-access.name + } + source_restriction = "SOURCE_RESTRICTION_ENABLED" + } } } } diff --git a/website/docs/r/access_context_manager_access_level.html.markdown b/website/docs/r/access_context_manager_access_level.html.markdown index b59eae4027c..b5763905132 100644 --- a/website/docs/r/access_context_manager_access_level.html.markdown +++ b/website/docs/r/access_context_manager_access_level.html.markdown @@ -177,6 +177,11 @@ The following arguments are supported: countries/regions. Format: A valid ISO 3166-1 alpha-2 code. +* `vpc_network_sources` - + (Optional) + The request must originate from one of the provided VPC networks in Google Cloud. Cannot specify this field together with `ip_subnetworks`. + Structure is [documented below](#nested_vpc_network_sources). + The `device_policy` block supports: @@ -229,6 +234,24 @@ The following arguments are supported: The operating system type of the device. Possible values are: `OS_UNSPECIFIED`, `DESKTOP_MAC`, `DESKTOP_WINDOWS`, `DESKTOP_LINUX`, `DESKTOP_CHROME_OS`, `ANDROID`, `IOS`. +The `vpc_network_sources` block supports: + +* `vpc_subnetwork` - + (Optional) + Sub networks within a VPC network. + Structure is [documented below](#nested_vpc_subnetwork). + + +The `vpc_subnetwork` block supports: + +* `network` - + (Required) + Required. Network name to be allowed by this Access Level. Networks of foreign organizations requires `compute.network.get` permission to be granted to caller. + +* `vpc_ip_subnetworks` - + (Optional) + CIDR block IP subnetwork specification. Must be IPv4. + The `custom` block supports: * `expr` - diff --git a/website/docs/r/access_context_manager_access_level_condition.html.markdown b/website/docs/r/access_context_manager_access_level_condition.html.markdown index 86b4d12c919..67943700c67 100644 --- a/website/docs/r/access_context_manager_access_level_condition.html.markdown +++ b/website/docs/r/access_context_manager_access_level_condition.html.markdown @@ -162,6 +162,11 @@ The following arguments are supported: countries/regions. Format: A valid ISO 3166-1 alpha-2 code. +* `vpc_network_sources` - + (Optional) + The request must originate from one of the provided VPC networks in Google Cloud. Cannot specify this field together with `ip_subnetworks`. + Structure is [documented below](#nested_vpc_network_sources). + The `device_policy` block supports: @@ -210,6 +215,24 @@ The following arguments are supported: The operating system type of the device. Possible values are: `OS_UNSPECIFIED`, `DESKTOP_MAC`, `DESKTOP_WINDOWS`, `DESKTOP_LINUX`, `DESKTOP_CHROME_OS`, `ANDROID`, `IOS`. +The `vpc_network_sources` block supports: + +* `vpc_subnetwork` - + (Optional) + Sub networks within a VPC network. + Structure is [documented below](#nested_vpc_subnetwork). + + +The `vpc_subnetwork` block supports: + +* `network` - + (Required) + Required. Network name to be allowed by this Access Level. Networks of foreign organizations requires `compute.network.get` permission to be granted to caller. + +* `vpc_ip_subnetworks` - + (Optional) + CIDR block IP subnetwork specification. Must be IPv4. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: diff --git a/website/docs/r/access_context_manager_access_levels.html.markdown b/website/docs/r/access_context_manager_access_levels.html.markdown index 68bedae7e17..b88ce5c1ff8 100644 --- a/website/docs/r/access_context_manager_access_levels.html.markdown +++ b/website/docs/r/access_context_manager_access_levels.html.markdown @@ -201,6 +201,11 @@ The following arguments are supported: countries/regions. Format: A valid ISO 3166-1 alpha-2 code. +* `vpc_network_sources` - + (Optional) + The request must originate from one of the provided VPC networks in Google Cloud. Cannot specify this field together with `ip_subnetworks`. + Structure is [documented below](#nested_vpc_network_sources). + The `device_policy` block supports: @@ -249,6 +254,24 @@ The following arguments are supported: The operating system type of the device. Possible values are: `OS_UNSPECIFIED`, `DESKTOP_MAC`, `DESKTOP_WINDOWS`, `DESKTOP_LINUX`, `DESKTOP_CHROME_OS`, `ANDROID`, `IOS`. +The `vpc_network_sources` block supports: + +* `vpc_subnetwork` - + (Optional) + Sub networks within a VPC network. + Structure is [documented below](#nested_vpc_subnetwork). + + +The `vpc_subnetwork` block supports: + +* `network` - + (Required) + Required. Network name to be allowed by this Access Level. Networks of foreign organizations requires `compute.network.get` permission to be granted to caller. + +* `vpc_ip_subnetworks` - + (Optional) + CIDR block IP subnetwork specification. Must be IPv4. + The `custom` block supports: * `expr` - diff --git a/website/docs/r/access_context_manager_service_perimeter.html.markdown b/website/docs/r/access_context_manager_service_perimeter.html.markdown index 49055b0727b..c712adeff32 100644 --- a/website/docs/r/access_context_manager_service_perimeter.html.markdown +++ b/website/docs/r/access_context_manager_service_perimeter.html.markdown @@ -494,12 +494,29 @@ The following arguments are supported: be allowed access. Possible values are: `IDENTITY_TYPE_UNSPECIFIED`, `ANY_IDENTITY`, `ANY_USER_ACCOUNT`, `ANY_SERVICE_ACCOUNT`. +* `sources` - + (Optional) + Sources that this EgressPolicy authorizes access from. + Structure is [documented below](#nested_sources). + +* `source_restriction` - + (Optional) + Whether to enforce traffic restrictions based on `sources` field. If the `sources` field is non-empty, then this field must be set to `SOURCE_RESTRICTION_ENABLED`. + Possible values are: `SOURCE_RESTRICTION_UNSPECIFIED`, `SOURCE_RESTRICTION_ENABLED`, `SOURCE_RESTRICTION_DISABLED`. + * `identities` - (Optional) 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. + +The `sources` block supports: + +* `access_level` - + (Optional) + An AccessLevel resource name that allows resources outside the ServicePerimeter to be accessed from the inside. + The `egress_to` block supports: * `resources` - @@ -747,12 +764,29 @@ The following arguments are supported: be allowed access. Possible values are: `IDENTITY_TYPE_UNSPECIFIED`, `ANY_IDENTITY`, `ANY_USER_ACCOUNT`, `ANY_SERVICE_ACCOUNT`. +* `sources` - + (Optional) + Sources that this EgressPolicy authorizes access from. + Structure is [documented below](#nested_sources). + +* `source_restriction` - + (Optional) + Whether to enforce traffic restrictions based on `sources` field. If the `sources` field is non-empty, then this field must be set to `SOURCE_RESTRICTION_ENABLED`. + Possible values are: `SOURCE_RESTRICTION_UNSPECIFIED`, `SOURCE_RESTRICTION_ENABLED`, `SOURCE_RESTRICTION_DISABLED`. + * `identities` - (Optional) 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. + +The `sources` block supports: + +* `access_level` - + (Optional) + An AccessLevel resource name that allows resources outside the ServicePerimeter to be accessed from the inside. + The `egress_to` block supports: * `resources` - diff --git a/website/docs/r/access_context_manager_service_perimeter_egress_policy.html.markdown b/website/docs/r/access_context_manager_service_perimeter_egress_policy.html.markdown index 396c26624c5..07212d46492 100644 --- a/website/docs/r/access_context_manager_service_perimeter_egress_policy.html.markdown +++ b/website/docs/r/access_context_manager_service_perimeter_egress_policy.html.markdown @@ -72,6 +72,23 @@ The following arguments are supported: Should be in the format of email address. The email address should represent individual user or service account only. +* `sources` - + (Optional) + Sources that this EgressPolicy authorizes access from. + Structure is [documented below](#nested_sources). + +* `source_restriction` - + (Optional) + Whether to enforce traffic restrictions based on `sources` field. If the `sources` field is non-empty, then this field must be set to `SOURCE_RESTRICTION_ENABLED`. + Possible values are: `SOURCE_RESTRICTION_UNSPECIFIED`, `SOURCE_RESTRICTION_ENABLED`, `SOURCE_RESTRICTION_DISABLED`. + + +The `sources` block supports: + +* `access_level` - + (Optional) + An AccessLevel resource name that allows resources outside the ServicePerimeter to be accessed from the inside. + The `egress_to` block supports: * `resources` - diff --git a/website/docs/r/access_context_manager_service_perimeters.html.markdown b/website/docs/r/access_context_manager_service_perimeters.html.markdown index 859f7d85016..8a8cbbb97e1 100644 --- a/website/docs/r/access_context_manager_service_perimeters.html.markdown +++ b/website/docs/r/access_context_manager_service_perimeters.html.markdown @@ -373,6 +373,23 @@ The following arguments are supported: Should be in the format of email address. The email address should represent individual user or service account only. +* `sources` - + (Optional) + Sources that this EgressPolicy authorizes access from. + Structure is [documented below](#nested_sources). + +* `source_restriction` - + (Optional) + Whether to enforce traffic restrictions based on `sources` field. If the `sources` field is non-empty, then this field must be set to `SOURCE_RESTRICTION_ENABLED`. + Possible values are: `SOURCE_RESTRICTION_UNSPECIFIED`, `SOURCE_RESTRICTION_ENABLED`, `SOURCE_RESTRICTION_DISABLED`. + + +The `sources` block supports: + +* `access_level` - + (Optional) + An AccessLevel resource name that allows resources outside the ServicePerimeter to be accessed from the inside. + The `egress_to` block supports: * `resources` - @@ -626,6 +643,23 @@ The following arguments are supported: Should be in the format of email address. The email address should represent individual user or service account only. +* `sources` - + (Optional) + Sources that this EgressPolicy authorizes access from. + Structure is [documented below](#nested_sources). + +* `source_restriction` - + (Optional) + Whether to enforce traffic restrictions based on `sources` field. If the `sources` field is non-empty, then this field must be set to `SOURCE_RESTRICTION_ENABLED`. + Possible values are: `SOURCE_RESTRICTION_UNSPECIFIED`, `SOURCE_RESTRICTION_ENABLED`, `SOURCE_RESTRICTION_DISABLED`. + + +The `sources` block supports: + +* `access_level` - + (Optional) + An AccessLevel resource name that allows resources outside the ServicePerimeter to be accessed from the inside. + The `egress_to` block supports: * `resources` -