diff --git a/docs/data-sources/connection.md b/docs/data-sources/connection.md index 5ed045510..b3f801cbf 100644 --- a/docs/data-sources/connection.md +++ b/docs/data-sources/connection.md @@ -97,6 +97,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 7c93189e4..8bf9bbbf7 100644 --- a/docs/resources/connection.md +++ b/docs/resources/connection.md @@ -667,6 +667,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 1f68b96fc..b47e619b0 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, @@ -723,6 +726,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 2d6991878..f902c91a6 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) } @@ -601,3 +603,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 0df68e9d4..707538286 100644 --- a/internal/auth0/connection/resource_test.go +++ b/internal/auth0/connection/resource_test.go @@ -1719,3 +1719,176 @@ resource "auth0_connection" "twitter" { } } ` + +func TestAccConnectionPingFederate(t *testing.T) { + acctest.Test(t, resource.TestCase{ + Steps: []resource.TestStep{ + { + 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())), + 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: 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())), + 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 = <