Skip to content

Commit

Permalink
DXCDT-450: Remove client deprecated fields (#725)
Browse files Browse the repository at this point in the history
* Transfering client_secret and token endpoint auth method fields from client resource to client data source

* Changing client arg to pointer

* Fixing test

* Modifying recording mechanism to not scrub 404 client responses

* Regenerating docs

---------

Co-authored-by: Will Vedder <[email protected]>
  • Loading branch information
willvedd and willvedd authored Jul 16, 2023
1 parent 5499aab commit 3525cea
Show file tree
Hide file tree
Showing 13 changed files with 788 additions and 830 deletions.
4 changes: 2 additions & 2 deletions docs/data-sources/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ data "auth0_client" "some-client-by-id" {
- `callbacks` (List of String) URLs that Auth0 may call back to after a user authenticates for the client. Make sure to specify the protocol (https://) otherwise the callback may fail in some cases. With the exception of custom URI schemes for native clients, all callbacks should use protocol https://.
- `client_aliases` (List of String) List of audiences/realms for SAML protocol. Used by the wsfed addon.
- `client_metadata` (Map of String) Metadata associated with the client, in the form of an object with string values (max 255 chars). Maximum of 10 metadata properties allowed. Field names (max 255 chars) are alphanumeric and may only include the following special characters: `:,-+=_*?"/\()<>@ [Tab] [Space]`.
- `client_secret` (String) Secret for the client. Keep this private. To access this attribute you need to add the `read:client_keys` scope to the Terraform client. Otherwise, the attribute will contain an empty string.
- `client_secret` (String, Sensitive) Secret for the client. Keep this private. To access this attribute you need to add the `read:client_keys` scope to the Terraform client. Otherwise, the attribute will contain an empty string.
- `cross_origin_auth` (Boolean) Whether this client can be used to make cross-origin authentication requests (`true`) or it is not allowed to make such requests (`false`). Requires the `coa_toggle_enabled` feature flag to be enabled on the tenant by the support team.
- `cross_origin_loc` (String) URL of the location in your site where the cross-origin verification takes place for the cross-origin auth flow when performing authentication in your own domain instead of Auth0 Universal Login page.
- `custom_login_page` (String) The content (HTML, CSS, JS) of the custom login page.
Expand All @@ -65,7 +65,7 @@ data "auth0_client" "some-client-by-id" {
- `signing_keys` (List of Map of String) List containing a map of the public cert of the signing key and the public cert of the signing key in PKCS7.
- `sso` (Boolean) Applies only to SSO clients and determines whether Auth0 will handle Single Sign-On (true) or whether the identity provider will (false).
- `sso_disabled` (Boolean) Indicates whether or not SSO is disabled.
- `token_endpoint_auth_method` (String) Defines the requested authentication method for the token endpoint. Options include `none` (public client without a client secret), `client_secret_post` (client uses HTTP POST parameters), `client_secret_basic` (client uses HTTP Basic). Managing the authentication method through this attribute is deprecated and it will be removed in a future major version. Migrate to the `auth0_client_credentials` resource to manage a client's authentication method instead. Check the [MIGRATION GUIDE](https://github.com/auth0/terraform-provider-auth0/blob/main/MIGRATION_GUIDE.md#client-authentication-method) on how to do that.
- `token_endpoint_auth_method` (String) The authentication method for the token endpoint. Results include `none` (public client without a client secret), `client_secret_post` (client uses HTTP POST parameters), `client_secret_basic` (client uses HTTP Basic). Managing a client's authentication method can be done via the `auth0_client_credentials` resource.
- `web_origins` (List of String) URLs that represent valid web origins for use with web message response mode.

<a id="nestedatt--addons"></a>
Expand Down
2 changes: 0 additions & 2 deletions docs/resources/client.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,13 +119,11 @@ resource "auth0_client" "my_client" {
- `refresh_token` (Block List, Max: 1) Configuration settings for the refresh tokens issued for this client. (see [below for nested schema](#nestedblock--refresh_token))
- `sso` (Boolean) Applies only to SSO clients and determines whether Auth0 will handle Single Sign-On (true) or whether the identity provider will (false).
- `sso_disabled` (Boolean) Indicates whether or not SSO is disabled.
- `token_endpoint_auth_method` (String, Deprecated) Defines the requested authentication method for the token endpoint. Options include `none` (public client without a client secret), `client_secret_post` (client uses HTTP POST parameters), `client_secret_basic` (client uses HTTP Basic). Managing the authentication method through this attribute is deprecated and it will be removed in a future major version. Migrate to the `auth0_client_credentials` resource to manage a client's authentication method instead. Check the [MIGRATION GUIDE](https://github.com/auth0/terraform-provider-auth0/blob/main/MIGRATION_GUIDE.md#client-authentication-method) on how to do that.
- `web_origins` (List of String) URLs that represent valid web origins for use with web message response mode.

### Read-Only

- `client_id` (String) The ID of the client.
- `client_secret` (String, Sensitive, Deprecated) Secret for the client. Keep this private. To access this attribute you need to add the `read:client_keys` scope to the Terraform client. Otherwise, the attribute will contain an empty string. Use this attribute on the `auth0_client_credentials` resource instead, to allow managing it directly or use the `auth0_client` data source to read this property.
- `id` (String) The ID of this resource.
- `signing_keys` (List of Map of String, Sensitive) List containing a map of the public cert of the signing key and the public cert of the signing key in PKCS7.

Expand Down
7 changes: 4 additions & 3 deletions internal/acctest/http_recorder.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,11 @@ func redactSensitiveDataInClient(t *testing.T, i *cassette.Interaction, domain s
!strings.Contains(i.Request.URL, "credentials") &&
i.Request.Method == http.MethodPatch

rotateSecret := strings.Contains(i.Request.URL, "clients") &&
strings.Contains(i.Request.URL, "/rotate-secret")
if create || read || update {
if i.Response.Code == http.StatusNotFound {
return
}

if create || read || update || rotateSecret {
var client management.Client
err := json.Unmarshal([]byte(i.Response.Body), &client)
require.NoError(t, err)
Expand Down
41 changes: 31 additions & 10 deletions internal/auth0/client/data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import (
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"

auth0 "github.com/auth0/terraform-provider-auth0/internal/auth0"
"github.com/auth0/terraform-provider-auth0/internal/config"
internalSchema "github.com/auth0/terraform-provider-auth0/internal/schema"
)
Expand All @@ -29,33 +28,54 @@ func dataSourceSchema() map[string]*schema.Schema {
dataSourceSchema["name"].Description = "The name of the client. If not provided, `client_id` must be set."
dataSourceSchema["client_id"].Description = "The ID of the client. If not provided, `name` must be set."

dataSourceSchema["client_secret"].Deprecated = ""
dataSourceSchema["client_secret"].Description = "Secret for the client. Keep this private. To access this attribute you need to add the " +
"`read:client_keys` scope to the Terraform client. Otherwise, the attribute will contain an " +
"empty string."
dataSourceSchema["client_secret"] = &schema.Schema{
Type: schema.TypeString,
Computed: true,
Sensitive: true,
Description: "Secret for the client. Keep this private. To access this attribute you need to add the " +
"`read:client_keys` scope to the Terraform client. Otherwise, the attribute will contain an empty string.",
}

dataSourceSchema["token_endpoint_auth_method"] = &schema.Schema{
Type: schema.TypeString,
Computed: true,
Description: "The authentication method for the token endpoint. " +
"Results include `none` (public client without a client secret), " +
"`client_secret_post` (client uses HTTP POST parameters), " +
"`client_secret_basic` (client uses HTTP Basic). " +
"Managing a client's authentication method can be done via the " +
"`auth0_client_credentials` resource.",
}

return dataSourceSchema
}

func readClientForDataSource(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
api := m.(*config.Config).GetAPI()

clientID := d.Get("client_id").(string)
if clientID != "" {
d.SetId(clientID)
return auth0.CheckFor404Error(ctx, readClient, d, m)

client, err := api.Client.Read(ctx, d.Id())
if err != nil {
return diag.FromErr(err)
}

err = flattenClientForDataSource(d, client)

return diag.FromErr(err)
}

name := d.Get("name").(string)
if name == "" {
return diag.Errorf("One of 'client_id' or 'name' is required.")
}

api := m.(*config.Config).GetAPI()

var page int
for {
clients, err := api.Client.List(
ctx,
management.IncludeFields("client_id", "name"),
management.Page(page),
)
if err != nil {
Expand All @@ -65,7 +85,8 @@ func readClientForDataSource(ctx context.Context, d *schema.ResourceData, m inte
for _, client := range clients.Clients {
if client.GetName() == name {
d.SetId(client.GetClientID())
return auth0.CheckFor404Error(ctx, readClient, d, m)
err = flattenClientForDataSource(d, client)
return diag.FromErr(err)
}
}

Expand Down
17 changes: 13 additions & 4 deletions internal/auth0/client/data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const testAccGivenAClient = `
resource "auth0_client" "my_client" {
name = "Acceptance Test - {{.testName}}"
app_type = "non_interactive"
description = "Description for {{.testName}}"
}
`

Expand All @@ -27,6 +28,8 @@ data "auth0_client" "test" {

const testAccDataClientConfigByID = `
data "auth0_client" "test" {
depends_on = [ auth0_client.my_client ]
client_id = auth0_client.my_client.client_id
}
`
Expand All @@ -35,13 +38,17 @@ func TestAccDataClientByName(t *testing.T) {
acctest.Test(t, resource.TestCase{
PreventPostDestroyRefresh: true,
Steps: []resource.TestStep{
{
Config: acctest.ParseTestName(testAccGivenAClient, t.Name()),
},
{
Config: acctest.ParseTestName(testAccGivenAClient+testAccDataClientConfigByName, t.Name()),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("data.auth0_client.test", "client_id"),
resource.TestCheckResourceAttr("data.auth0_client.test", "signing_keys.#", "1"),
resource.TestCheckResourceAttrSet("data.auth0_client.test", "client_secret"),
resource.TestCheckResourceAttr("data.auth0_client.test", "name", fmt.Sprintf("Acceptance Test - %v", t.Name())),
resource.TestCheckResourceAttr("data.auth0_client.test", "app_type", "non_interactive"),
resource.TestCheckResourceAttr("data.auth0_client.test", "description", "Description for TestAccDataClientByName"),
),
},
},
Expand All @@ -56,8 +63,10 @@ func TestAccDataClientById(t *testing.T) {
Config: acctest.ParseTestName(testAccGivenAClient+testAccDataClientConfigByID, t.Name()),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("data.auth0_client.test", "id"),
resource.TestCheckResourceAttrSet("data.auth0_client.test", "name"),
resource.TestCheckResourceAttr("data.auth0_client.test", "signing_keys.#", "1"),
resource.TestCheckResourceAttr("data.auth0_client.test", "name", fmt.Sprintf("Acceptance Test - %v", t.Name())),
resource.TestCheckResourceAttrSet("data.auth0_client.test", "client_secret"),
resource.TestCheckResourceAttr("data.auth0_client.test", "app_type", "non_interactive"),
resource.TestCheckResourceAttr("data.auth0_client.test", "description", "Description for TestAccDataClientById"),
),
},
},
Expand All @@ -76,7 +85,7 @@ func TestAccDataSourceClientNonexistentID(t *testing.T) {
{
Config: acctest.ParseTestName(testAccDataSourceClientNonexistentID, t.Name()),
ExpectError: regexp.MustCompile(
`no resource found with that identifier \((404\))`,
` 404 Not Found: The client does not exist`,
),
},
},
Expand Down
1 change: 0 additions & 1 deletion internal/auth0/client/expand.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ func expandClient(d *schema.ResourceData) *management.Client {
CustomLoginPageOn: value.Bool(config.GetAttr("custom_login_page_on")),
CustomLoginPage: value.String(config.GetAttr("custom_login_page")),
FormTemplate: value.String(config.GetAttr("form_template")),
TokenEndpointAuthMethod: value.String(config.GetAttr("token_endpoint_auth_method")),
InitiateLoginURI: value.String(config.GetAttr("initiate_login_uri")),
EncryptionKey: value.MapOfStrings(config.GetAttr("encryption_key")),
OIDCBackchannelLogout: expandOIDCBackchannelLogout(d),
Expand Down
52 changes: 52 additions & 0 deletions internal/auth0/client/flatten.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package client

import (
"github.com/auth0/go-auth0/management"
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func flattenCustomSocialConfiguration(customSocial *management.ClientNativeSocialLogin) []interface{} {
Expand Down Expand Up @@ -496,3 +498,53 @@ func flattenClientAddonWithNoConfig(addon interface{}) []interface{} {

return []interface{}{map[string]interface{}{}}
}

func flattenClient(d *schema.ResourceData, client *management.Client) error {
result := multierror.Append(
d.Set("client_id", client.GetClientID()),
d.Set("client_aliases", client.GetClientAliases()),
d.Set("name", client.GetName()),
d.Set("description", client.GetDescription()),
d.Set("app_type", client.GetAppType()),
d.Set("logo_uri", client.GetLogoURI()),
d.Set("is_first_party", client.GetIsFirstParty()),
d.Set("is_token_endpoint_ip_header_trusted", client.GetIsTokenEndpointIPHeaderTrusted()),
d.Set("oidc_conformant", client.GetOIDCConformant()),
d.Set("callbacks", client.GetCallbacks()),
d.Set("allowed_logout_urls", client.GetAllowedLogoutURLs()),
d.Set("allowed_origins", client.GetAllowedOrigins()),
d.Set("allowed_clients", client.GetAllowedClients()),
d.Set("grant_types", client.GetGrantTypes()),
d.Set("organization_usage", client.GetOrganizationUsage()),
d.Set("organization_require_behavior", client.GetOrganizationRequireBehavior()),
d.Set("web_origins", client.GetWebOrigins()),
d.Set("sso", client.GetSSO()),
d.Set("sso_disabled", client.GetSSODisabled()),
d.Set("cross_origin_auth", client.GetCrossOriginAuth()),
d.Set("cross_origin_loc", client.GetCrossOriginLocation()),
d.Set("custom_login_page_on", client.GetCustomLoginPageOn()),
d.Set("custom_login_page", client.GetCustomLoginPage()),
d.Set("form_template", client.GetFormTemplate()),
d.Set("native_social_login", flattenCustomSocialConfiguration(client.GetNativeSocialLogin())),
d.Set("jwt_configuration", flattenClientJwtConfiguration(client.GetJWTConfiguration())),
d.Set("refresh_token", flattenClientRefreshTokenConfiguration(client.GetRefreshToken())),
d.Set("encryption_key", client.GetEncryptionKey()),
d.Set("addons", flattenClientAddons(client.Addons)),
d.Set("mobile", flattenClientMobile(client.GetMobile())),
d.Set("initiate_login_uri", client.GetInitiateLoginURI()),
d.Set("signing_keys", client.SigningKeys),
d.Set("client_metadata", client.ClientMetadata),
d.Set("oidc_backchannel_logout_urls", client.OIDCBackchannelLogout.GetBackChannelLogoutURLs()),
)
return result.ErrorOrNil()
}

func flattenClientForDataSource(d *schema.ResourceData, client *management.Client) error {
result := multierror.Append(
flattenClient(d, client),
d.Set("client_secret", client.GetClientSecret()),
d.Set("token_endpoint_auth_method", client.GetTokenEndpointAuthMethod()),
)

return result.ErrorOrNil()
}
Loading

0 comments on commit 3525cea

Please sign in to comment.