diff --git a/google-beta/provider_accesscontextmanager_gen.go b/google-beta/provider_accesscontextmanager_gen.go index 79920461bf..05b479d222 100644 --- a/google-beta/provider_accesscontextmanager_gen.go +++ b/google-beta/provider_accesscontextmanager_gen.go @@ -18,4 +18,5 @@ import "github.com/hashicorp/terraform/helper/schema" var GeneratedAccessContextManagerResourcesMap = map[string]*schema.Resource{ "google_access_context_manager_access_policy": resourceAccessContextManagerAccessPolicy(), + "google_access_context_manager_access_level": resourceAccessContextManagerAccessLevel(), } diff --git a/google-beta/resource_access_context_manager_access_level_test.go b/google-beta/resource_access_context_manager_access_level_test.go new file mode 100644 index 0000000000..c55fcc331d --- /dev/null +++ b/google-beta/resource_access_context_manager_access_level_test.go @@ -0,0 +1,154 @@ +package google + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +// Access Context Manager tests need to run serially +func TestAccAccessContextManagerAccessLevel_basic(t *testing.T) { + org := getTestOrgFromEnv(t) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAccessContextManagerAccessLevelDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAccessContextManagerAccessLevel_basic(org, "my policy", "level"), + }, + { + ResourceName: "google_access_context_manager_access_level.test-access", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccAccessContextManagerAccessLevel_basicUpdated(org, "my new policy", "level"), + }, + { + ResourceName: "google_access_context_manager_access_level.test-access", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccAccessContextManagerAccessLevel_full(t *testing.T) { + org := getTestOrgFromEnv(t) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckAccessContextManagerAccessLevelDestroy, + Steps: []resource.TestStep{ + { + Config: testAccAccessContextManagerAccessLevel_full(org, "my policy", "level"), + }, + { + ResourceName: "google_access_context_manager_access_level.test-access", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccCheckAccessContextManagerAccessLevelDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "google_access_context_manager_access_level" { + continue + } + + config := testAccProvider.Meta().(*Config) + + url, err := replaceVarsForTest(rs, "https://accesscontextmanager.googleapis.com/v1beta/{{name}}") + if err != nil { + return err + } + + _, err = sendRequest(config, "GET", url, nil) + if err == nil { + return fmt.Errorf("AccessLevel still exists at %s", url) + } + } + + return nil +} + +func testAccAccessContextManagerAccessLevel_basic(org, policyTitle, levelTitleName 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"] + } + } +} +`, org, policyTitle, levelTitleName, levelTitleName) +} + +func testAccAccessContextManagerAccessLevel_basicUpdated(org, policyTitle, levelTitleName 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 = "OR" + conditions { + ip_subnetworks = ["192.0.2.0/24"] + } + } +} +`, org, policyTitle, levelTitleName, levelTitleName) +} + +func testAccAccessContextManagerAccessLevel_full(org, policyTitle, levelTitleName 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"] + members = ["user:test@google.com", "user:test2@google.com"] + negate = false + device_policy { + require_screen_lock = false + os_constraints { + os_type = "IOS" + } + } + } + } +} +`, org, policyTitle, levelTitleName, levelTitleName) +} diff --git a/google-beta/resource_access_context_manager_access_policy_test.go b/google-beta/resource_access_context_manager_access_policy_test.go index a793461917..23ef5eccde 100644 --- a/google-beta/resource_access_context_manager_access_policy_test.go +++ b/google-beta/resource_access_context_manager_access_policy_test.go @@ -8,10 +8,8 @@ import ( "github.com/hashicorp/terraform/terraform" ) -// We can only have a single test as long as we are using a single organization +// Access Context Manager tests need to run serially func TestAccAccessContextManagerAccessPolicy_basic(t *testing.T) { - t.Parallel() - org := getTestOrgFromEnv(t) resource.Test(t, resource.TestCase{ diff --git a/google-beta/resource_accesscontextmanager_access_level.go b/google-beta/resource_accesscontextmanager_access_level.go new file mode 100644 index 0000000000..d944172d23 --- /dev/null +++ b/google-beta/resource_accesscontextmanager_access_level.go @@ -0,0 +1,720 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "fmt" + "log" + "reflect" + "strings" + "time" + + "github.com/hashicorp/terraform/helper/schema" + "github.com/hashicorp/terraform/helper/validation" + accesscontextmanager "google.golang.org/api/accesscontextmanager/v1beta" +) + +func resourceAccessContextManagerAccessLevel() *schema.Resource { + return &schema.Resource{ + Create: resourceAccessContextManagerAccessLevelCreate, + Read: resourceAccessContextManagerAccessLevelRead, + Update: resourceAccessContextManagerAccessLevelUpdate, + Delete: resourceAccessContextManagerAccessLevelDelete, + + Importer: &schema.ResourceImporter{ + State: resourceAccessContextManagerAccessLevelImport, + }, + + Timeouts: &schema.ResourceTimeout{ + Create: schema.DefaultTimeout(240 * time.Second), + Update: schema.DefaultTimeout(240 * time.Second), + Delete: schema.DefaultTimeout(240 * time.Second), + }, + + Schema: map[string]*schema.Schema{ + "name": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "parent": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + }, + "title": { + Type: schema.TypeString, + Required: true, + }, + "basic": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "conditions": { + Type: schema.TypeList, + Required: true, + MinItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "device_policy": { + Type: schema.TypeList, + Optional: true, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allowed_device_management_levels": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "allowed_encryption_statuses": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "os_constraints": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "minimum_version": { + Type: schema.TypeString, + Optional: true, + }, + "os_type": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"OS_UNSPECIFIED", "DESKTOP_MAC", "DESKTOP_WINDOWS", "DESKTOP_LINUX", "DESKTOP_CHROME_OS", "ANDROID", "IOS", ""}, false), + }, + }, + }, + }, + "require_screen_lock": { + Type: schema.TypeBool, + Optional: true, + }, + }, + }, + }, + "ip_subnetworks": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "members": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + "negate": { + Type: schema.TypeBool, + Optional: true, + }, + "required_access_levels": { + Type: schema.TypeList, + Optional: true, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + }, + }, + }, + }, + "combining_function": { + Type: schema.TypeString, + Optional: true, + ValidateFunc: validation.StringInSlice([]string{"AND", "OR", ""}, false), + Default: "AND", + }, + }, + }, + }, + "description": { + Type: schema.TypeString, + Optional: true, + }, + }, + } +} + +func resourceAccessContextManagerAccessLevelCreate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + obj := make(map[string]interface{}) + titleProp, err := expandAccessContextManagerAccessLevelTitle(d.Get("title"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("title"); !isEmptyValue(reflect.ValueOf(titleProp)) && (ok || !reflect.DeepEqual(v, titleProp)) { + obj["title"] = titleProp + } + descriptionProp, err := expandAccessContextManagerAccessLevelDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(descriptionProp)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + basicProp, err := expandAccessContextManagerAccessLevelBasic(d.Get("basic"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("basic"); !isEmptyValue(reflect.ValueOf(basicProp)) && (ok || !reflect.DeepEqual(v, basicProp)) { + obj["basic"] = basicProp + } + parentProp, err := expandAccessContextManagerAccessLevelParent(d.Get("parent"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("parent"); !isEmptyValue(reflect.ValueOf(parentProp)) && (ok || !reflect.DeepEqual(v, parentProp)) { + obj["parent"] = parentProp + } + nameProp, err := expandAccessContextManagerAccessLevelName(d.Get("name"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("name"); !isEmptyValue(reflect.ValueOf(nameProp)) && (ok || !reflect.DeepEqual(v, nameProp)) { + obj["name"] = nameProp + } + + obj, err = resourceAccessContextManagerAccessLevelEncoder(d, meta, obj) + if err != nil { + return err + } + + url, err := replaceVars(d, config, "https://accesscontextmanager.googleapis.com/v1beta/{{parent}}/accessLevels") + if err != nil { + return err + } + + log.Printf("[DEBUG] Creating new AccessLevel: %#v", obj) + res, err := sendRequest(config, "POST", url, obj) + if err != nil { + return fmt.Errorf("Error creating AccessLevel: %s", err) + } + + // Store the ID now + id, err := replaceVars(d, config, "{{name}}") + if err != nil { + return fmt.Errorf("Error constructing id: %s", err) + } + d.SetId(id) + + op := &accesscontextmanager.Operation{} + err = Convert(res, op) + if err != nil { + return err + } + + waitErr := accessContextManagerOperationWaitTime( + config.clientAccessContextManager, op, "Creating AccessLevel", + int(d.Timeout(schema.TimeoutCreate).Minutes())) + + if waitErr != nil { + // The resource didn't actually create + d.SetId("") + return fmt.Errorf("Error waiting to create AccessLevel: %s", waitErr) + } + + log.Printf("[DEBUG] Finished creating AccessLevel %q: %#v", d.Id(), res) + + return resourceAccessContextManagerAccessLevelRead(d, meta) +} + +func resourceAccessContextManagerAccessLevelRead(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + url, err := replaceVars(d, config, "https://accesscontextmanager.googleapis.com/v1beta/{{name}}") + if err != nil { + return err + } + + res, err := sendRequest(config, "GET", url, nil) + if err != nil { + return handleNotFoundError(err, d, fmt.Sprintf("AccessContextManagerAccessLevel %q", d.Id())) + } + + if err := d.Set("title", flattenAccessContextManagerAccessLevelTitle(res["title"], d)); err != nil { + return fmt.Errorf("Error reading AccessLevel: %s", err) + } + if err := d.Set("description", flattenAccessContextManagerAccessLevelDescription(res["description"], d)); err != nil { + return fmt.Errorf("Error reading AccessLevel: %s", err) + } + if err := d.Set("basic", flattenAccessContextManagerAccessLevelBasic(res["basic"], d)); err != nil { + return fmt.Errorf("Error reading AccessLevel: %s", err) + } + if err := d.Set("name", flattenAccessContextManagerAccessLevelName(res["name"], d)); err != nil { + return fmt.Errorf("Error reading AccessLevel: %s", err) + } + + return nil +} + +func resourceAccessContextManagerAccessLevelUpdate(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + obj := make(map[string]interface{}) + titleProp, err := expandAccessContextManagerAccessLevelTitle(d.Get("title"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("title"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, titleProp)) { + obj["title"] = titleProp + } + descriptionProp, err := expandAccessContextManagerAccessLevelDescription(d.Get("description"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("description"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, descriptionProp)) { + obj["description"] = descriptionProp + } + basicProp, err := expandAccessContextManagerAccessLevelBasic(d.Get("basic"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("basic"); !isEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, basicProp)) { + obj["basic"] = basicProp + } + + obj, err = resourceAccessContextManagerAccessLevelEncoder(d, meta, obj) + + url, err := replaceVars(d, config, "https://accesscontextmanager.googleapis.com/v1beta/{{name}}") + if err != nil { + return err + } + + log.Printf("[DEBUG] Updating AccessLevel %q: %#v", d.Id(), obj) + updateMask := []string{} + + if d.HasChange("title") { + updateMask = append(updateMask, "title") + } + + if d.HasChange("description") { + updateMask = append(updateMask, "description") + } + + if d.HasChange("basic") { + updateMask = append(updateMask, "basic") + } + // updateMask is a URL parameter but not present in the schema, so replaceVars + // won't set it + url, err = addQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")}) + if err != nil { + return err + } + res, err := sendRequest(config, "PATCH", url, obj) + + if err != nil { + return fmt.Errorf("Error updating AccessLevel %q: %s", d.Id(), err) + } + + op := &accesscontextmanager.Operation{} + err = Convert(res, op) + if err != nil { + return err + } + + err = accessContextManagerOperationWaitTime( + config.clientAccessContextManager, op, "Updating AccessLevel", + int(d.Timeout(schema.TimeoutUpdate).Minutes())) + + if err != nil { + return err + } + + return resourceAccessContextManagerAccessLevelRead(d, meta) +} + +func resourceAccessContextManagerAccessLevelDelete(d *schema.ResourceData, meta interface{}) error { + config := meta.(*Config) + + url, err := replaceVars(d, config, "https://accesscontextmanager.googleapis.com/v1beta/{{name}}") + if err != nil { + return err + } + + var obj map[string]interface{} + log.Printf("[DEBUG] Deleting AccessLevel %q", d.Id()) + res, err := sendRequest(config, "DELETE", url, obj) + if err != nil { + return handleNotFoundError(err, d, "AccessLevel") + } + + op := &accesscontextmanager.Operation{} + err = Convert(res, op) + if err != nil { + return err + } + + err = accessContextManagerOperationWaitTime( + config.clientAccessContextManager, op, "Deleting AccessLevel", + int(d.Timeout(schema.TimeoutDelete).Minutes())) + + if err != nil { + return err + } + + log.Printf("[DEBUG] Finished deleting AccessLevel %q: %#v", d.Id(), res) + return nil +} + +func resourceAccessContextManagerAccessLevelImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { + config := meta.(*Config) + + // current import_formats can't import ids with forward slashes in them. + parseImportId([]string{"(?P.+)"}, d, config) + stringParts := strings.Split(d.Get("name").(string), "/") + d.Set("parent", fmt.Sprintf("%s/%s", stringParts[0], stringParts[1])) + return []*schema.ResourceData{d}, nil +} + +func flattenAccessContextManagerAccessLevelTitle(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenAccessContextManagerAccessLevelDescription(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenAccessContextManagerAccessLevelBasic(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["combining_function"] = + flattenAccessContextManagerAccessLevelBasicCombiningFunction(original["combiningFunction"], d) + transformed["conditions"] = + flattenAccessContextManagerAccessLevelBasicConditions(original["conditions"], d) + return []interface{}{transformed} +} +func flattenAccessContextManagerAccessLevelBasicCombiningFunction(v interface{}, d *schema.ResourceData) interface{} { + if v == nil || v.(string) == "" { + return "AND" + } + return v +} + +func flattenAccessContextManagerAccessLevelBasicConditions(v interface{}, d *schema.ResourceData) 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{}{ + "ip_subnetworks": flattenAccessContextManagerAccessLevelBasicConditionsIpSubnetworks(original["ipSubnetworks"], d), + "required_access_levels": flattenAccessContextManagerAccessLevelBasicConditionsRequiredAccessLevels(original["requiredAccessLevels"], d), + "members": flattenAccessContextManagerAccessLevelBasicConditionsMembers(original["members"], d), + "negate": flattenAccessContextManagerAccessLevelBasicConditionsNegate(original["negate"], d), + "device_policy": flattenAccessContextManagerAccessLevelBasicConditionsDevicePolicy(original["devicePolicy"], d), + }) + } + return transformed +} +func flattenAccessContextManagerAccessLevelBasicConditionsIpSubnetworks(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenAccessContextManagerAccessLevelBasicConditionsRequiredAccessLevels(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenAccessContextManagerAccessLevelBasicConditionsMembers(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenAccessContextManagerAccessLevelBasicConditionsNegate(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenAccessContextManagerAccessLevelBasicConditionsDevicePolicy(v interface{}, d *schema.ResourceData) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["require_screen_lock"] = + flattenAccessContextManagerAccessLevelBasicConditionsDevicePolicyRequireScreenLock(original["requireScreenLock"], d) + transformed["allowed_encryption_statuses"] = + flattenAccessContextManagerAccessLevelBasicConditionsDevicePolicyAllowedEncryptionStatuses(original["allowedEncryptionStatuses"], d) + transformed["allowed_device_management_levels"] = + flattenAccessContextManagerAccessLevelBasicConditionsDevicePolicyAllowedDeviceManagementLevels(original["allowedDeviceManagementLevels"], d) + transformed["os_constraints"] = + flattenAccessContextManagerAccessLevelBasicConditionsDevicePolicyOsConstraints(original["osConstraints"], d) + return []interface{}{transformed} +} +func flattenAccessContextManagerAccessLevelBasicConditionsDevicePolicyRequireScreenLock(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenAccessContextManagerAccessLevelBasicConditionsDevicePolicyAllowedEncryptionStatuses(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenAccessContextManagerAccessLevelBasicConditionsDevicePolicyAllowedDeviceManagementLevels(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenAccessContextManagerAccessLevelBasicConditionsDevicePolicyOsConstraints(v interface{}, d *schema.ResourceData) 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{}{ + "minimum_version": flattenAccessContextManagerAccessLevelBasicConditionsDevicePolicyOsConstraintsMinimumVersion(original["minimumVersion"], d), + "os_type": flattenAccessContextManagerAccessLevelBasicConditionsDevicePolicyOsConstraintsOsType(original["osType"], d), + }) + } + return transformed +} +func flattenAccessContextManagerAccessLevelBasicConditionsDevicePolicyOsConstraintsMinimumVersion(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenAccessContextManagerAccessLevelBasicConditionsDevicePolicyOsConstraintsOsType(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func flattenAccessContextManagerAccessLevelName(v interface{}, d *schema.ResourceData) interface{} { + return v +} + +func expandAccessContextManagerAccessLevelTitle(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerAccessLevelDescription(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerAccessLevelBasic(v interface{}, d *schema.ResourceData, 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{}) + + transformedCombiningFunction, err := expandAccessContextManagerAccessLevelBasicCombiningFunction(original["combining_function"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedCombiningFunction); val.IsValid() && !isEmptyValue(val) { + transformed["combiningFunction"] = transformedCombiningFunction + } + + transformedConditions, err := expandAccessContextManagerAccessLevelBasicConditions(original["conditions"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedConditions); val.IsValid() && !isEmptyValue(val) { + transformed["conditions"] = transformedConditions + } + + return transformed, nil +} + +func expandAccessContextManagerAccessLevelBasicCombiningFunction(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerAccessLevelBasicConditions(v interface{}, d *schema.ResourceData, config *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{}) + + transformedIpSubnetworks, err := expandAccessContextManagerAccessLevelBasicConditionsIpSubnetworks(original["ip_subnetworks"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedIpSubnetworks); val.IsValid() && !isEmptyValue(val) { + transformed["ipSubnetworks"] = transformedIpSubnetworks + } + + transformedRequiredAccessLevels, err := expandAccessContextManagerAccessLevelBasicConditionsRequiredAccessLevels(original["required_access_levels"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequiredAccessLevels); val.IsValid() && !isEmptyValue(val) { + transformed["requiredAccessLevels"] = transformedRequiredAccessLevels + } + + transformedMembers, err := expandAccessContextManagerAccessLevelBasicConditionsMembers(original["members"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMembers); val.IsValid() && !isEmptyValue(val) { + transformed["members"] = transformedMembers + } + + transformedNegate, err := expandAccessContextManagerAccessLevelBasicConditionsNegate(original["negate"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedNegate); val.IsValid() && !isEmptyValue(val) { + transformed["negate"] = transformedNegate + } + + transformedDevicePolicy, err := expandAccessContextManagerAccessLevelBasicConditionsDevicePolicy(original["device_policy"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedDevicePolicy); val.IsValid() && !isEmptyValue(val) { + transformed["devicePolicy"] = transformedDevicePolicy + } + + req = append(req, transformed) + } + return req, nil +} + +func expandAccessContextManagerAccessLevelBasicConditionsIpSubnetworks(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerAccessLevelBasicConditionsRequiredAccessLevels(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerAccessLevelBasicConditionsMembers(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerAccessLevelBasicConditionsNegate(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerAccessLevelBasicConditionsDevicePolicy(v interface{}, d *schema.ResourceData, 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{}) + + transformedRequireScreenLock, err := expandAccessContextManagerAccessLevelBasicConditionsDevicePolicyRequireScreenLock(original["require_screen_lock"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRequireScreenLock); val.IsValid() && !isEmptyValue(val) { + transformed["requireScreenLock"] = transformedRequireScreenLock + } + + transformedAllowedEncryptionStatuses, err := expandAccessContextManagerAccessLevelBasicConditionsDevicePolicyAllowedEncryptionStatuses(original["allowed_encryption_statuses"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAllowedEncryptionStatuses); val.IsValid() && !isEmptyValue(val) { + transformed["allowedEncryptionStatuses"] = transformedAllowedEncryptionStatuses + } + + transformedAllowedDeviceManagementLevels, err := expandAccessContextManagerAccessLevelBasicConditionsDevicePolicyAllowedDeviceManagementLevels(original["allowed_device_management_levels"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAllowedDeviceManagementLevels); val.IsValid() && !isEmptyValue(val) { + transformed["allowedDeviceManagementLevels"] = transformedAllowedDeviceManagementLevels + } + + transformedOsConstraints, err := expandAccessContextManagerAccessLevelBasicConditionsDevicePolicyOsConstraints(original["os_constraints"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedOsConstraints); val.IsValid() && !isEmptyValue(val) { + transformed["osConstraints"] = transformedOsConstraints + } + + return transformed, nil +} + +func expandAccessContextManagerAccessLevelBasicConditionsDevicePolicyRequireScreenLock(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerAccessLevelBasicConditionsDevicePolicyAllowedEncryptionStatuses(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerAccessLevelBasicConditionsDevicePolicyAllowedDeviceManagementLevels(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerAccessLevelBasicConditionsDevicePolicyOsConstraints(v interface{}, d *schema.ResourceData, config *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{}) + + transformedMinimumVersion, err := expandAccessContextManagerAccessLevelBasicConditionsDevicePolicyOsConstraintsMinimumVersion(original["minimum_version"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMinimumVersion); val.IsValid() && !isEmptyValue(val) { + transformed["minimumVersion"] = transformedMinimumVersion + } + + transformedOsType, err := expandAccessContextManagerAccessLevelBasicConditionsDevicePolicyOsConstraintsOsType(original["os_type"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedOsType); val.IsValid() && !isEmptyValue(val) { + transformed["osType"] = transformedOsType + } + + req = append(req, transformed) + } + return req, nil +} + +func expandAccessContextManagerAccessLevelBasicConditionsDevicePolicyOsConstraintsMinimumVersion(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerAccessLevelBasicConditionsDevicePolicyOsConstraintsOsType(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerAccessLevelParent(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandAccessContextManagerAccessLevelName(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func resourceAccessContextManagerAccessLevelEncoder(d *schema.ResourceData, meta interface{}, obj map[string]interface{}) (map[string]interface{}, error) { + delete(obj, "parent") + return obj, nil +} diff --git a/website/docs/r/accesscontextmanager_access_level.html.markdown b/website/docs/r/accesscontextmanager_access_level.html.markdown new file mode 100644 index 0000000000..5a788b8b72 --- /dev/null +++ b/website/docs/r/accesscontextmanager_access_level.html.markdown @@ -0,0 +1,207 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +# +# ---------------------------------------------------------------------------- +# +# This file is automatically generated by Magic Modules and manual +# changes will be clobbered when the file is regenerated. +# +# Please read more about how to change this file in +# .github/CONTRIBUTING.md. +# +# ---------------------------------------------------------------------------- +layout: "google" +page_title: "Google: google_access_context_manager_access_level" +sidebar_current: "docs-google-access-context-manager-access-level" +description: |- + An AccessLevel is a label that can be applied to requests to GCP services, + along with a list of requirements necessary for the label to be applied. +--- + +# google\_access\_context\_manager\_access\_level + +An AccessLevel is a label that can be applied to requests to GCP services, +along with a list of requirements necessary for the label to be applied. + +~> **Warning:** This resource is in beta, and should be used with the terraform-provider-google-beta provider. +See [Provider Versions](https://terraform.io/docs/providers/google/provider_versions.html) for more details on beta resources. + +To get more information about AccessLevel, see: + +* [API documentation](https://cloud.google.com/access-context-manager/docs/reference/rest/v1beta/accessPolicies.accessLevels) +* How-to Guides + * [Access Policy Quickstart](https://cloud.google.com/access-context-manager/docs/quickstart) + +## Example Usage - Access Context Manager Access Level Basic + + +```hcl +resource "google_access_context_manager_access_level" "access-level" { + parent = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}" + name = "accessPolicies/${google_access_context_manager_access_policy.test-access.name}/accessLevels/ios_no_lock" + title = "ios_no_lock" + basic { + conditions { + device_policy { + require_screen_lock = false + os_constraints { + os_type = "IOS" + } + } + } + } +} + +resource "google_access_context_manager_access_policy" "access-policy" { + parent = "organizations/123456789" + title = "my policy" +} +``` + +## Argument Reference + +The following arguments are supported: + + +* `title` - + (Required) + Human readable title. Must be unique within the Policy. + +* `parent` - + (Required) + The AccessPolicy this AccessLevel lives in. + Format: accessPolicies/{policy_id} + +* `name` - + (Required) + Resource name for the Access Level. The short_name component must begin + with a letter and only include alphanumeric and '_'. + Format: accessPolicies/{policy_id}/accessLevels/{short_name} + + +- - - + + +* `description` - + (Optional) + Description of the AccessLevel and its use. Does not affect behavior. + +* `basic` - + (Optional) + A set of predefined conditions for the access level and a combining function. Structure is documented below. + + +The `basic` block supports: + +* `combining_function` - + (Optional) + How the conditions list should be combined to determine if a request + is granted this AccessLevel. If AND is used, each Condition in + conditions must be satisfied for the AccessLevel to be applied. If + OR is used, at least one Condition in conditions must be satisfied + for the AccessLevel to be applied. Defaults to AND if unspecified. + +* `conditions` - + (Required) + A set of requirements for the AccessLevel to be granted. Structure is documented below. + + +The `conditions` block supports: + +* `ip_subnetworks` - + (Optional) + A list of CIDR block IP subnetwork specification. May be IPv4 + or IPv6. + Note that for a CIDR IP address block, the specified IP address + portion must be properly truncated (i.e. all the host bits must + be zero) or the input is considered malformed. For example, + "192.0.2.0/24" is accepted but "192.0.2.1/24" is not. Similarly, + for IPv6, "2001:db8::/32" is accepted whereas "2001:db8::1/32" + is not. The originating IP of a request must be in one of the + listed subnets in order for this Condition to be true. + If empty, all IP addresses are allowed. + +* `required_access_levels` - + (Optional) + A list of other access levels defined in the same Policy, + referenced by resource name. Referencing an AccessLevel which + does not exist is an error. All access levels listed must be + granted for the Condition to be true. + Format: accessPolicies/{policy_id}/accessLevels/{short_name} + +* `members` - + (Optional) + An allowed list of members (users, groups, service accounts). + The signed-in user originating the request must be a part of one + of the provided members. If not specified, a request may come + from any user (logged in/not logged in, not present in any + groups, etc.). + Formats: `user:{emailid}`, `group:{emailid}`, `serviceAccount:{emailid}` + +* `negate` - + (Optional) + Whether to negate the Condition. If true, the Condition becomes + a NAND over its non-empty fields, each field must be false for + the Condition overall to be satisfied. Defaults to false. + +* `device_policy` - + (Optional) + Device specific restrictions, all restrictions must hold for + the Condition to be true. If not specified, all devices are + allowed. Structure is documented below. + + +The `device_policy` block supports: + +* `require_screen_lock` - + (Optional) + Whether or not screenlock is required for the DevicePolicy + to be true. Defaults to false. + +* `allowed_encryption_statuses` - + (Optional) + A list of allowed encryptions statuses. + An empty list allows all statuses. + +* `allowed_device_management_levels` - + (Optional) + A list of allowed device management levels. + An empty list allows all management levels. + +* `os_constraints` - + (Optional) + A list of allowed OS versions. + An empty list allows all types and all versions. Structure is documented below. + + +The `os_constraints` block supports: + +* `minimum_version` - + (Optional) + The minimum allowed OS version. If not set, any version + of this OS satisfies the constraint. + Format: "major.minor.patch" such as "10.5.301", "9.2.1". + +* `os_type` - + (Optional) + The operating system type of the device. + + +## Timeouts + +This resource provides the following +[Timeouts](/docs/configuration/resources.html#timeouts) configuration options: + +- `create` - Default is 4 minutes. +- `update` - Default is 4 minutes. +- `delete` - Default is 4 minutes. + +## Import + +AccessLevel can be imported using any of these accepted formats: + +``` +$ terraform import google_access_context_manager_access_level.default {{name}} +```