From 138a262fb1d27863ac7de79d2513e225aacd51c0 Mon Sep 17 00:00:00 2001 From: Sergiu Ghitea <28300158+sergiught@users.noreply.github.com> Date: Sun, 12 Mar 2023 01:20:06 +0100 Subject: [PATCH 1/4] Add support for ping federate connections --- docs/data-sources/connection.md | 1 + docs/resources/connection.md | 1 + internal/auth0/connection/expand.go | 36 +++ internal/auth0/connection/flatten.go | 41 +++ internal/auth0/connection/resource_test.go | 173 +++++++++++ internal/auth0/connection/schema.go | 7 + .../TestAccConnectionPingFederate.yaml | 290 ++++++++++++++++++ 7 files changed, 549 insertions(+) create mode 100644 test/data/recordings/TestAccConnectionPingFederate.yaml diff --git a/docs/data-sources/connection.md b/docs/data-sources/connection.md index 81fca960b..0e71c4009 100644 --- a/docs/data-sources/connection.md +++ b/docs/data-sources/connection.md @@ -96,6 +96,7 @@ Read-Only: - `password_history` (List of Object) (see [below for nested schema](#nestedobjatt--options--password_history)) - `password_no_personal_info` (List of Object) (see [below for nested schema](#nestedobjatt--options--password_no_personal_info)) - `password_policy` (String) +- `ping_federate_base_url` (String) - `pkce_enabled` (Boolean) - `protocol_binding` (String) - `provider` (String) diff --git a/docs/resources/connection.md b/docs/resources/connection.md index 0ffe90d06..72907b312 100644 --- a/docs/resources/connection.md +++ b/docs/resources/connection.md @@ -666,6 +666,7 @@ Optional: - `password_history` (Block List) Configuration settings for the password history that is maintained for each user to prevent the reuse of passwords. (see [below for nested schema](#nestedblock--options--password_history)) - `password_no_personal_info` (Block List, Max: 1) Configuration settings for the password personal info check, which does not allow passwords that contain any part of the user's personal data, including user's `name`, `username`, `nickname`, `user_metadata.name`, `user_metadata.first`, `user_metadata.last`, user's `email`, or first part of the user's `email`. (see [below for nested schema](#nestedblock--options--password_no_personal_info)) - `password_policy` (String) Indicates level of password strength to enforce during authentication. A strong password policy will make it difficult, if not improbable, for someone to guess a password through either manual or automated means. Options include `none`, `low`, `fair`, `good`, `excellent`. +- `ping_federate_base_url` (String) Ping Federate Server URL. - `pkce_enabled` (Boolean) Enables Proof Key for Code Exchange (PKCE) functionality for OAuth2 connections. - `protocol_binding` (String) The SAML Response Binding: how the SAML token is received by Auth0 from the IdP. - `provider` (String) Defines the custom `sms_gateway` provider. diff --git a/internal/auth0/connection/expand.go b/internal/auth0/connection/expand.go index 5457c338f..1ad112a76 100644 --- a/internal/auth0/connection/expand.go +++ b/internal/auth0/connection/expand.go @@ -102,6 +102,9 @@ func expandConnection(d *schema.ResourceData, api *management.Management) (*mana case management.ConnectionStrategyADFS: connection.ShowAsButton = showAsButton connection.Options, diagnostics = expandConnectionOptionsADFS(options) + case management.ConnectionStrategyPingFederate: + connection.ShowAsButton = showAsButton + connection.Options, diagnostics = expandConnectionOptionsPingFederate(options) default: diagnostics = append(diagnostics, diag.Diagnostic{ Severity: diag.Error, @@ -722,6 +725,39 @@ func expandConnectionOptionsADFS(config cty.Value) (*management.ConnectionOption return options, diag.FromErr(err) } +func expandConnectionOptionsPingFederate( + config cty.Value, +) (*management.ConnectionOptionsPingFederate, diag.Diagnostics) { + options := &management.ConnectionOptionsPingFederate{ + SigningCert: value.String(config.GetAttr("signing_cert")), + LogoURL: value.String(config.GetAttr("icon_url")), + TenantDomain: value.String(config.GetAttr("tenant_domain")), + DomainAliases: value.Strings(config.GetAttr("domain_aliases")), + SignInEndpoint: value.String(config.GetAttr("sign_in_endpoint")), + DigestAlgorithm: value.String(config.GetAttr("digest_algorithm")), + SignSAMLRequest: value.Bool(config.GetAttr("sign_saml_request")), + SignatureAlgorithm: value.String(config.GetAttr("signature_algorithm")), + PingFederateBaseURL: value.String(config.GetAttr("ping_federate_base_url")), + NonPersistentAttrs: value.Strings(config.GetAttr("non_persistent_attrs")), + SetUserAttributes: value.String(config.GetAttr("set_user_root_attributes")), + } + + config.GetAttr("idp_initiated").ForEachElement(func(_ cty.Value, idp cty.Value) (stop bool) { + options.IdpInitiated = &management.ConnectionOptionsSAMLIdpInitiated{ + ClientID: value.String(idp.GetAttr("client_id")), + ClientProtocol: value.String(idp.GetAttr("client_protocol")), + ClientAuthorizeQuery: value.String(idp.GetAttr("client_authorize_query")), + } + + return stop + }) + + var err error + options.UpstreamParams, err = value.MapFromJSON(config.GetAttr("upstream_params")) + + return options, diag.FromErr(err) +} + type scoper interface { Scopes() []string SetScopes(enable bool, scopes ...string) diff --git a/internal/auth0/connection/flatten.go b/internal/auth0/connection/flatten.go index f11d9eb13..450a57f90 100644 --- a/internal/auth0/connection/flatten.go +++ b/internal/auth0/connection/flatten.go @@ -52,6 +52,8 @@ func flattenConnectionOptions(d *schema.ResourceData, options interface{}) ([]in m, diags = flattenConnectionOptionsAzureAD(connectionOptions) case *management.ConnectionOptionsADFS: m, diags = flattenConnectionOptionsADFS(connectionOptions) + case *management.ConnectionOptionsPingFederate: + m, diags = flattenConnectionOptionsPingFederate(connectionOptions) case *management.ConnectionOptionsSAML: m, diags = flattenConnectionOptionsSAML(d, connectionOptions) } @@ -600,3 +602,42 @@ func flattenConnectionOptionsSAML( return m, nil } + +func flattenConnectionOptionsPingFederate( + options *management.ConnectionOptionsPingFederate, +) (interface{}, diag.Diagnostics) { + signingCert := options.GetSigningCert() + if signingCert == "" { + signingCert = options.GetCert() + } + + m := map[string]interface{}{ + "signing_cert": signingCert, + "tenant_domain": options.GetTenantDomain(), + "domain_aliases": options.GetDomainAliases(), + "sign_in_endpoint": options.GetSignInEndpoint(), + "signature_algorithm": options.GetSignatureAlgorithm(), + "digest_algorithm": options.GetDigestAlgorithm(), + "sign_saml_request": options.GetSignSAMLRequest(), + "ping_federate_base_url": options.GetPingFederateBaseURL(), + "icon_url": options.GetLogoURL(), + "set_user_root_attributes": options.GetSetUserAttributes(), + "non_persistent_attrs": options.GetNonPersistentAttrs(), + } + + m["idp_initiated"] = []interface{}{ + map[string]interface{}{ + "client_id": options.GetIdpInitiated().GetClientID(), + "client_protocol": options.GetIdpInitiated().GetClientProtocol(), + "client_authorize_query": options.GetIdpInitiated().GetClientAuthorizeQuery(), + }, + } + + upstreamParams, err := structure.FlattenJsonToString(options.UpstreamParams) + if err != nil { + return nil, diag.FromErr(err) + } + m["upstream_params"] = upstreamParams + + return m, nil +} diff --git a/internal/auth0/connection/resource_test.go b/internal/auth0/connection/resource_test.go index 187c19748..fb7225f05 100644 --- a/internal/auth0/connection/resource_test.go +++ b/internal/auth0/connection/resource_test.go @@ -1716,3 +1716,176 @@ resource "auth0_connection" "twitter" { } } ` + +func TestAccConnectionPingFederate(t *testing.T) { + acctest.Test(t, resource.TestCase{ + Steps: []resource.TestStep{ + { + Config: template.ParseTestName(testConnectionPingFederateConfigCreate, t.Name()), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("auth0_connection.my_connection", "name", fmt.Sprintf("Acceptance-Test-PingFederate-%s", t.Name())), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "display_name", fmt.Sprintf("Acceptance-Test-PingFederate-%s", t.Name())), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "strategy", "pingfederate"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "show_as_button", "false"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.#", "1"), + resource.TestCheckResourceAttrSet("auth0_connection.my_connection", "options.0.signing_cert"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.tenant_domain", "example.com"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.ping_federate_base_url", "https://pingfederate.example.com"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.sign_in_endpoint", "https://pingfederate.example.com"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.domain_aliases.#", "2"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.domain_aliases.0", "example.com"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.domain_aliases.1", "example.coz"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.signature_algorithm", "rsa-sha256"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.sign_saml_request", "false"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.digest_algorithm", "sha256"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.icon_url", "https://example.com/logo.svg"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.set_user_root_attributes", "on_first_login"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.non_persistent_attrs.#", "2"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.non_persistent_attrs.0", "gender"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.non_persistent_attrs.1", "hair_color"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.idp_initiated.#", "1"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.idp_initiated.0.client_id", "client_id"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.idp_initiated.0.client_protocol", "samlp"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.idp_initiated.0.client_authorize_query", "type=code&timeout=30"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.upstream_params", "{\"screen_name\":{\"alias\":\"login_hint\"}}"), + ), + }, + { + Config: template.ParseTestName(testConnectionPingFederateConfigUpdate, t.Name()), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("auth0_connection.my_connection", "name", fmt.Sprintf("Acceptance-Test-PingFederate-%s", t.Name())), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "display_name", fmt.Sprintf("Acceptance-Test-PingFederate-%s", t.Name())), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "strategy", "pingfederate"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "show_as_button", "true"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.#", "1"), + resource.TestCheckResourceAttrSet("auth0_connection.my_connection", "options.0.signing_cert"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.tenant_domain", "example.com"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.ping_federate_base_url", "https://pingfederate.example.com"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.sign_in_endpoint", "https://pingfederate.example.com"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.domain_aliases.#", "2"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.domain_aliases.0", "example.com"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.domain_aliases.1", "example.coz"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.signature_algorithm", "rsa-sha256"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.sign_saml_request", "true"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.digest_algorithm", "sha256"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.icon_url", ""), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.set_user_root_attributes", "on_first_login"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.non_persistent_attrs.#", "2"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.non_persistent_attrs.0", "gender"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.non_persistent_attrs.1", "hair_color"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.idp_initiated.#", "1"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.idp_initiated.0.client_id", "client_id"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.idp_initiated.0.client_protocol", "samlp"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.idp_initiated.0.client_authorize_query", "type=code&timeout=60"), + resource.TestCheckResourceAttr("auth0_connection.my_connection", "options.0.upstream_params", ""), + ), + }, + }, + }) +} + +const testConnectionPingFederateConfigCreate = ` +resource "auth0_connection" "my_connection" { + name = "Acceptance-Test-PingFederate-{{.testName}}" + display_name = "Acceptance-Test-PingFederate-{{.testName}}" + strategy = "pingfederate" + show_as_button = false + options { + signing_cert = < Date: Thu, 16 Mar 2023 13:46:46 +0100 Subject: [PATCH 2/4] Update internal/auth0/connection/resource_test.go --- internal/auth0/connection/resource_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/auth0/connection/resource_test.go b/internal/auth0/connection/resource_test.go index b1832b8b2..616492253 100644 --- a/internal/auth0/connection/resource_test.go +++ b/internal/auth0/connection/resource_test.go @@ -1724,7 +1724,7 @@ func TestAccConnectionPingFederate(t *testing.T) { acctest.Test(t, resource.TestCase{ Steps: []resource.TestStep{ { - Config: template.ParseTestName(testConnectionPingFederateConfigCreate, t.Name()), + Config: acctest.ParseTestName(testConnectionPingFederateConfigCreate, t.Name()), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("auth0_connection.my_connection", "name", fmt.Sprintf("Acceptance-Test-PingFederate-%s", t.Name())), resource.TestCheckResourceAttr("auth0_connection.my_connection", "display_name", fmt.Sprintf("Acceptance-Test-PingFederate-%s", t.Name())), From 7d86e82ca9a9d1289244da2f64aa242077a1ad62 Mon Sep 17 00:00:00 2001 From: Sergiu Ghitea <28300158+sergiught@users.noreply.github.com> Date: Thu, 16 Mar 2023 13:47:04 +0100 Subject: [PATCH 3/4] Update internal/auth0/connection/resource_test.go --- internal/auth0/connection/resource_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/auth0/connection/resource_test.go b/internal/auth0/connection/resource_test.go index 616492253..707538286 100644 --- a/internal/auth0/connection/resource_test.go +++ b/internal/auth0/connection/resource_test.go @@ -1754,7 +1754,7 @@ func TestAccConnectionPingFederate(t *testing.T) { ), }, { - Config: template.ParseTestName(testConnectionPingFederateConfigUpdate, t.Name()), + Config: acctest.ParseTestName(testConnectionPingFederateConfigUpdate, t.Name()), Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr("auth0_connection.my_connection", "name", fmt.Sprintf("Acceptance-Test-PingFederate-%s", t.Name())), resource.TestCheckResourceAttr("auth0_connection.my_connection", "display_name", fmt.Sprintf("Acceptance-Test-PingFederate-%s", t.Name())), From 4d110bd9359a6fad1cbd5f533282d40e147a0996 Mon Sep 17 00:00:00 2001 From: Sergiu Ghitea <28300158+sergiught@users.noreply.github.com> Date: Fri, 17 Mar 2023 11:59:04 +0100 Subject: [PATCH 4/4] Update ping federate base url validation to disallow empty --- internal/auth0/connection/schema.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/auth0/connection/schema.go b/internal/auth0/connection/schema.go index 8f4088241..c8fff6a04 100644 --- a/internal/auth0/connection/schema.go +++ b/internal/auth0/connection/schema.go @@ -9,7 +9,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" internalSchema "github.com/auth0/terraform-provider-auth0/internal/schema" - internalValidation "github.com/auth0/terraform-provider-auth0/internal/validation" ) var resourceSchema = map[string]*schema.Schema{ @@ -327,7 +326,7 @@ var resourceSchema = map[string]*schema.Schema{ "ping_federate_base_url": { Type: schema.TypeString, Optional: true, - ValidateFunc: internalValidation.IsURLWithHTTPSorEmptyString, + ValidateFunc: validation.IsURLWithHTTPorHTTPS, Description: "Ping Federate Server URL.", }, "identity_api": {