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` -