From 19f133a42435af1cbaaa829cdf7ada74d81a9d8e Mon Sep 17 00:00:00 2001 From: Modular Magician Date: Fri, 15 Sep 2023 22:26:21 +0000 Subject: [PATCH] Move sign_in from google_identity_platform_project_default_config to google_identity_platform_config. (#8559) Co-authored-by: Shuya Ma <87669292+shuyama1@users.noreply.github.com> Signed-off-by: Modular Magician --- .changelog/8559.txt | 6 + .../resource_identity_platform_config.go | 491 ++++++++++++++++++ ...identity_platform_config_generated_test.go | 18 +- .../resource_identity_platform_config_test.go | 129 +++++ ...dentity_platform_project_default_config.go | 4 + .../guides/version_5_upgrade.html.markdown | 6 + .../r/identity_platform_config.html.markdown | 100 +++- 7 files changed, 752 insertions(+), 2 deletions(-) create mode 100644 .changelog/8559.txt create mode 100644 google/services/identityplatform/resource_identity_platform_config_test.go diff --git a/.changelog/8559.txt b/.changelog/8559.txt new file mode 100644 index 00000000000..3f3abe35791 --- /dev/null +++ b/.changelog/8559.txt @@ -0,0 +1,6 @@ +```release-note:enhancement +identityplayform: added `sign-in` field to `google_identity_platform_config` resource +``` +```release-note:deprecation +identityplayform: deprecated `google_identity_platform_project_default_config` resource. Use `google_identity_platform_config` resource instead +``` diff --git a/google/services/identityplatform/resource_identity_platform_config.go b/google/services/identityplatform/resource_identity_platform_config.go index 3cbd1daeb37..01d20de57ce 100644 --- a/google/services/identityplatform/resource_identity_platform_config.go +++ b/google/services/identityplatform/resource_identity_platform_config.go @@ -155,6 +155,113 @@ func ResourceIdentityPlatformConfig() *schema.Resource { }, }, }, + "sign_in": { + Type: schema.TypeList, + Optional: true, + Description: `Configuration related to local sign in methods.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "allow_duplicate_emails": { + Type: schema.TypeBool, + Optional: true, + Description: `Whether to allow more than one account to have the same email.`, + }, + "anonymous": { + Type: schema.TypeList, + Optional: true, + Description: `Configuration options related to authenticating an anonymous user.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Whether anonymous user auth is enabled for the project or not.`, + }, + }, + }, + }, + "email": { + Type: schema.TypeList, + Optional: true, + Description: `Configuration options related to authenticating a user by their email address.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Whether email auth is enabled for the project or not.`, + }, + "password_required": { + Type: schema.TypeBool, + Optional: true, + Description: `Whether a password is required for email auth or not. If true, both an email and +password must be provided to sign in. If false, a user may sign in via either +email/password or email link.`, + }, + }, + }, + }, + "phone_number": { + Type: schema.TypeList, + Optional: true, + Description: `Configuration options related to authenticated a user by their phone number.`, + MaxItems: 1, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "enabled": { + Type: schema.TypeBool, + Required: true, + Description: `Whether phone number auth is enabled for the project or not.`, + }, + "test_phone_numbers": { + Type: schema.TypeMap, + Optional: true, + Description: `A map of that can be used for phone auth testing.`, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + }, + }, + "hash_config": { + Type: schema.TypeList, + Computed: true, + Description: `Output only. Hash config information.`, + Elem: &schema.Resource{ + Schema: map[string]*schema.Schema{ + "algorithm": { + Type: schema.TypeString, + Computed: true, + Description: `Different password hash algorithms used in Identity Toolkit.`, + }, + "memory_cost": { + Type: schema.TypeInt, + Computed: true, + Description: `Memory cost for hash calculation. Used by scrypt and other similar password derivation algorithms. See https://tools.ietf.org/html/rfc7914 for explanation of field.`, + }, + "rounds": { + Type: schema.TypeInt, + Computed: true, + Description: `How many rounds for hash calculation. Used by scrypt and other similar password derivation algorithms.`, + }, + "salt_separator": { + Type: schema.TypeString, + Computed: true, + Description: `Non-printable character to be inserted between the salt and plain text password in base64.`, + }, + "signer_key": { + Type: schema.TypeString, + Computed: true, + Description: `Signer key in base64.`, + }, + }, + }, + }, + }, + }, + }, "name": { Type: schema.TypeString, Computed: true, @@ -274,6 +381,9 @@ func resourceIdentityPlatformConfigRead(d *schema.ResourceData, meta interface{} if err := d.Set("autodelete_anonymous_users", flattenIdentityPlatformConfigAutodeleteAnonymousUsers(res["autodeleteAnonymousUsers"], d, config)); err != nil { return fmt.Errorf("Error reading Config: %s", err) } + if err := d.Set("sign_in", flattenIdentityPlatformConfigSignIn(res["signIn"], d, config)); err != nil { + return fmt.Errorf("Error reading Config: %s", err) + } if err := d.Set("blocking_functions", flattenIdentityPlatformConfigBlockingFunctions(res["blockingFunctions"], d, config)); err != nil { return fmt.Errorf("Error reading Config: %s", err) } @@ -309,6 +419,12 @@ func resourceIdentityPlatformConfigUpdate(d *schema.ResourceData, meta interface } else if v, ok := d.GetOkExists("autodelete_anonymous_users"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, autodeleteAnonymousUsersProp)) { obj["autodeleteAnonymousUsers"] = autodeleteAnonymousUsersProp } + signInProp, err := expandIdentityPlatformConfigSignIn(d.Get("sign_in"), d, config) + if err != nil { + return err + } else if v, ok := d.GetOkExists("sign_in"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, signInProp)) { + obj["signIn"] = signInProp + } blockingFunctionsProp, err := expandIdentityPlatformConfigBlockingFunctions(d.Get("blocking_functions"), d, config) if err != nil { return err @@ -340,6 +456,10 @@ func resourceIdentityPlatformConfigUpdate(d *schema.ResourceData, meta interface updateMask = append(updateMask, "autodeleteAnonymousUsers") } + if d.HasChange("sign_in") { + updateMask = append(updateMask, "signIn") + } + if d.HasChange("blocking_functions") { updateMask = append(updateMask, "blockingFunctions") } @@ -419,6 +539,161 @@ func flattenIdentityPlatformConfigAutodeleteAnonymousUsers(v interface{}, d *sch return v } +func flattenIdentityPlatformConfigSignIn(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["email"] = + flattenIdentityPlatformConfigSignInEmail(original["email"], d, config) + transformed["phone_number"] = + flattenIdentityPlatformConfigSignInPhoneNumber(original["phoneNumber"], d, config) + transformed["anonymous"] = + flattenIdentityPlatformConfigSignInAnonymous(original["anonymous"], d, config) + transformed["allow_duplicate_emails"] = + flattenIdentityPlatformConfigSignInAllowDuplicateEmails(original["allowDuplicateEmails"], d, config) + transformed["hash_config"] = + flattenIdentityPlatformConfigSignInHashConfig(original["hashConfig"], d, config) + return []interface{}{transformed} +} +func flattenIdentityPlatformConfigSignInEmail(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["enabled"] = + flattenIdentityPlatformConfigSignInEmailEnabled(original["enabled"], d, config) + transformed["password_required"] = + flattenIdentityPlatformConfigSignInEmailPasswordRequired(original["passwordRequired"], d, config) + return []interface{}{transformed} +} +func flattenIdentityPlatformConfigSignInEmailEnabled(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenIdentityPlatformConfigSignInEmailPasswordRequired(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenIdentityPlatformConfigSignInPhoneNumber(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["enabled"] = + flattenIdentityPlatformConfigSignInPhoneNumberEnabled(original["enabled"], d, config) + transformed["test_phone_numbers"] = + flattenIdentityPlatformConfigSignInPhoneNumberTestPhoneNumbers(original["testPhoneNumbers"], d, config) + return []interface{}{transformed} +} +func flattenIdentityPlatformConfigSignInPhoneNumberEnabled(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenIdentityPlatformConfigSignInPhoneNumberTestPhoneNumbers(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenIdentityPlatformConfigSignInAnonymous(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + + original := v.(map[string]interface{}) + transformed := make(map[string]interface{}) + + if original["enabled"] == nil { + transformed["enabled"] = false + } else { + transformed["enabled"] = original["enabled"] + } + + return []interface{}{transformed} +} + +func flattenIdentityPlatformConfigSignInAllowDuplicateEmails(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenIdentityPlatformConfigSignInHashConfig(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + if v == nil { + return nil + } + original := v.(map[string]interface{}) + if len(original) == 0 { + return nil + } + transformed := make(map[string]interface{}) + transformed["algorithm"] = + flattenIdentityPlatformConfigSignInHashConfigAlgorithm(original["algorithm"], d, config) + transformed["signer_key"] = + flattenIdentityPlatformConfigSignInHashConfigSignerKey(original["signerKey"], d, config) + transformed["salt_separator"] = + flattenIdentityPlatformConfigSignInHashConfigSaltSeparator(original["saltSeparator"], d, config) + transformed["rounds"] = + flattenIdentityPlatformConfigSignInHashConfigRounds(original["rounds"], d, config) + transformed["memory_cost"] = + flattenIdentityPlatformConfigSignInHashConfigMemoryCost(original["memoryCost"], d, config) + return []interface{}{transformed} +} +func flattenIdentityPlatformConfigSignInHashConfigAlgorithm(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenIdentityPlatformConfigSignInHashConfigSignerKey(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenIdentityPlatformConfigSignInHashConfigSaltSeparator(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + return v +} + +func flattenIdentityPlatformConfigSignInHashConfigRounds(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + +func flattenIdentityPlatformConfigSignInHashConfigMemoryCost(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { + // Handles the string fixed64 format + if strVal, ok := v.(string); ok { + if intVal, err := tpgresource.StringToFixed64(strVal); err == nil { + return intVal + } + } + + // number values are represented as float64 + if floatVal, ok := v.(float64); ok { + intVal := int(floatVal) + return intVal + } + + return v // let terraform core handle it otherwise +} + func flattenIdentityPlatformConfigBlockingFunctions(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} { if v == nil { return nil @@ -550,6 +825,222 @@ func expandIdentityPlatformConfigAutodeleteAnonymousUsers(v interface{}, d tpgre return v, nil } +func expandIdentityPlatformConfigSignIn(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedEmail, err := expandIdentityPlatformConfigSignInEmail(original["email"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEmail); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["email"] = transformedEmail + } + + transformedPhoneNumber, err := expandIdentityPlatformConfigSignInPhoneNumber(original["phone_number"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPhoneNumber); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["phoneNumber"] = transformedPhoneNumber + } + + transformedAnonymous, err := expandIdentityPlatformConfigSignInAnonymous(original["anonymous"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAnonymous); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["anonymous"] = transformedAnonymous + } + + transformedAllowDuplicateEmails, err := expandIdentityPlatformConfigSignInAllowDuplicateEmails(original["allow_duplicate_emails"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAllowDuplicateEmails); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["allowDuplicateEmails"] = transformedAllowDuplicateEmails + } + + transformedHashConfig, err := expandIdentityPlatformConfigSignInHashConfig(original["hash_config"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedHashConfig); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["hashConfig"] = transformedHashConfig + } + + return transformed, nil +} + +func expandIdentityPlatformConfigSignInEmail(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedEnabled, err := expandIdentityPlatformConfigSignInEmailEnabled(original["enabled"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEnabled); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["enabled"] = transformedEnabled + } + + transformedPasswordRequired, err := expandIdentityPlatformConfigSignInEmailPasswordRequired(original["password_required"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedPasswordRequired); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["passwordRequired"] = transformedPasswordRequired + } + + return transformed, nil +} + +func expandIdentityPlatformConfigSignInEmailEnabled(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandIdentityPlatformConfigSignInEmailPasswordRequired(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandIdentityPlatformConfigSignInPhoneNumber(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedEnabled, err := expandIdentityPlatformConfigSignInPhoneNumberEnabled(original["enabled"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedEnabled); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["enabled"] = transformedEnabled + } + + transformedTestPhoneNumbers, err := expandIdentityPlatformConfigSignInPhoneNumberTestPhoneNumbers(original["test_phone_numbers"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedTestPhoneNumbers); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["testPhoneNumbers"] = transformedTestPhoneNumbers + } + + return transformed, nil +} + +func expandIdentityPlatformConfigSignInPhoneNumberEnabled(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandIdentityPlatformConfigSignInPhoneNumberTestPhoneNumbers(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) { + if v == nil { + return map[string]string{}, nil + } + m := make(map[string]string) + for k, val := range v.(map[string]interface{}) { + m[k] = val.(string) + } + return m, nil +} + +func expandIdentityPlatformConfigSignInAnonymous(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedEnabled, err := expandIdentityPlatformConfigSignInAnonymousEnabled(original["enabled"], d, config) + if err != nil { + return nil, err + } else { + transformed["enabled"] = transformedEnabled + } + + return transformed, nil +} + +func expandIdentityPlatformConfigSignInAnonymousEnabled(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandIdentityPlatformConfigSignInAllowDuplicateEmails(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandIdentityPlatformConfigSignInHashConfig(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + l := v.([]interface{}) + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedAlgorithm, err := expandIdentityPlatformConfigSignInHashConfigAlgorithm(original["algorithm"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedAlgorithm); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["algorithm"] = transformedAlgorithm + } + + transformedSignerKey, err := expandIdentityPlatformConfigSignInHashConfigSignerKey(original["signer_key"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSignerKey); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["signerKey"] = transformedSignerKey + } + + transformedSaltSeparator, err := expandIdentityPlatformConfigSignInHashConfigSaltSeparator(original["salt_separator"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSaltSeparator); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["saltSeparator"] = transformedSaltSeparator + } + + transformedRounds, err := expandIdentityPlatformConfigSignInHashConfigRounds(original["rounds"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRounds); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["rounds"] = transformedRounds + } + + transformedMemoryCost, err := expandIdentityPlatformConfigSignInHashConfigMemoryCost(original["memory_cost"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedMemoryCost); val.IsValid() && !tpgresource.IsEmptyValue(val) { + transformed["memoryCost"] = transformedMemoryCost + } + + return transformed, nil +} + +func expandIdentityPlatformConfigSignInHashConfigAlgorithm(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandIdentityPlatformConfigSignInHashConfigSignerKey(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandIdentityPlatformConfigSignInHashConfigSaltSeparator(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandIdentityPlatformConfigSignInHashConfigRounds(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + +func expandIdentityPlatformConfigSignInHashConfigMemoryCost(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { + return v, nil +} + func expandIdentityPlatformConfigBlockingFunctions(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) { l := v.([]interface{}) if len(l) == 0 || l[0] == nil { diff --git a/google/services/identityplatform/resource_identity_platform_config_generated_test.go b/google/services/identityplatform/resource_identity_platform_config_generated_test.go index f5fec30f788..2722c3d0883 100644 --- a/google/services/identityplatform/resource_identity_platform_config_generated_test.go +++ b/google/services/identityplatform/resource_identity_platform_config_generated_test.go @@ -71,10 +71,26 @@ resource "google_project_service" "identitytoolkit" { service = "identitytoolkit.googleapis.com" } - resource "google_identity_platform_config" "default" { project = google_project.default.project_id autodelete_anonymous_users = true + sign_in { + allow_duplicate_emails = true + + anonymous { + enabled = true + } + email { + enabled = true + password_required = false + } + phone_number { + enabled = true + test_phone_numbers = { + "+11231231234" = "000000" + } + } + } blocking_functions { triggers { event_type = "beforeSignIn" diff --git a/google/services/identityplatform/resource_identity_platform_config_test.go b/google/services/identityplatform/resource_identity_platform_config_test.go new file mode 100644 index 00000000000..d06ef3ad03a --- /dev/null +++ b/google/services/identityplatform/resource_identity_platform_config_test.go @@ -0,0 +1,129 @@ +// Copyright (c) HashiCorp, Inc. +// SPDX-License-Identifier: MPL-2.0 +package identityplatform_test + +import ( + "testing" + "time" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + + "github.com/hashicorp/terraform-provider-google/google/acctest" + "github.com/hashicorp/terraform-provider-google/google/envvar" +) + +func TestAccIdentityPlatformConfig_update(t *testing.T) { + acctest.SkipIfVcr(t) + t.Parallel() + + context := map[string]interface{}{ + "org_id": envvar.GetTestOrgFromEnv(t), + "billing_acct": envvar.GetTestBillingAccountFromEnv(t), + "quota_start_time": time.Now().AddDate(0, 0, 1).Format(time.RFC3339), + "random_suffix": acctest.RandString(t, 10), + } + + acctest.VcrTest(t, resource.TestCase{ + PreCheck: func() { acctest.AccTestPreCheck(t) }, + ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t), + Steps: []resource.TestStep{ + { + Config: testAccIdentityPlatformConfig_basic(context), + }, + { + ResourceName: "google_identity_platform_config.basic", + ImportState: true, + ImportStateVerify: true, + }, + { + Config: testAccIdentityPlatformConfig_update(context), + }, + { + ResourceName: "google_identity_platform_config.basic", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} + +func testAccIdentityPlatformConfig_basic(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_project" "basic" { + project_id = "tf-test-my-project%{random_suffix}" + name = "tf-test-my-project%{random_suffix}" + org_id = "%{org_id}" + billing_account = "%{billing_acct}" + labels = { + firebase = "enabled" + } +} + +resource "google_project_service" "identitytoolkit" { + project = google_project.basic.project_id + service = "identitytoolkit.googleapis.com" +} + +resource "google_identity_platform_config" "basic" { + project = google_project.basic.project_id + autodelete_anonymous_users = true + sign_in { + allow_duplicate_emails = true + + anonymous { + enabled = true + } + email { + enabled = true + password_required = false + } + phone_number { + enabled = true + test_phone_numbers = { + "+11231231234" = "000000" + } + } + } +} +`, context) +} + +func testAccIdentityPlatformConfig_update(context map[string]interface{}) string { + return acctest.Nprintf(` +resource "google_project" "basic" { + project_id = "tf-test-my-project%{random_suffix}" + name = "tf-test-my-project%{random_suffix}" + org_id = "%{org_id}" + billing_account = "%{billing_acct}" + labels = { + firebase = "enabled" + } +} + +resource "google_project_service" "identitytoolkit" { + project = google_project.basic.project_id + service = "identitytoolkit.googleapis.com" +} + +resource "google_identity_platform_config" "basic" { + project = google_project.basic.project_id + sign_in { + allow_duplicate_emails = false + + anonymous { + enabled = false + } + email { + enabled = true + password_required = true + } + phone_number { + enabled = true + test_phone_numbers = { + "+17651212343" = "111111" + } + } + } +} +`, context) +} diff --git a/google/services/identityplatform/resource_identity_platform_project_default_config.go b/google/services/identityplatform/resource_identity_platform_project_default_config.go index 8d48ccdd6ee..71a926de19d 100644 --- a/google/services/identityplatform/resource_identity_platform_project_default_config.go +++ b/google/services/identityplatform/resource_identity_platform_project_default_config.go @@ -47,6 +47,10 @@ func ResourceIdentityPlatformProjectDefaultConfig() *schema.Resource { Delete: schema.DefaultTimeout(20 * time.Minute), }, + DeprecationMessage: "Deprecated. Use the `google_identity_platform_config` resource instead. " + + "It contains a more comprehensive list of fields, and was created before " + + "`google_identity_platform_project_default_config` was added.", + Schema: map[string]*schema.Schema{ "sign_in": { Type: schema.TypeList, diff --git a/website/docs/guides/version_5_upgrade.html.markdown b/website/docs/guides/version_5_upgrade.html.markdown index 7264d81c38b..ed27d4175f4 100644 --- a/website/docs/guides/version_5_upgrade.html.markdown +++ b/website/docs/guides/version_5_upgrade.html.markdown @@ -510,3 +510,9 @@ resource "google_secret_manager_secret" "my-secret" { } } ``` + +## Resource: `google_identity_platform_project_default_config` + +### `google_identity_platform_project_default_config` has been removed from the provider + +Use the `google_identity_platform_config` resource instead. It contains a more comprehensive list of fields, and was created before `google_identity_platform_project_default_config` was added. \ No newline at end of file diff --git a/website/docs/r/identity_platform_config.html.markdown b/website/docs/r/identity_platform_config.html.markdown index be086559506..c09dcf2b6b8 100644 --- a/website/docs/r/identity_platform_config.html.markdown +++ b/website/docs/r/identity_platform_config.html.markdown @@ -53,10 +53,26 @@ resource "google_project_service" "identitytoolkit" { service = "identitytoolkit.googleapis.com" } - resource "google_identity_platform_config" "default" { project = google_project.default.project_id autodelete_anonymous_users = true + sign_in { + allow_duplicate_emails = true + + anonymous { + enabled = true + } + email { + enabled = true + password_required = false + } + phone_number { + enabled = true + test_phone_numbers = { + "+11231231234" = "000000" + } + } + } blocking_functions { triggers { event_type = "beforeSignIn" @@ -96,6 +112,11 @@ The following arguments are supported: (Optional) Whether anonymous users will be auto-deleted after a period of 30 days +* `sign_in` - + (Optional) + Configuration related to local sign in methods. + Structure is [documented below](#nested_sign_in). + * `blocking_functions` - (Optional) Configuration related to blocking functions. @@ -114,6 +135,83 @@ The following arguments are supported: If it is not provided, the provider project is used. +The `sign_in` block supports: + +* `email` - + (Optional) + Configuration options related to authenticating a user by their email address. + Structure is [documented below](#nested_email). + +* `phone_number` - + (Optional) + Configuration options related to authenticated a user by their phone number. + Structure is [documented below](#nested_phone_number). + +* `anonymous` - + (Optional) + Configuration options related to authenticating an anonymous user. + Structure is [documented below](#nested_anonymous). + +* `allow_duplicate_emails` - + (Optional) + Whether to allow more than one account to have the same email. + +* `hash_config` - + (Output) + Output only. Hash config information. + Structure is [documented below](#nested_hash_config). + + +The `email` block supports: + +* `enabled` - + (Required) + Whether email auth is enabled for the project or not. + +* `password_required` - + (Optional) + Whether a password is required for email auth or not. If true, both an email and + password must be provided to sign in. If false, a user may sign in via either + email/password or email link. + +The `phone_number` block supports: + +* `enabled` - + (Required) + Whether phone number auth is enabled for the project or not. + +* `test_phone_numbers` - + (Optional) + A map of that can be used for phone auth testing. + +The `anonymous` block supports: + +* `enabled` - + (Required) + Whether anonymous user auth is enabled for the project or not. + +The `hash_config` block contains: + +* `algorithm` - + (Output) + Different password hash algorithms used in Identity Toolkit. + +* `signer_key` - + (Output) + Signer key in base64. + +* `salt_separator` - + (Output) + Non-printable character to be inserted between the salt and plain text password in base64. + +* `rounds` - + (Output) + How many rounds for hash calculation. Used by scrypt and other similar password derivation algorithms. + +* `memory_cost` - + (Output) + Memory cost for hash calculation. Used by scrypt and other similar password derivation algorithms. See https://tools.ietf.org/html/rfc7914 for explanation of field. + The `blocking_functions` block supports: * `triggers` -