From 5183207dca70467494c587ce07508068f6ed2131 Mon Sep 17 00:00:00 2001 From: Jakub Michalak Date: Fri, 5 Jul 2024 16:15:14 +0200 Subject: [PATCH 1/7] Fill fields in datasource for saml2 and scim --- docs/data-sources/security_integrations.md | 270 +++++++++++++++++- .../security_integrations_acceptance_test.go | 118 +++++++- .../optionals_set/test.tf | 11 +- .../optionals_set/variables.tf | 3 + .../optionals_unset/test.tf | 13 +- .../optionals_unset/variables.tf | 3 + .../saml2/optionals_set/test.tf | 25 ++ .../saml2/optionals_set/variables.tf | 52 ++++ .../saml2/optionals_unset/test.tf | 26 ++ .../saml2/optionals_unset/variables.tf | 52 ++++ pkg/helpers/helpers.go | 14 + pkg/resources/database.go | 2 +- pkg/resources/helpers.go | 14 - pkg/resources/secondary_database.go | 2 +- pkg/resources/shared_database.go | 2 +- pkg/schemas/saml2_security_integration.go | 47 +-- pkg/schemas/scim_security_integration.go | 28 +- pkg/schemas/security_integration.go | 18 +- 18 files changed, 619 insertions(+), 81 deletions(-) create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_set/test.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_set/variables.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_unset/test.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_unset/variables.tf diff --git a/docs/data-sources/security_integrations.md b/docs/data-sources/security_integrations.md index 225a2f8703..1d19cdcc36 100644 --- a/docs/data-sources/security_integrations.md +++ b/docs/data-sources/security_integrations.md @@ -100,10 +100,274 @@ Read-Only: Read-Only: -- `todo` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--todo)) +- `allowed_email_patterns` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--allowed_email_patterns)) +- `allowed_user_domains` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--allowed_user_domains)) +- `comment` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--comment)) +- `enabled` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--enabled)) +- `network_policy` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--network_policy)) +- `run_as_role` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--run_as_role)) +- `saml2_digest_methods_used` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_digest_methods_used)) +- `saml2_enable_sp_initiated` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_enable_sp_initiated)) +- `saml2_force_authn` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_force_authn)) +- `saml2_issuer` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_issuer)) +- `saml2_post_logout_redirect_url` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_post_logout_redirect_url)) +- `saml2_provider` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_provider)) +- `saml2_requested_nameid_format` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_requested_nameid_format)) +- `saml2_sign_request` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_sign_request)) +- `saml2_signature_methods_used` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_signature_methods_used)) +- `saml2_snowflake_acs_url` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_snowflake_acs_url)) +- `saml2_snowflake_issuer_url` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_snowflake_issuer_url)) +- `saml2_snowflake_metadata` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_snowflake_metadata)) +- `saml2_snowflake_x509_cert` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_snowflake_x509_cert)) +- `saml2_sp_initiated_login_page_label` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_sp_initiated_login_page_label)) +- `saml2_sso_url` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_sso_url)) +- `saml2_x509_cert` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_x509_cert)) +- `sync_password` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--sync_password)) + + +### Nested Schema for `security_integrations.describe_output.allowed_email_patterns` - -### Nested Schema for `security_integrations.describe_output.todo` +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.allowed_user_domains` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.comment` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.enabled` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.network_policy` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.run_as_role` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_digest_methods_used` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_enable_sp_initiated` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_force_authn` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_issuer` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_post_logout_redirect_url` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_provider` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_requested_nameid_format` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_sign_request` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_signature_methods_used` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_snowflake_acs_url` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_snowflake_issuer_url` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_snowflake_metadata` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_snowflake_x509_cert` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_sp_initiated_login_page_label` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_sso_url` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_x509_cert` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.sync_password` Read-Only: diff --git a/pkg/datasources/security_integrations_acceptance_test.go b/pkg/datasources/security_integrations_acceptance_test.go index 245b4abc3c..6bd72ceb4d 100644 --- a/pkg/datasources/security_integrations_acceptance_test.go +++ b/pkg/datasources/security_integrations_acceptance_test.go @@ -8,7 +8,6 @@ import ( acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" - "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/testenvs" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/resources" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-testing/config" @@ -16,16 +15,110 @@ import ( "github.com/hashicorp/terraform-plugin-testing/tfversion" ) -// TODO [SNOW-1348100]: add other security integrations when they are ready -// TODO [SNOW-1348100]: test specific describe properties +func TestAcc_SecurityIntegrations_Saml2(t *testing.T) { + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() + issuer := acc.TestClient().Ids.Alpha() + cert := random.GenerateX509(t) + validUrl := "http://example.com" + acsURL := acc.TestClient().Context.ACSURL(t) + issuerURL := acc.TestClient().Context.IssuerURL(t) + + m := func() map[string]config.Variable { + return map[string]config.Variable{ + "allowed_email_patterns": config.ListVariable(config.StringVariable("^(.+dev)@example.com$")), + "allowed_user_domains": config.ListVariable(config.StringVariable("example.com")), + "comment": config.StringVariable("foo"), + "enabled": config.BoolVariable(true), + "name": config.StringVariable(id.Name()), + "saml2_enable_sp_initiated": config.BoolVariable(true), + "saml2_force_authn": config.BoolVariable(true), + "saml2_issuer": config.StringVariable(issuer), + "saml2_post_logout_redirect_url": config.StringVariable(validUrl), + "saml2_provider": config.StringVariable(string(sdk.Saml2SecurityIntegrationSaml2ProviderCustom)), + "saml2_requested_nameid_format": config.StringVariable(string(sdk.Saml2SecurityIntegrationSaml2RequestedNameidFormatUnspecified)), + "saml2_sign_request": config.BoolVariable(true), + "saml2_snowflake_acs_url": config.StringVariable(acsURL), + "saml2_snowflake_issuer_url": config.StringVariable(issuerURL), + "saml2_sp_initiated_login_page_label": config.StringVariable("foo"), + "saml2_sso_url": config.StringVariable(validUrl), + "saml2_x509_cert": config.StringVariable(cert), + // TODO(SNOW-1479617): set saml2_snowflake_x509_cert + } + } + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + CheckDestroy: acc.CheckDestroy(t, resources.Saml2SecurityIntegration), + Steps: []resource.TestStep{ + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecurityIntegrations/saml2/optionals_set"), + ConfigVariables: m(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "1"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.saml2_issuer.0.value", issuer), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.saml2_sso_url.0.value", validUrl), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.saml2_provider.0.value", string(sdk.Saml2SecurityIntegrationSaml2ProviderCustom)), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.saml2_x509_cert.0.value", cert), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.saml2_sp_initiated_login_page_label.0.value", "foo"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.saml2_enable_sp_initiated.0.value", "true"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.saml2_snowflake_x509_cert.0.value"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.saml2_sign_request.0.value", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.saml2_requested_nameid_format.0.value", string(sdk.Saml2SecurityIntegrationSaml2RequestedNameidFormatUnspecified)), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.saml2_post_logout_redirect_url.0.value", "http://example.com"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.saml2_force_authn.0.value", "true"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.saml2_snowflake_issuer_url.0.value"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.saml2_snowflake_acs_url.0.value"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.saml2_snowflake_metadata.0.value"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.saml2_digest_methods_used.0.value"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.saml2_signature_methods_used.0.value"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.allowed_user_domains.0.value", "[example.com]"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.allowed_email_patterns.0.value", "[^(.+dev)@example.com$]"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.comment.0.value", "foo"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.integration_type", "SAML2"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.category", "SECURITY"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.enabled", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.comment", "foo"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.created_on"), + ), + }, + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecurityIntegrations/saml2/optionals_unset"), + ConfigVariables: m(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "1"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.integration_type", "SAML2"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.category", "SECURITY"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.enabled", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.comment", "foo"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.created_on"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.#", "0"), + ), + }, + }, + }) +} + func TestAcc_SecurityIntegrations_Scim(t *testing.T) { - _ = testenvs.GetOrSkipTest(t, testenvs.ConfigureClientOnce) id := acc.TestClient().Ids.RandomAccountObjectIdentifier() comment := random.Comment() - + networkPolicy, networkPolicyCleanup := acc.TestClient().NetworkPolicy.CreateNetworkPolicy(t) + t.Cleanup(networkPolicyCleanup) configVariables := config.Variables{ - "name": config.StringVariable(id.Name()), - "comment": config.StringVariable(comment), + "name": config.StringVariable(id.Name()), + "comment": config.StringVariable(comment), + "network_policy": config.StringVariable(networkPolicy.Name), } resource.Test(t, resource.TestCase{ @@ -38,7 +131,7 @@ func TestAcc_SecurityIntegrations_Scim(t *testing.T) { { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecurityIntegrations/optionals_set"), ConfigVariables: configVariables, - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "1"), resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.name", id.Name()), @@ -49,14 +142,17 @@ func TestAcc_SecurityIntegrations_Scim(t *testing.T) { resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.created_on"), resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.#", "1"), - resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.todo.#", "1"), - resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.todo.0.value"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.enabled.0.value", "false"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.network_policy.0.value", sdk.NewAccountObjectIdentifier(networkPolicy.Name).Name()), // TODO(SNOW-999049): Fix during identifiers rework + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.run_as_role.0.value", "GENERIC_SCIM_PROVISIONER"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.sync_password.0.value", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.comment.0.value", comment), ), }, { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecurityIntegrations/optionals_unset"), ConfigVariables: configVariables, - Check: resource.ComposeTestCheckFunc( + Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "1"), resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.name", id.Name()), diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/optionals_set/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/optionals_set/test.tf index dbd9db0930..d5e5f705aa 100644 --- a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/optionals_set/test.tf +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/optionals_set/test.tf @@ -1,9 +1,10 @@ resource "snowflake_scim_integration" "test" { - name = var.name - enabled = false - scim_client = "GENERIC" - run_as_role = "GENERIC_SCIM_PROVISIONER" - comment = var.comment + name = var.name + enabled = false + scim_client = "GENERIC" + run_as_role = "GENERIC_SCIM_PROVISIONER" + network_policy = var.network_policy + comment = var.comment } data "snowflake_security_integrations" "test" { diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/optionals_set/variables.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/optionals_set/variables.tf index 821eeebe89..d77b1d5405 100644 --- a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/optionals_set/variables.tf +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/optionals_set/variables.tf @@ -5,3 +5,6 @@ variable "name" { variable "comment" { type = string } +variable "network_policy" { + type = string +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/optionals_unset/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/optionals_unset/test.tf index e5cc5bddb8..c30f18b62f 100644 --- a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/optionals_unset/test.tf +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/optionals_unset/test.tf @@ -1,9 +1,10 @@ resource "snowflake_scim_integration" "test" { - name = var.name - enabled = false - scim_client = "GENERIC" - run_as_role = "GENERIC_SCIM_PROVISIONER" - comment = var.comment + name = var.name + enabled = false + scim_client = "GENERIC" + run_as_role = "GENERIC_SCIM_PROVISIONER" + network_policy = var.network_policy + comment = var.comment } data "snowflake_security_integrations" "test" { @@ -11,4 +12,4 @@ data "snowflake_security_integrations" "test" { with_describe = false like = var.name -} \ No newline at end of file +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/optionals_unset/variables.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/optionals_unset/variables.tf index 821eeebe89..d77b1d5405 100644 --- a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/optionals_unset/variables.tf +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/optionals_unset/variables.tf @@ -5,3 +5,6 @@ variable "name" { variable "comment" { type = string } +variable "network_policy" { + type = string +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_set/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_set/test.tf new file mode 100644 index 0000000000..eb65721110 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_set/test.tf @@ -0,0 +1,25 @@ +resource "snowflake_saml2_integration" "test" { + allowed_email_patterns = var.allowed_email_patterns + allowed_user_domains = var.allowed_user_domains + comment = var.comment + enabled = var.enabled + name = var.name + saml2_enable_sp_initiated = var.saml2_enable_sp_initiated + saml2_force_authn = var.saml2_force_authn + saml2_issuer = var.saml2_issuer + saml2_post_logout_redirect_url = var.saml2_post_logout_redirect_url + saml2_provider = var.saml2_provider + saml2_requested_nameid_format = var.saml2_requested_nameid_format + saml2_sign_request = var.saml2_sign_request + saml2_snowflake_acs_url = var.saml2_snowflake_acs_url + saml2_snowflake_issuer_url = var.saml2_snowflake_issuer_url + saml2_sp_initiated_login_page_label = var.saml2_sp_initiated_login_page_label + saml2_sso_url = var.saml2_sso_url + saml2_x509_cert = var.saml2_x509_cert +} + +data "snowflake_security_integrations" "test" { + depends_on = [snowflake_saml2_integration.test] + + like = var.name +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_set/variables.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_set/variables.tf new file mode 100644 index 0000000000..a2fe9260ee --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_set/variables.tf @@ -0,0 +1,52 @@ + +variable "allowed_email_patterns" { + type = list(string) +} +variable "allowed_user_domains" { + type = list(string) +} +variable "comment" { + type = string +} +variable "enabled" { + type = bool +} +variable "name" { + type = string +} +variable "saml2_enable_sp_initiated" { + type = bool +} +variable "saml2_force_authn" { + type = bool +} +variable "saml2_issuer" { + type = string +} +variable "saml2_post_logout_redirect_url" { + type = string +} +variable "saml2_provider" { + type = string +} +variable "saml2_requested_nameid_format" { + type = string +} +variable "saml2_sign_request" { + type = bool +} +variable "saml2_snowflake_acs_url" { + type = string +} +variable "saml2_snowflake_issuer_url" { + type = string +} +variable "saml2_sp_initiated_login_page_label" { + type = string +} +variable "saml2_sso_url" { + type = string +} +variable "saml2_x509_cert" { + type = string +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_unset/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_unset/test.tf new file mode 100644 index 0000000000..a691106eee --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_unset/test.tf @@ -0,0 +1,26 @@ +resource "snowflake_saml2_integration" "test" { + allowed_email_patterns = var.allowed_email_patterns + allowed_user_domains = var.allowed_user_domains + comment = var.comment + enabled = var.enabled + name = var.name + saml2_enable_sp_initiated = var.saml2_enable_sp_initiated + saml2_force_authn = var.saml2_force_authn + saml2_issuer = var.saml2_issuer + saml2_post_logout_redirect_url = var.saml2_post_logout_redirect_url + saml2_provider = var.saml2_provider + saml2_requested_nameid_format = var.saml2_requested_nameid_format + saml2_sign_request = var.saml2_sign_request + saml2_snowflake_acs_url = var.saml2_snowflake_acs_url + saml2_snowflake_issuer_url = var.saml2_snowflake_issuer_url + saml2_sp_initiated_login_page_label = var.saml2_sp_initiated_login_page_label + saml2_sso_url = var.saml2_sso_url + saml2_x509_cert = var.saml2_x509_cert +} + +data "snowflake_security_integrations" "test" { + depends_on = [snowflake_saml2_integration.test] + + with_describe = false + like = var.name +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_unset/variables.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_unset/variables.tf new file mode 100644 index 0000000000..a2fe9260ee --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_unset/variables.tf @@ -0,0 +1,52 @@ + +variable "allowed_email_patterns" { + type = list(string) +} +variable "allowed_user_domains" { + type = list(string) +} +variable "comment" { + type = string +} +variable "enabled" { + type = bool +} +variable "name" { + type = string +} +variable "saml2_enable_sp_initiated" { + type = bool +} +variable "saml2_force_authn" { + type = bool +} +variable "saml2_issuer" { + type = string +} +variable "saml2_post_logout_redirect_url" { + type = string +} +variable "saml2_provider" { + type = string +} +variable "saml2_requested_nameid_format" { + type = string +} +variable "saml2_sign_request" { + type = bool +} +variable "saml2_snowflake_acs_url" { + type = string +} +variable "saml2_snowflake_issuer_url" { + type = string +} +variable "saml2_sp_initiated_login_page_label" { + type = string +} +variable "saml2_sso_url" { + type = string +} +variable "saml2_x509_cert" { + type = string +} diff --git a/pkg/helpers/helpers.go b/pkg/helpers/helpers.go index 47263e19ac..5586a631fb 100644 --- a/pkg/helpers/helpers.go +++ b/pkg/helpers/helpers.go @@ -137,3 +137,17 @@ func DecodeSnowflakeAccountIdentifier(identifier string) (sdk.AccountIdentifier, return sdk.AccountIdentifier{}, fmt.Errorf("unable to classify account identifier: %s, expected format: .", identifier) } } + +// TODO(SNOW-1479870): Test +// MergeMaps takes any number of maps (of the same type) and concatenates them. +// In case of key collision, the value will be selected from the map that is provided +// later in the src function parameter. +func MergeMaps[M ~map[K]V, K comparable, V any](src ...M) M { + merged := make(M) + for _, m := range src { + for k, v := range m { + merged[k] = v + } + } + return merged +} diff --git a/pkg/resources/database.go b/pkg/resources/database.go index bc73e4ec5b..d6c1085cf1 100644 --- a/pkg/resources/database.go +++ b/pkg/resources/database.go @@ -84,7 +84,7 @@ func Database() *schema.Resource { DeleteContext: DeleteDatabase, Description: "Represents a standard database. If replication configuration is specified, the database is promoted to serve as a primary database for replication.", - Schema: MergeMaps(databaseSchema, DatabaseParametersSchema), + Schema: helpers.MergeMaps(databaseSchema, DatabaseParametersSchema), Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, diff --git a/pkg/resources/helpers.go b/pkg/resources/helpers.go index e661f7b761..7b91689d48 100644 --- a/pkg/resources/helpers.go +++ b/pkg/resources/helpers.go @@ -295,20 +295,6 @@ func getTags(from interface{}) (to tags) { return to } -// TODO(SNOW-1479870): Test -// MergeMaps takes any number of maps (of the same type) and concatenates them. -// In case of key collision, the value will be selected from the map that is provided -// later in the src function parameter. -func MergeMaps[M ~map[K]V, K comparable, V any](src ...M) M { - merged := make(M) - for _, m := range src { - for k, v := range m { - merged[k] = v - } - } - return merged -} - // TODO(SNOW-1479870): Test // JoinDiags iterates through passed diag.Diagnostics and joins them into one diag.Diagnostics. // If none of the passed diagnostics contained any element a nil reference will be returned. diff --git a/pkg/resources/secondary_database.go b/pkg/resources/secondary_database.go index a1110251cb..a135663732 100644 --- a/pkg/resources/secondary_database.go +++ b/pkg/resources/secondary_database.go @@ -46,7 +46,7 @@ func SecondaryDatabase() *schema.Resource { Description: "A secondary database creates a replica of an existing primary database (i.e. a secondary database). For more information about database replication, see [Introduction to database replication across multiple accounts](https://docs.snowflake.com/en/user-guide/db-replication-intro).", CustomizeDiff: DatabaseParametersCustomDiff, - Schema: MergeMaps(secondaryDatabaseSchema, DatabaseParametersSchema), + Schema: helpers.MergeMaps(secondaryDatabaseSchema, DatabaseParametersSchema), Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, diff --git a/pkg/resources/shared_database.go b/pkg/resources/shared_database.go index 6bbf799d2f..a9c26400b6 100644 --- a/pkg/resources/shared_database.go +++ b/pkg/resources/shared_database.go @@ -46,7 +46,7 @@ func SharedDatabase() *schema.Resource { DeleteContext: DeleteSharedDatabase, Description: "A shared database creates a database from a share provided by another Snowflake account. For more information about shares, see [Introduction to Secure Data Sharing](https://docs.snowflake.com/en/user-guide/data-sharing-intro).", - Schema: MergeMaps(sharedDatabaseSchema, SharedDatabaseParametersSchema), + Schema: helpers.MergeMaps(sharedDatabaseSchema, SharedDatabaseParametersSchema), Importer: &schema.ResourceImporter{ StateContext: schema.ImportStatePassthroughContext, }, diff --git a/pkg/schemas/saml2_security_integration.go b/pkg/schemas/saml2_security_integration.go index 6c1ed3ef8d..25f200efba 100644 --- a/pkg/schemas/saml2_security_integration.go +++ b/pkg/schemas/saml2_security_integration.go @@ -2,6 +2,7 @@ package schemas import ( "log" + "slices" "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -30,33 +31,35 @@ var DescribeSaml2IntegrationSchema = map[string]*schema.Schema{ "comment": DescribePropertyListSchema, } +var Saml2PropertiesNames = []string{ + "COMMENT", + "SAML2_ISSUER", + "SAML2_SSO_URL", + "SAML2_PROVIDER", + "SAML2_X509_CERT", + "SAML2_SP_INITIATED_LOGIN_PAGE_LABEL", + "SAML2_SNOWFLAKE_X509_CERT", + "SAML2_REQUESTED_NAMEID_FORMAT", + "SAML2_POST_LOGOUT_REDIRECT_URL", + "SAML2_SNOWFLAKE_ISSUER_URL", + "SAML2_SNOWFLAKE_ACS_URL", + "SAML2_SNOWFLAKE_METADATA", + "SAML2_DIGEST_METHODS_USED", + "SAML2_SIGNATURE_METHODS_USED", + "SAML2_ENABLE_SP_INITIATED", + "SAML2_SIGN_REQUEST", + "SAML2_FORCE_AUTHN", + "ALLOWED_USER_DOMAINS", + "ALLOWED_EMAIL_PATTERNS", +} + func DescribeSaml2IntegrationToSchema(props []sdk.SecurityIntegrationProperty) map[string]any { propsSchema := make(map[string]any) for _, property := range props { property := property - switch property.Name { - case "ENABLED", - "COMMENT", - "SAML2_ISSUER", - "SAML2_SSO_URL", - "SAML2_PROVIDER", - "SAML2_X509_CERT", - "SAML2_SP_INITIATED_LOGIN_PAGE_LABEL", - "SAML2_SNOWFLAKE_X509_CERT", - "SAML2_REQUESTED_NAMEID_FORMAT", - "SAML2_POST_LOGOUT_REDIRECT_URL", - "SAML2_SNOWFLAKE_ISSUER_URL", - "SAML2_SNOWFLAKE_ACS_URL", - "SAML2_SNOWFLAKE_METADATA", - "SAML2_DIGEST_METHODS_USED", - "SAML2_SIGNATURE_METHODS_USED", - "SAML2_ENABLE_SP_INITIATED", - "SAML2_SIGN_REQUEST", - "SAML2_FORCE_AUTHN", - "ALLOWED_USER_DOMAINS", - "ALLOWED_EMAIL_PATTERNS": + if slices.Contains(Saml2PropertiesNames, property.Name) { propsSchema[strings.ToLower(property.Name)] = []map[string]any{SecurityIntegrationPropertyToSchema(&property)} - default: + } else { log.Printf("[WARN] unexpected property %v returned from Snowflake", property.Name) } } diff --git a/pkg/schemas/scim_security_integration.go b/pkg/schemas/scim_security_integration.go index f21083bd4e..f17a8a848c 100644 --- a/pkg/schemas/scim_security_integration.go +++ b/pkg/schemas/scim_security_integration.go @@ -1,6 +1,8 @@ package schemas import ( + "log" + "slices" "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -16,19 +18,25 @@ var DescribeScimSecurityIntegrationSchema = map[string]*schema.Schema{ "comment": DescribePropertyListSchema, } -var _ = DescribeScimSecurityIntegrationSchema +var ( + _ = DescribeScimSecurityIntegrationSchema + ScimPropertiesNames = []string{ + "ENABLED", + "NETWORK_POLICY", + "RUN_AS_ROLE", + "SYNC_PASSWORD", + "COMMENT", + } +) func ScimSecurityIntegrationPropertiesToSchema(securityIntegrationProperties []sdk.SecurityIntegrationProperty) map[string]any { securityIntegrationSchema := make(map[string]any) - for _, securityIntegrationProperty := range securityIntegrationProperties { - securityIntegrationProperty := securityIntegrationProperty - switch securityIntegrationProperty.Name { - case "ENABLED", - "NETWORK_POLICY", - "RUN_AS_ROLE", - "SYNC_PASSWORD", - "COMMENT": - securityIntegrationSchema[strings.ToLower(securityIntegrationProperty.Name)] = []map[string]any{SecurityIntegrationPropertyToSchema(&securityIntegrationProperty)} + for _, property := range securityIntegrationProperties { + property := property + if slices.Contains(ScimPropertiesNames, property.Name) { + securityIntegrationSchema[strings.ToLower(property.Name)] = []map[string]any{SecurityIntegrationPropertyToSchema(&property)} + } else { + log.Printf("[WARN] unexpected property %v returned from Snowflake", property.Name) } } return securityIntegrationSchema diff --git a/pkg/schemas/security_integration.go b/pkg/schemas/security_integration.go index e278a293a5..305e81627c 100644 --- a/pkg/schemas/security_integration.go +++ b/pkg/schemas/security_integration.go @@ -1,21 +1,25 @@ package schemas import ( + "slices" + "strings" + + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" - "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" ) -// TODO [SNOW-1348100]: multiple PRs touching the security integrations are in progress, this should be filled by all the possible properties (the mapping method below should be too) -var SecurityIntegrationDescribeSchema = map[string]*schema.Schema{ - "todo": DescribePropertyListSchema, -} +var ( + SecurityIntegrationDescribeSchema = helpers.MergeMaps(DescribeSaml2IntegrationSchema, DescribeScimSecurityIntegrationSchema) + allSecurityIntegrationPropertiesNames = append(Saml2PropertiesNames, ScimPropertiesNames...) +) func SecurityIntegrationsDescriptionsToSchema(descriptions []sdk.SecurityIntegrationProperty) map[string]any { securityIntegrationProperties := make(map[string]any) for _, desc := range descriptions { desc := desc - propertySchema := SecurityIntegrationPropertyToSchema(&desc) - securityIntegrationProperties["todo"] = []map[string]any{propertySchema} + if slices.Contains(allSecurityIntegrationPropertiesNames, desc.Name) { + securityIntegrationProperties[strings.ToLower(desc.Name)] = []map[string]any{SecurityIntegrationPropertyToSchema(&desc)} + } } return securityIntegrationProperties } From 2dcc9c351d2a6d7678d0c49150e539dff615e764 Mon Sep 17 00:00:00 2001 From: Jakub Michalak Date: Tue, 9 Jul 2024 13:35:41 +0200 Subject: [PATCH 2/7] Add remaining integrations --- docs/data-sources/security_integrations.md | 242 +++++++++-------- pkg/acceptance/check_destroy.go | 9 + .../security_integrations_acceptance_test.go | 252 ++++++++++++++++++ .../optionals_set/test.tf | 19 ++ .../optionals_set/variables.tf | 33 +++ .../optionals_unset/test.tf | 20 ++ .../optionals_unset/variables.tf | 33 +++ .../optionals_set/test.tf | 24 ++ .../optionals_set/variables.tf | 46 ++++ .../optionals_unset/test.tf | 25 ++ .../optionals_unset/variables.tf | 46 ++++ .../optionals_set/test.tf | 16 ++ .../optionals_set/variables.tf | 24 ++ .../optionals_unset/test.tf | 17 ++ .../optionals_unset/variables.tf | 24 ++ pkg/helpers/helpers.go | 9 + pkg/provider/resources/resources.go | 91 ++++--- ...tegration_with_authorization_code_grant.go | 2 +- ...uthorization_code_grant_acceptance_test.go | 3 + ...ion_integration_with_client_credentials.go | 2 +- ...with_client_credentials_acceptance_test.go | 3 + ...hentication_integration_with_jwt_bearer.go | 2 +- ...api_authentication_security_integration.go | 31 ++- .../oauth_integration_for_custom_clients.go | 46 ++-- ...ty_integration_for_partner_applications.go | 46 ++-- pkg/schemas/security_integration.go | 16 +- 26 files changed, 872 insertions(+), 209 deletions(-) create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_set/test.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_set/variables.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_unset/test.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_unset/variables.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_set/test.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_set/variables.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_unset/test.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_unset/variables.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_set/test.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_set/variables.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_unset/test.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_unset/variables.tf diff --git a/docs/data-sources/security_integrations.md b/docs/data-sources/security_integrations.md index 8c9459597d..83129c966a 100644 --- a/docs/data-sources/security_integrations.md +++ b/docs/data-sources/security_integrations.md @@ -100,12 +100,33 @@ Read-Only: Read-Only: -<<<<<<< HEAD - `allowed_email_patterns` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--allowed_email_patterns)) - `allowed_user_domains` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--allowed_user_domains)) +- `auth_type` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--auth_type)) +- `blocked_roles_list` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--blocked_roles_list)) - `comment` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--comment)) - `enabled` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--enabled)) - `network_policy` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--network_policy)) +- `oauth_access_token_validity` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_access_token_validity)) +- `oauth_allow_non_tls_redirect_uri` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_allow_non_tls_redirect_uri)) +- `oauth_allowed_authorization_endpoints` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_allowed_authorization_endpoints)) +- `oauth_allowed_scopes` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_allowed_scopes)) +- `oauth_allowed_token_endpoints` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_allowed_token_endpoints)) +- `oauth_authorization_endpoint` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_authorization_endpoint)) +- `oauth_client_auth_method` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_client_auth_method)) +- `oauth_client_id` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_client_id)) +- `oauth_client_rsa_public_key_2_fp` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_client_rsa_public_key_2_fp)) +- `oauth_client_rsa_public_key_fp` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_client_rsa_public_key_fp)) +- `oauth_client_type` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_client_type)) +- `oauth_enforce_pkce` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_enforce_pkce)) +- `oauth_grant` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_grant)) +- `oauth_issue_refresh_tokens` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_issue_refresh_tokens)) +- `oauth_redirect_uri` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_redirect_uri)) +- `oauth_refresh_token_validity` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_refresh_token_validity)) +- `oauth_token_endpoint` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_token_endpoint)) +- `oauth_use_secondary_roles` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_use_secondary_roles)) +- `parent_integration` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--parent_integration)) +- `pre_authorized_roles_list` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--pre_authorized_roles_list)) - `run_as_role` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--run_as_role)) - `saml2_digest_methods_used` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_digest_methods_used)) - `saml2_enable_sp_initiated` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_enable_sp_initiated)) @@ -124,31 +145,7 @@ Read-Only: - `saml2_sso_url` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_sso_url)) - `saml2_x509_cert` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--saml2_x509_cert)) - `sync_password` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--sync_password)) -||||||| d0c136d1 -- `todo` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--todo)) -======= -- `blocked_roles_list` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--blocked_roles_list)) -- `comment` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--comment)) -- `enabled` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--enabled)) -- `network_policy` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--network_policy)) -- `oauth_allow_non_tls_redirect_uri` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_allow_non_tls_redirect_uri)) -- `oauth_allowed_authorization_endpoints` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_allowed_authorization_endpoints)) -- `oauth_allowed_token_endpoints` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_allowed_token_endpoints)) -- `oauth_authorization_endpoint` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_authorization_endpoint)) -- `oauth_client_id` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_client_id)) -- `oauth_client_rsa_public_key_2_fp` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_client_rsa_public_key_2_fp)) -- `oauth_client_rsa_public_key_fp` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_client_rsa_public_key_fp)) -- `oauth_client_type` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_client_type)) -- `oauth_enforce_pkce` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_enforce_pkce)) -- `oauth_issue_refresh_tokens` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_issue_refresh_tokens)) -- `oauth_redirect_uri` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_redirect_uri)) -- `oauth_refresh_token_validity` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_refresh_token_validity)) -- `oauth_token_endpoint` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_token_endpoint)) -- `oauth_use_secondary_roles` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_use_secondary_roles)) -- `pre_authorized_roles_list` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--pre_authorized_roles_list)) ->>>>>>> origin/main -<<<<<<< HEAD ### Nested Schema for `security_integrations.describe_output.allowed_email_patterns` @@ -171,6 +168,28 @@ Read-Only: - `value` (String) + +### Nested Schema for `security_integrations.describe_output.auth_type` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.blocked_roles_list` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + ### Nested Schema for `security_integrations.describe_output.comment` @@ -204,8 +223,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.run_as_role` + +### Nested Schema for `security_integrations.describe_output.oauth_access_token_validity` Read-Only: @@ -215,8 +234,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.saml2_digest_methods_used` + +### Nested Schema for `security_integrations.describe_output.oauth_allow_non_tls_redirect_uri` Read-Only: @@ -226,8 +245,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.saml2_enable_sp_initiated` + +### Nested Schema for `security_integrations.describe_output.oauth_allowed_authorization_endpoints` Read-Only: @@ -237,8 +256,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.saml2_force_authn` + +### Nested Schema for `security_integrations.describe_output.oauth_allowed_scopes` Read-Only: @@ -248,8 +267,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.saml2_issuer` + +### Nested Schema for `security_integrations.describe_output.oauth_allowed_token_endpoints` Read-Only: @@ -259,8 +278,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.saml2_post_logout_redirect_url` + +### Nested Schema for `security_integrations.describe_output.oauth_authorization_endpoint` Read-Only: @@ -270,8 +289,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.saml2_provider` + +### Nested Schema for `security_integrations.describe_output.oauth_client_auth_method` Read-Only: @@ -281,8 +300,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.saml2_requested_nameid_format` + +### Nested Schema for `security_integrations.describe_output.oauth_client_id` Read-Only: @@ -292,8 +311,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.saml2_sign_request` + +### Nested Schema for `security_integrations.describe_output.oauth_client_rsa_public_key_2_fp` Read-Only: @@ -303,8 +322,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.saml2_signature_methods_used` + +### Nested Schema for `security_integrations.describe_output.oauth_client_rsa_public_key_fp` Read-Only: @@ -314,8 +333,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.saml2_snowflake_acs_url` + +### Nested Schema for `security_integrations.describe_output.oauth_client_type` Read-Only: @@ -325,8 +344,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.saml2_snowflake_issuer_url` + +### Nested Schema for `security_integrations.describe_output.oauth_enforce_pkce` Read-Only: @@ -336,8 +355,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.saml2_snowflake_metadata` + +### Nested Schema for `security_integrations.describe_output.oauth_grant` Read-Only: @@ -347,8 +366,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.saml2_snowflake_x509_cert` + +### Nested Schema for `security_integrations.describe_output.oauth_issue_refresh_tokens` Read-Only: @@ -358,8 +377,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.saml2_sp_initiated_login_page_label` + +### Nested Schema for `security_integrations.describe_output.oauth_redirect_uri` Read-Only: @@ -369,8 +388,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.saml2_sso_url` + +### Nested Schema for `security_integrations.describe_output.oauth_refresh_token_validity` Read-Only: @@ -380,8 +399,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.saml2_x509_cert` + +### Nested Schema for `security_integrations.describe_output.oauth_token_endpoint` Read-Only: @@ -391,14 +410,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.sync_password` -||||||| d0c136d1 - -### Nested Schema for `security_integrations.describe_output.todo` -======= - -### Nested Schema for `security_integrations.describe_output.blocked_roles_list` + +### Nested Schema for `security_integrations.describe_output.oauth_use_secondary_roles` Read-Only: @@ -408,8 +421,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.comment` + +### Nested Schema for `security_integrations.describe_output.parent_integration` Read-Only: @@ -419,8 +432,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.enabled` + +### Nested Schema for `security_integrations.describe_output.pre_authorized_roles_list` Read-Only: @@ -430,8 +443,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.network_policy` + +### Nested Schema for `security_integrations.describe_output.run_as_role` Read-Only: @@ -441,8 +454,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.oauth_allow_non_tls_redirect_uri` + +### Nested Schema for `security_integrations.describe_output.saml2_digest_methods_used` Read-Only: @@ -452,8 +465,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.oauth_allowed_authorization_endpoints` + +### Nested Schema for `security_integrations.describe_output.saml2_enable_sp_initiated` Read-Only: @@ -463,8 +476,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.oauth_allowed_token_endpoints` + +### Nested Schema for `security_integrations.describe_output.saml2_force_authn` Read-Only: @@ -474,8 +487,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.oauth_authorization_endpoint` + +### Nested Schema for `security_integrations.describe_output.saml2_issuer` Read-Only: @@ -485,8 +498,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.oauth_client_id` + +### Nested Schema for `security_integrations.describe_output.saml2_post_logout_redirect_url` Read-Only: @@ -496,8 +509,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.oauth_client_rsa_public_key_2_fp` + +### Nested Schema for `security_integrations.describe_output.saml2_provider` Read-Only: @@ -507,8 +520,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.oauth_client_rsa_public_key_fp` + +### Nested Schema for `security_integrations.describe_output.saml2_requested_nameid_format` Read-Only: @@ -518,8 +531,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.oauth_client_type` + +### Nested Schema for `security_integrations.describe_output.saml2_sign_request` Read-Only: @@ -529,8 +542,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.oauth_enforce_pkce` + +### Nested Schema for `security_integrations.describe_output.saml2_signature_methods_used` Read-Only: @@ -540,8 +553,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.oauth_issue_refresh_tokens` + +### Nested Schema for `security_integrations.describe_output.saml2_snowflake_acs_url` Read-Only: @@ -551,8 +564,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.oauth_redirect_uri` + +### Nested Schema for `security_integrations.describe_output.saml2_snowflake_issuer_url` Read-Only: @@ -562,8 +575,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.oauth_refresh_token_validity` + +### Nested Schema for `security_integrations.describe_output.saml2_snowflake_metadata` Read-Only: @@ -573,8 +586,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.oauth_token_endpoint` + +### Nested Schema for `security_integrations.describe_output.saml2_snowflake_x509_cert` Read-Only: @@ -584,8 +597,8 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.oauth_use_secondary_roles` + +### Nested Schema for `security_integrations.describe_output.saml2_sp_initiated_login_page_label` Read-Only: @@ -595,9 +608,30 @@ Read-Only: - `value` (String) - -### Nested Schema for `security_integrations.describe_output.pre_authorized_roles_list` ->>>>>>> origin/main + +### Nested Schema for `security_integrations.describe_output.saml2_sso_url` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.saml2_x509_cert` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.sync_password` Read-Only: diff --git a/pkg/acceptance/check_destroy.go b/pkg/acceptance/check_destroy.go index ef663fdf20..1f53be12d8 100644 --- a/pkg/acceptance/check_destroy.go +++ b/pkg/acceptance/check_destroy.go @@ -67,6 +67,15 @@ var showByIdFunctions = map[resources.Resource]showByIdFunc{ resources.Alert: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { return runShowById(ctx, id, client.Alerts.ShowByID) }, + resources.ApiAuthenticationIntegrationWithAuthorizationCodeGrant: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { + return runShowById(ctx, id, client.SecurityIntegrations.ShowByID) + }, + resources.ApiAuthenticationIntegrationWithClientCredentials: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { + return runShowById(ctx, id, client.SecurityIntegrations.ShowByID) + }, + resources.ApiAuthenticationIntegrationWithJwtBearer: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { + return runShowById(ctx, id, client.SecurityIntegrations.ShowByID) + }, resources.ApiIntegration: func(ctx context.Context, client *sdk.Client, id sdk.ObjectIdentifier) error { return runShowById(ctx, id, client.ApiIntegrations.ShowByID) }, diff --git a/pkg/datasources/security_integrations_acceptance_test.go b/pkg/datasources/security_integrations_acceptance_test.go index 6bd72ceb4d..f113a6b7d0 100644 --- a/pkg/datasources/security_integrations_acceptance_test.go +++ b/pkg/datasources/security_integrations_acceptance_test.go @@ -15,6 +15,258 @@ import ( "github.com/hashicorp/terraform-plugin-testing/tfversion" ) +func TestAcc_SecurityIntegrations_ApiAuthentication(t *testing.T) { + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() + + m := func() map[string]config.Variable { + return map[string]config.Variable{ + "comment": config.StringVariable("foo"), + "enabled": config.BoolVariable(true), + "name": config.StringVariable(id.Name()), + "oauth_access_token_validity": config.IntegerVariable(42), + "oauth_authorization_endpoint": config.StringVariable("https://example.com"), + "oauth_client_auth_method": config.StringVariable(string(sdk.ApiAuthenticationSecurityIntegrationOauthClientAuthMethodClientSecretPost)), + "oauth_client_id": config.StringVariable("foo"), + "oauth_client_secret": config.StringVariable("foo"), + "oauth_refresh_token_validity": config.IntegerVariable(12345), + "oauth_token_endpoint": config.StringVariable("https://example.com"), + "oauth_allowed_scopes": config.SetVariable(config.StringVariable("foo")), + } + } + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + CheckDestroy: acc.CheckDestroy(t, resources.ApiAuthenticationIntegrationWithAuthorizationCodeGrant), + Steps: []resource.TestStep{ + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_set"), + ConfigVariables: m(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "1"), + + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.#", "1"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.integration_type", "API_AUTHENTICATION"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.category", "SECURITY"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.enabled", "true"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.comment", "foo"), + resource.TestCheckResourceAttrSet("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.created_on"), + + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.#", "1"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.enabled.0.value", "true"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.oauth_access_token_validity.0.value", "42"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.oauth_refresh_token_validity.0.value", "12345"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.oauth_client_id.0.value", "foo"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.oauth_client_auth_method.0.value", string(sdk.ApiAuthenticationSecurityIntegrationOauthClientAuthMethodClientSecretPost)), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.oauth_authorization_endpoint.0.value", "https://example.com"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.oauth_token_endpoint.0.value", "https://example.com"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.oauth_allowed_scopes.0.value", "[foo]"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.oauth_grant.0.value", sdk.ApiAuthenticationSecurityIntegrationOauthGrantAuthorizationCode), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.parent_integration.0.value", ""), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.auth_type.0.value", "OAUTH2"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.comment.0.value", "foo")), + }, + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_unset"), + ConfigVariables: m(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "1"), + + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.#", "1"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.integration_type", "API_AUTHENTICATION"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.category", "SECURITY"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.enabled", "true"), + resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.comment", "foo"), + resource.TestCheckResourceAttrSet("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.created_on"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.#", "0"), + ), + }, + }, + }) +} + +func TestAcc_SecurityIntegrations_OauthForCustomClients(t *testing.T) { + networkPolicy, networkPolicyCleanup := acc.TestClient().NetworkPolicy.CreateNetworkPolicy(t) + t.Cleanup(networkPolicyCleanup) + + preAuthorizedRole, preauthorizedRoleCleanup := acc.TestClient().Role.CreateRole(t) + t.Cleanup(preauthorizedRoleCleanup) + + blockedRole, blockedRoleCleanup := acc.TestClient().Role.CreateRole(t) + t.Cleanup(blockedRoleCleanup) + + validUrl := "https://example.com" + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() + key, _ := random.GenerateRSAPublicKey(t) + comment := random.Comment() + m := func() map[string]config.Variable { + return map[string]config.Variable{ + "name": config.StringVariable(id.Name()), + "oauth_client_type": config.StringVariable(string(sdk.OauthSecurityIntegrationClientTypeConfidential)), + "oauth_redirect_uri": config.StringVariable(validUrl), + "blocked_roles_list": config.SetVariable(config.StringVariable("ACCOUNTADMIN"), config.StringVariable("SECURITYADMIN"), config.StringVariable(blockedRole.ID().Name())), + "comment": config.StringVariable(comment), + "enabled": config.BoolVariable(true), + "network_policy": config.StringVariable(networkPolicy.Name), + "oauth_allow_non_tls_redirect_uri": config.BoolVariable(true), + "oauth_allowed_authorization_endpoints": config.SetVariable(config.StringVariable("http://allowed.com")), + "oauth_allowed_token_endpoints": config.SetVariable(config.StringVariable("http://allowed.com")), + "oauth_authorization_endpoint": config.StringVariable("http://auth.com"), + "oauth_client_rsa_public_key": config.StringVariable(key), + "oauth_client_rsa_public_key_2": config.StringVariable(key), + "oauth_enforce_pkce": config.BoolVariable(true), + "oauth_issue_refresh_tokens": config.BoolVariable(true), + "oauth_refresh_token_validity": config.IntegerVariable(86400), + "oauth_token_endpoint": config.StringVariable("http://auth.com"), + "oauth_use_secondary_roles": config.StringVariable(string(sdk.OauthSecurityIntegrationUseSecondaryRolesNone)), + "pre_authorized_roles_list": config.SetVariable(config.StringVariable(preAuthorizedRole.ID().Name())), + } + } + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + CheckDestroy: acc.CheckDestroy(t, resources.OauthIntegrationForCustomClients), + Steps: []resource.TestStep{ + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_set"), + ConfigVariables: m(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "1"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_client_type.0.value", string(sdk.OauthSecurityIntegrationClientTypeConfidential)), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_redirect_uri.0.value", validUrl), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.enabled.0.value", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_allow_non_tls_redirect_uri.0.value", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_enforce_pkce.0.value", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_use_secondary_roles.0.value", string(sdk.OauthSecurityIntegrationUseSecondaryRolesImplicit)), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.pre_authorized_roles_list.0.value", preAuthorizedRole.ID().Name()), + // Not asserted, because it also contains other default roles + // resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.blocked_roles_list.0.value"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_issue_refresh_tokens.0.value", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_refresh_token_validity.0.value", "86400"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.network_policy.0.value", sdk.NewAccountObjectIdentifier(networkPolicy.Name).Name()), // TODO(SNOW-999049): Fix during identifiers rework + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_client_rsa_public_key_fp.0.value", ""), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_client_rsa_public_key_2_fp.0.value", ""), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.comment.0.value", comment), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_client_id.0.value"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_authorization_endpoint.0.value"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_token_endpoint.0.value"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_allowed_authorization_endpoints.0.value"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_allowed_token_endpoints.0.value"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.integration_type", "OAUTH - CUSTOM"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.category", "SECURITY"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.enabled", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.comment", comment), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.created_on"), + ), + }, + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_unset"), + ConfigVariables: m(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "1"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.integration_type", "OAUTH - CUSTOM"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.category", "SECURITY"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.enabled", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.comment", comment), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.created_on"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.#", "0"), + ), + }, + }, + }) +} + +func TestAcc_SecurityIntegrations_OauthForPartnerApplications(t *testing.T) { + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() + comment := random.Comment() + m := func() map[string]config.Variable { + return map[string]config.Variable{ + "name": config.StringVariable(id.Name()), + "oauth_client": config.StringVariable(string(sdk.OauthSecurityIntegrationClientTableauServer)), + "blocked_roles_list": config.SetVariable(config.StringVariable("ACCOUNTADMIN"), config.StringVariable("SECURITYADMIN")), + "enabled": config.BoolVariable(true), + "oauth_issue_refresh_tokens": config.BoolVariable(false), + "oauth_refresh_token_validity": config.IntegerVariable(86400), + "oauth_use_secondary_roles": config.StringVariable(string(sdk.OauthSecurityIntegrationUseSecondaryRolesImplicit)), + "comment": config.StringVariable(comment), + } + } + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + CheckDestroy: acc.CheckDestroy(t, resources.OauthIntegrationForPartnerApplications), + Steps: []resource.TestStep{ + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_set"), + ConfigVariables: m(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "1"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_client_type.0.value", string(sdk.OauthSecurityIntegrationClientTypePublic)), + resource.TestCheckNoResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_redirect_uri.0.value"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.enabled.0.value", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_use_secondary_roles.0.value", string(sdk.OauthSecurityIntegrationUseSecondaryRolesImplicit)), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.blocked_roles_list.0.value", "ACCOUNTADMIN,SECURITYADMIN"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_issue_refresh_tokens.0.value", "false"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_refresh_token_validity.0.value", "86400"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.comment.0.value", comment), + resource.TestCheckNoResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_client_id.0.value"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_authorization_endpoint.0.value"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_token_endpoint.0.value"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_allowed_authorization_endpoints.0.value"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_allowed_token_endpoints.0.value"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.integration_type", "OAUTH - TABLEAU_SERVER"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.category", "SECURITY"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.enabled", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.comment", comment), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.created_on"), + ), + }, + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_unset"), + ConfigVariables: m(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "1"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.integration_type", "OAUTH - TABLEAU_SERVER"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.category", "SECURITY"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.enabled", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.comment", comment), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.created_on"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.#", "0"), + ), + }, + }, + }) +} + func TestAcc_SecurityIntegrations_Saml2(t *testing.T) { id := acc.TestClient().Ids.RandomAccountObjectIdentifier() issuer := acc.TestClient().Ids.Alpha() diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_set/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_set/test.tf new file mode 100644 index 0000000000..930dad11c2 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_set/test.tf @@ -0,0 +1,19 @@ +resource "snowflake_api_authentication_integration_with_authorization_code_grant" "test" { + comment = var.comment + enabled = var.enabled + name = var.name + oauth_access_token_validity = var.oauth_access_token_validity + oauth_authorization_endpoint = var.oauth_authorization_endpoint + oauth_client_auth_method = var.oauth_client_auth_method + oauth_client_id = var.oauth_client_id + oauth_client_secret = var.oauth_client_secret + oauth_refresh_token_validity = var.oauth_refresh_token_validity + oauth_token_endpoint = var.oauth_token_endpoint + oauth_allowed_scopes = var.oauth_allowed_scopes +} + +data "snowflake_security_integrations" "test" { + depends_on = [snowflake_api_authentication_integration_with_authorization_code_grant.test] + + like = var.name +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_set/variables.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_set/variables.tf new file mode 100644 index 0000000000..06e9998ff5 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_set/variables.tf @@ -0,0 +1,33 @@ +variable "comment" { + type = string +} +variable "enabled" { + type = bool +} +variable "name" { + type = string +} +variable "oauth_access_token_validity" { + type = number +} +variable "oauth_authorization_endpoint" { + type = string +} +variable "oauth_client_auth_method" { + type = string +} +variable "oauth_client_id" { + type = string +} +variable "oauth_client_secret" { + type = string +} +variable "oauth_refresh_token_validity" { + type = number +} +variable "oauth_token_endpoint" { + type = string +} +variable "oauth_allowed_scopes" { + type = set(string) +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_unset/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_unset/test.tf new file mode 100644 index 0000000000..c96b04b898 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_unset/test.tf @@ -0,0 +1,20 @@ +resource "snowflake_api_authentication_integration_with_authorization_code_grant" "test" { + comment = var.comment + enabled = var.enabled + name = var.name + oauth_access_token_validity = var.oauth_access_token_validity + oauth_authorization_endpoint = var.oauth_authorization_endpoint + oauth_client_auth_method = var.oauth_client_auth_method + oauth_client_id = var.oauth_client_id + oauth_client_secret = var.oauth_client_secret + oauth_refresh_token_validity = var.oauth_refresh_token_validity + oauth_token_endpoint = var.oauth_token_endpoint + oauth_allowed_scopes = var.oauth_allowed_scopes +} + +data "snowflake_security_integrations" "test" { + depends_on = [snowflake_api_authentication_integration_with_authorization_code_grant.test] + + with_describe = false + like = var.name +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_unset/variables.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_unset/variables.tf new file mode 100644 index 0000000000..06e9998ff5 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_unset/variables.tf @@ -0,0 +1,33 @@ +variable "comment" { + type = string +} +variable "enabled" { + type = bool +} +variable "name" { + type = string +} +variable "oauth_access_token_validity" { + type = number +} +variable "oauth_authorization_endpoint" { + type = string +} +variable "oauth_client_auth_method" { + type = string +} +variable "oauth_client_id" { + type = string +} +variable "oauth_client_secret" { + type = string +} +variable "oauth_refresh_token_validity" { + type = number +} +variable "oauth_token_endpoint" { + type = string +} +variable "oauth_allowed_scopes" { + type = set(string) +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_set/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_set/test.tf new file mode 100644 index 0000000000..b1faba1325 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_set/test.tf @@ -0,0 +1,24 @@ +resource "snowflake_oauth_integration_for_custom_clients" "test" { + blocked_roles_list = var.blocked_roles_list + comment = var.comment + enabled = var.enabled + name = var.name + network_policy = var.network_policy + oauth_allow_non_tls_redirect_uri = var.oauth_allow_non_tls_redirect_uri + oauth_client_rsa_public_key = var.oauth_client_rsa_public_key + oauth_client_rsa_public_key_2 = var.oauth_client_rsa_public_key_2 + oauth_client_type = var.oauth_client_type + oauth_enforce_pkce = var.oauth_enforce_pkce + oauth_issue_refresh_tokens = var.oauth_issue_refresh_tokens + oauth_redirect_uri = var.oauth_redirect_uri + oauth_refresh_token_validity = var.oauth_refresh_token_validity + oauth_use_secondary_roles = var.oauth_use_secondary_roles + pre_authorized_roles_list = var.pre_authorized_roles_list +} + + +data "snowflake_security_integrations" "test" { + depends_on = [snowflake_oauth_integration_for_custom_clients.test] + + like = var.name +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_set/variables.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_set/variables.tf new file mode 100644 index 0000000000..9d98ea92c8 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_set/variables.tf @@ -0,0 +1,46 @@ + +variable "blocked_roles_list" { + type = set(string) +} +variable "comment" { + type = string +} +variable "enabled" { + type = bool +} +variable "name" { + type = string +} +variable "network_policy" { + type = string +} +variable "oauth_allow_non_tls_redirect_uri" { + type = bool +} +variable "oauth_client_rsa_public_key" { + type = string +} +variable "oauth_client_rsa_public_key_2" { + type = string +} +variable "oauth_client_type" { + type = string +} +variable "oauth_enforce_pkce" { + type = bool +} +variable "oauth_issue_refresh_tokens" { + type = bool +} +variable "oauth_redirect_uri" { + type = string +} +variable "oauth_refresh_token_validity" { + type = number +} +variable "oauth_use_secondary_roles" { + type = string +} +variable "pre_authorized_roles_list" { + type = set(string) +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_unset/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_unset/test.tf new file mode 100644 index 0000000000..e780bf0c13 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_unset/test.tf @@ -0,0 +1,25 @@ +resource "snowflake_oauth_integration_for_custom_clients" "test" { + blocked_roles_list = var.blocked_roles_list + comment = var.comment + enabled = var.enabled + name = var.name + network_policy = var.network_policy + oauth_allow_non_tls_redirect_uri = var.oauth_allow_non_tls_redirect_uri + oauth_client_rsa_public_key = var.oauth_client_rsa_public_key + oauth_client_rsa_public_key_2 = var.oauth_client_rsa_public_key_2 + oauth_client_type = var.oauth_client_type + oauth_enforce_pkce = var.oauth_enforce_pkce + oauth_issue_refresh_tokens = var.oauth_issue_refresh_tokens + oauth_redirect_uri = var.oauth_redirect_uri + oauth_refresh_token_validity = var.oauth_refresh_token_validity + oauth_use_secondary_roles = var.oauth_use_secondary_roles + pre_authorized_roles_list = var.pre_authorized_roles_list +} + + +data "snowflake_security_integrations" "test" { + depends_on = [snowflake_oauth_integration_for_custom_clients.test] + + with_describe = false + like = var.name +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_unset/variables.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_unset/variables.tf new file mode 100644 index 0000000000..9d98ea92c8 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_custom_clients/optionals_unset/variables.tf @@ -0,0 +1,46 @@ + +variable "blocked_roles_list" { + type = set(string) +} +variable "comment" { + type = string +} +variable "enabled" { + type = bool +} +variable "name" { + type = string +} +variable "network_policy" { + type = string +} +variable "oauth_allow_non_tls_redirect_uri" { + type = bool +} +variable "oauth_client_rsa_public_key" { + type = string +} +variable "oauth_client_rsa_public_key_2" { + type = string +} +variable "oauth_client_type" { + type = string +} +variable "oauth_enforce_pkce" { + type = bool +} +variable "oauth_issue_refresh_tokens" { + type = bool +} +variable "oauth_redirect_uri" { + type = string +} +variable "oauth_refresh_token_validity" { + type = number +} +variable "oauth_use_secondary_roles" { + type = string +} +variable "pre_authorized_roles_list" { + type = set(string) +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_set/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_set/test.tf new file mode 100644 index 0000000000..77382c9177 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_set/test.tf @@ -0,0 +1,16 @@ +resource "snowflake_oauth_integration_for_partner_applications" "test" { + name = var.name + oauth_client = var.oauth_client + blocked_roles_list = var.blocked_roles_list + enabled = var.enabled + oauth_issue_refresh_tokens = var.oauth_issue_refresh_tokens + oauth_refresh_token_validity = var.oauth_refresh_token_validity + oauth_use_secondary_roles = var.oauth_use_secondary_roles + comment = var.comment +} + +data "snowflake_security_integrations" "test" { + depends_on = [snowflake_oauth_integration_for_partner_applications.test] + + like = var.name +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_set/variables.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_set/variables.tf new file mode 100644 index 0000000000..0c6ad5489e --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_set/variables.tf @@ -0,0 +1,24 @@ +variable "name" { + type = string +} +variable "oauth_client" { + type = string +} +variable "blocked_roles_list" { + type = set(string) +} +variable "enabled" { + type = string +} +variable "oauth_issue_refresh_tokens" { + type = string +} +variable "oauth_refresh_token_validity" { + type = string +} +variable "oauth_use_secondary_roles" { + type = string +} +variable "comment" { + type = string +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_unset/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_unset/test.tf new file mode 100644 index 0000000000..5d0b5c0ba6 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_unset/test.tf @@ -0,0 +1,17 @@ +resource "snowflake_oauth_integration_for_partner_applications" "test" { + name = var.name + oauth_client = var.oauth_client + blocked_roles_list = var.blocked_roles_list + enabled = var.enabled + oauth_issue_refresh_tokens = var.oauth_issue_refresh_tokens + oauth_refresh_token_validity = var.oauth_refresh_token_validity + oauth_use_secondary_roles = var.oauth_use_secondary_roles + comment = var.comment +} + +data "snowflake_security_integrations" "test" { + depends_on = [snowflake_oauth_integration_for_partner_applications.test] + + with_describe = false + like = var.name +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_unset/variables.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_unset/variables.tf new file mode 100644 index 0000000000..0c6ad5489e --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/oauth_for_partner_applications/optionals_unset/variables.tf @@ -0,0 +1,24 @@ +variable "name" { + type = string +} +variable "oauth_client" { + type = string +} +variable "blocked_roles_list" { + type = set(string) +} +variable "enabled" { + type = string +} +variable "oauth_issue_refresh_tokens" { + type = string +} +variable "oauth_refresh_token_validity" { + type = string +} +variable "oauth_use_secondary_roles" { + type = string +} +variable "comment" { + type = string +} diff --git a/pkg/helpers/helpers.go b/pkg/helpers/helpers.go index 5586a631fb..c190f4f3d9 100644 --- a/pkg/helpers/helpers.go +++ b/pkg/helpers/helpers.go @@ -151,3 +151,12 @@ func MergeMaps[M ~map[K]V, K comparable, V any](src ...M) M { } return merged } + +// TODO: use slices.Concat in Go 1.22 +func ConcatSlices[T any](slices ...[]T) []T { + var tmp []T + for _, s := range slices { + tmp = append(tmp, s...) + } + return tmp +} diff --git a/pkg/provider/resources/resources.go b/pkg/provider/resources/resources.go index db621745c8..7cc5adf9d8 100644 --- a/pkg/provider/resources/resources.go +++ b/pkg/provider/resources/resources.go @@ -3,50 +3,53 @@ package resources type resource string const ( - Account resource = "snowflake_account" - Alert resource = "snowflake_alert" - ApiIntegration resource = "snowflake_api_integration" - CortexSearchService resource = "snowflake_cortex_search_service" - DatabaseOld resource = "snowflake_database_old" - Database resource = "snowflake_database" - DatabaseRole resource = "snowflake_database_role" - DynamicTable resource = "snowflake_dynamic_table" - EmailNotificationIntegration resource = "snowflake_email_notification_integration" - ExternalFunction resource = "snowflake_external_function" - ExternalTable resource = "snowflake_external_table" - FailoverGroup resource = "snowflake_failover_group" - FileFormat resource = "snowflake_file_format" - Function resource = "snowflake_function" - ManagedAccount resource = "snowflake_managed_account" - MaskingPolicy resource = "snowflake_masking_policy" - MaterializedView resource = "snowflake_materialized_view" - NetworkPolicy resource = "snowflake_network_policy" - NetworkRule resource = "snowflake_network_rule" - NotificationIntegration resource = "snowflake_notification_integration" - OauthIntegrationForCustomClients resource = "snowflake_oauth_integration_for_custom_clients" - OauthIntegrationForPartnerApplications resource = "snowflake_oauth_integration_for_partner_applications" - PasswordPolicy resource = "snowflake_password_policy" - Pipe resource = "snowflake_pipe" - Procedure resource = "snowflake_procedure" - ResourceMonitor resource = "snowflake_resource_monitor" - Role resource = "snowflake_role" - RowAccessPolicy resource = "snowflake_row_access_policy" - Saml2SecurityIntegration resource = "snowflake_saml2_integration" - Schema resource = "snowflake_schema" - ScimSecurityIntegration resource = "snowflake_scim_integration" - SecondaryDatabase resource = "snowflake_secondary_database" - Sequence resource = "snowflake_sequence" - Share resource = "snowflake_share" - SharedDatabase resource = "snowflake_shared_database" - Stage resource = "snowflake_stage" - StorageIntegration resource = "snowflake_storage_integration" - Stream resource = "snowflake_stream" - Table resource = "snowflake_table" - Tag resource = "snowflake_tag" - Task resource = "snowflake_task" - User resource = "snowflake_user" - View resource = "snowflake_view" - Warehouse resource = "snowflake_warehouse" + Account resource = "snowflake_account" + Alert resource = "snowflake_alert" + ApiAuthenticationIntegrationWithAuthorizationCodeGrant resource = "snowflake_api_authentication_integration_with_authorization_code_grant" + ApiAuthenticationIntegrationWithClientCredentials resource = "snowflake_api_authentication_integration_with_client_credentials" + ApiAuthenticationIntegrationWithJwtBearer resource = "snowflake_api_authentication_integration_with_jwt_bearer" + ApiIntegration resource = "snowflake_api_integration" + CortexSearchService resource = "snowflake_cortex_search_service" + DatabaseOld resource = "snowflake_database_old" + Database resource = "snowflake_database" + DatabaseRole resource = "snowflake_database_role" + DynamicTable resource = "snowflake_dynamic_table" + EmailNotificationIntegration resource = "snowflake_email_notification_integration" + ExternalFunction resource = "snowflake_external_function" + ExternalTable resource = "snowflake_external_table" + FailoverGroup resource = "snowflake_failover_group" + FileFormat resource = "snowflake_file_format" + Function resource = "snowflake_function" + ManagedAccount resource = "snowflake_managed_account" + MaskingPolicy resource = "snowflake_masking_policy" + MaterializedView resource = "snowflake_materialized_view" + NetworkPolicy resource = "snowflake_network_policy" + NetworkRule resource = "snowflake_network_rule" + NotificationIntegration resource = "snowflake_notification_integration" + OauthIntegrationForCustomClients resource = "snowflake_oauth_integration_for_custom_clients" + OauthIntegrationForPartnerApplications resource = "snowflake_oauth_integration_for_partner_applications" + PasswordPolicy resource = "snowflake_password_policy" + Pipe resource = "snowflake_pipe" + Procedure resource = "snowflake_procedure" + ResourceMonitor resource = "snowflake_resource_monitor" + Role resource = "snowflake_role" + RowAccessPolicy resource = "snowflake_row_access_policy" + Saml2SecurityIntegration resource = "snowflake_saml2_integration" + Schema resource = "snowflake_schema" + ScimSecurityIntegration resource = "snowflake_scim_integration" + SecondaryDatabase resource = "snowflake_secondary_database" + Sequence resource = "snowflake_sequence" + Share resource = "snowflake_share" + SharedDatabase resource = "snowflake_shared_database" + Stage resource = "snowflake_stage" + StorageIntegration resource = "snowflake_storage_integration" + Stream resource = "snowflake_stream" + Table resource = "snowflake_table" + Tag resource = "snowflake_tag" + Task resource = "snowflake_task" + User resource = "snowflake_user" + View resource = "snowflake_view" + Warehouse resource = "snowflake_warehouse" ) type Resource interface { diff --git a/pkg/resources/api_authentication_integration_with_authorization_code_grant.go b/pkg/resources/api_authentication_integration_with_authorization_code_grant.go index 8bad64fd68..9f320e33c5 100644 --- a/pkg/resources/api_authentication_integration_with_authorization_code_grant.go +++ b/pkg/resources/api_authentication_integration_with_authorization_code_grant.go @@ -31,7 +31,7 @@ var apiAuthAuthorizationCodeGrantSchema = func() map[string]*schema.Schema { Description: "Specifies a list of scopes to use when making a request from the OAuth by a role with USAGE on the integration during the OAuth client credentials flow.", }, } - return MergeMaps(apiAuthCommonSchema, apiAuthAuthorizationCodeGrant) + return helpers.MergeMaps(apiAuthCommonSchema, apiAuthAuthorizationCodeGrant) }() func ApiAuthenticationIntegrationWithAuthorizationCodeGrant() *schema.Resource { diff --git a/pkg/resources/api_authentication_integration_with_authorization_code_grant_acceptance_test.go b/pkg/resources/api_authentication_integration_with_authorization_code_grant_acceptance_test.go index ee2caa26a1..046f5d0cc6 100644 --- a/pkg/resources/api_authentication_integration_with_authorization_code_grant_acceptance_test.go +++ b/pkg/resources/api_authentication_integration_with_authorization_code_grant_acceptance_test.go @@ -6,6 +6,7 @@ import ( acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/importchecks" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/resources" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-testing/config" @@ -39,6 +40,7 @@ func TestAcc_ApiAuthenticationIntegrationWithAuthorizationCodeGrant_basic(t *tes TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.RequireAbove(tfversion.Version1_5_0), }, + CheckDestroy: acc.CheckDestroy(t, resources.ApiAuthenticationIntegrationWithAuthorizationCodeGrant), Steps: []resource.TestStep{ { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_ApiAuthenticationIntegrationWithAuthorizationCodeGrant/basic"), @@ -194,6 +196,7 @@ func TestAcc_ApiAuthenticationIntegrationWithAuthorizationCodeGrant_complete(t * TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.RequireAbove(tfversion.Version1_5_0), }, + CheckDestroy: acc.CheckDestroy(t, resources.ApiAuthenticationIntegrationWithAuthorizationCodeGrant), Steps: []resource.TestStep{ { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_ApiAuthenticationIntegrationWithAuthorizationCodeGrant/complete"), diff --git a/pkg/resources/api_authentication_integration_with_client_credentials.go b/pkg/resources/api_authentication_integration_with_client_credentials.go index 862c2ed21f..40e3736f7f 100644 --- a/pkg/resources/api_authentication_integration_with_client_credentials.go +++ b/pkg/resources/api_authentication_integration_with_client_credentials.go @@ -26,7 +26,7 @@ var apiAuthClientCredentialsSchema = func() map[string]*schema.Schema { Description: "Specifies a list of scopes to use when making a request from the OAuth by a role with USAGE on the integration during the OAuth client credentials flow.", }, } - return MergeMaps(apiAuthCommonSchema, apiAuthClientCredentials) + return helpers.MergeMaps(apiAuthCommonSchema, apiAuthClientCredentials) }() func ApiAuthenticationIntegrationWithClientCredentials() *schema.Resource { diff --git a/pkg/resources/api_authentication_integration_with_client_credentials_acceptance_test.go b/pkg/resources/api_authentication_integration_with_client_credentials_acceptance_test.go index 1609e678ab..3b259d8026 100644 --- a/pkg/resources/api_authentication_integration_with_client_credentials_acceptance_test.go +++ b/pkg/resources/api_authentication_integration_with_client_credentials_acceptance_test.go @@ -6,6 +6,7 @@ import ( acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/importchecks" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/resources" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" "github.com/hashicorp/terraform-plugin-testing/config" @@ -38,6 +39,7 @@ func TestAcc_ApiAuthenticationIntegrationWithClientCredentials_basic(t *testing. TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.RequireAbove(tfversion.Version1_5_0), }, + CheckDestroy: acc.CheckDestroy(t, resources.ApiAuthenticationIntegrationWithClientCredentials), Steps: []resource.TestStep{ { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_ApiAuthenticationIntegrationWithClientCredentials/basic"), @@ -188,6 +190,7 @@ func TestAcc_ApiAuthenticationIntegrationWithClientCredentials_complete(t *testi TerraformVersionChecks: []tfversion.TerraformVersionCheck{ tfversion.RequireAbove(tfversion.Version1_5_0), }, + CheckDestroy: acc.CheckDestroy(t, resources.ApiAuthenticationIntegrationWithClientCredentials), Steps: []resource.TestStep{ { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_ApiAuthenticationIntegrationWithClientCredentials/complete"), diff --git a/pkg/resources/api_authentication_integration_with_jwt_bearer.go b/pkg/resources/api_authentication_integration_with_jwt_bearer.go index e93d40ced9..73252185d5 100644 --- a/pkg/resources/api_authentication_integration_with_jwt_bearer.go +++ b/pkg/resources/api_authentication_integration_with_jwt_bearer.go @@ -29,7 +29,7 @@ var apiAuthJwtBearerSchema = func() map[string]*schema.Schema { Required: true, }, } - return MergeMaps(apiAuthCommonSchema, apiAuthJwtBearer) + return helpers.MergeMaps(apiAuthCommonSchema, apiAuthJwtBearer) }() func ApiAuthenticationIntegrationWithJwtBearer() *schema.Resource { diff --git a/pkg/schemas/api_authentication_security_integration.go b/pkg/schemas/api_authentication_security_integration.go index 913c99574e..2f52758421 100644 --- a/pkg/schemas/api_authentication_security_integration.go +++ b/pkg/schemas/api_authentication_security_integration.go @@ -2,6 +2,7 @@ package schemas import ( "log" + "slices" "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -24,27 +25,29 @@ var DescribeApiAuthSecurityIntegrationSchema = map[string]*schema.Schema{ "comment": DescribePropertyListSchema, } +var ApiAuthenticationPropertiesKeys = []string{ + "ENABLED", + "OAUTH_ACCESS_TOKEN_VALIDITY", + "OAUTH_REFRESH_TOKEN_VALIDITY", + "OAUTH_CLIENT_ID", + "OAUTH_CLIENT_AUTH_METHOD", + "OAUTH_AUTHORIZATION_ENDPOINT", + "OAUTH_TOKEN_ENDPOINT", + "OAUTH_ALLOWED_SCOPES", + "OAUTH_GRANT", + "PARENT_INTEGRATION", + "AUTH_TYPE", + "COMMENT", +} var _ = DescribeApiAuthSecurityIntegrationSchema func ApiAuthSecurityIntegrationPropertiesToSchema(securityIntegrationProperties []sdk.SecurityIntegrationProperty) map[string]any { securityIntegrationSchema := make(map[string]any) for _, securityIntegrationProperty := range securityIntegrationProperties { securityIntegrationProperty := securityIntegrationProperty - switch securityIntegrationProperty.Name { - case "ENABLED", - "OAUTH_ACCESS_TOKEN_VALIDITY", - "OAUTH_REFRESH_TOKEN_VALIDITY", - "OAUTH_CLIENT_ID", - "OAUTH_CLIENT_AUTH_METHOD", - "OAUTH_AUTHORIZATION_ENDPOINT", - "OAUTH_TOKEN_ENDPOINT", - "OAUTH_ALLOWED_SCOPES", - "OAUTH_GRANT", - "PARENT_INTEGRATION", - "AUTH_TYPE", - "COMMENT": + if slices.Contains(ApiAuthenticationPropertiesKeys, securityIntegrationProperty.Name) { securityIntegrationSchema[strings.ToLower(securityIntegrationProperty.Name)] = []map[string]any{SecurityIntegrationPropertyToSchema(&securityIntegrationProperty)} - default: + } else { log.Printf("unknown field from DESCRIBE: %v", securityIntegrationProperty.Name) } } diff --git a/pkg/schemas/oauth_integration_for_custom_clients.go b/pkg/schemas/oauth_integration_for_custom_clients.go index 06f35e4106..f6b1bbee8a 100644 --- a/pkg/schemas/oauth_integration_for_custom_clients.go +++ b/pkg/schemas/oauth_integration_for_custom_clients.go @@ -2,6 +2,7 @@ package schemas import ( "log" + "slices" "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -30,32 +31,35 @@ var DescribeOauthIntegrationForCustomClients = map[string]*schema.Schema{ "oauth_allowed_token_endpoints": DescribePropertyListSchema, } +var OauthIntegrationForCustomClientsPropertiesNames = []string{ + "OAUTH_CLIENT_TYPE", + "OAUTH_REDIRECT_URI", + "ENABLED", + "OAUTH_ALLOW_NON_TLS_REDIRECT_URI", + "OAUTH_ENFORCE_PKCE", + "OAUTH_USE_SECONDARY_ROLES", + "PRE_AUTHORIZED_ROLES_LIST", + "BLOCKED_ROLES_LIST", + "OAUTH_ISSUE_REFRESH_TOKENS", + "OAUTH_REFRESH_TOKEN_VALIDITY", + "NETWORK_POLICY", + "OAUTH_CLIENT_RSA_PUBLIC_KEY_FP", + "OAUTH_CLIENT_RSA_PUBLIC_KEY_2_FP", + "COMMENT", + "OAUTH_CLIENT_ID", + "OAUTH_AUTHORIZATION_ENDPOINT", + "OAUTH_TOKEN_ENDPOINT", + "OAUTH_ALLOWED_AUTHORIZATION_ENDPOINTS", + "OAUTH_ALLOWED_TOKEN_ENDPOINTS", +} + func DescribeOauthIntegrationForCustomClientsToSchema(integrationProperties []sdk.SecurityIntegrationProperty) map[string]any { propsSchema := make(map[string]any) for _, property := range integrationProperties { property := property - switch property.Name { - case "OAUTH_CLIENT_TYPE", - "OAUTH_REDIRECT_URI", - "ENABLED", - "OAUTH_ALLOW_NON_TLS_REDIRECT_URI", - "OAUTH_ENFORCE_PKCE", - "OAUTH_USE_SECONDARY_ROLES", - "PRE_AUTHORIZED_ROLES_LIST", - "BLOCKED_ROLES_LIST", - "OAUTH_ISSUE_REFRESH_TOKENS", - "OAUTH_REFRESH_TOKEN_VALIDITY", - "NETWORK_POLICY", - "OAUTH_CLIENT_RSA_PUBLIC_KEY_FP", - "OAUTH_CLIENT_RSA_PUBLIC_KEY_2_FP", - "COMMENT", - "OAUTH_CLIENT_ID", - "OAUTH_AUTHORIZATION_ENDPOINT", - "OAUTH_TOKEN_ENDPOINT", - "OAUTH_ALLOWED_AUTHORIZATION_ENDPOINTS", - "OAUTH_ALLOWED_TOKEN_ENDPOINTS": + if slices.Contains(OauthIntegrationForCustomClientsPropertiesNames, property.Name) { propsSchema[strings.ToLower(property.Name)] = []map[string]any{SecurityIntegrationPropertyToSchema(&property)} - default: + } else { log.Printf("[WARN] unexpected property %v returned from Snowflake", property.Name) } } diff --git a/pkg/schemas/oauth_security_integration_for_partner_applications.go b/pkg/schemas/oauth_security_integration_for_partner_applications.go index b17811f3cd..1a6aa61acb 100644 --- a/pkg/schemas/oauth_security_integration_for_partner_applications.go +++ b/pkg/schemas/oauth_security_integration_for_partner_applications.go @@ -2,6 +2,7 @@ package schemas import ( "log" + "slices" "strings" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/sdk" @@ -30,32 +31,35 @@ var DescribeOauthIntegrationForPartnerApplications = map[string]*schema.Schema{ "oauth_allowed_token_endpoints": DescribePropertyListSchema, } +var OauthIntegrationForPartnerApplicationsPropertiesNames = []string{ + "OAUTH_CLIENT_TYPE", + "OAUTH_REDIRECT_URI", + "ENABLED", + "OAUTH_ALLOW_NON_TLS_REDIRECT_URI", + "OAUTH_ENFORCE_PKCE", + "OAUTH_USE_SECONDARY_ROLES", + "PRE_AUTHORIZED_ROLES_LIST", + "BLOCKED_ROLES_LIST", + "OAUTH_ISSUE_REFRESH_TOKENS", + "OAUTH_REFRESH_TOKEN_VALIDITY", + "NETWORK_POLICY", + "OAUTH_CLIENT_RSA_PUBLIC_KEY_FP", + "OAUTH_CLIENT_RSA_PUBLIC_KEY_2_FP", + "COMMENT", + "OAUTH_CLIENT_ID", + "OAUTH_AUTHORIZATION_ENDPOINT", + "OAUTH_TOKEN_ENDPOINT", + "OAUTH_ALLOWED_AUTHORIZATION_ENDPOINTS", + "OAUTH_ALLOWED_TOKEN_ENDPOINTS", +} + func DescribeOauthIntegrationForPartnerApplicationsToSchema(integrationProperties []sdk.SecurityIntegrationProperty) map[string]any { securityIntegrationProperties := make(map[string]any) for _, property := range integrationProperties { property := property - switch property.Name { - case "OAUTH_CLIENT_TYPE", - "OAUTH_REDIRECT_URI", - "ENABLED", - "OAUTH_ALLOW_NON_TLS_REDIRECT_URI", - "OAUTH_ENFORCE_PKCE", - "OAUTH_USE_SECONDARY_ROLES", - "PRE_AUTHORIZED_ROLES_LIST", - "BLOCKED_ROLES_LIST", - "OAUTH_ISSUE_REFRESH_TOKENS", - "OAUTH_REFRESH_TOKEN_VALIDITY", - "NETWORK_POLICY", - "OAUTH_CLIENT_RSA_PUBLIC_KEY_FP", - "OAUTH_CLIENT_RSA_PUBLIC_KEY_2_FP", - "COMMENT", - "OAUTH_CLIENT_ID", - "OAUTH_AUTHORIZATION_ENDPOINT", - "OAUTH_TOKEN_ENDPOINT", - "OAUTH_ALLOWED_AUTHORIZATION_ENDPOINTS", - "OAUTH_ALLOWED_TOKEN_ENDPOINTS": + if slices.Contains(OauthIntegrationForPartnerApplicationsPropertiesNames, property.Name) { securityIntegrationProperties[strings.ToLower(property.Name)] = []map[string]any{SecurityIntegrationPropertyToSchema(&property)} - default: + } else { log.Printf("[WARN] unexpected property %v returned from Snowflake", property.Name) } } diff --git a/pkg/schemas/security_integration.go b/pkg/schemas/security_integration.go index 7159240a1e..5e6f868b00 100644 --- a/pkg/schemas/security_integration.go +++ b/pkg/schemas/security_integration.go @@ -9,8 +9,20 @@ import ( ) var ( - SecurityIntegrationDescribeSchema = helpers.MergeMaps(DescribeSaml2IntegrationSchema, DescribeScimSecurityIntegrationSchema) - allSecurityIntegrationPropertiesNames = append(Saml2PropertiesNames, ScimPropertiesNames...) + SecurityIntegrationDescribeSchema = helpers.MergeMaps( + DescribeApiAuthSecurityIntegrationSchema, + DescribeOauthIntegrationForCustomClients, + DescribeOauthIntegrationForPartnerApplications, + DescribeSaml2IntegrationSchema, + DescribeScimSecurityIntegrationSchema, + ) + allSecurityIntegrationPropertiesNames = helpers.ConcatSlices( + ApiAuthenticationPropertiesKeys, + OauthIntegrationForCustomClientsPropertiesNames, + OauthIntegrationForPartnerApplicationsPropertiesNames, + Saml2PropertiesNames, + ScimPropertiesNames, + ) ) func SecurityIntegrationsDescriptionsToSchema(integrationProperties []sdk.SecurityIntegrationProperty) map[string]any { From 9c802cc6053db7ee7f6e0fc43b8f086ae55df4e5 Mon Sep 17 00:00:00 2001 From: Jakub Michalak Date: Tue, 9 Jul 2024 14:36:15 +0200 Subject: [PATCH 3/7] Add external oauth --- docs/data-sources/security_integrations.md | 132 ++++++++++++++++++ .../security_integrations_acceptance_test.go | 79 +++++++++++ .../external_oauth/optionals_set/test.tf | 21 +++ .../external_oauth/optionals_set/variables.tf | 39 ++++++ .../external_oauth/optionals_unset/test.tf | 22 +++ .../optionals_unset/variables.tf | 39 ++++++ ...api_authentication_security_integration.go | 6 +- .../external_oauth_security_integration.go | 34 +++-- .../oauth_integration_for_custom_clients.go | 2 +- ...ty_integration_for_partner_applications.go | 2 +- pkg/schemas/saml2_security_integration.go | 2 +- pkg/schemas/scim_security_integration.go | 2 +- pkg/schemas/security_integration.go | 4 +- 13 files changed, 361 insertions(+), 23 deletions(-) create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/external_oauth/optionals_set/test.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/external_oauth/optionals_set/variables.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/external_oauth/optionals_unset/test.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/external_oauth/optionals_unset/variables.tf diff --git a/docs/data-sources/security_integrations.md b/docs/data-sources/security_integrations.md index 83129c966a..16f187dfb3 100644 --- a/docs/data-sources/security_integrations.md +++ b/docs/data-sources/security_integrations.md @@ -106,6 +106,17 @@ Read-Only: - `blocked_roles_list` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--blocked_roles_list)) - `comment` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--comment)) - `enabled` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--enabled)) +- `external_oauth_allowed_roles_list` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--external_oauth_allowed_roles_list)) +- `external_oauth_any_role_mode` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--external_oauth_any_role_mode)) +- `external_oauth_audience_list` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--external_oauth_audience_list)) +- `external_oauth_blocked_roles_list` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--external_oauth_blocked_roles_list)) +- `external_oauth_issuer` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--external_oauth_issuer)) +- `external_oauth_jws_keys_url` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--external_oauth_jws_keys_url)) +- `external_oauth_rsa_public_key` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--external_oauth_rsa_public_key)) +- `external_oauth_rsa_public_key_2` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--external_oauth_rsa_public_key_2)) +- `external_oauth_scope_delimiter` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--external_oauth_scope_delimiter)) +- `external_oauth_snowflake_user_mapping_attribute` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--external_oauth_snowflake_user_mapping_attribute)) +- `external_oauth_token_user_mapping_claim` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--external_oauth_token_user_mapping_claim)) - `network_policy` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--network_policy)) - `oauth_access_token_validity` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_access_token_validity)) - `oauth_allow_non_tls_redirect_uri` (List of Object) (see [below for nested schema](#nestedobjatt--security_integrations--describe_output--oauth_allow_non_tls_redirect_uri)) @@ -212,6 +223,127 @@ Read-Only: - `value` (String) + +### Nested Schema for `security_integrations.describe_output.external_oauth_allowed_roles_list` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.external_oauth_any_role_mode` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.external_oauth_audience_list` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.external_oauth_blocked_roles_list` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.external_oauth_issuer` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.external_oauth_jws_keys_url` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.external_oauth_rsa_public_key` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.external_oauth_rsa_public_key_2` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.external_oauth_scope_delimiter` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.external_oauth_snowflake_user_mapping_attribute` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + + +### Nested Schema for `security_integrations.describe_output.external_oauth_token_user_mapping_claim` + +Read-Only: + +- `default` (String) +- `name` (String) +- `type` (String) +- `value` (String) + + ### Nested Schema for `security_integrations.describe_output.network_policy` diff --git a/pkg/datasources/security_integrations_acceptance_test.go b/pkg/datasources/security_integrations_acceptance_test.go index f113a6b7d0..7bb4720f06 100644 --- a/pkg/datasources/security_integrations_acceptance_test.go +++ b/pkg/datasources/security_integrations_acceptance_test.go @@ -90,6 +90,85 @@ func TestAcc_SecurityIntegrations_ApiAuthentication(t *testing.T) { }) } +func TestAcc_SecurityIntegrations_ExternalOauth(t *testing.T) { + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() + role, roleCleanup := acc.TestClient().Role.CreateRole(t) + issuer := random.String() + t.Cleanup(roleCleanup) + + m := func() map[string]config.Variable { + return map[string]config.Variable{ + "comment": config.StringVariable("foo"), + "enabled": config.BoolVariable(true), + "external_oauth_allowed_roles_list": config.SetVariable(config.StringVariable(role.ID().Name())), + "external_oauth_any_role_mode": config.StringVariable(string(sdk.ExternalOauthSecurityIntegrationAnyRoleModeDisable)), + "external_oauth_audience_list": config.SetVariable(config.StringVariable("foo")), + "external_oauth_issuer": config.StringVariable(issuer), + "external_oauth_jws_keys_url": config.SetVariable(config.StringVariable("https://example.com")), + "external_oauth_scope_delimiter": config.StringVariable("."), + "external_oauth_scope_mapping_attribute": config.StringVariable("foo"), + "external_oauth_snowflake_user_mapping_attribute": config.StringVariable(string(sdk.ExternalOauthSecurityIntegrationSnowflakeUserMappingAttributeEmailAddress)), + "external_oauth_token_user_mapping_claim": config.SetVariable(config.StringVariable("foo")), + "name": config.StringVariable(id.Name()), + "external_oauth_type": config.StringVariable(string(sdk.ExternalOauthSecurityIntegrationTypeCustom)), + } + } + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + CheckDestroy: acc.CheckDestroy(t, resources.ExternalOauthSecurityIntegration), + Steps: []resource.TestStep{ + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecurityIntegrations/external_oauth/optionals_set"), + ConfigVariables: m(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "1"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.integration_type", "EXTERNAL_OAUTH - CUSTOM"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.category", "SECURITY"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.enabled", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.comment", "foo"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.created_on"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.enabled.0.value", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.external_oauth_issuer.0.value", issuer), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.external_oauth_jws_keys_url.0.value", "https://example.com"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.external_oauth_any_role_mode.0.value", string(sdk.ExternalOauthSecurityIntegrationAnyRoleModeDisable)), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.external_oauth_allowed_roles_list.0.value", role.Name), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.external_oauth_audience_list.0.value", "foo"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.external_oauth_token_user_mapping_claim.0.value", "['foo']"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.external_oauth_snowflake_user_mapping_attribute.0.value", string(sdk.ExternalOauthSecurityIntegrationSnowflakeUserMappingAttributeEmailAddress)), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.external_oauth_scope_delimiter.0.value", "."), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.comment.0.value", "foo"), + ), + }, + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecurityIntegrations/external_oauth/optionals_unset"), + ConfigVariables: m(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "1"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.integration_type", "EXTERNAL_OAUTH - CUSTOM"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.category", "SECURITY"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.enabled", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.comment", "foo"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.created_on"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.#", "0"), + ), + }, + }, + }) +} + func TestAcc_SecurityIntegrations_OauthForCustomClients(t *testing.T) { networkPolicy, networkPolicyCleanup := acc.TestClient().NetworkPolicy.CreateNetworkPolicy(t) t.Cleanup(networkPolicyCleanup) diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/external_oauth/optionals_set/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/external_oauth/optionals_set/test.tf new file mode 100644 index 0000000000..2eeca56bed --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/external_oauth/optionals_set/test.tf @@ -0,0 +1,21 @@ +resource "snowflake_external_oauth_integration" "test" { + comment = var.comment + enabled = var.enabled + external_oauth_allowed_roles_list = var.external_oauth_allowed_roles_list + external_oauth_any_role_mode = var.external_oauth_any_role_mode + external_oauth_audience_list = var.external_oauth_audience_list + external_oauth_issuer = var.external_oauth_issuer + external_oauth_jws_keys_url = var.external_oauth_jws_keys_url + external_oauth_scope_delimiter = var.external_oauth_scope_delimiter + external_oauth_scope_mapping_attribute = var.external_oauth_scope_mapping_attribute + external_oauth_snowflake_user_mapping_attribute = var.external_oauth_snowflake_user_mapping_attribute + external_oauth_token_user_mapping_claim = var.external_oauth_token_user_mapping_claim + name = var.name + external_oauth_type = var.external_oauth_type +} + +data "snowflake_security_integrations" "test" { + depends_on = [snowflake_external_oauth_integration.test] + + like = var.name +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/external_oauth/optionals_set/variables.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/external_oauth/optionals_set/variables.tf new file mode 100644 index 0000000000..ac964d6100 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/external_oauth/optionals_set/variables.tf @@ -0,0 +1,39 @@ +variable "comment" { + type = string +} +variable "enabled" { + type = bool +} +variable "external_oauth_allowed_roles_list" { + type = set(string) +} +variable "external_oauth_any_role_mode" { + type = string +} +variable "external_oauth_audience_list" { + type = set(string) +} +variable "external_oauth_issuer" { + type = string +} +variable "external_oauth_jws_keys_url" { + type = set(string) +} +variable "external_oauth_scope_delimiter" { + type = string +} +variable "external_oauth_scope_mapping_attribute" { + type = string +} +variable "external_oauth_snowflake_user_mapping_attribute" { + type = string +} +variable "external_oauth_token_user_mapping_claim" { + type = set(string) +} +variable "name" { + type = string +} +variable "external_oauth_type" { + type = string +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/external_oauth/optionals_unset/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/external_oauth/optionals_unset/test.tf new file mode 100644 index 0000000000..f432e7031a --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/external_oauth/optionals_unset/test.tf @@ -0,0 +1,22 @@ +resource "snowflake_external_oauth_integration" "test" { + comment = var.comment + enabled = var.enabled + external_oauth_allowed_roles_list = var.external_oauth_allowed_roles_list + external_oauth_any_role_mode = var.external_oauth_any_role_mode + external_oauth_audience_list = var.external_oauth_audience_list + external_oauth_issuer = var.external_oauth_issuer + external_oauth_jws_keys_url = var.external_oauth_jws_keys_url + external_oauth_scope_delimiter = var.external_oauth_scope_delimiter + external_oauth_scope_mapping_attribute = var.external_oauth_scope_mapping_attribute + external_oauth_snowflake_user_mapping_attribute = var.external_oauth_snowflake_user_mapping_attribute + external_oauth_token_user_mapping_claim = var.external_oauth_token_user_mapping_claim + name = var.name + external_oauth_type = var.external_oauth_type +} + +data "snowflake_security_integrations" "test" { + depends_on = [snowflake_external_oauth_integration.test] + + with_describe = false + like = var.name +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/external_oauth/optionals_unset/variables.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/external_oauth/optionals_unset/variables.tf new file mode 100644 index 0000000000..ac964d6100 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/external_oauth/optionals_unset/variables.tf @@ -0,0 +1,39 @@ +variable "comment" { + type = string +} +variable "enabled" { + type = bool +} +variable "external_oauth_allowed_roles_list" { + type = set(string) +} +variable "external_oauth_any_role_mode" { + type = string +} +variable "external_oauth_audience_list" { + type = set(string) +} +variable "external_oauth_issuer" { + type = string +} +variable "external_oauth_jws_keys_url" { + type = set(string) +} +variable "external_oauth_scope_delimiter" { + type = string +} +variable "external_oauth_scope_mapping_attribute" { + type = string +} +variable "external_oauth_snowflake_user_mapping_attribute" { + type = string +} +variable "external_oauth_token_user_mapping_claim" { + type = set(string) +} +variable "name" { + type = string +} +variable "external_oauth_type" { + type = string +} diff --git a/pkg/schemas/api_authentication_security_integration.go b/pkg/schemas/api_authentication_security_integration.go index 2f52758421..1fb2de6bca 100644 --- a/pkg/schemas/api_authentication_security_integration.go +++ b/pkg/schemas/api_authentication_security_integration.go @@ -25,7 +25,7 @@ var DescribeApiAuthSecurityIntegrationSchema = map[string]*schema.Schema{ "comment": DescribePropertyListSchema, } -var ApiAuthenticationPropertiesKeys = []string{ +var ApiAuthenticationPropertiesNames = []string{ "ENABLED", "OAUTH_ACCESS_TOKEN_VALIDITY", "OAUTH_REFRESH_TOKEN_VALIDITY", @@ -45,10 +45,10 @@ func ApiAuthSecurityIntegrationPropertiesToSchema(securityIntegrationProperties securityIntegrationSchema := make(map[string]any) for _, securityIntegrationProperty := range securityIntegrationProperties { securityIntegrationProperty := securityIntegrationProperty - if slices.Contains(ApiAuthenticationPropertiesKeys, securityIntegrationProperty.Name) { + if slices.Contains(ApiAuthenticationPropertiesNames, securityIntegrationProperty.Name) { securityIntegrationSchema[strings.ToLower(securityIntegrationProperty.Name)] = []map[string]any{SecurityIntegrationPropertyToSchema(&securityIntegrationProperty)} } else { - log.Printf("unknown field from DESCRIBE: %v", securityIntegrationProperty.Name) + log.Printf("[WARN] unexpected property %v in api auth security integration returned from Snowflake", securityIntegrationProperty.Name) } } return securityIntegrationSchema diff --git a/pkg/schemas/external_oauth_security_integration.go b/pkg/schemas/external_oauth_security_integration.go index 544d057690..4150f64b73 100644 --- a/pkg/schemas/external_oauth_security_integration.go +++ b/pkg/schemas/external_oauth_security_integration.go @@ -1,6 +1,7 @@ package schemas import ( + "log" "slices" "strings" @@ -25,27 +26,30 @@ var DescribeExternalOauthSecurityIntegrationSchema = map[string]*schema.Schema{ "comment": DescribePropertyListSchema, } -var _ = DescribeExternalOauthSecurityIntegrationSchema +var ExternalOauthPropertiesNames = []string{ + "ENABLED", + "EXTERNAL_OAUTH_ISSUER", + "EXTERNAL_OAUTH_JWS_KEYS_URL", + "EXTERNAL_OAUTH_ANY_ROLE_MODE", + "EXTERNAL_OAUTH_RSA_PUBLIC_KEY", + "EXTERNAL_OAUTH_RSA_PUBLIC_KEY_2", + "EXTERNAL_OAUTH_BLOCKED_ROLES_LIST", + "EXTERNAL_OAUTH_ALLOWED_ROLES_LIST", + "EXTERNAL_OAUTH_AUDIENCE_LIST", + "EXTERNAL_OAUTH_TOKEN_USER_MAPPING_CLAIM", + "EXTERNAL_OAUTH_SNOWFLAKE_USER_MAPPING_ATTRIBUTE", + "EXTERNAL_OAUTH_SCOPE_DELIMITER", + "COMMENT", +} func ExternalOauthSecurityIntegrationPropertiesToSchema(securityIntegrationProperties []sdk.SecurityIntegrationProperty) map[string]any { securityIntegrationSchema := make(map[string]any) for _, securityIntegrationProperty := range securityIntegrationProperties { securityIntegrationProperty := securityIntegrationProperty - switch securityIntegrationProperty.Name { - case "ENABLED", - "EXTERNAL_OAUTH_ISSUER", - "EXTERNAL_OAUTH_JWS_KEYS_URL", - "EXTERNAL_OAUTH_ANY_ROLE_MODE", - "EXTERNAL_OAUTH_RSA_PUBLIC_KEY", - "EXTERNAL_OAUTH_RSA_PUBLIC_KEY_2", - "EXTERNAL_OAUTH_BLOCKED_ROLES_LIST", - "EXTERNAL_OAUTH_ALLOWED_ROLES_LIST", - "EXTERNAL_OAUTH_AUDIENCE_LIST", - "EXTERNAL_OAUTH_TOKEN_USER_MAPPING_CLAIM", - "EXTERNAL_OAUTH_SNOWFLAKE_USER_MAPPING_ATTRIBUTE", - "EXTERNAL_OAUTH_SCOPE_DELIMITER", - "COMMENT": + if slices.Contains(ExternalOauthPropertiesNames, securityIntegrationProperty.Name) { securityIntegrationSchema[strings.ToLower(securityIntegrationProperty.Name)] = []map[string]any{SecurityIntegrationPropertyToSchema(&securityIntegrationProperty)} + } else { + log.Printf("[WARN] unexpected property %v in external oauth security integration returned from Snowflake", securityIntegrationProperty.Name) } } return securityIntegrationSchema diff --git a/pkg/schemas/oauth_integration_for_custom_clients.go b/pkg/schemas/oauth_integration_for_custom_clients.go index f6b1bbee8a..081c780167 100644 --- a/pkg/schemas/oauth_integration_for_custom_clients.go +++ b/pkg/schemas/oauth_integration_for_custom_clients.go @@ -60,7 +60,7 @@ func DescribeOauthIntegrationForCustomClientsToSchema(integrationProperties []sd if slices.Contains(OauthIntegrationForCustomClientsPropertiesNames, property.Name) { propsSchema[strings.ToLower(property.Name)] = []map[string]any{SecurityIntegrationPropertyToSchema(&property)} } else { - log.Printf("[WARN] unexpected property %v returned from Snowflake", property.Name) + log.Printf("[WARN] unexpected property %v in oauth security integration returned from Snowflake", property.Name) } } return propsSchema diff --git a/pkg/schemas/oauth_security_integration_for_partner_applications.go b/pkg/schemas/oauth_security_integration_for_partner_applications.go index 1a6aa61acb..9aff99dd42 100644 --- a/pkg/schemas/oauth_security_integration_for_partner_applications.go +++ b/pkg/schemas/oauth_security_integration_for_partner_applications.go @@ -60,7 +60,7 @@ func DescribeOauthIntegrationForPartnerApplicationsToSchema(integrationPropertie if slices.Contains(OauthIntegrationForPartnerApplicationsPropertiesNames, property.Name) { securityIntegrationProperties[strings.ToLower(property.Name)] = []map[string]any{SecurityIntegrationPropertyToSchema(&property)} } else { - log.Printf("[WARN] unexpected property %v returned from Snowflake", property.Name) + log.Printf("[WARN] unexpected property %v in oauth security integration returned from Snowflake", property.Name) } } return securityIntegrationProperties diff --git a/pkg/schemas/saml2_security_integration.go b/pkg/schemas/saml2_security_integration.go index 25f200efba..b5e180e8f4 100644 --- a/pkg/schemas/saml2_security_integration.go +++ b/pkg/schemas/saml2_security_integration.go @@ -60,7 +60,7 @@ func DescribeSaml2IntegrationToSchema(props []sdk.SecurityIntegrationProperty) m if slices.Contains(Saml2PropertiesNames, property.Name) { propsSchema[strings.ToLower(property.Name)] = []map[string]any{SecurityIntegrationPropertyToSchema(&property)} } else { - log.Printf("[WARN] unexpected property %v returned from Snowflake", property.Name) + log.Printf("[WARN] unexpected property %v in saml2 security integration returned from Snowflake", property.Name) } } return propsSchema diff --git a/pkg/schemas/scim_security_integration.go b/pkg/schemas/scim_security_integration.go index f17a8a848c..0fa5fa35f3 100644 --- a/pkg/schemas/scim_security_integration.go +++ b/pkg/schemas/scim_security_integration.go @@ -36,7 +36,7 @@ func ScimSecurityIntegrationPropertiesToSchema(securityIntegrationProperties []s if slices.Contains(ScimPropertiesNames, property.Name) { securityIntegrationSchema[strings.ToLower(property.Name)] = []map[string]any{SecurityIntegrationPropertyToSchema(&property)} } else { - log.Printf("[WARN] unexpected property %v returned from Snowflake", property.Name) + log.Printf("[WARN] unexpected property %v in scim security integration returned from Snowflake", property.Name) } } return securityIntegrationSchema diff --git a/pkg/schemas/security_integration.go b/pkg/schemas/security_integration.go index 5e6f868b00..2d83f21b15 100644 --- a/pkg/schemas/security_integration.go +++ b/pkg/schemas/security_integration.go @@ -11,13 +11,15 @@ import ( var ( SecurityIntegrationDescribeSchema = helpers.MergeMaps( DescribeApiAuthSecurityIntegrationSchema, + DescribeExternalOauthSecurityIntegrationSchema, DescribeOauthIntegrationForCustomClients, DescribeOauthIntegrationForPartnerApplications, DescribeSaml2IntegrationSchema, DescribeScimSecurityIntegrationSchema, ) allSecurityIntegrationPropertiesNames = helpers.ConcatSlices( - ApiAuthenticationPropertiesKeys, + ApiAuthenticationPropertiesNames, + ExternalOauthPropertiesNames, OauthIntegrationForCustomClientsPropertiesNames, OauthIntegrationForPartnerApplicationsPropertiesNames, Saml2PropertiesNames, From 89fa99d07fd69df12f1be9a623dc1178da589cb7 Mon Sep 17 00:00:00 2001 From: Jakub Michalak Date: Tue, 9 Jul 2024 14:54:27 +0200 Subject: [PATCH 4/7] Fix tests and add more --- .../security_integrations_acceptance_test.go | 131 ++++++++++++++---- .../optionals_set/test.tf | 18 +++ .../optionals_set/variables.tf | 30 ++++ .../optionals_unset/test.tf | 19 +++ .../optionals_unset/variables.tf | 30 ++++ 5 files changed, 199 insertions(+), 29 deletions(-) create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_set/test.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_set/variables.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_unset/test.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_unset/variables.tf diff --git a/pkg/datasources/security_integrations_acceptance_test.go b/pkg/datasources/security_integrations_acceptance_test.go index 7bb4720f06..f05ae6f4ca 100644 --- a/pkg/datasources/security_integrations_acceptance_test.go +++ b/pkg/datasources/security_integrations_acceptance_test.go @@ -15,7 +15,7 @@ import ( "github.com/hashicorp/terraform-plugin-testing/tfversion" ) -func TestAcc_SecurityIntegrations_ApiAuthentication(t *testing.T) { +func TestAcc_SecurityIntegrations_ApiAuthenticationWithAuthorizationCodeGrant(t *testing.T) { id := acc.TestClient().Ids.RandomAccountObjectIdentifier() m := func() map[string]config.Variable { @@ -47,27 +47,27 @@ func TestAcc_SecurityIntegrations_ApiAuthentication(t *testing.T) { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "1"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.#", "1"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.name", id.Name()), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.integration_type", "API_AUTHENTICATION"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.category", "SECURITY"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.enabled", "true"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.comment", "foo"), - resource.TestCheckResourceAttrSet("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.created_on"), - - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.#", "1"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.enabled.0.value", "true"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.oauth_access_token_validity.0.value", "42"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.oauth_refresh_token_validity.0.value", "12345"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.oauth_client_id.0.value", "foo"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.oauth_client_auth_method.0.value", string(sdk.ApiAuthenticationSecurityIntegrationOauthClientAuthMethodClientSecretPost)), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.oauth_authorization_endpoint.0.value", "https://example.com"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.oauth_token_endpoint.0.value", "https://example.com"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.oauth_allowed_scopes.0.value", "[foo]"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.oauth_grant.0.value", sdk.ApiAuthenticationSecurityIntegrationOauthGrantAuthorizationCode), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.parent_integration.0.value", ""), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.auth_type.0.value", "OAUTH2"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "describe_output.0.comment.0.value", "foo")), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.integration_type", "API_AUTHENTICATION"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.category", "SECURITY"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.enabled", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.comment", "foo"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.created_on"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.enabled.0.value", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_access_token_validity.0.value", "42"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_refresh_token_validity.0.value", "12345"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_client_id.0.value", "foo"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_client_auth_method.0.value", string(sdk.ApiAuthenticationSecurityIntegrationOauthClientAuthMethodClientSecretPost)), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_authorization_endpoint.0.value", "https://example.com"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_token_endpoint.0.value", "https://example.com"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_allowed_scopes.0.value", "[foo]"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_grant.0.value", sdk.ApiAuthenticationSecurityIntegrationOauthGrantAuthorizationCode), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.parent_integration.0.value", ""), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.auth_type.0.value", "OAUTH2"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.comment.0.value", "foo")), }, { ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecurityIntegrations/api_authentication_with_authorization_code_grant/optionals_unset"), @@ -75,13 +75,86 @@ func TestAcc_SecurityIntegrations_ApiAuthentication(t *testing.T) { Check: resource.ComposeAggregateTestCheckFunc( resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "1"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.#", "1"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.name", id.Name()), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.integration_type", "API_AUTHENTICATION"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.category", "SECURITY"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.enabled", "true"), - resource.TestCheckResourceAttr("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.comment", "foo"), - resource.TestCheckResourceAttrSet("snowflake_api_authentication_integration_with_authorization_code_grant.test", "show_output.0.created_on"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.integration_type", "API_AUTHENTICATION"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.category", "SECURITY"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.enabled", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.comment", "foo"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.created_on"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.#", "0"), + ), + }, + }, + }) +} + +func TestAcc_SecurityIntegrations_ApiAuthenticationWithClientCredentials(t *testing.T) { + id := acc.TestClient().Ids.RandomAccountObjectIdentifier() + + m := func() map[string]config.Variable { + return map[string]config.Variable{ + "comment": config.StringVariable("foo"), + "enabled": config.BoolVariable(true), + "name": config.StringVariable(id.Name()), + "oauth_access_token_validity": config.IntegerVariable(42), + "oauth_client_auth_method": config.StringVariable(string(sdk.ApiAuthenticationSecurityIntegrationOauthClientAuthMethodClientSecretPost)), + "oauth_client_id": config.StringVariable("foo"), + "oauth_client_secret": config.StringVariable("foo"), + "oauth_refresh_token_validity": config.IntegerVariable(12345), + "oauth_token_endpoint": config.StringVariable("https://example.com"), + "oauth_allowed_scopes": config.SetVariable(config.StringVariable("foo")), + } + } + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + CheckDestroy: acc.CheckDestroy(t, resources.ApiAuthenticationIntegrationWithClientCredentials), + Steps: []resource.TestStep{ + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_set"), + ConfigVariables: m(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "1"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.integration_type", "API_AUTHENTICATION"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.category", "SECURITY"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.enabled", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.comment", "foo"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.created_on"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.enabled.0.value", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_access_token_validity.0.value", "42"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_refresh_token_validity.0.value", "12345"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_client_id.0.value", "foo"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_client_auth_method.0.value", string(sdk.ApiAuthenticationSecurityIntegrationOauthClientAuthMethodClientSecretPost)), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_token_endpoint.0.value", "https://example.com"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_allowed_scopes.0.value", "[foo]"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_grant.0.value", sdk.ApiAuthenticationSecurityIntegrationOauthGrantClientCredentials), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.parent_integration.0.value", ""), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.auth_type.0.value", "OAUTH2"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.comment.0.value", "foo")), + }, + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_unset"), + ConfigVariables: m(), + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "1"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.name", id.Name()), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.integration_type", "API_AUTHENTICATION"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.category", "SECURITY"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.enabled", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.comment", "foo"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.created_on"), resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.#", "0"), ), diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_set/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_set/test.tf new file mode 100644 index 0000000000..bf8e125fe0 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_set/test.tf @@ -0,0 +1,18 @@ +resource "snowflake_api_authentication_integration_with_client_credentials" "test" { + comment = var.comment + enabled = var.enabled + name = var.name + oauth_access_token_validity = var.oauth_access_token_validity + oauth_refresh_token_validity = var.oauth_refresh_token_validity + oauth_client_auth_method = var.oauth_client_auth_method + oauth_client_id = var.oauth_client_id + oauth_client_secret = var.oauth_client_secret + oauth_token_endpoint = var.oauth_token_endpoint + oauth_allowed_scopes = var.oauth_allowed_scopes +} + +data "snowflake_security_integrations" "test" { + depends_on = [snowflake_api_authentication_integration_with_client_credentials.test] + + like = var.name +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_set/variables.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_set/variables.tf new file mode 100644 index 0000000000..4ccccac436 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_set/variables.tf @@ -0,0 +1,30 @@ +variable "comment" { + type = string +} +variable "enabled" { + type = bool +} +variable "name" { + type = string +} +variable "oauth_access_token_validity" { + type = number +} +variable "oauth_refresh_token_validity" { + type = number +} +variable "oauth_client_auth_method" { + type = string +} +variable "oauth_client_id" { + type = string +} +variable "oauth_client_secret" { + type = string +} +variable "oauth_token_endpoint" { + type = string +} +variable "oauth_allowed_scopes" { + type = set(string) +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_unset/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_unset/test.tf new file mode 100644 index 0000000000..487a75acc7 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_unset/test.tf @@ -0,0 +1,19 @@ +resource "snowflake_api_authentication_integration_with_client_credentials" "test" { + comment = var.comment + enabled = var.enabled + name = var.name + oauth_access_token_validity = var.oauth_access_token_validity + oauth_refresh_token_validity = var.oauth_refresh_token_validity + oauth_client_auth_method = var.oauth_client_auth_method + oauth_client_id = var.oauth_client_id + oauth_client_secret = var.oauth_client_secret + oauth_token_endpoint = var.oauth_token_endpoint + oauth_allowed_scopes = var.oauth_allowed_scopes +} + +data "snowflake_security_integrations" "test" { + depends_on = [snowflake_api_authentication_integration_with_client_credentials.test] + + with_describe = false + like = var.name +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_unset/variables.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_unset/variables.tf new file mode 100644 index 0000000000..4ccccac436 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/api_authentication_with_client_credentials/optionals_unset/variables.tf @@ -0,0 +1,30 @@ +variable "comment" { + type = string +} +variable "enabled" { + type = bool +} +variable "name" { + type = string +} +variable "oauth_access_token_validity" { + type = number +} +variable "oauth_refresh_token_validity" { + type = number +} +variable "oauth_client_auth_method" { + type = string +} +variable "oauth_client_id" { + type = string +} +variable "oauth_client_secret" { + type = string +} +variable "oauth_token_endpoint" { + type = string +} +variable "oauth_allowed_scopes" { + type = set(string) +} From 460baddca44798a096dcd2853e1a11bab3874520 Mon Sep 17 00:00:00 2001 From: Jakub Michalak Date: Wed, 10 Jul 2024 11:32:53 +0200 Subject: [PATCH 5/7] Add multiple types test case and fix things from review --- .../security_integrations_acceptance_test.go | 66 +++++++++++++++++++ .../multiple_types/test.tf | 20 ++++++ .../multiple_types/variables.tf | 34 ++++++++++ .../saml2/optionals_set/test.tf | 23 ++----- .../oauth_integration_for_custom_clients.go | 2 +- ...ty_integration_for_partner_applications.go | 2 +- pkg/schemas/security_integration.go | 3 + 7 files changed, 130 insertions(+), 20 deletions(-) create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/multiple_types/test.tf create mode 100644 pkg/datasources/testdata/TestAcc_SecurityIntegrations/multiple_types/variables.tf diff --git a/pkg/datasources/security_integrations_acceptance_test.go b/pkg/datasources/security_integrations_acceptance_test.go index f05ae6f4ca..cbcc1f8c5c 100644 --- a/pkg/datasources/security_integrations_acceptance_test.go +++ b/pkg/datasources/security_integrations_acceptance_test.go @@ -6,6 +6,7 @@ import ( "testing" acc "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance" + "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/internal/snowflakeroles" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/acceptance/helpers/random" "github.com/Snowflake-Labs/terraform-provider-snowflake/pkg/provider/resources" @@ -15,6 +16,71 @@ import ( "github.com/hashicorp/terraform-plugin-testing/tfversion" ) +func TestAcc_SecurityIntegrations_MultipleTypes(t *testing.T) { + prefix := random.AlphaN(4) + idOne := acc.TestClient().Ids.RandomAccountObjectIdentifierWithPrefix(prefix) + idTwo := acc.TestClient().Ids.RandomAccountObjectIdentifierWithPrefix(prefix) + issuer := acc.TestClient().Ids.Alpha() + cert := random.GenerateX509(t) + validUrl := "http://example.com" + + role := snowflakeroles.GenericScimProvisioner + configVariables := config.Variables{ + // saml2 + "name_1": config.StringVariable(idOne.Name()), + "saml2_issuer": config.StringVariable(issuer), + "saml2_provider": config.StringVariable(string(sdk.Saml2SecurityIntegrationSaml2ProviderCustom)), + "saml2_sso_url": config.StringVariable(validUrl), + "saml2_x509_cert": config.StringVariable(cert), + // scim + "name_2": config.StringVariable(idTwo.Name()), + "scim_client": config.StringVariable(string(sdk.ScimSecurityIntegrationScimClientGeneric)), + "run_as_role": config.StringVariable(role.Name()), + "enabled": config.BoolVariable(true), + + "like": config.StringVariable(prefix + "%"), + } + + resource.Test(t, resource.TestCase{ + ProtoV6ProviderFactories: acc.TestAccProtoV6ProviderFactories, + TerraformVersionChecks: []tfversion.TerraformVersionCheck{ + tfversion.RequireAbove(tfversion.Version1_5_0), + }, + Steps: []resource.TestStep{ + { + ConfigDirectory: acc.ConfigurationDirectory("TestAcc_SecurityIntegrations/multiple_types"), + ConfigVariables: configVariables, + Check: resource.ComposeAggregateTestCheckFunc( + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.#", "2"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.name", idOne.Name()), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.integration_type", "SCIM - GENERIC"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.category", sdk.SecurityIntegrationCategory), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.enabled", "true"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.show_output.0.created_on"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.enabled.0.value", "true"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.run_as_role.0.value", "GENERIC_SCIM_PROVISIONER"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.sync_password.0.value", "true"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.1.show_output.0.name", idTwo.Name()), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.1.show_output.0.integration_type", "SAML2"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.1.show_output.0.category", sdk.SecurityIntegrationCategory), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.1.show_output.0.enabled", "false"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.1.show_output.0.created_on"), + + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.1.describe_output.#", "1"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.1.describe_output.0.saml2_issuer.0.value", issuer), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.1.describe_output.0.saml2_provider.0.value", "CUSTOM"), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.1.describe_output.0.saml2_sso_url.0.value", validUrl), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.1.describe_output.0.saml2_x509_cert.0.value", cert), + ), + }, + }, + }) +} + func TestAcc_SecurityIntegrations_ApiAuthenticationWithAuthorizationCodeGrant(t *testing.T) { id := acc.TestClient().Ids.RandomAccountObjectIdentifier() diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/multiple_types/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/multiple_types/test.tf new file mode 100644 index 0000000000..dfaf0ebbd7 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/multiple_types/test.tf @@ -0,0 +1,20 @@ +resource "snowflake_scim_integration" "test" { + name = var.name_1 + scim_client = var.scim_client + run_as_role = var.run_as_role + enabled = var.enabled +} + +resource "snowflake_saml2_integration" "test" { + name = var.name_2 + saml2_issuer = var.saml2_issuer + saml2_sso_url = var.saml2_sso_url + saml2_provider = var.saml2_provider + saml2_x509_cert = var.saml2_x509_cert +} + +data "snowflake_security_integrations" "test" { + depends_on = [snowflake_scim_integration.test, snowflake_saml2_integration.test] + + like = var.like +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/multiple_types/variables.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/multiple_types/variables.tf new file mode 100644 index 0000000000..960c2cf847 --- /dev/null +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/multiple_types/variables.tf @@ -0,0 +1,34 @@ +# saml2 +variable "name_1" { + type = string +} +variable "saml2_issuer" { + type = string +} +variable "saml2_provider" { + type = string +} +variable "saml2_sso_url" { + type = string +} +variable "saml2_x509_cert" { + type = string +} + +# scim +variable "name_2" { + type = string +} +variable "scim_client" { + type = string +} +variable "run_as_role" { + type = string +} +variable "enabled" { + type = bool +} + +variable "like" { + type = string +} diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_set/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_set/test.tf index eb65721110..3c4ea74228 100644 --- a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_set/test.tf +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_set/test.tf @@ -1,21 +1,8 @@ -resource "snowflake_saml2_integration" "test" { - allowed_email_patterns = var.allowed_email_patterns - allowed_user_domains = var.allowed_user_domains - comment = var.comment - enabled = var.enabled - name = var.name - saml2_enable_sp_initiated = var.saml2_enable_sp_initiated - saml2_force_authn = var.saml2_force_authn - saml2_issuer = var.saml2_issuer - saml2_post_logout_redirect_url = var.saml2_post_logout_redirect_url - saml2_provider = var.saml2_provider - saml2_requested_nameid_format = var.saml2_requested_nameid_format - saml2_sign_request = var.saml2_sign_request - saml2_snowflake_acs_url = var.saml2_snowflake_acs_url - saml2_snowflake_issuer_url = var.saml2_snowflake_issuer_url - saml2_sp_initiated_login_page_label = var.saml2_sp_initiated_login_page_label - saml2_sso_url = var.saml2_sso_url - saml2_x509_cert = var.saml2_x509_cert +resource "snowflake_scim_integration" "test" { + name = var.name + scim_client = var.scim_client + run_as_role = var.run_as_role + enabled = var.enabled } data "snowflake_security_integrations" "test" { diff --git a/pkg/schemas/oauth_integration_for_custom_clients.go b/pkg/schemas/oauth_integration_for_custom_clients.go index 081c780167..c517f9b03b 100644 --- a/pkg/schemas/oauth_integration_for_custom_clients.go +++ b/pkg/schemas/oauth_integration_for_custom_clients.go @@ -60,7 +60,7 @@ func DescribeOauthIntegrationForCustomClientsToSchema(integrationProperties []sd if slices.Contains(OauthIntegrationForCustomClientsPropertiesNames, property.Name) { propsSchema[strings.ToLower(property.Name)] = []map[string]any{SecurityIntegrationPropertyToSchema(&property)} } else { - log.Printf("[WARN] unexpected property %v in oauth security integration returned from Snowflake", property.Name) + log.Printf("[WARN] unexpected property %v in oauth security integration for custom clients returned from Snowflake", property.Name) } } return propsSchema diff --git a/pkg/schemas/oauth_security_integration_for_partner_applications.go b/pkg/schemas/oauth_security_integration_for_partner_applications.go index 9aff99dd42..61bb3d2efc 100644 --- a/pkg/schemas/oauth_security_integration_for_partner_applications.go +++ b/pkg/schemas/oauth_security_integration_for_partner_applications.go @@ -60,7 +60,7 @@ func DescribeOauthIntegrationForPartnerApplicationsToSchema(integrationPropertie if slices.Contains(OauthIntegrationForPartnerApplicationsPropertiesNames, property.Name) { securityIntegrationProperties[strings.ToLower(property.Name)] = []map[string]any{SecurityIntegrationPropertyToSchema(&property)} } else { - log.Printf("[WARN] unexpected property %v in oauth security integration returned from Snowflake", property.Name) + log.Printf("[WARN] unexpected property %v in oauth security integration for partner applications returned from Snowflake", property.Name) } } return securityIntegrationProperties diff --git a/pkg/schemas/security_integration.go b/pkg/schemas/security_integration.go index 2d83f21b15..051b49ea5d 100644 --- a/pkg/schemas/security_integration.go +++ b/pkg/schemas/security_integration.go @@ -1,6 +1,7 @@ package schemas import ( + "log" "slices" "strings" @@ -33,6 +34,8 @@ func SecurityIntegrationsDescriptionsToSchema(integrationProperties []sdk.Securi desc := desc if slices.Contains(allSecurityIntegrationPropertiesNames, desc.Name) { securityIntegrationProperties[strings.ToLower(desc.Name)] = []map[string]any{SecurityIntegrationPropertyToSchema(&desc)} + } else { + log.Printf("[WARN] unexpected property %v in security integration returned from Snowflake", desc.Name) } } return securityIntegrationProperties From cc6788d5e1ce5bb54831ae0ec17d80b3864f5f69 Mon Sep 17 00:00:00 2001 From: Jakub Michalak Date: Wed, 10 Jul 2024 12:47:17 +0200 Subject: [PATCH 6/7] Fix tests --- .../security_integrations_acceptance_test.go | 6 ++--- .../saml2/optionals_set/test.tf | 23 +++++++++++++++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/pkg/datasources/security_integrations_acceptance_test.go b/pkg/datasources/security_integrations_acceptance_test.go index cbcc1f8c5c..8294157454 100644 --- a/pkg/datasources/security_integrations_acceptance_test.go +++ b/pkg/datasources/security_integrations_acceptance_test.go @@ -365,15 +365,15 @@ func TestAcc_SecurityIntegrations_OauthForCustomClients(t *testing.T) { resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.enabled.0.value", "true"), resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_allow_non_tls_redirect_uri.0.value", "true"), resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_enforce_pkce.0.value", "true"), - resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_use_secondary_roles.0.value", string(sdk.OauthSecurityIntegrationUseSecondaryRolesImplicit)), + resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_use_secondary_roles.0.value", string(sdk.OauthSecurityIntegrationUseSecondaryRolesNone)), resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.pre_authorized_roles_list.0.value", preAuthorizedRole.ID().Name()), // Not asserted, because it also contains other default roles // resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.blocked_roles_list.0.value"), resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_issue_refresh_tokens.0.value", "true"), resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_refresh_token_validity.0.value", "86400"), resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.network_policy.0.value", sdk.NewAccountObjectIdentifier(networkPolicy.Name).Name()), // TODO(SNOW-999049): Fix during identifiers rework - resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_client_rsa_public_key_fp.0.value", ""), - resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_client_rsa_public_key_2_fp.0.value", ""), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_client_rsa_public_key_fp.0.value"), + resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_client_rsa_public_key_2_fp.0.value"), resource.TestCheckResourceAttr("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.comment.0.value", comment), resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_client_id.0.value"), resource.TestCheckResourceAttrSet("data.snowflake_security_integrations.test", "security_integrations.0.describe_output.0.oauth_authorization_endpoint.0.value"), diff --git a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_set/test.tf b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_set/test.tf index 3c4ea74228..eb65721110 100644 --- a/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_set/test.tf +++ b/pkg/datasources/testdata/TestAcc_SecurityIntegrations/saml2/optionals_set/test.tf @@ -1,8 +1,21 @@ -resource "snowflake_scim_integration" "test" { - name = var.name - scim_client = var.scim_client - run_as_role = var.run_as_role - enabled = var.enabled +resource "snowflake_saml2_integration" "test" { + allowed_email_patterns = var.allowed_email_patterns + allowed_user_domains = var.allowed_user_domains + comment = var.comment + enabled = var.enabled + name = var.name + saml2_enable_sp_initiated = var.saml2_enable_sp_initiated + saml2_force_authn = var.saml2_force_authn + saml2_issuer = var.saml2_issuer + saml2_post_logout_redirect_url = var.saml2_post_logout_redirect_url + saml2_provider = var.saml2_provider + saml2_requested_nameid_format = var.saml2_requested_nameid_format + saml2_sign_request = var.saml2_sign_request + saml2_snowflake_acs_url = var.saml2_snowflake_acs_url + saml2_snowflake_issuer_url = var.saml2_snowflake_issuer_url + saml2_sp_initiated_login_page_label = var.saml2_sp_initiated_login_page_label + saml2_sso_url = var.saml2_sso_url + saml2_x509_cert = var.saml2_x509_cert } data "snowflake_security_integrations" "test" { From a0db22b83d65e048a7d7705b703c2b67512771f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20Cie=C5=9Blak?= Date: Wed, 10 Jul 2024 15:17:50 +0200 Subject: [PATCH 7/7] Adjust migration guide --- MIGRATION_GUIDE.md | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/MIGRATION_GUIDE.md b/MIGRATION_GUIDE.md index 9764cd426d..97bbbb6c66 100644 --- a/MIGRATION_GUIDE.md +++ b/MIGRATION_GUIDE.md @@ -85,16 +85,22 @@ The fields listed below had diff suppress which removed '-' from strings. Now, t - `external_oauth_type` - `external_oauth_any_role_mode` +### *(new feature)* snowflake_saml2_integration resource + +The new `snowflake_saml2_integration` is introduced and deprecates `snowflake_saml_integration`. It contains new fields +and follows our new conventions making it more stable. The old SAML integration wasn't changed, so no migration needed, +but we recommend to eventually migrate to the newer counterpart. + ### snowflake_scim_integration resource changes #### *(behavior change)* Changed behavior of `sync_password` -Now, the `sync_password` field will set the state value to `unknown` whenever the value is not set in the config. This indicates that the value on the Snowflake side is set to the Snowflake default. +Now, the `sync_password` field will set the state value to `default` whenever the value is not set in the config. This indicates that the value on the Snowflake side is set to the Snowflake default. #### *(behavior change)* Renamed fields Renamed field `provisioner_role` to `run_as_role` to align with Snowflake docs. Please rename this field in your configuration files. State will be migrated automatically. -#### *(feature)* New fields +#### *(new feature)* New fields Fields added to the resource: - `enabled` - `sync_password` @@ -104,7 +110,7 @@ Fields added to the resource: New field `enabled` is required. Previously the default value during create in Snowflake was `true`. If you created a resource with Terraform, please add `enabled = true` to have the same value. #### *(behavior change)* Force new for multiple attributes -Force new was added for the following attributes (because there are no usable SQL alter statements for them): +ForceNew was added for the following attributes (because there are no usable SQL alter statements for them): - `scim_client` - `run_as_role` @@ -122,9 +128,9 @@ As part of the [redesign](https://github.com/Snowflake-Labs/terraform-provider-s - `statement_queued_timeout_in_seconds` (previously `0`) - `statement_timeout_in_seconds` (previously `172800`) -**Beware!** For attributes being Snowflake parameters (in case of warehouse: `max_concurrency_level`, `statement_queued_timeout_in_seconds`, and `statement_timeout_in_seconds`), this is a breaking change (read more in [Snowflake parameters](./v1-preparations/CHANGES_BEFORE_V1.md#snowflake-parameters)). Previously, not setting a value for them was treated as a fallback to values hardcoded on the provider side. This caused warehouse creation with these parameters set on the warehouse level (and not using the Snowflake default from hierarchy; read more in the [parameters documentation](https://docs.snowflake.com/en/sql-reference/parameters)). To keep the previous values, fill in your configs to the default values listed above. +**Beware!** For attributes being Snowflake parameters (in case of warehouse: `max_concurrency_level`, `statement_queued_timeout_in_seconds`, and `statement_timeout_in_seconds`), this is a breaking change (read more in [Snowflake parameters](./v1-preparations/CHANGES_BEFORE_V1.md#snowflake-parameters)). Previously, not setting a value for them was treated as a fallback to values hardcoded on the provider side. This caused warehouse creation with these parameters set on the warehouse level (and not using the Snowflake default from hierarchy; read more in the [parameters documentation](https://docs.snowflake.com/en/sql-reference/parameters)). To keep the previous values, fill in your configs to the default values listed above. -All previous defaults were aligned with the current Snowflake ones, however it's not possible to distinguish between filled out value and no value in the automatic state upgrader. Therefore, if the given attribute is not filled out in your configuration, terraform will try to perform update after the change (to UNSET the given attribute to the Snowflake default); it should result in no changes on Snowflake object side, but it is required to make Terraform state aligned with your config. **All** other optional fields that were not set inside the config at all (because of the change in handling state logic on our provider side) will follow the same logic. To avoid the need for the changes, fill out the default fields in your config. Alternatively run apply; no further changes should be shown as a part of the plan. +All previous defaults were aligned with the current Snowflake ones, however it's not possible to distinguish between filled out value and no value in the automatic state upgrader. Therefore, if the given attribute is not filled out in your configuration, terraform will try to perform update after the change (to UNSET the given attribute to the Snowflake default); it should result in no changes on Snowflake object side, but it is required to make Terraform state aligned with your config. **All** other optional fields that were not set inside the config at all (because of the change in handling state logic on our provider side) will follow the same logic. To avoid the need for the changes, fill out the default fields in your config. Alternatively, run `terraform apply`; no further changes should be shown as a part of the plan. #### *(note)* Automatic state migrations There are three migrations that should happen automatically with the version bump: @@ -172,7 +178,7 @@ To easily handle three-value logic (true, false, unknown) in provider's configs, You can read more in ["raw Snowflake output"](./v1-preparations/CHANGES_BEFORE_V1.md#empty-values). -### new database resources +### *(new feature)* new database resources As part of the [preparation for v1](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/ROADMAP.md#preparing-essential-ga-objects-for-the-provider-v1), we split up the database resource into multiple ones: - Standard database - can be used as `snowflake_database` (replaces the old one and is used to create databases with optional ability to become a primary database ready for replication) - Shared database - can be used as `snowflake_shared_database` (used to create databases from externally defined shares) @@ -184,7 +190,6 @@ All the field changes in comparison to the previous database resource are: - removed: the field is removed from `snowflake_shared_database` as it doesn't have any effect on shared databases. - `from_database` - database cloning was entirely removed and is not possible by any of the new database resources. - `from_share` - the parameter was moved to the dedicated resource for databases created from shares `snowflake_shared_database`. Right now, it's a text field instead of a map. Additionally, instead of legacy account identifier format we're expecting the new one that with share looks like this: `..`. For more information on account identifiers, visit the [official documentation](https://docs.snowflake.com/en/user-guide/admin-account-identifier). -- p, - `from_replication` - the parameter was moved to the dedicated resource for databases created from primary databases `snowflake_secondary_database` - `replication_configuration` - renamed: was renamed to `configuration` and is only available in the `snowflake_database`. Its internal schema changed that instead of list of accounts, we expect a list of nested objects with accounts for which replication (and optionally failover) should be enabled. More information about converting between both versions [here](#resource-renamed-snowflake_database---snowflake_database_old). Additionally, instead of legacy account identifier format we're expecting the new one that looks like this: `.` (it will be automatically migrated to the recommended format by the state upgrader). For more information on account identifiers, visit the [official documentation](https://docs.snowflake.com/en/user-guide/admin-account-identifier). - `data_retention_time_in_days` @@ -212,7 +217,7 @@ All the field changes in comparison to the previous database resource are: The split was done (and will be done for several objects during the refactor) to simplify the resource on maintainability and usage level. Its purpose was also to divide the resources by their specific purpose rather than cramping every use case of an object into one resource. -### Resource renamed snowflake_database -> snowflake_database_old +### *(behavior change)* Resource renamed snowflake_database -> snowflake_database_old We made a decision to use the existing `snowflake_database` resource for redesigning it into a standard database. The previous `snowflake_database` was renamed to `snowflake_database_old` and the current `snowflake_database` contains completely new implementation that follows our guidelines we set for V1. @@ -258,7 +263,7 @@ cloned databases diverge in behavior from standard databases, it may cause issue For databases with one of the fields mentioned above, manual migration will be needed. Please refer to our [migration guide](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/resource_migration.md) to perform zero downtime migration. -If you would like to upgrade to the latest version and postpone the upgrade, you still have to perform the maunal migration +If you would like to upgrade to the latest version and postpone the upgrade, you still have to perform the manual migration to the `snowflake_database_old` resource by following the [zero downtime migrations document](https://github.com/Snowflake-Labs/terraform-provider-snowflake/blob/main/docs/technical-documentation/resource_migration.md). The only difference would be that instead of writing/generating new configurations you have to just rename the existing ones to contain `_old` suffix.