Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed nil pointers when importing Okta Workflows #616

Merged
merged 2 commits into from
Aug 30, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion okta/app.go
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ func appRead(d *schema.ResourceData, name, status, signOn, label string, accy *o
_ = d.Set("label", label)
_ = d.Set("accessibility_self_service", *accy.SelfService)
_ = d.Set("accessibility_error_redirect_url", accy.ErrorRedirectUrl)
_ = d.Set("accessibility_login_redirect_url", accy.LoginRedirectUrl)
_ = d.Set("auto_submit_toolbar", vis.AutoSubmitToolbar)
_ = d.Set("hide_ios", vis.Hide.IOS)
_ = d.Set("hide_web", vis.Hide.Web)
Expand Down
4 changes: 2 additions & 2 deletions okta/policy_rule.go
Original file line number Diff line number Diff line change
Expand Up @@ -202,13 +202,13 @@ func syncRuleFromUpstream(d *schema.ResourceData, rule *sdk.PolicyRule) error {
_ = d.Set("network_connection", rule.Conditions.Network.Connection)
if rule.Conditions.Network.Connection != "ANYWHERE" {
return setNonPrimitives(d, map[string]interface{}{
"users_excluded": convertStringSliceToSet(rule.Conditions.People.Users.Exclude),
"users_excluded": convertStringSliceToSetNullable(rule.Conditions.People.Users.Exclude),
"network_includes": convertStringArrToInterface(rule.Conditions.Network.Include),
"network_excludes": convertStringArrToInterface(rule.Conditions.Network.Exclude),
})
}
return setNonPrimitives(d, map[string]interface{}{
"users_excluded": convertStringSliceToSet(rule.Conditions.People.Users.Exclude),
"users_excluded": convertStringSliceToSetNullable(rule.Conditions.People.Users.Exclude),
})
}

Expand Down
213 changes: 115 additions & 98 deletions okta/resource_okta_app_oauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ func resourceAppOAuth() *schema.Resource {
Schema: buildAppSchema(map[string]*schema.Schema{
"type": {
Type: schema.TypeString,
ValidateDiagFunc: elemInSlice([]string{"web", "native", "browser", "service"}),
ValidateDiagFunc: elemInSlice([]string{"", "web", "native", "browser", "service"}),
Required: true,
ForceNew: true,
Description: "The type of client application.",
Expand Down Expand Up @@ -328,37 +328,39 @@ func resourceAppOAuth() *schema.Resource {
MaxItems: 1,
Description: "Groups claim for an OpenID Connect client application",
Optional: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"type": {
Description: "Groups claim type.",
Type: schema.TypeString,
Required: true,
ValidateDiagFunc: elemInSlice([]string{"FILTER", "EXPRESSION"}),
},
"filter_type": {
Description: "Groups claim filter. Can only be set if type is FILTER.",
Type: schema.TypeString,
Optional: true,
ValidateDiagFunc: elemInSlice([]string{"EQUALS", "STARTS_WITH", "CONTAINS", "REGEX"}),
},
"name": {
Description: "Name of the claim that will be used in the token.",
Type: schema.TypeString,
Required: true,
},
"value": {
Description: "Value of the claim. Can be an Okta Expression Language statement that evaluates at the time the token is minted.",
Type: schema.TypeString,
Required: true,
},
},
},
Elem: groupsClaimResource,
},
}),
}
}

var groupsClaimResource = &schema.Resource{
Schema: map[string]*schema.Schema{
"type": {
Description: "Groups claim type.",
Type: schema.TypeString,
Required: true,
ValidateDiagFunc: elemInSlice([]string{"FILTER", "EXPRESSION"}),
},
"filter_type": {
Description: "Groups claim filter. Can only be set if type is FILTER.",
Type: schema.TypeString,
Optional: true,
ValidateDiagFunc: elemInSlice([]string{"EQUALS", "STARTS_WITH", "CONTAINS", "REGEX"}),
},
"name": {
Description: "Name of the claim that will be used in the token.",
Type: schema.TypeString,
Required: true,
},
"value": {
Description: "Value of the claim. Can be an Okta Expression Language statement that evaluates at the time the token is minted.",
Type: schema.TypeString,
Required: true,
},
},
}

func resourceAppOAuthCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
client := getOktaClientFromMetadata(m)
if err := validateGrantTypes(d); err != nil {
Expand Down Expand Up @@ -454,18 +456,11 @@ func resourceAppOAuthRead(ctx context.Context, d *schema.ResourceData, m interfa
_ = d.Set("sign_on_mode", app.SignOnMode)
_ = d.Set("label", app.Label)
_ = d.Set("profile", rawProfile)
_ = d.Set("type", app.Settings.OauthClient.ApplicationType)
// Not setting client_secret, it is only provided on create and update for auth methods that require it
_ = d.Set("client_id", app.Credentials.OauthClient.ClientId)
_ = d.Set("token_endpoint_auth_method", app.Credentials.OauthClient.TokenEndpointAuthMethod)
_ = d.Set("auto_key_rotation", app.Credentials.OauthClient.AutoKeyRotation)
_ = d.Set("client_uri", app.Settings.OauthClient.ClientUri)
_ = d.Set("logo_uri", app.Settings.OauthClient.LogoUri)
_ = d.Set("tos_uri", app.Settings.OauthClient.TosUri)
_ = d.Set("policy_uri", app.Settings.OauthClient.PolicyUri)
_ = d.Set("login_uri", app.Settings.OauthClient.InitiateLoginUri)
if app.Settings.OauthClient.WildcardRedirect != "" {
_ = d.Set("wildcard_redirect", app.Settings.OauthClient.WildcardRedirect)
if app.Credentials.OauthClient != nil {
_ = d.Set("client_id", app.Credentials.OauthClient.ClientId)
_ = d.Set("token_endpoint_auth_method", app.Credentials.OauthClient.TokenEndpointAuthMethod)
_ = d.Set("auto_key_rotation", app.Credentials.OauthClient.AutoKeyRotation)
}
_ = d.Set("auto_submit_toolbar", app.Visibility.AutoSubmitToolbar)
_ = d.Set("hide_ios", app.Visibility.Hide.IOS)
Expand All @@ -474,24 +469,70 @@ func resourceAppOAuthRead(ctx context.Context, d *schema.ResourceData, m interfa
if app.Settings.ImplicitAssignment != nil {
_ = d.Set("implicit_assignment", *app.Settings.ImplicitAssignment)
}
if app.Settings.OauthClient.ConsentMethod != "" { // Early Access Property, might be empty
_ = d.Set("consent_method", app.Settings.OauthClient.ConsentMethod)
// If this is ever changed omit it.
if d.Get("omit_secret").(bool) {
_ = d.Set("client_secret", "")
}
if app.Settings.OauthClient.IssuerMode != "" {
_ = d.Set("issuer_mode", app.Settings.OauthClient.IssuerMode)
// When the implicit_assignment is turned on, calls to the user/group assignments will error with a bad request
// So Skip setting assignments while this is on
if !d.Get("implicit_assignment").(bool) {
if err = syncGroupsAndUsers(ctx, app.Id, d, m); err != nil {
return diag.Errorf("failed to sync groups and users for OAuth application: %v", err)
}
}
if app.Settings.OauthClient.RefreshToken != nil {
_ = d.Set("refresh_token_rotation", app.Settings.OauthClient.RefreshToken.RotationType)
_ = d.Set("refresh_token_leeway", app.Settings.OauthClient.RefreshToken.Leeway)
gc, err := flattenGroupsClaim(ctx, d, m)
if err != nil {
return diag.FromErr(err)
}
_ = d.Set("groups_claim", gc)
return setOAuthClientSettings(d, app.Settings.OauthClient)
}

// If this is ever changed omit it.
if d.Get("omit_secret").(bool) {
_ = d.Set("client_secret", "")
func flattenGroupsClaim(ctx context.Context, d *schema.ResourceData, m interface{}) (*schema.Set, error) {
gc, resp, err := getSupplementFromMetadata(m).GetAppOauthGroupsClaim(ctx, d.Id())
if err := suppressErrorOn404(resp, err); err != nil {
return nil, fmt.Errorf("failed to get groups claim for OAuth application: %w", err)
}
if gc == nil || gc.Name == "" {
return nil, nil
}
elem := map[string]interface{}{
"name": gc.Name,
"value": gc.Value,
"type": gc.ValueType,
}
if gc.ValueType == "GROUPS" {
elem["type"] = "FILTER"
elem["filter_type"] = gc.GroupFilterType
}
return schema.NewSet(schema.HashResource(groupsClaimResource), []interface{}{elem}), nil
}

if app.Settings.OauthClient.Jwks != nil {
jwks := app.Settings.OauthClient.Jwks.Keys
func setOAuthClientSettings(d *schema.ResourceData, oauthClient *okta.OpenIdConnectApplicationSettingsClient) diag.Diagnostics {
if oauthClient == nil {
return nil
}
_ = d.Set("type", oauthClient.ApplicationType)
_ = d.Set("client_uri", oauthClient.ClientUri)
_ = d.Set("logo_uri", oauthClient.LogoUri)
_ = d.Set("tos_uri", oauthClient.TosUri)
_ = d.Set("policy_uri", oauthClient.PolicyUri)
_ = d.Set("login_uri", oauthClient.InitiateLoginUri)
if oauthClient.WildcardRedirect != "" {
_ = d.Set("wildcard_redirect", oauthClient.WildcardRedirect)
}
if oauthClient.ConsentMethod != "" { // Early Access Property, might be empty
_ = d.Set("consent_method", oauthClient.ConsentMethod)
}
if oauthClient.IssuerMode != "" {
_ = d.Set("issuer_mode", oauthClient.IssuerMode)
}
if oauthClient.RefreshToken != nil {
_ = d.Set("refresh_token_rotation", oauthClient.RefreshToken.RotationType)
_ = d.Set("refresh_token_leeway", oauthClient.RefreshToken.Leeway)
}
if oauthClient.Jwks != nil {
jwks := oauthClient.Jwks.Keys
arr := make([]map[string]interface{}, len(jwks))
for i, jwk := range jwks {
arr[i] = map[string]interface{}{
Expand All @@ -501,62 +542,34 @@ func resourceAppOAuthRead(ctx context.Context, d *schema.ResourceData, m interfa
"n": jwk.N,
}
}
err = setNonPrimitives(d, map[string]interface{}{"jwks": arr})
err := setNonPrimitives(d, map[string]interface{}{"jwks": arr})
if err != nil {
return diag.Errorf("failed to set OAuth application properties: %v", err)
}
}

respTypes := make([]string, len(app.Settings.OauthClient.ResponseTypes))
for i := range app.Settings.OauthClient.ResponseTypes {
respTypes[i] = string(*app.Settings.OauthClient.ResponseTypes[i])
respTypes := make([]string, len(oauthClient.ResponseTypes))
for i := range oauthClient.ResponseTypes {
respTypes[i] = string(*oauthClient.ResponseTypes[i])
}
grantTypes := make([]string, len(app.Settings.OauthClient.GrantTypes))
for i := range app.Settings.OauthClient.GrantTypes {
grantTypes[i] = string(*app.Settings.OauthClient.GrantTypes[i])
}
// When the implicit_assignment is turned on, calls to the user/group assignments will error with a bad request
// So Skip setting assignments while this is on
if !d.Get("implicit_assignment").(bool) {
if err = syncGroupsAndUsers(ctx, app.Id, d, m); err != nil {
return diag.Errorf("failed to sync groups and users for OAuth application: %v", err)
}
grantTypes := make([]string, len(oauthClient.GrantTypes))
for i := range oauthClient.GrantTypes {
grantTypes[i] = string(*oauthClient.GrantTypes[i])
}
aggMap := map[string]interface{}{
"redirect_uris": convertStringSliceToSet(app.Settings.OauthClient.RedirectUris),
"redirect_uris": convertStringSliceToSet(oauthClient.RedirectUris),
"response_types": convertStringSliceToSet(respTypes),
"grant_types": convertStringSliceToSet(grantTypes),
"post_logout_redirect_uris": convertStringSliceToSet(app.Settings.OauthClient.PostLogoutRedirectUris),
"post_logout_redirect_uris": convertStringSliceToSet(oauthClient.PostLogoutRedirectUris),
}
if app.Settings.OauthClient.IdpInitiatedLogin != nil {
_ = d.Set("login_mode", app.Settings.OauthClient.IdpInitiatedLogin.Mode)
aggMap["login_scopes"] = convertStringSliceToSet(app.Settings.OauthClient.IdpInitiatedLogin.DefaultScope)
if oauthClient.IdpInitiatedLogin != nil {
_ = d.Set("login_mode", oauthClient.IdpInitiatedLogin.Mode)
aggMap["login_scopes"] = convertStringSliceToSet(oauthClient.IdpInitiatedLogin.DefaultScope)
}
err = setNonPrimitives(d, aggMap)
err := setNonPrimitives(d, aggMap)
if err != nil {
return diag.Errorf("failed to set OAuth application properties: %v", err)
}
gc, _, err := getSupplementFromMetadata(m).GetAppOauthGroupsClaim(ctx, d.Id())
if err != nil {
return diag.Errorf("failed to get groups claim for OAuth application: %v", err)
}
if gc.Name != "" {
arr := []map[string]interface{}{
{
"name": gc.Name,
"value": gc.Value,
"type": gc.ValueType,
},
}
if gc.ValueType == "GROUPS" {
arr[0]["type"] = "FILTER"
arr[0]["filter_type"] = gc.GroupFilterType
}
err = setNonPrimitives(d, map[string]interface{}{"groups_claim": arr})
if err != nil {
return diag.Errorf("failed to set OAuth application properties: %v", err)
}
}
return nil
}

Expand Down Expand Up @@ -620,11 +633,13 @@ func buildAppOAuth(d *schema.ResourceData) *okta.OpenIdConnectApplication {

// If grant_types are not set, we default to the bare minimum.
if len(grantTypes) < 1 {
appMap := appGrantTypeMap[appType]
if appMap.RequiredGrantTypes == nil {
grantTypes = appMap.ValidGrantTypes
} else {
grantTypes = appMap.RequiredGrantTypes
appMap, ok := appGrantTypeMap[appType]
if ok {
if appMap.RequiredGrantTypes == nil {
grantTypes = appMap.ValidGrantTypes
} else {
grantTypes = appMap.RequiredGrantTypes
}
}
}

Expand Down Expand Up @@ -737,8 +752,10 @@ func buildAppOAuth(d *schema.ResourceData) *okta.OpenIdConnectApplication {
func validateGrantTypes(d *schema.ResourceData) error {
grantTypeList := convertInterfaceToStringSet(d.Get("grant_types"))
appType := d.Get("type").(string)
appMap := appGrantTypeMap[appType]

appMap, ok := appGrantTypeMap[appType]
if !ok {
return nil
}
// There is some conditional validation around grant types depending on application type.
return conditionalValidator("grant_types", appType, appMap.RequiredGrantTypes, appMap.ValidGrantTypes, grantTypeList)
}
Expand Down
1 change: 1 addition & 0 deletions okta/resource_okta_app_saml.go
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,7 @@ func resourceAppSamlRead(ctx context.Context, d *schema.ResourceData, m interfac
_ = d.Set("entity_key", key)
_ = d.Set("certificate", desc.KeyDescriptors[0].KeyInfo.Certificate)
}
_ = d.Set("accessibility_login_redirect_url", app.Accessibility.LoginRedirectUrl)
appRead(d, app.Name, app.Status, app.SignOnMode, app.Label, app.Accessibility, app.Visibility, app.Settings.Notes)
if app.SignOnMode == "SAML_1_1" {
_ = d.Set("saml_version", saml11)
Expand Down
1 change: 1 addition & 0 deletions okta/resource_okta_app_shared_credentials.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ func resourceAppSharedCredentialsRead(ctx context.Context, d *schema.ResourceDat
_ = d.Set("user_name_template_type", app.Credentials.UserNameTemplate.Type)
_ = d.Set("user_name_template_suffix", app.Credentials.UserNameTemplate.Suffix)
_ = d.Set("logo_url", linksValue(app.Links, "logo", "href"))
_ = d.Set("accessibility_login_redirect_url", app.Accessibility.LoginRedirectUrl)
appRead(d, app.Name, app.Status, app.SignOnMode, app.Label, app.Accessibility, app.Visibility, app.Settings.Notes)
return nil
}
Expand Down
1 change: 1 addition & 0 deletions okta/resource_okta_policy_mfa.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ func buildMFAPolicy(d *schema.ResourceData) sdk.Policy {

func syncFactor(d *schema.ResourceData, k string, f *sdk.PolicyFactor) {
if f == nil {
_ = d.Set(k, nil)
return
}
_ = d.Set(k, map[string]interface{}{
Expand Down