diff --git a/.changelog/12782.txt b/.changelog/12782.txt new file mode 100644 index 0000000000..c6e997b275 --- /dev/null +++ b/.changelog/12782.txt @@ -0,0 +1,9 @@ +```release-note:new-resource +`google_beyondcorp_security_gateway_iam_binding` +``` +```release-note:new-resource +`google_beyondcorp_security_gateway_iam_member` +``` +```release-note:new-resource +`google_beyondcorp_security_gateway_iam_policy` +``` \ No newline at end of file diff --git a/google-beta/provider/provider_mmv1_resources.go b/google-beta/provider/provider_mmv1_resources.go index 82c0b9ea60..3208780dda 100644 --- a/google-beta/provider/provider_mmv1_resources.go +++ b/google-beta/provider/provider_mmv1_resources.go @@ -404,6 +404,7 @@ var generatedIAMDatasources = map[string]*schema.Resource{ "google_api_gateway_gateway_iam_policy": tpgiamresource.DataSourceIamPolicy(apigateway.ApiGatewayGatewayIamSchema, apigateway.ApiGatewayGatewayIamUpdaterProducer), "google_apigee_environment_iam_policy": tpgiamresource.DataSourceIamPolicy(apigee.ApigeeEnvironmentIamSchema, apigee.ApigeeEnvironmentIamUpdaterProducer), "google_artifact_registry_repository_iam_policy": tpgiamresource.DataSourceIamPolicy(artifactregistry.ArtifactRegistryRepositoryIamSchema, artifactregistry.ArtifactRegistryRepositoryIamUpdaterProducer), + "google_beyondcorp_security_gateway_iam_policy": tpgiamresource.DataSourceIamPolicy(beyondcorp.BeyondcorpSecurityGatewayIamSchema, beyondcorp.BeyondcorpSecurityGatewayIamUpdaterProducer), "google_bigquery_table_iam_policy": tpgiamresource.DataSourceIamPolicy(bigquery.BigQueryTableIamSchema, bigquery.BigQueryTableIamUpdaterProducer), "google_bigquery_analytics_hub_data_exchange_iam_policy": tpgiamresource.DataSourceIamPolicy(bigqueryanalyticshub.BigqueryAnalyticsHubDataExchangeIamSchema, bigqueryanalyticshub.BigqueryAnalyticsHubDataExchangeIamUpdaterProducer), "google_bigquery_analytics_hub_listing_iam_policy": tpgiamresource.DataSourceIamPolicy(bigqueryanalyticshub.BigqueryAnalyticsHubListingIamSchema, bigqueryanalyticshub.BigqueryAnalyticsHubListingIamUpdaterProducer), @@ -528,8 +529,8 @@ var handwrittenIAMDatasources = map[string]*schema.Resource{ // Resources // Generated resources: 592 -// Generated IAM resources: 300 -// Total generated resources: 892 +// Generated IAM resources: 303 +// Total generated resources: 895 var generatedResources = map[string]*schema.Resource{ "google_folder_access_approval_settings": accessapproval.ResourceAccessApprovalFolderSettings(), "google_organization_access_approval_settings": accessapproval.ResourceAccessApprovalOrganizationSettings(), @@ -619,6 +620,9 @@ var generatedResources = map[string]*schema.Resource{ "google_beyondcorp_app_connector": beyondcorp.ResourceBeyondcorpAppConnector(), "google_beyondcorp_app_gateway": beyondcorp.ResourceBeyondcorpAppGateway(), "google_beyondcorp_security_gateway": beyondcorp.ResourceBeyondcorpSecurityGateway(), + "google_beyondcorp_security_gateway_iam_binding": tpgiamresource.ResourceIamBinding(beyondcorp.BeyondcorpSecurityGatewayIamSchema, beyondcorp.BeyondcorpSecurityGatewayIamUpdaterProducer, beyondcorp.BeyondcorpSecurityGatewayIdParseFunc), + "google_beyondcorp_security_gateway_iam_member": tpgiamresource.ResourceIamMember(beyondcorp.BeyondcorpSecurityGatewayIamSchema, beyondcorp.BeyondcorpSecurityGatewayIamUpdaterProducer, beyondcorp.BeyondcorpSecurityGatewayIdParseFunc), + "google_beyondcorp_security_gateway_iam_policy": tpgiamresource.ResourceIamPolicy(beyondcorp.BeyondcorpSecurityGatewayIamSchema, beyondcorp.BeyondcorpSecurityGatewayIamUpdaterProducer, beyondcorp.BeyondcorpSecurityGatewayIdParseFunc), "google_biglake_catalog": biglake.ResourceBiglakeCatalog(), "google_biglake_database": biglake.ResourceBiglakeDatabase(), "google_biglake_table": biglake.ResourceBiglakeTable(), diff --git a/google-beta/services/beyondcorp/iam_beyondcorp_security_gateway.go b/google-beta/services/beyondcorp/iam_beyondcorp_security_gateway.go new file mode 100644 index 0000000000..cab84b805a --- /dev/null +++ b/google-beta/services/beyondcorp/iam_beyondcorp_security_gateway.go @@ -0,0 +1,249 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// 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 beyondcorp + +import ( + "fmt" + + "github.com/hashicorp/errwrap" + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "google.golang.org/api/cloudresourcemanager/v1" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgiamresource" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" + transport_tpg "github.com/hashicorp/terraform-provider-google-beta/google-beta/transport" +) + +var BeyondcorpSecurityGatewayIamSchema = map[string]*schema.Schema{ + "project": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + }, + "location": { + Type: schema.TypeString, + Computed: true, + Optional: true, + ForceNew: true, + }, + "security_gateway_id": { + Type: schema.TypeString, + Required: true, + ForceNew: true, + DiffSuppressFunc: tpgresource.CompareSelfLinkOrResourceName, + }, +} + +type BeyondcorpSecurityGatewayIamUpdater struct { + project string + location string + securityGatewayId string + d tpgresource.TerraformResourceData + Config *transport_tpg.Config +} + +func BeyondcorpSecurityGatewayIamUpdaterProducer(d tpgresource.TerraformResourceData, config *transport_tpg.Config) (tpgiamresource.ResourceIamUpdater, error) { + values := make(map[string]string) + + project, _ := tpgresource.GetProject(d, config) + if project != "" { + if err := d.Set("project", project); err != nil { + return nil, fmt.Errorf("Error setting project: %s", err) + } + } + values["project"] = project + location, _ := tpgresource.GetLocation(d, config) + if location != "" { + if err := d.Set("location", location); err != nil { + return nil, fmt.Errorf("Error setting location: %s", err) + } + } + values["location"] = location + if v, ok := d.GetOk("security_gateway_id"); ok { + values["security_gateway_id"] = v.(string) + } + + // We may have gotten either a long or short name, so attempt to parse long name if possible + m, err := tpgresource.GetImportIdQualifiers([]string{"projects/(?P[^/]+)/locations/(?P[^/]+)/securityGateways/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)"}, d, config, d.Get("security_gateway_id").(string)) + if err != nil { + return nil, err + } + + for k, v := range m { + values[k] = v + } + + u := &BeyondcorpSecurityGatewayIamUpdater{ + project: values["project"], + location: values["location"], + securityGatewayId: values["security_gateway_id"], + d: d, + Config: config, + } + + if err := d.Set("project", u.project); err != nil { + return nil, fmt.Errorf("Error setting project: %s", err) + } + if err := d.Set("location", u.location); err != nil { + return nil, fmt.Errorf("Error setting location: %s", err) + } + if err := d.Set("security_gateway_id", u.GetResourceId()); err != nil { + return nil, fmt.Errorf("Error setting security_gateway_id: %s", err) + } + + return u, nil +} + +func BeyondcorpSecurityGatewayIdParseFunc(d *schema.ResourceData, config *transport_tpg.Config) error { + values := make(map[string]string) + + project, _ := tpgresource.GetProject(d, config) + if project != "" { + values["project"] = project + } + + location, _ := tpgresource.GetLocation(d, config) + if location != "" { + values["location"] = location + } + + m, err := tpgresource.GetImportIdQualifiers([]string{"projects/(?P[^/]+)/locations/(?P[^/]+)/securityGateways/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)/(?P[^/]+)", "(?P[^/]+)"}, d, config, d.Id()) + if err != nil { + return err + } + + for k, v := range m { + values[k] = v + } + + u := &BeyondcorpSecurityGatewayIamUpdater{ + project: values["project"], + location: values["location"], + securityGatewayId: values["security_gateway_id"], + d: d, + Config: config, + } + if err := d.Set("security_gateway_id", u.GetResourceId()); err != nil { + return fmt.Errorf("Error setting security_gateway_id: %s", err) + } + d.SetId(u.GetResourceId()) + return nil +} + +func (u *BeyondcorpSecurityGatewayIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) { + url, err := u.qualifySecurityGatewayUrl("getIamPolicy") + if err != nil { + return nil, err + } + + project, err := tpgresource.GetProject(u.d, u.Config) + if err != nil { + return nil, err + } + var obj map[string]interface{} + url, err = transport_tpg.AddQueryParams(url, map[string]string{"options.requestedPolicyVersion": fmt.Sprintf("%d", tpgiamresource.IamPolicyVersion)}) + if err != nil { + return nil, err + } + + userAgent, err := tpgresource.GenerateUserAgentString(u.d, u.Config.UserAgent) + if err != nil { + return nil, err + } + + policy, err := transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: u.Config, + Method: "GET", + Project: project, + RawURL: url, + UserAgent: userAgent, + Body: obj, + }) + if err != nil { + return nil, errwrap.Wrapf(fmt.Sprintf("Error retrieving IAM policy for %s: {{err}}", u.DescribeResource()), err) + } + + out := &cloudresourcemanager.Policy{} + err = tpgresource.Convert(policy, out) + if err != nil { + return nil, errwrap.Wrapf("Cannot convert a policy to a resource manager policy: {{err}}", err) + } + + return out, nil +} + +func (u *BeyondcorpSecurityGatewayIamUpdater) SetResourceIamPolicy(policy *cloudresourcemanager.Policy) error { + json, err := tpgresource.ConvertToMap(policy) + if err != nil { + return err + } + + obj := make(map[string]interface{}) + obj["policy"] = json + + url, err := u.qualifySecurityGatewayUrl("setIamPolicy") + if err != nil { + return err + } + project, err := tpgresource.GetProject(u.d, u.Config) + if err != nil { + return err + } + + userAgent, err := tpgresource.GenerateUserAgentString(u.d, u.Config.UserAgent) + if err != nil { + return err + } + + _, err = transport_tpg.SendRequest(transport_tpg.SendRequestOptions{ + Config: u.Config, + Method: "POST", + Project: project, + RawURL: url, + UserAgent: userAgent, + Body: obj, + Timeout: u.d.Timeout(schema.TimeoutCreate), + }) + if err != nil { + return errwrap.Wrapf(fmt.Sprintf("Error setting IAM policy for %s: {{err}}", u.DescribeResource()), err) + } + + return nil +} + +func (u *BeyondcorpSecurityGatewayIamUpdater) qualifySecurityGatewayUrl(methodIdentifier string) (string, error) { + urlTemplate := fmt.Sprintf("{{BeyondcorpBasePath}}%s:%s", fmt.Sprintf("projects/%s/locations/%s/securityGateways/%s", u.project, u.location, u.securityGatewayId), methodIdentifier) + url, err := tpgresource.ReplaceVars(u.d, u.Config, urlTemplate) + if err != nil { + return "", err + } + return url, nil +} + +func (u *BeyondcorpSecurityGatewayIamUpdater) GetResourceId() string { + return fmt.Sprintf("projects/%s/locations/%s/securityGateways/%s", u.project, u.location, u.securityGatewayId) +} + +func (u *BeyondcorpSecurityGatewayIamUpdater) GetMutexKey() string { + return fmt.Sprintf("iam-beyondcorp-securitygateway-%s", u.GetResourceId()) +} + +func (u *BeyondcorpSecurityGatewayIamUpdater) DescribeResource() string { + return fmt.Sprintf("beyondcorp securitygateway %q", u.GetResourceId()) +} diff --git a/google-beta/services/beyondcorp/iam_beyondcorp_security_gateway_generated_test.go b/google-beta/services/beyondcorp/iam_beyondcorp_security_gateway_generated_test.go new file mode 100644 index 0000000000..e65461b96b --- /dev/null +++ b/google-beta/services/beyondcorp/iam_beyondcorp_security_gateway_generated_test.go @@ -0,0 +1,611 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 + +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** Type: MMv1 *** +// +// ---------------------------------------------------------------------------- +// +// 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 beyondcorp_test + +import ( + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-testing/helper/resource" + + "github.com/hashicorp/terraform-provider-google-beta/google-beta/acctest" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/envvar" + "github.com/hashicorp/terraform-provider-google-beta/google-beta/tpgresource" +) + +func TestAccBeyondcorpSecurityGatewayIamBindingGenerated(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/beyondcorp.securityGatewayUser", + "condition_title": "expires_after_2019_12_31", + "condition_expr": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + "condition_desc": "Expiring at midnight of 2019-12-31", + "condition_title_no_desc": "expires_after_2019_12_31-no-description", + "condition_expr_no_desc": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccBeyondcorpSecurityGatewayIamBinding_basicGenerated(context), + }, + { + ResourceName: "google_beyondcorp_security_gateway_iam_binding.foo", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/securityGateways/%s roles/beyondcorp.securityGatewayUser", envvar.GetTestProjectFromEnv(), "global", fmt.Sprintf("default%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + { + // Test Iam Binding update + Config: testAccBeyondcorpSecurityGatewayIamBinding_updateGenerated(context), + }, + { + ResourceName: "google_beyondcorp_security_gateway_iam_binding.foo", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/securityGateways/%s roles/beyondcorp.securityGatewayUser", envvar.GetTestProjectFromEnv(), "global", fmt.Sprintf("default%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccBeyondcorpSecurityGatewayIamMemberGenerated(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/beyondcorp.securityGatewayUser", + "condition_title": "expires_after_2019_12_31", + "condition_expr": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + "condition_desc": "Expiring at midnight of 2019-12-31", + "condition_title_no_desc": "expires_after_2019_12_31-no-description", + "condition_expr_no_desc": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + // Test Iam Member creation (no update for member, no need to test) + Config: testAccBeyondcorpSecurityGatewayIamMember_basicGenerated(context), + }, + { + ResourceName: "google_beyondcorp_security_gateway_iam_member.foo", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/securityGateways/%s roles/beyondcorp.securityGatewayUser user:admin@hashicorptest.com", envvar.GetTestProjectFromEnv(), "global", fmt.Sprintf("default%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccBeyondcorpSecurityGatewayIamPolicyGenerated(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/beyondcorp.securityGatewayUser", + "condition_title": "expires_after_2019_12_31", + "condition_expr": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + "condition_desc": "Expiring at midnight of 2019-12-31", + "condition_title_no_desc": "expires_after_2019_12_31-no-description", + "condition_expr_no_desc": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccBeyondcorpSecurityGatewayIamPolicy_basicGenerated(context), + Check: resource.TestCheckResourceAttrSet("data.google_beyondcorp_security_gateway_iam_policy.foo", "policy_data"), + }, + { + ResourceName: "google_beyondcorp_security_gateway_iam_policy.foo", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/securityGateways/%s", envvar.GetTestProjectFromEnv(), "global", fmt.Sprintf("default%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccBeyondcorpSecurityGatewayIamPolicy_emptyBinding(context), + }, + { + ResourceName: "google_beyondcorp_security_gateway_iam_policy.foo", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/securityGateways/%s", envvar.GetTestProjectFromEnv(), "global", fmt.Sprintf("default%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccBeyondcorpSecurityGatewayIamBindingGenerated_withCondition(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/beyondcorp.securityGatewayUser", + "condition_title": "expires_after_2019_12_31", + "condition_expr": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + "condition_desc": "Expiring at midnight of 2019-12-31", + "condition_title_no_desc": "expires_after_2019_12_31-no-description", + "condition_expr_no_desc": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccBeyondcorpSecurityGatewayIamBinding_withConditionGenerated(context), + }, + { + ResourceName: "google_beyondcorp_security_gateway_iam_binding.foo", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/securityGateways/%s roles/beyondcorp.securityGatewayUser %s", envvar.GetTestProjectFromEnv(), "global", fmt.Sprintf("default%s", context["random_suffix"]), context["condition_title"]), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccBeyondcorpSecurityGatewayIamBindingGenerated_withAndWithoutCondition(t *testing.T) { + // Multiple fine-grained resources + acctest.SkipIfVcr(t) + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/beyondcorp.securityGatewayUser", + "condition_title": "expires_after_2019_12_31", + "condition_expr": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + "condition_desc": "Expiring at midnight of 2019-12-31", + "condition_title_no_desc": "expires_after_2019_12_31-no-description", + "condition_expr_no_desc": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccBeyondcorpSecurityGatewayIamBinding_withAndWithoutConditionGenerated(context), + }, + { + ResourceName: "google_beyondcorp_security_gateway_iam_binding.foo", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/securityGateways/%s roles/beyondcorp.securityGatewayUser", envvar.GetTestProjectFromEnv(), "global", fmt.Sprintf("default%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: "google_beyondcorp_security_gateway_iam_binding.foo2", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/securityGateways/%s roles/beyondcorp.securityGatewayUser %s", envvar.GetTestProjectFromEnv(), "global", fmt.Sprintf("default%s", context["random_suffix"]), context["condition_title"]), + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: "google_beyondcorp_security_gateway_iam_binding.foo3", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/securityGateways/%s roles/beyondcorp.securityGatewayUser %s", envvar.GetTestProjectFromEnv(), "global", fmt.Sprintf("default%s", context["random_suffix"]), context["condition_title_no_desc"]), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccBeyondcorpSecurityGatewayIamMemberGenerated_withCondition(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/beyondcorp.securityGatewayUser", + "condition_title": "expires_after_2019_12_31", + "condition_expr": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + "condition_desc": "Expiring at midnight of 2019-12-31", + "condition_title_no_desc": "expires_after_2019_12_31-no-description", + "condition_expr_no_desc": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccBeyondcorpSecurityGatewayIamMember_withConditionGenerated(context), + }, + { + ResourceName: "google_beyondcorp_security_gateway_iam_member.foo", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/securityGateways/%s roles/beyondcorp.securityGatewayUser user:admin@hashicorptest.com %s", envvar.GetTestProjectFromEnv(), "global", fmt.Sprintf("default%s", context["random_suffix"]), context["condition_title"]), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccBeyondcorpSecurityGatewayIamMemberGenerated_withAndWithoutCondition(t *testing.T) { + // Multiple fine-grained resources + acctest.SkipIfVcr(t) + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/beyondcorp.securityGatewayUser", + "condition_title": "expires_after_2019_12_31", + "condition_expr": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + "condition_desc": "Expiring at midnight of 2019-12-31", + "condition_title_no_desc": "expires_after_2019_12_31-no-description", + "condition_expr_no_desc": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccBeyondcorpSecurityGatewayIamMember_withAndWithoutConditionGenerated(context), + }, + { + ResourceName: "google_beyondcorp_security_gateway_iam_member.foo", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/securityGateways/%s roles/beyondcorp.securityGatewayUser user:admin@hashicorptest.com", envvar.GetTestProjectFromEnv(), "global", fmt.Sprintf("default%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: "google_beyondcorp_security_gateway_iam_member.foo2", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/securityGateways/%s roles/beyondcorp.securityGatewayUser user:admin@hashicorptest.com %s", envvar.GetTestProjectFromEnv(), "global", fmt.Sprintf("default%s", context["random_suffix"]), context["condition_title"]), + ImportState: true, + ImportStateVerify: true, + }, + { + ResourceName: "google_beyondcorp_security_gateway_iam_member.foo3", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/securityGateways/%s roles/beyondcorp.securityGatewayUser user:admin@hashicorptest.com %s", envvar.GetTestProjectFromEnv(), "global", fmt.Sprintf("default%s", context["random_suffix"]), context["condition_title_no_desc"]), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func TestAccBeyondcorpSecurityGatewayIamPolicyGenerated_withCondition(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": acctest.RandString(t, 10), + "role": "roles/beyondcorp.securityGatewayUser", + "condition_title": "expires_after_2019_12_31", + "condition_expr": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + "condition_desc": "Expiring at midnight of 2019-12-31", + "condition_title_no_desc": "expires_after_2019_12_31-no-description", + "condition_expr_no_desc": `request.time < timestamp(\"2020-01-01T00:00:00Z\")`, + } + + // Test should have 2 bindings: one with a description and one without. Any < chars are converted to a unicode character by the API. + expectedPolicyData := acctest.Nprintf(`{"bindings":[{"condition":{"description":"%{condition_desc}","expression":"%{condition_expr}","title":"%{condition_title}"},"members":["user:admin@hashicorptest.com"],"role":"%{role}"},{"condition":{"expression":"%{condition_expr}","title":"%{condition_title}-no-description"},"members":["user:admin@hashicorptest.com"],"role":"%{role}"}]}`, context) + expectedPolicyData = strings.Replace(expectedPolicyData, "<", "\\u003c", -1) + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccBeyondcorpSecurityGatewayIamPolicy_withConditionGenerated(context), + Check: resource.ComposeAggregateTestCheckFunc( + // TODO(SarahFrench) - uncomment once https://github.com/GoogleCloudPlatform/magic-modules/pull/6466 merged + // resource.TestCheckResourceAttr("data.google_iam_policy.foo", "policy_data", expectedPolicyData), + resource.TestCheckResourceAttr("google_beyondcorp_security_gateway_iam_policy.foo", "policy_data", expectedPolicyData), + resource.TestCheckResourceAttrWith("data.google_iam_policy.foo", "policy_data", tpgresource.CheckGoogleIamPolicy), + ), + }, + { + ResourceName: "google_beyondcorp_security_gateway_iam_policy.foo", + ImportStateId: fmt.Sprintf("projects/%s/locations/%s/securityGateways/%s", envvar.GetTestProjectFromEnv(), "global", fmt.Sprintf("default%s", context["random_suffix"])), + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccBeyondcorpSecurityGatewayIamMember_basicGenerated(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_beyondcorp_security_gateway" "example" { + security_gateway_id = "default%{random_suffix}" + display_name = "My Security Gateway resource" + hubs { region = "us-central1" } +} + +resource "google_beyondcorp_security_gateway_iam_member" "foo" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + role = "%{role}" + member = "user:admin@hashicorptest.com" +} +`, context) +} + +func testAccBeyondcorpSecurityGatewayIamPolicy_basicGenerated(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_beyondcorp_security_gateway" "example" { + security_gateway_id = "default%{random_suffix}" + display_name = "My Security Gateway resource" + hubs { region = "us-central1" } +} + +data "google_iam_policy" "foo" { + binding { + role = "%{role}" + members = ["user:admin@hashicorptest.com"] + } +} + +resource "google_beyondcorp_security_gateway_iam_policy" "foo" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + policy_data = data.google_iam_policy.foo.policy_data +} + +data "google_beyondcorp_security_gateway_iam_policy" "foo" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + depends_on = [ + google_beyondcorp_security_gateway_iam_policy.foo + ] +} +`, context) +} + +func testAccBeyondcorpSecurityGatewayIamPolicy_emptyBinding(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_beyondcorp_security_gateway" "example" { + security_gateway_id = "default%{random_suffix}" + display_name = "My Security Gateway resource" + hubs { region = "us-central1" } +} + +data "google_iam_policy" "foo" { +} + +resource "google_beyondcorp_security_gateway_iam_policy" "foo" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + policy_data = data.google_iam_policy.foo.policy_data +} +`, context) +} + +func testAccBeyondcorpSecurityGatewayIamBinding_basicGenerated(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_beyondcorp_security_gateway" "example" { + security_gateway_id = "default%{random_suffix}" + display_name = "My Security Gateway resource" + hubs { region = "us-central1" } +} + +resource "google_beyondcorp_security_gateway_iam_binding" "foo" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + role = "%{role}" + members = ["user:admin@hashicorptest.com"] +} +`, context) +} + +func testAccBeyondcorpSecurityGatewayIamBinding_updateGenerated(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_beyondcorp_security_gateway" "example" { + security_gateway_id = "default%{random_suffix}" + display_name = "My Security Gateway resource" + hubs { region = "us-central1" } +} + +resource "google_beyondcorp_security_gateway_iam_binding" "foo" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + role = "%{role}" + members = ["user:admin@hashicorptest.com", "user:gterraformtest1@gmail.com"] +} +`, context) +} + +func testAccBeyondcorpSecurityGatewayIamBinding_withConditionGenerated(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_beyondcorp_security_gateway" "example" { + security_gateway_id = "default%{random_suffix}" + display_name = "My Security Gateway resource" + hubs { region = "us-central1" } +} + +resource "google_beyondcorp_security_gateway_iam_binding" "foo" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + role = "%{role}" + members = ["user:admin@hashicorptest.com"] + condition { + title = "%{condition_title}" + description = "%{condition_desc}" + expression = "%{condition_expr}" + } +} +`, context) +} + +func testAccBeyondcorpSecurityGatewayIamBinding_withAndWithoutConditionGenerated(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_beyondcorp_security_gateway" "example" { + security_gateway_id = "default%{random_suffix}" + display_name = "My Security Gateway resource" + hubs { region = "us-central1" } +} + +resource "google_beyondcorp_security_gateway_iam_binding" "foo" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + role = "%{role}" + members = ["user:admin@hashicorptest.com"] +} + +resource "google_beyondcorp_security_gateway_iam_binding" "foo2" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + role = "%{role}" + members = ["user:admin@hashicorptest.com"] + condition { + title = "%{condition_title}" + description = "%{condition_desc}" + expression = "%{condition_expr}" + } +} + +resource "google_beyondcorp_security_gateway_iam_binding" "foo3" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + role = "%{role}" + members = ["user:admin@hashicorptest.com"] + condition { + # Check that lack of description doesn't cause any issues + # Relates to issue : https://github.com/hashicorp/terraform-provider-google/issues/8701 + title = "%{condition_title_no_desc}" + expression = "%{condition_expr_no_desc}" + } +} +`, context) +} + +func testAccBeyondcorpSecurityGatewayIamMember_withConditionGenerated(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_beyondcorp_security_gateway" "example" { + security_gateway_id = "default%{random_suffix}" + display_name = "My Security Gateway resource" + hubs { region = "us-central1" } +} + +resource "google_beyondcorp_security_gateway_iam_member" "foo" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + role = "%{role}" + member = "user:admin@hashicorptest.com" + condition { + title = "%{condition_title}" + description = "%{condition_desc}" + expression = "%{condition_expr}" + } +} +`, context) +} + +func testAccBeyondcorpSecurityGatewayIamMember_withAndWithoutConditionGenerated(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_beyondcorp_security_gateway" "example" { + security_gateway_id = "default%{random_suffix}" + display_name = "My Security Gateway resource" + hubs { region = "us-central1" } +} + +resource "google_beyondcorp_security_gateway_iam_member" "foo" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + role = "%{role}" + member = "user:admin@hashicorptest.com" +} + +resource "google_beyondcorp_security_gateway_iam_member" "foo2" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + role = "%{role}" + member = "user:admin@hashicorptest.com" + condition { + title = "%{condition_title}" + description = "%{condition_desc}" + expression = "%{condition_expr}" + } +} + +resource "google_beyondcorp_security_gateway_iam_member" "foo3" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + role = "%{role}" + member = "user:admin@hashicorptest.com" + condition { + # Check that lack of description doesn't cause any issues + # Relates to issue : https://github.com/hashicorp/terraform-provider-google/issues/8701 + title = "%{condition_title_no_desc}" + expression = "%{condition_expr_no_desc}" + } +} +`, context) +} + +func testAccBeyondcorpSecurityGatewayIamPolicy_withConditionGenerated(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_beyondcorp_security_gateway" "example" { + security_gateway_id = "default%{random_suffix}" + display_name = "My Security Gateway resource" + hubs { region = "us-central1" } +} + +data "google_iam_policy" "foo" { + binding { + role = "%{role}" + members = ["user:admin@hashicorptest.com"] + condition { + # Check that lack of description doesn't cause any issues + # Relates to issue : https://github.com/hashicorp/terraform-provider-google/issues/8701 + title = "%{condition_title_no_desc}" + expression = "%{condition_expr_no_desc}" + } + } + binding { + role = "%{role}" + members = ["user:admin@hashicorptest.com"] + condition { + title = "%{condition_title}" + description = "%{condition_desc}" + expression = "%{condition_expr}" + } + } +} + +resource "google_beyondcorp_security_gateway_iam_policy" "foo" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + policy_data = data.google_iam_policy.foo.policy_data +} +`, context) +} diff --git a/website/docs/d/beyondcorp_security_gateway_iam_policy.html.markdown b/website/docs/d/beyondcorp_security_gateway_iam_policy.html.markdown new file mode 100644 index 0000000000..a87f550a9e --- /dev/null +++ b/website/docs/d/beyondcorp_security_gateway_iam_policy.html.markdown @@ -0,0 +1,53 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: MMv1 *** +# +# ---------------------------------------------------------------------------- +# +# 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. +# +# ---------------------------------------------------------------------------- +subcategory: "BeyondCorp" +description: |- + A datasource to retrieve the IAM policy state for BeyondCorp SecurityGateway +--- + + +# `google_beyondcorp_security_gateway_iam_policy` +Retrieves the current IAM policy data for securitygateway + + +## example + +```hcl +data "google_beyondcorp_security_gateway_iam_policy" "policy" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id +} +``` + +## Argument Reference + +The following arguments are supported: + +* `location` - (Optional) Resource ID segment making up resource `name`. It identifies the resource within its parent collection as described in https://google.aip.dev/122. Must be omitted or set to `global`. Used to find the parent resource to bind the IAM policy to. If not specified, + the value will be parsed from the identifier of the parent resource. If no location is provided in the parent identifier and no + location is specified, it is taken from the provider configuration. + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the project will be parsed from the identifier of the parent resource. If no project is provided in the parent identifier and no project is specified, the provider project is used. + +## Attributes Reference + +The attributes are exported: + +* `etag` - (Computed) The etag of the IAM policy. + +* `policy_data` - (Required only by `google_beyondcorp_security_gateway_iam_policy`) The policy data generated by + a `google_iam_policy` data source. diff --git a/website/docs/r/beyondcorp_security_gateway_iam.html.markdown b/website/docs/r/beyondcorp_security_gateway_iam.html.markdown new file mode 100644 index 0000000000..4090dc94f7 --- /dev/null +++ b/website/docs/r/beyondcorp_security_gateway_iam.html.markdown @@ -0,0 +1,232 @@ +--- +# ---------------------------------------------------------------------------- +# +# *** AUTO GENERATED CODE *** Type: MMv1 *** +# +# ---------------------------------------------------------------------------- +# +# 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. +# +# ---------------------------------------------------------------------------- +subcategory: "BeyondCorp" +description: |- + Collection of resources to manage IAM policy for BeyondCorp SecurityGateway +--- + +# IAM policy for BeyondCorp SecurityGateway +Three different resources help you manage your IAM policy for BeyondCorp SecurityGateway. Each of these resources serves a different use case: + +* `google_beyondcorp_security_gateway_iam_policy`: Authoritative. Sets the IAM policy for the securitygateway and replaces any existing policy already attached. +* `google_beyondcorp_security_gateway_iam_binding`: Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. Other roles within the IAM policy for the securitygateway are preserved. +* `google_beyondcorp_security_gateway_iam_member`: Non-authoritative. Updates the IAM policy to grant a role to a new member. Other members for the role for the securitygateway are preserved. + +A data source can be used to retrieve policy data in advent you do not need creation + +* `google_beyondcorp_security_gateway_iam_policy`: Retrieves the IAM policy for the securitygateway + +~> **Note:** `google_beyondcorp_security_gateway_iam_policy` **cannot** be used in conjunction with `google_beyondcorp_security_gateway_iam_binding` and `google_beyondcorp_security_gateway_iam_member` or they will fight over what your policy should be. + +~> **Note:** `google_beyondcorp_security_gateway_iam_binding` resources **can be** used in conjunction with `google_beyondcorp_security_gateway_iam_member` resources **only if** they do not grant privilege to the same role. + +~> **Note:** This resource supports IAM Conditions but they have some known limitations which can be found [here](https://cloud.google.com/iam/docs/conditions-overview#limitations). Please review this article if you are having issues with IAM Conditions. + + +## google_beyondcorp_security_gateway_iam_policy + +```hcl +data "google_iam_policy" "admin" { + binding { + role = "roles/beyondcorp.securityGatewayUser" + members = [ + "user:jane@example.com", + ] + } +} + +resource "google_beyondcorp_security_gateway_iam_policy" "policy" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + policy_data = data.google_iam_policy.admin.policy_data +} +``` + +With IAM Conditions: + +```hcl +data "google_iam_policy" "admin" { + binding { + role = "roles/beyondcorp.securityGatewayUser" + members = [ + "user:jane@example.com", + ] + + condition { + title = "expires_after_2019_12_31" + description = "Expiring at midnight of 2019-12-31" + expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")" + } + } +} + +resource "google_beyondcorp_security_gateway_iam_policy" "policy" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + policy_data = data.google_iam_policy.admin.policy_data +} +``` +## google_beyondcorp_security_gateway_iam_binding + +```hcl +resource "google_beyondcorp_security_gateway_iam_binding" "binding" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + role = "roles/beyondcorp.securityGatewayUser" + members = [ + "user:jane@example.com", + ] +} +``` + +With IAM Conditions: + +```hcl +resource "google_beyondcorp_security_gateway_iam_binding" "binding" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + role = "roles/beyondcorp.securityGatewayUser" + members = [ + "user:jane@example.com", + ] + + condition { + title = "expires_after_2019_12_31" + description = "Expiring at midnight of 2019-12-31" + expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")" + } +} +``` +## google_beyondcorp_security_gateway_iam_member + +```hcl +resource "google_beyondcorp_security_gateway_iam_member" "member" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + role = "roles/beyondcorp.securityGatewayUser" + member = "user:jane@example.com" +} +``` + +With IAM Conditions: + +```hcl +resource "google_beyondcorp_security_gateway_iam_member" "member" { + project = google_beyondcorp_security_gateway.example.project + location = google_beyondcorp_security_gateway.example.location + security_gateway_id = google_beyondcorp_security_gateway.example.security_gateway_id + role = "roles/beyondcorp.securityGatewayUser" + member = "user:jane@example.com" + + condition { + title = "expires_after_2019_12_31" + description = "Expiring at midnight of 2019-12-31" + expression = "request.time < timestamp(\"2020-01-01T00:00:00Z\")" + } +} +``` + +## Argument Reference + +The following arguments are supported: + +* `location` - (Optional) Resource ID segment making up resource `name`. It identifies the resource within its parent collection as described in https://google.aip.dev/122. Must be omitted or set to `global`. Used to find the parent resource to bind the IAM policy to. If not specified, + the value will be parsed from the identifier of the parent resource. If no location is provided in the parent identifier and no + location is specified, it is taken from the provider configuration. + +* `project` - (Optional) The ID of the project in which the resource belongs. + If it is not provided, the project will be parsed from the identifier of the parent resource. If no project is provided in the parent identifier and no project is specified, the provider project is used. + +* `member/members` - (Required) Identities that will be granted the privilege in `role`. + Each entry can have one of the following values: + * **allUsers**: A special identifier that represents anyone who is on the internet; with or without a Google account. + * **allAuthenticatedUsers**: A special identifier that represents anyone who is authenticated with a Google account or a service account. + * **user:{emailid}**: An email address that represents a specific Google account. For example, alice@gmail.com or joe@example.com. + * **serviceAccount:{emailid}**: An email address that represents a service account. For example, my-other-app@appspot.gserviceaccount.com. + * **group:{emailid}**: An email address that represents a Google group. For example, admins@example.com. + * **domain:{domain}**: A G Suite domain (primary, instead of alias) name that represents all the users of that domain. For example, google.com or example.com. + * **projectOwner:projectid**: Owners of the given project. For example, "projectOwner:my-example-project" + * **projectEditor:projectid**: Editors of the given project. For example, "projectEditor:my-example-project" + * **projectViewer:projectid**: Viewers of the given project. For example, "projectViewer:my-example-project" + +* `role` - (Required) The role that should be applied. Only one + `google_beyondcorp_security_gateway_iam_binding` can be used per role. Note that custom roles must be of the format + `[projects|organizations]/{parent-name}/roles/{role-name}`. + +* `policy_data` - (Required only by `google_beyondcorp_security_gateway_iam_policy`) The policy data generated by + a `google_iam_policy` data source. + +* `condition` - (Optional) An [IAM Condition](https://cloud.google.com/iam/docs/conditions-overview) for a given binding. + Structure is documented below. + +--- + +The `condition` block supports: + +* `expression` - (Required) Textual representation of an expression in Common Expression Language syntax. + +* `title` - (Required) A title for the expression, i.e. a short string describing its purpose. + +* `description` - (Optional) An optional description of the expression. This is a longer text which describes the expression, e.g. when hovered over it in a UI. + +~> **Warning:** Terraform considers the `role` and condition contents (`title`+`description`+`expression`) as the + identifier for the binding. This means that if any part of the condition is changed out-of-band, Terraform will + consider it to be an entirely different resource and will treat it as such. +## Attributes Reference + +In addition to the arguments listed above, the following computed attributes are +exported: + +* `etag` - (Computed) The etag of the IAM policy. + +## Import + +For all import syntaxes, the "resource in question" can take any of the following forms: + +* projects/{{project}}/locations/{{location}}/securityGateways/{{security_gateway_id}} +* {{project}}/{{location}}/{{security_gateway_id}} +* {{location}}/{{security_gateway_id}} +* {{security_gateway_id}} + +Any variables not passed in the import command will be taken from the provider configuration. + +BeyondCorp securitygateway IAM resources can be imported using the resource identifiers, role, and member. + +IAM member imports use space-delimited identifiers: the resource in question, the role, and the member identity, e.g. +``` +$ terraform import google_beyondcorp_security_gateway_iam_member.editor "projects/{{project}}/locations/{{location}}/securityGateways/{{security_gateway_id}} roles/beyondcorp.securityGatewayUser user:jane@example.com" +``` + +IAM binding imports use space-delimited identifiers: the resource in question and the role, e.g. +``` +$ terraform import google_beyondcorp_security_gateway_iam_binding.editor "projects/{{project}}/locations/{{location}}/securityGateways/{{security_gateway_id}} roles/beyondcorp.securityGatewayUser" +``` + +IAM policy imports use the identifier of the resource in question, e.g. +``` +$ terraform import google_beyondcorp_security_gateway_iam_policy.editor projects/{{project}}/locations/{{location}}/securityGateways/{{security_gateway_id}} +``` + +-> **Custom Roles** If you're importing a IAM resource with a custom role, make sure to use the + full name of the custom role, e.g. `[projects/my-project|organizations/my-org]/roles/my-custom-role`. + +## User Project Overrides + +This resource supports [User Project Overrides](https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/provider_reference#user_project_override).