From 63d7c6f810fa0d486ec3049779e4ae0f3968d079 Mon Sep 17 00:00:00 2001 From: The Magician Date: Mon, 30 Mar 2020 09:34:30 -0700 Subject: [PATCH] ACM: service perimeter's vpc_accessible_services (#3318) (#6006) Signed-off-by: Modular Magician --- .changelog/3318.txt | 3 + ...ccess_context_manager_service_perimeter.go | 97 +++++++++++++++++++ ..._context_manager_service_perimeter_test.go | 46 +++++++++ ...xt_manager_service_perimeter.html.markdown | 18 ++++ 4 files changed, 164 insertions(+) create mode 100644 .changelog/3318.txt diff --git a/.changelog/3318.txt b/.changelog/3318.txt new file mode 100644 index 00000000000..26eb5a47b42 --- /dev/null +++ b/.changelog/3318.txt @@ -0,0 +1,3 @@ +```release-note:enhancement +accesscontextmanager: added `status.vpc_accessible_services` to `google_access_context_manager_service_perimeter` to control which services are available from the perimeter's VPC networks to the restricted Google APIs IP address range. +``` diff --git a/google/resource_access_context_manager_service_perimeter.go b/google/resource_access_context_manager_service_perimeter.go index fc52e0ddf9a..a3b917a6bb8 100644 --- a/google/resource_access_context_manager_service_perimeter.go +++ b/google/resource_access_context_manager_service_perimeter.go @@ -144,6 +144,33 @@ restrictions.`, Set: schema.HashString, AtLeastOneOf: []string{"status.0.resources", "status.0.access_levels", "status.0.restricted_services"}, }, + "vpc_accessible_services": { + Type: schema.TypeList, + Optional: true, + Description: `Specifies how APIs are allowed to communicate within the Service +Perimeter.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allowed_services": { + Type: schema.TypeSet, + Optional: true, + Description: `The list of APIs usable within the Service Perimeter. +Must be empty unless 'enableRestriction' is True.`, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Set: schema.HashString, + }, + "enable_restriction": { + Type: schema.TypeBool, + Optional: true, + Description: `Whether to restrict API calls within the Service Perimeter to the +list of APIs specified in 'allowedServices'.`, + }, + }, + }, + }, }, }, }, @@ -464,6 +491,8 @@ func flattenAccessContextManagerServicePerimeterStatus(v interface{}, d *schema. flattenAccessContextManagerServicePerimeterStatusAccessLevels(original["accessLevels"], d, config) transformed["restricted_services"] = flattenAccessContextManagerServicePerimeterStatusRestrictedServices(original["restrictedServices"], d, config) + transformed["vpc_accessible_services"] = + flattenAccessContextManagerServicePerimeterStatusVPCAccessibleServices(original["vpcAccessibleServices"], d, config) return []interface{}{transformed} } func flattenAccessContextManagerServicePerimeterStatusResources(v interface{}, d *schema.ResourceData, config *Config) interface{} { @@ -481,6 +510,32 @@ func flattenAccessContextManagerServicePerimeterStatusRestrictedServices(v inter return schema.NewSet(schema.HashString, v.([]interface{})) } +func flattenAccessContextManagerServicePerimeterStatusVPCAccessibleServices(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["enable_restriction"] = + flattenAccessContextManagerServicePerimeterStatusVPCAccessibleServicesEnableRestriction(original["enableRestriction"], d, config) + transformed["allowed_services"] = + flattenAccessContextManagerServicePerimeterStatusVPCAccessibleServicesAllowedServices(original["allowedServices"], d, config) + return []interface{}{transformed} +} +func flattenAccessContextManagerServicePerimeterStatusVPCAccessibleServicesEnableRestriction(v interface{}, d *schema.ResourceData, config *Config) interface{} { + return v +} + +func flattenAccessContextManagerServicePerimeterStatusVPCAccessibleServicesAllowedServices(v interface{}, d *schema.ResourceData, config *Config) interface{} { + if v == nil { + return v + } + return schema.NewSet(schema.HashString, v.([]interface{})) +} + func flattenAccessContextManagerServicePerimeterName(v interface{}, d *schema.ResourceData, config *Config) interface{} { return v } @@ -527,6 +582,13 @@ func expandAccessContextManagerServicePerimeterStatus(v interface{}, d Terraform transformed["restrictedServices"] = transformedRestrictedServices } + transformedVPCAccessibleServices, err := expandAccessContextManagerServicePerimeterStatusVPCAccessibleServices(original["vpc_accessible_services"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedVPCAccessibleServices); val.IsValid() && !isEmptyValue(val) { + transformed["vpcAccessibleServices"] = transformedVPCAccessibleServices + } + return transformed, nil } @@ -543,6 +605,41 @@ func expandAccessContextManagerServicePerimeterStatusRestrictedServices(v interf return v, nil } +func expandAccessContextManagerServicePerimeterStatusVPCAccessibleServices(v interface{}, d TerraformResourceData, config *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{}) + + transformedEnableRestriction, err := expandAccessContextManagerServicePerimeterStatusVPCAccessibleServicesEnableRestriction(original["enable_restriction"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEnableRestriction); val.IsValid() && !isEmptyValue(val) { + transformed["enableRestriction"] = transformedEnableRestriction + } + + transformedAllowedServices, err := expandAccessContextManagerServicePerimeterStatusVPCAccessibleServicesAllowedServices(original["allowed_services"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAllowedServices); val.IsValid() && !isEmptyValue(val) { + transformed["allowedServices"] = transformedAllowedServices + } + + return transformed, nil +} + +func expandAccessContextManagerServicePerimeterStatusVPCAccessibleServicesEnableRestriction(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerServicePerimeterStatusVPCAccessibleServicesAllowedServices(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { + v = v.(*schema.Set).List() + return v, nil +} + func expandAccessContextManagerServicePerimeterParent(v interface{}, d TerraformResourceData, config *Config) (interface{}, error) { return v, nil } diff --git a/google/resource_access_context_manager_service_perimeter_test.go b/google/resource_access_context_manager_service_perimeter_test.go index e018b95ea23..b4ba8ace29a 100644 --- a/google/resource_access_context_manager_service_perimeter_test.go +++ b/google/resource_access_context_manager_service_perimeter_test.go @@ -54,6 +54,14 @@ func testAccAccessContextManagerServicePerimeter_updateTest(t *testing.T) { ImportState: true, ImportStateVerify: true, }, + { + Config: testAccAccessContextManagerServicePerimeter_updateAllowed(org, "my policy", "level", "perimeter"), + }, + { + ResourceName: "google_access_context_manager_service_perimeter.test-access", + ImportState: true, + ImportStateVerify: true, + }, }, }) } @@ -144,3 +152,41 @@ resource "google_access_context_manager_service_perimeter" "test-access" { } `, org, policyTitle, levelTitleName, levelTitleName, perimeterTitleName, perimeterTitleName) } + +func testAccAccessContextManagerServicePerimeter_updateAllowed(org, policyTitle, levelTitleName, perimeterTitleName string) string { + return fmt.Sprintf(` +resource "google_access_context_manager_access_policy" "test-access" { + parent = "organizations/%s" + title = "%s" +} + +resource "google_access_context_manager_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/%s" + title = "%s" + description = "hello" + basic { + combining_function = "AND" + conditions { + ip_subnetworks = ["192.0.4.0/24"] + } + } +} + +resource "google_access_context_manager_service_perimeter" "test-access" { + parent = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}" + name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/servicePerimeters/%s" + title = "%s" + perimeter_type = "PERIMETER_TYPE_REGULAR" + status { + restricted_services = ["bigquery.googleapis.com"] + access_levels = [google_access_context_manager_access_level.test-access.name] + + vpc_accessible_services { + enable_restriction = true + allowed_services = ["bigquery.googleapis.com"] + } + } +} +`, org, policyTitle, levelTitleName, levelTitleName, perimeterTitleName, perimeterTitleName) +} 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 c1f6fa5cc93..a57d5314889 100644 --- a/website/docs/r/access_context_manager_service_perimeter.html.markdown +++ b/website/docs/r/access_context_manager_service_perimeter.html.markdown @@ -162,6 +162,24 @@ The `status` block supports: buckets inside the perimeter must meet the perimeter's access restrictions. +* `vpc_accessible_services` - + (Optional) + Specifies how APIs are allowed to communicate within the Service + Perimeter. Structure is documented below. + + +The `vpc_accessible_services` block supports: + +* `enable_restriction` - + (Optional) + Whether to restrict API calls within the Service Perimeter to the + list of APIs specified in 'allowedServices'. + +* `allowed_services` - + (Optional) + The list of APIs usable within the Service Perimeter. + Must be empty unless `enableRestriction` is True. + ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: