Skip to content

Commit

Permalink
feat: re-add changes to omit_secret post git branch fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
tgoodsell-tempus committed Dec 16, 2023
1 parent 151744a commit 341f774
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 13 deletions.
47 changes: 37 additions & 10 deletions okta/resource_okta_app_oauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -136,20 +136,20 @@ func resourceAppOAuth() *schema.Resource {
Type: schema.TypeBool,
Optional: true,
// No ForceNew to avoid recreating when going from false => true
Description: "This tells the provider not to persist the application's secret to state. If this is ever changes from true => false your app will be recreated.",
Description: "This tells the provider not manage the client_secret value in state. When this is false (the default), it will cause the auto-generated client_secret to be persisted in the client_secret attribute in state. This also means that every time an update to this app is run, this value is also set on the API. If this changes from false => true, the `client_secret` is dropped from state and the secret at the time of the apply is what remains. If this is ever changes from true => false your app will be recreated, due to the need to regenerate a secret we can store in state.",
Default: false,
},
"client_secret": {
Type: schema.TypeString,
Computed: true,
Sensitive: true,
Description: "OAuth client secret key. This will be in plain text in your statefile unless you set omit_secret above.",
Description: "OAuth client secret value, this is output only. This will be in plain text in your statefile unless you set omit_secret above.",
},
"client_basic_secret": {
Type: schema.TypeString,
Optional: true,
Sensitive: true,
Description: "OAuth client secret key, this can be set when token_endpoint_auth_method is client_secret_basic.",
Description: "The user provided OAuth client secret key value, this can be set when token_endpoint_auth_method is client_secret_basic. This does nothing when `omit_secret is set to true.",
},
"token_endpoint_auth_method": {
Type: schema.TypeString,
Expand Down Expand Up @@ -419,10 +419,14 @@ func resourceAppOAuthCreate(ctx context.Context, d *schema.ResourceData, m inter
app := buildAppOAuth(d)
activate := d.Get("status").(string) == statusActive
params := &query.Params{Activate: &activate}
_, _, err := client.Application.CreateApplication(ctx, app, params)
appResp, _, err := client.Application.CreateApplication(ctx, app, params)
if err != nil {
return diag.Errorf("failed to create OAuth application: %v", err)
}
app, err = verifyOidcAppType(appResp)
if err != nil {
return diag.FromErr(err)
}
d.SetId(app.Id)
if !d.Get("omit_secret").(bool) {
_ = d.Set("client_secret", app.Credentials.OauthClient.ClientSecret)
Expand Down Expand Up @@ -534,10 +538,6 @@ func resourceAppOAuthRead(ctx context.Context, d *schema.ResourceData, m interfa
} else {
_ = d.Set("implicit_assignment", false)
}
// If this is ever changed omit it.
if d.Get("omit_secret").(bool) {
_ = d.Set("client_secret", "")
}

c := m.(*Config)
if c.IsOAuth20Auth() {
Expand Down Expand Up @@ -669,11 +669,30 @@ func resourceAppOAuthUpdate(ctx context.Context, d *schema.ResourceData, m inter
return diag.Errorf("failed to create OAuth application: %v", err)
}
app := buildAppOAuth(d)
_, _, err = client.Application.UpdateApplication(ctx, d.Id(), app)
// When omit_secret is true on update, we make sure that we empty the client secret value
// in the api call.
// This is to ensure that when this is "toggled on", the apply which this occurs also does
// not do a final "reset" of the client secret value to the original stored in state.
if d.Get("omit_secret").(bool) {
app.Credentials.OauthClient.ClientSecret = ""
}
appResp, _, err := client.Application.UpdateApplication(ctx, d.Id(), app)
if err != nil {
return diag.Errorf("failed to update OAuth application: %v", err)
}
if !d.Get("omit_secret").(bool) {
app, err = verifyOidcAppType(appResp)
if err != nil {
return diag.FromErr(err)
}

// The `client_secret` value is always returned from the API when it set on update
// Regardless if we pass a value or not.
// We need to make sure that we set the value in state based upon the `omit_secret` behavior
// When `true`: We blank out the secret value
// When `false`: We set the secret value to the value returned from the API
if d.Get("omit_secret").(bool) {
_ = d.Set("client_secret", "")
} else {
_ = d.Set("client_secret", app.Credentials.OauthClient.ClientSecret)
}
if d.HasChange("logo") {
Expand Down Expand Up @@ -931,3 +950,11 @@ func validateAppOAuth(d *schema.ResourceData, m interface{}) error {
}
return nil
}

func verifyOidcAppType(app sdk.App) (*sdk.OpenIdConnectApplication, error) {
oidcApp, ok := app.(*sdk.OpenIdConnectApplication)
if !ok {
return nil, fmt.Errorf("unexpected application response return from Okta: %v", app)
}
return oidcApp, nil
}
32 changes: 32 additions & 0 deletions okta/resource_okta_app_oauth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -865,3 +865,35 @@ func TestAccResourceOktaAppOauth_config_combinations(t *testing.T) {
})
}
}

func TestAccResourceOktaAppOauth_omitSecretSafeEnable(t *testing.T) {
mgr := newFixtureManager("resources", appOAuth, t.Name())
omit_secret_off := mgr.GetFixtures("omit_secret_off.tf", t)
omit_secret_on := mgr.GetFixtures("omit_secret_on.tf", t)
resourceName := fmt.Sprintf("%s.test", appOAuth)

oktaResourceTest(t, resource.TestCase{
PreCheck: testAccPreCheck(t),
ErrorCheck: testAccErrorChecks(t),
ProviderFactories: testAccProvidersFactories,
CheckDestroy: checkResourceDestroy(appOAuth, createDoesAppExist(sdk.NewOpenIdConnectApplication())),
Steps: []resource.TestStep{
{
Config: omit_secret_off,
Check: resource.ComposeTestCheckFunc(
ensureResourceExists(resourceName, createDoesAppExist(sdk.NewOpenIdConnectApplication())),
resource.TestCheckResourceAttrSet(resourceName, "client_id"),
resource.TestCheckResourceAttrSet(resourceName, "client_secret"),
),
},
{
Config: omit_secret_on,
Check: resource.ComposeTestCheckFunc(
ensureResourceExists(resourceName, createDoesAppExist(sdk.NewOpenIdConnectApplication())),
resource.TestCheckResourceAttrSet(resourceName, "client_id"),
resource.TestCheckResourceAttr(resourceName, "client_secret", ""),
),
},
},
})
}
6 changes: 3 additions & 3 deletions website/docs/r/app_oauth.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ The following arguments are supported:

- `auto_submit_toolbar` - (Optional) Display auto submit toolbar.

- `client_basic_secret` - (Optional) OAuth client secret key, this can be set when `token_endpoint_auth_method` is `"client_secret_basic"`.
- `client_basic_secret` - (Optional) The user provided OAuth client secret key value, this can be set when `token_endpoint_auth_method` is `"client_secret_basic"`. This does nothing when `omit_secret` is set to true.

- `client_id` - (Optional) OAuth client ID. If set during creation, app is created with this id. See: https://developer.okta.com/docs/reference/api/apps/#oauth-credential-object

Expand Down Expand Up @@ -130,7 +130,7 @@ Valid values: `"CUSTOM_URL"`,`"ORG_URL"` or `"DYNAMIC"`. Default is `"ORG_URL"`.

- `logo_uri` - (Optional) URI that references a logo for the client.

- `omit_secret` - (Optional) This tells the provider not to persist the application's secret to state. Your app's `client_secret` will be recreated if this ever changes from true => false.
- `omit_secret` - (Optional) This tells the provider not manage the `client_secret` value in state. When this is false (the default), it will cause the auto-generated `client_secret` to be persisted in the `client_secret` attribute in state. This also means that every time an update to this app is run, this value is also set on the API. If this changes from false => true, the `client_secret` is dropped from state and the secret at the time of the apply is what remains. If this is ever changes from true => false your app will be recreated, due to the need to regenerate a secret we can store in state.

- `pkce_required` - (Optional) Require Proof Key for Code Exchange (PKCE) for
additional verification. If `pkce_required` isn't specified when adding a new
Expand Down Expand Up @@ -191,7 +191,7 @@ Valid values: `"CUSTOM_URL"`,`"ORG_URL"` or `"DYNAMIC"`. Default is `"ORG_URL"`.

- `client_id` - The client ID of the application.

- `client_secret` - The client secret of the application. See: https://developer.okta.com/docs/reference/api/apps/#oauth-credential-object
- `client_secret` - OAuth client secret value, this is output only. This will be in plain text in your statefile unless you set omit_secret above. See: https://developer.okta.com/docs/reference/api/apps/#oauth-credential-object

- `id` - ID of the application.

Expand Down

0 comments on commit 341f774

Please sign in to comment.