diff --git a/CHANGELOG.md b/CHANGELOG.md index b0bc831b1..1f04adcae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,29 @@ # Changelog +## 3.25.0 (April 21, 2022) + +ENHANCEMENTS: +* Upgrade okta-sdk-golang to v2.12.1. [#1001](https://github.com/okta/terraform-provider-okta/pull/1001). Thanks, [@monde](https://github.com/monde)! + * Removing/Updating local sdk code + * Application.UploadApplicationLogo + * Authenticator + * EnrollFactor + * LinkedObjects + * PasswordPolicy + * ProfileMapping + * Subscription + * UserFactor + * Fixed ACC tests + * TestAccOktaAppSignOnPolicyRule + * TestAccOktaDataSourceIdpSocial_read + * TestAccOktaDefaultPasswordPolicy + * TestAccOktaIdpSocial_crud + * TestAccOktaPolicyPassword_crud + * TestAccOktaPolicySignOn_crud + * TestAccAppOAuthApplication_postLogoutRedirectCrud + * Backoff/retry on application delete +* Update okta_app_saml resource documentation. [#1076](https://github.com/okta/terraform-provider-okta/pull/1076). Thanks, [@jphuynh](https://github.com/jphuynh)! + ## 3.24.0 (April 15, 2022) ENHANCEMENTS: diff --git a/examples/okta_app_oauth_post_logout_redirect_uri/basic.tf b/examples/okta_app_oauth_post_logout_redirect_uri/basic.tf index 7513497c4..5cae2c550 100644 --- a/examples/okta_app_oauth_post_logout_redirect_uri/basic.tf +++ b/examples/okta_app_oauth_post_logout_redirect_uri/basic.tf @@ -13,7 +13,7 @@ resource "okta_app_oauth" "test" { // Since Okta forces us to create it with a redirect URI we have to ignore future changes, they will be detected as config drift. lifecycle { - ignore_changes = [redirect_uris] + ignore_changes = [post_logout_redirect_uris] } } diff --git a/examples/okta_app_oauth_post_logout_redirect_uri/basic_updated.tf b/examples/okta_app_oauth_post_logout_redirect_uri/basic_updated.tf index 55d7031c7..07ff1351e 100644 --- a/examples/okta_app_oauth_post_logout_redirect_uri/basic_updated.tf +++ b/examples/okta_app_oauth_post_logout_redirect_uri/basic_updated.tf @@ -14,7 +14,7 @@ resource "okta_app_oauth" "test" { // Since Okta forces us to create it with a redirect URI we have to ignore future changes, they will be detected as config drift. lifecycle { - ignore_changes = [redirect_uris] + ignore_changes = [post_logout_redirect_uris] } } diff --git a/examples/okta_app_signon_policy_rule/basic_updated.tf b/examples/okta_app_signon_policy_rule/basic_updated.tf index 7cda15495..f46606699 100644 --- a/examples/okta_app_signon_policy_rule/basic_updated.tf +++ b/examples/okta_app_signon_policy_rule/basic_updated.tf @@ -91,14 +91,18 @@ resource "okta_app_signon_policy_rule" "test" { os_type = "MACOS" type = "DESKTOP" } - platform_include { - os_type = "OTHER" - type = "DESKTOP" - } - platform_include { - os_type = "OTHER" - type = "MOBILE" - } +# FIXME Okta API for /api/v1/policies/{policyId}/rules/{ruleId} +# is not returning os_expression even when it has been set throwing off the TF state. +# platform_include { +# os_expression = ".*" +# os_type = "OTHER" +# type = "DESKTOP" +# } +# platform_include { +# os_expression = ".*" +# os_type = "OTHER" +# type = "MOBILE" +# } platform_include { os_type = "WINDOWS" type = "DESKTOP" diff --git a/examples/okta_idp_social/auto_provision_disabled.tf b/examples/okta_idp_social/auto_provision_disabled.tf index 3ddd69eb7..73d87ec4b 100644 --- a/examples/okta_idp_social/auto_provision_disabled.tf +++ b/examples/okta_idp_social/auto_provision_disabled.tf @@ -1,6 +1,6 @@ resource "okta_idp_social" "google" { type = "GOOGLE" - protocol_type = "OAUTH2" + protocol_type = "OIDC" name = "testAcc_google_replace_with_uuid" provisioning_action = "DISABLED" diff --git a/examples/okta_idp_social/basic.tf b/examples/okta_idp_social/basic.tf index 5fee4c090..c62cf23d2 100644 --- a/examples/okta_idp_social/basic.tf +++ b/examples/okta_idp_social/basic.tf @@ -27,7 +27,7 @@ resource "okta_user_schema_property" "schema_custom" { resource "okta_idp_social" "google" { type = "GOOGLE" - protocol_type = "OAUTH2" + protocol_type = "OIDC" name = "testAcc_google_replace_with_uuid" scopes = [ diff --git a/examples/okta_idp_social/datasource.tf b/examples/okta_idp_social/datasource.tf index dc1842d12..0ce256953 100644 --- a/examples/okta_idp_social/datasource.tf +++ b/examples/okta_idp_social/datasource.tf @@ -27,7 +27,7 @@ resource "okta_idp_social" "facebook" { resource "okta_idp_social" "google" { type = "GOOGLE" - protocol_type = "OAUTH2" + protocol_type = "OIDC" name = "testAcc_google_replace_with_uuid" scopes = [ diff --git a/examples/okta_profile_mapping/basic.tf b/examples/okta_profile_mapping/basic.tf index fd527dadf..ac5eb2d6c 100644 --- a/examples/okta_profile_mapping/basic.tf +++ b/examples/okta_profile_mapping/basic.tf @@ -26,7 +26,7 @@ resource "okta_profile_mapping" "test" { resource "okta_idp_social" "google" { type = "GOOGLE" - protocol_type = "OAUTH2" + protocol_type = "OIDC" name = "testAcc_google_replace_with_uuid" scopes = [ diff --git a/examples/okta_profile_mapping/prevent_delete.tf b/examples/okta_profile_mapping/prevent_delete.tf index f74fe583c..b427341a0 100644 --- a/examples/okta_profile_mapping/prevent_delete.tf +++ b/examples/okta_profile_mapping/prevent_delete.tf @@ -51,7 +51,7 @@ resource "okta_profile_mapping" "test" { resource "okta_idp_social" "google" { type = "GOOGLE" - protocol_type = "OAUTH2" + protocol_type = "OIDC" name = "testAcc_google_replace_with_uuid" scopes = [ diff --git a/examples/okta_profile_mapping/updated.tf b/examples/okta_profile_mapping/updated.tf index 4741dde1c..c08278aef 100644 --- a/examples/okta_profile_mapping/updated.tf +++ b/examples/okta_profile_mapping/updated.tf @@ -31,7 +31,7 @@ resource "okta_profile_mapping" "test" { resource "okta_idp_social" "google" { type = "GOOGLE" - protocol_type = "OAUTH2" + protocol_type = "OIDC" name = "testAcc_google_replace_with_uuid" scopes = [ diff --git a/go.mod b/go.mod index 1071cd4c1..7517e1fb6 100644 --- a/go.mod +++ b/go.mod @@ -3,6 +3,7 @@ module github.com/okta/terraform-provider-okta go 1.17 require ( + github.com/cenkalti/backoff v2.2.1+incompatible github.com/cenkalti/backoff/v4 v4.1.3 github.com/crewjam/saml v0.4.6 github.com/hashicorp/go-cleanhttp v0.5.2 @@ -10,7 +11,7 @@ require ( github.com/hashicorp/go-hclog v1.2.0 github.com/hashicorp/go-retryablehttp v0.7.1 github.com/hashicorp/terraform-plugin-sdk/v2 v2.14.0 - github.com/okta/okta-sdk-golang/v2 v2.9.3-0.20211209083930-a123a8c6e20d + github.com/okta/okta-sdk-golang/v2 v2.12.1-0.20220418232441-a4b5722f6e4f ) require ( diff --git a/go.sum b/go.sum index e85520f1f..603768a85 100644 --- a/go.sum +++ b/go.sum @@ -30,7 +30,9 @@ github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkE github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/beevik/etree v1.1.0 h1:T0xke/WvNtMoCqgzPhkX2r4rjY3GDZFi+FjpRZY2Jbs= github.com/beevik/etree v1.1.0/go.mod h1:r8Aw8JqVegEf0w2fDnATrX9VpkMcyFeM0FhwO62wh+A= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= +github.com/cenkalti/backoff v2.2.1+incompatible h1:tNowT99t7UNflLxfYYSlKYsBpXdEet03Pg2g16Swow4= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.3 h1:cFAlzYUlVYDysBEH2T5hyJZMh3+5+WCBvSnK6Q8UtC4= github.com/cenkalti/backoff/v4 v4.1.3/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= @@ -163,7 +165,7 @@ github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87 h1:xixZ2bWeofWV68J github.com/hashicorp/yamux v0.0.0-20211028200310-0bc27b27de87/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/jarcoal/httpmock v1.0.8/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= +github.com/jarcoal/httpmock v1.0.7/go.mod h1:ATjnClrvW/3tijVmpL/va5Z3aAyGvqU3gCT8nX0Txik= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4= @@ -220,8 +222,8 @@ github.com/nsf/jsondiff v0.0.0-20200515183724-f29ed568f4ce/go.mod h1:uFMI8w+ref4 github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= -github.com/okta/okta-sdk-golang/v2 v2.9.3-0.20211209083930-a123a8c6e20d h1:eXkHa6fD88r12g1xQskQ7pDxBx4dW6jU8FMWlMuutCw= -github.com/okta/okta-sdk-golang/v2 v2.9.3-0.20211209083930-a123a8c6e20d/go.mod h1:UhdEFuTLCIJirz6x4zGjsuwQl1xhCLKizNyj/h14tFA= +github.com/okta/okta-sdk-golang/v2 v2.12.1-0.20220418232441-a4b5722f6e4f h1:sI7Kn1I17DoJbZEd6zQMmEZ2RR4Ek40siBvgS+CmFZQ= +github.com/okta/okta-sdk-golang/v2 v2.12.1-0.20220418232441-a4b5722f6e4f/go.mod h1:KRoAArk1H216oiRnQT77UN6JAhBOnOWkK27yA1SM7FQ= github.com/patrickmn/go-cache v0.0.0-20180815053127-5633e0862627 h1:pSCLCl6joCFRnjpeojzOpEYs4q7Vditq8fySFG5ap3Y= github.com/patrickmn/go-cache v0.0.0-20180815053127-5633e0862627/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -407,6 +409,7 @@ gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= diff --git a/okta/app.go b/okta/app.go index 6d72c661a..8d74bf17d 100644 --- a/okta/app.go +++ b/okta/app.go @@ -13,7 +13,9 @@ import ( "os" "strings" "sync" + "time" + "github.com/cenkalti/backoff" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/okta/okta-sdk-golang/v2/okta" "github.com/okta/okta-sdk-golang/v2/okta/query" @@ -435,7 +437,7 @@ func handleAppLogo(ctx context.Context, d *schema.ResourceData, m interface{}, a if !ok { return nil } - _, err := getSupplementFromMetadata(m).UploadAppLogo(ctx, appID, l.(string)) + _, err := getOktaClientFromMetadata(m).Application.UploadApplicationLogo(ctx, appID, l.(string)) return err } @@ -683,7 +685,17 @@ func deleteApplication(ctx context.Context, d *schema.ResourceData, m interface{ return err } } - _, err := client.Application.DeleteApplication(ctx, d.Id()) + + // Okta Core can have eventual consistency issues when deactivating an app + // which is required before deleting the app. + b := backoff.NewExponentialBackOff() + b.MaxElapsedTime = 5 * time.Second + + err := backoff.Retry(func() error { + _, err := client.Application.DeleteApplication(ctx, d.Id()) + return err + }, b) + return err } diff --git a/okta/config.go b/okta/config.go index c691aea67..f5a7ded1d 100644 --- a/okta/config.go +++ b/okta/config.go @@ -101,7 +101,7 @@ func (c *Config) loadAndValidate(ctx context.Context) error { okta.WithRateLimitMaxBackOff(int64(c.maxWait)), okta.WithRequestTimeout(int64(c.requestTimeout)), okta.WithRateLimitMaxRetries(int32(c.retryCount)), - okta.WithUserAgentExtra("okta-terraform/3.23.0"), + okta.WithUserAgentExtra("okta-terraform/3.25.0"), } if c.apiToken == "" { setters = append(setters, okta.WithAuthorizationMode("PrivateKey")) diff --git a/okta/data_source_okta_app_signon_policy.go b/okta/data_source_okta_app_signon_policy.go index f890ad610..cf0fd7b3f 100644 --- a/okta/data_source_okta_app_signon_policy.go +++ b/okta/data_source_okta_app_signon_policy.go @@ -37,10 +37,12 @@ func dataSourceAppSignOnPolicyRead(ctx context.Context, d *schema.ResourceData, if accessPolicy == "" { return diag.Errorf("app does not support sign-on policy or this feature is not available") } - policy, _, err := getOktaClientFromMetadata(m).Policy.GetPolicy(ctx, path.Base(accessPolicy), nil) + policy := &okta.Policy{} + _policy, _, err := getOktaClientFromMetadata(m).Policy.GetPolicy(ctx, path.Base(accessPolicy), policy, nil) if err != nil { return diag.Errorf("failed get policy by ID: %v", err) } + policy = _policy.(*okta.Policy) d.SetId(policy.Id) _ = d.Set("name", policy.Name) return nil diff --git a/okta/data_source_okta_authenticator.go b/okta/data_source_okta_authenticator.go index 7bc256311..2d3122b95 100644 --- a/okta/data_source_okta_authenticator.go +++ b/okta/data_source_okta_authenticator.go @@ -7,7 +7,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/okta/terraform-provider-okta/sdk" + "github.com/okta/okta-sdk-golang/v2/okta" ) func dataSourceAuthenticator() *schema.Resource { @@ -78,18 +78,18 @@ func dataSourceAuthenticatorRead(ctx context.Context, d *schema.ResourceData, m return diag.Errorf("config must provide either 'id', 'name' or 'key' to retrieve the authenticator") } var ( - authenticator *sdk.Authenticator + authenticator *okta.Authenticator err error ) if id != "" { - authenticator, _, err = getSupplementFromMetadata(m).GetAuthenticator(ctx, id) + authenticator, _, err = getOktaClientFromMetadata(m).Authenticator.GetAuthenticator(ctx, id) } else { authenticator, err = findAuthenticator(ctx, m, name, key) } if err != nil { return diag.FromErr(err) } - d.SetId(authenticator.ID) + d.SetId(authenticator.Id) _ = d.Set("key", authenticator.Key) _ = d.Set("name", authenticator.Name) _ = d.Set("status", authenticator.Status) @@ -102,7 +102,7 @@ func dataSourceAuthenticatorRead(ctx context.Context, d *schema.ResourceData, m _ = d.Set("provider_type", authenticator.Provider.Type) _ = d.Set("provider_hostname", authenticator.Provider.Configuration.HostName) _ = d.Set("provider_auth_port", authenticator.Provider.Configuration.AuthPort) - _ = d.Set("provider_instance_id", authenticator.Provider.Configuration.InstanceID) + _ = d.Set("provider_instance_id", authenticator.Provider.Configuration.InstanceId) if authenticator.Provider.Configuration.UserNameTemplate != nil { _ = d.Set("provider_user_name_template", authenticator.Provider.Configuration.UserNameTemplate.Template) } @@ -110,8 +110,8 @@ func dataSourceAuthenticatorRead(ctx context.Context, d *schema.ResourceData, m return nil } -func findAuthenticator(ctx context.Context, m interface{}, name, key string) (*sdk.Authenticator, error) { - authenticators, _, err := getSupplementFromMetadata(m).ListAuthenticators(ctx) +func findAuthenticator(ctx context.Context, m interface{}, name, key string) (*okta.Authenticator, error) { + authenticators, _, err := getOktaClientFromMetadata(m).Authenticator.ListAuthenticators(ctx) if err != nil { return nil, err } diff --git a/okta/data_source_okta_role_subscription.go b/okta/data_source_okta_role_subscription.go index 254a0d4c7..78b68388d 100644 --- a/okta/data_source_okta_role_subscription.go +++ b/okta/data_source_okta_role_subscription.go @@ -34,7 +34,7 @@ func dataSourceRoleSubscription() *schema.Resource { } func dataSourceRoleSubscriptionRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - subscription, _, err := getSupplementFromMetadata(m).GetRoleTypeSubscription(ctx, d.Get("role_type").(string), d.Get("notification_type").(string)) + subscription, _, err := getOktaClientFromMetadata(m).Subscription.GetRoleSubscriptionByNotificationType(ctx, d.Get("role_type").(string), d.Get("notification_type").(string)) if err != nil { return diag.Errorf("failed get subscription: %v", err) } diff --git a/okta/data_source_okta_user_profile_mapping_source.go b/okta/data_source_okta_user_profile_mapping_source.go index 311969d8c..bc7b92224 100644 --- a/okta/data_source_okta_user_profile_mapping_source.go +++ b/okta/data_source_okta_user_profile_mapping_source.go @@ -30,12 +30,38 @@ func dataSourceUserProfileMappingSource() *schema.Resource { } func dataSourceUserProfileMappingSourceRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - mapping, err := getSupplementFromMetadata(m).FindProfileMappingSource(ctx, "user", "user", &query.Params{Limit: defaultPaginationLimit}) + mappings, resp, err := getOktaClientFromMetadata(m).ProfileMapping.ListProfileMappings(ctx, &query.Params{Limit: defaultPaginationLimit}) if err != nil { - return diag.Errorf("failed to find profile mapping source: %v", err) + return diag.Errorf("failed to list mappings: %v", err) } - d.SetId(mapping.ID) - _ = d.Set("type", mapping.Type) - _ = d.Set("name", mapping.Name) + name := "user" + typ := "user" + for { + for _, mapping := range mappings { + target := mapping.Target + source := mapping.Source + if target.Name == name && target.Type == typ { + d.SetId(target.Id) + _ = d.Set("type", target.Type) + _ = d.Set("name", target.Name) + return nil + } else if source.Name == name && source.Type == typ { + d.SetId(source.Id) + _ = d.Set("type", source.Type) + _ = d.Set("name", source.Name) + return nil + } + } + if resp.HasNextPage() { + resp, err = resp.Next(ctx, &mappings) + if err != nil { + return diag.Errorf("failed to find profile mapping source: %v", err) + } + continue + } else { + break + } + } + return nil } diff --git a/okta/policy.go b/okta/policy.go index c543c03ee..154079008 100644 --- a/okta/policy.go +++ b/okta/policy.go @@ -96,7 +96,8 @@ func findPolicy(ctx context.Context, m interface{}, name, policyType string) (*o return nil, fmt.Errorf("failed to list policies: %v", err) } for { - for _, policy := range policies { + for _, _policy := range policies { + policy := _policy.(*okta.Policy) if policy.Name == name { return policy, nil } diff --git a/okta/resource_okta_admin_role_targets.go b/okta/resource_okta_admin_role_targets.go index b5da4ab2b..68da7f520 100644 --- a/okta/resource_okta_admin_role_targets.go +++ b/okta/resource_okta_admin_role_targets.go @@ -211,7 +211,7 @@ func removeAllTargets(ctx context.Context, d *schema.ResourceData, m interface{} } ctx = context.WithValue(ctx, retryOnStatusCodes, []int{http.StatusConflict, http.StatusBadRequest}) role, _, err := getOktaClientFromMetadata(m).User.AssignRoleToUser(ctx, d.Get("user_id").(string), - &okta.AssignRoleRequest{Type: d.Get("role_type").(string)}, nil) + okta.AssignRoleRequest{Type: d.Get("role_type").(string)}, nil) if err != nil { d.SetId("") return "", fmt.Errorf("failed to assign '%s' role back to user: %v", d.Get("role_type").(string), err) diff --git a/okta/resource_okta_app_group_assignment.go b/okta/resource_okta_app_group_assignment.go index cbe4b99b6..c12d2ecdb 100644 --- a/okta/resource_okta_app_group_assignment.go +++ b/okta/resource_okta_app_group_assignment.go @@ -155,8 +155,7 @@ func buildAppGroupAssignment(d *schema.ResourceData) okta.ApplicationGroupAssign } p, ok := d.GetOk("priority") if ok { - priority := int64(p.(int)) - assignment.Priority = &priority + assignment.Priority = int64(p.(int)) } return assignment } diff --git a/okta/resource_okta_app_group_assignments.go b/okta/resource_okta_app_group_assignments.go index dbc02872c..1fb5bde08 100644 --- a/okta/resource_okta_app_group_assignments.go +++ b/okta/resource_okta_app_group_assignments.go @@ -179,8 +179,8 @@ func syncGroups(d *schema.ResourceData, groups []interface{}, assignments []*okt for _, assignment := range assignments { if assignment.Id == d.Get(fmt.Sprintf("group.%d.id", i)).(string) { present = true - if assignment.Priority != nil { - groups[i].(map[string]interface{})["priority"] = int(*assignment.Priority) + if assignment.Priority >= 0 { + groups[i].(map[string]interface{})["priority"] = assignment.Priority } groups[i].(map[string]interface{})["profile"] = buildProfile(d, i, assignment) } @@ -238,7 +238,7 @@ func containsAssignment(assignments []*okta.ApplicationGroupAssignment, assignme func containsEqualAssignment(assignments []*okta.ApplicationGroupAssignment, assignment *okta.ApplicationGroupAssignment) bool { for i := range assignments { if assignments[i].Id == assignment.Id && reflect.DeepEqual(assignments[i].Profile, assignment.Profile) { - if assignment.Priority != nil { + if assignment.Priority >= 0 { return reflect.DeepEqual(assignments[i].Priority, assignment.Priority) } return true @@ -272,8 +272,7 @@ func tfGroupsToGroupAssignments(d *schema.ResourceData) []*okta.ApplicationGroup } priority, ok := d.GetOk(fmt.Sprintf("group.%d.priority", i)) if ok { - p := int64(priority.(int)) - a.Priority = &p + a.Priority = int64(priority.(int)) } assignments[i] = a } diff --git a/okta/resource_okta_app_oauth_post_logout_redirect_uri_test.go b/okta/resource_okta_app_oauth_post_logout_redirect_uri_test.go index afdf5b2fc..79fef67ce 100644 --- a/okta/resource_okta_app_oauth_post_logout_redirect_uri_test.go +++ b/okta/resource_okta_app_oauth_post_logout_redirect_uri_test.go @@ -52,8 +52,8 @@ func TestAccAppOAuthApplication_postLogoutRedirectCrud(t *testing.T) { Config: config, Check: resource.ComposeTestCheckFunc( createPostLogoutRedirectURIExists(resourceName), - resource.TestCheckResourceAttr(resourceName, "id", "https://www.example.com"), - resource.TestCheckResourceAttr(resourceName, "uri", "https://www.example.com"), + resource.TestCheckResourceAttr(resourceName, "id", "http://google.com"), + resource.TestCheckResourceAttr(resourceName, "uri", "http://google.com"), resource.TestCheckResourceAttrSet(resourceName, "app_id"), ), }, diff --git a/okta/resource_okta_app_signon_policy_rule.go b/okta/resource_okta_app_signon_policy_rule.go index fa96a0cda..892a532ba 100644 --- a/okta/resource_okta_app_signon_policy_rule.go +++ b/okta/resource_okta_app_signon_policy_rule.go @@ -373,12 +373,10 @@ func buildAccessPolicyPlatformInclude(d *schema.ResourceData) []*okta.PlatformCo valueList := v.(*schema.Set).List() for _, item := range valueList { if value, ok := item.(map[string]interface{}); ok { - var expr *string + var expr string if typ := getMapString(value, "os_type"); typ == "OTHER" { if v := getMapString(value, "os_expression"); v != "" { - expr = &v - } else { - expr = stringPtr("") + expr = v } } includeList = append(includeList, &okta.PlatformConditionEvaluatorPlatform{ @@ -398,8 +396,8 @@ func flattenAccessPolicyPlatformInclude(platform *okta.PlatformPolicyRuleConditi if platform != nil && platform.Include != nil { for _, v := range platform.Include { var expr string - if v.Os.Expression != nil { - expr = *v.Os.Expression + if v.Os.Expression != "" { + expr = v.Os.Expression } flattened = append(flattened, map[string]interface{}{ "os_expression": expr, diff --git a/okta/resource_okta_app_signon_policy_rule_test.go b/okta/resource_okta_app_signon_policy_rule_test.go index 242cdb3ac..35ef1734f 100644 --- a/okta/resource_okta_app_signon_policy_rule_test.go +++ b/okta/resource_okta_app_signon_policy_rule_test.go @@ -60,7 +60,7 @@ func TestAccOktaAppSignOnPolicyRule(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "network_includes.#", "1"), resource.TestCheckResourceAttr(resourceName, "network_excludes.#", "0"), resource.TestCheckResourceAttr(resourceName, "network_connection", "ZONE"), - resource.TestCheckResourceAttr(resourceName, "platform_include.#", "6"), + resource.TestCheckResourceAttr(resourceName, "platform_include.#", "4"), resource.TestCheckResourceAttr(resourceName, "re_authentication_frequency", "PT43800H"), resource.TestCheckResourceAttr(resourceName, "type", "ASSURANCE"), resource.TestCheckResourceAttr(resourceName, "constraints.#", "2"), diff --git a/okta/resource_okta_authenticator.go b/okta/resource_okta_authenticator.go index e83dc617c..04a734ad3 100644 --- a/okta/resource_okta_authenticator.go +++ b/okta/resource_okta_authenticator.go @@ -7,6 +7,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" + "github.com/okta/okta-sdk-golang/v2/okta" "github.com/okta/terraform-provider-okta/sdk" ) @@ -102,13 +103,13 @@ func resourceAuthenticatorCreate(ctx context.Context, d *schema.ResourceData, m if err != nil { return diag.FromErr(err) } - d.SetId(authenticator.ID) + d.SetId(authenticator.Id) status, ok := d.GetOk("status") if ok && authenticator.Status != status.(string) { if status.(string) == statusInactive { - _, _, err = getSupplementFromMetadata(m).DeactivateAuthenticator(ctx, d.Id()) + _, _, err = getOktaClientFromMetadata(m).Authenticator.DeactivateAuthenticator(ctx, d.Id()) } else { - _, _, err = getSupplementFromMetadata(m).ActivateAuthenticator(ctx, d.Id()) + _, _, err = getOktaClientFromMetadata(m).Authenticator.ActivateAuthenticator(ctx, d.Id()) } if err != nil { return diag.Errorf("failed to change authenticator status: %v", err) @@ -118,7 +119,7 @@ func resourceAuthenticatorCreate(ctx context.Context, d *schema.ResourceData, m } func resourceAuthenticatorRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - authenticator, resp, err := getSupplementFromMetadata(m).GetAuthenticator(ctx, d.Id()) + authenticator, resp, err := getOktaClientFromMetadata(m).Authenticator.GetAuthenticator(ctx, d.Id()) if err := suppressErrorOn404(resp, err); err != nil { return diag.Errorf("failed to get authenticator: %v", err) } @@ -139,7 +140,7 @@ func resourceAuthenticatorRead(ctx context.Context, d *schema.ResourceData, m in _ = d.Set("provider_type", authenticator.Provider.Type) _ = d.Set("provider_hostname", authenticator.Provider.Configuration.HostName) _ = d.Set("provider_auth_port", authenticator.Provider.Configuration.AuthPort) - _ = d.Set("provider_instance_id", authenticator.Provider.Configuration.InstanceID) + _ = d.Set("provider_instance_id", authenticator.Provider.Configuration.InstanceId) if authenticator.Provider.Configuration.UserNameTemplate != nil { _ = d.Set("provider_user_name_template", authenticator.Provider.Configuration.UserNameTemplate.Template) } @@ -152,16 +153,16 @@ func resourceAuthenticatorUpdate(ctx context.Context, d *schema.ResourceData, m if err != nil { return diag.FromErr(err) } - _, _, err = getSupplementFromMetadata(m).UpdateAuthenticator(ctx, d.Id(), buildAuthenticator(d)) + _, _, err = getOktaClientFromMetadata(m).Authenticator.UpdateAuthenticator(ctx, d.Id(), *buildAuthenticator(d)) if err != nil { return diag.Errorf("failed to update authenticator: %v", err) } oldStatus, newStatus := d.GetChange("status") if oldStatus != newStatus { if newStatus == statusActive { - _, _, err = getSupplementFromMetadata(m).ActivateAuthenticator(ctx, d.Id()) + _, _, err = getOktaClientFromMetadata(m).Authenticator.ActivateAuthenticator(ctx, d.Id()) } else { - _, _, err = getSupplementFromMetadata(m).DeactivateAuthenticator(ctx, d.Id()) + _, _, err = getOktaClientFromMetadata(m).Authenticator.DeactivateAuthenticator(ctx, d.Id()) } if err != nil { return diag.Errorf("failed to change authenticator status: %v", err) @@ -175,34 +176,34 @@ func resourceAuthenticatorDelete(ctx context.Context, d *schema.ResourceData, m return nil } -func buildAuthenticator(d *schema.ResourceData) sdk.Authenticator { - authenticator := sdk.Authenticator{ +func buildAuthenticator(d *schema.ResourceData) *okta.Authenticator { + authenticator := okta.Authenticator{ Type: d.Get("type").(string), - ID: d.Id(), + Id: d.Id(), Key: d.Get("key").(string), Name: d.Get("name").(string), } if d.Get("type").(string) == "security_key" { - authenticator.Provider = &sdk.AuthenticatorProvider{ + authenticator.Provider = &okta.AuthenticatorProvider{ Type: d.Get("provider_type").(string), - Configuration: &sdk.AuthenticatorProviderConfiguration{ + Configuration: &okta.AuthenticatorProviderConfiguration{ HostName: d.Get("provider_hostname").(string), - AuthPort: d.Get("provider_auth_port").(int), - InstanceID: d.Get("provider_instance_id").(string), + AuthPort: d.Get("provider_auth_port").(int64), + InstanceId: d.Get("provider_instance_id").(string), SharedSecret: d.Get("provider_shared_secret").(string), - UserNameTemplate: &sdk.AuthenticatorProviderConfigurationUserNameTemplate{ + UserNameTemplate: &okta.AuthenticatorProviderConfigurationUserNamePlate{ Template: "", }, }, } } else { - var settings sdk.AuthenticatorSettings + var settings okta.AuthenticatorSettings if s, ok := d.GetOk("settings"); ok { _ = json.Unmarshal([]byte(s.(string)), &settings) } authenticator.Settings = &settings } - return authenticator + return &authenticator } func validateAuthenticator(d *schema.ResourceData) error { diff --git a/okta/resource_okta_group_custom_schema_property.go b/okta/resource_okta_group_custom_schema_property.go index f402b6da8..6c688fa94 100644 --- a/okta/resource_okta_group_custom_schema_property.go +++ b/okta/resource_okta_group_custom_schema_property.go @@ -180,10 +180,10 @@ func syncCustomGroupSchema(d *schema.ResourceData, subschema *okta.GroupSchemaAt if subschema.Items != nil { _ = d.Set("array_type", subschema.Items.Type) _ = d.Set("array_one_of", flattenOneOf(subschema.Items.OneOf)) - _ = d.Set("array_enum", flattenEnum(subschema.Items.Enum)) + _ = d.Set("array_enum", strToInterfaceSlice(subschema.Items.Enum)) } if len(subschema.Enum) > 0 { - _ = d.Set("enum", flattenEnum(subschema.Enum)) + _ = d.Set("enum", strToInterfaceSlice(subschema.Enum)) } return setNonPrimitives(d, map[string]interface{}{ "one_of": flattenOneOf(subschema.OneOf), @@ -224,12 +224,9 @@ func buildGroupCustomSchemaAttribute(d *schema.ResourceData) (*okta.GroupSchemaA return nil, err } } - var enum []interface{} + var enum []string if rawEnum, ok := d.GetOk("enum"); ok { - enum, err = buildEnum(rawEnum.([]interface{}), d.Get("type").(string)) - if err != nil { - return nil, err - } + enum = buildStringSlice(rawEnum.([]interface{})) } return &okta.GroupSchemaAttribute{ Title: d.Get("title").(string), diff --git a/okta/resource_okta_group_role.go b/okta/resource_okta_group_role.go index f2cabf7f9..81f1eb9f9 100644 --- a/okta/resource_okta_group_role.go +++ b/okta/resource_okta_group_role.go @@ -92,7 +92,7 @@ func resourceGroupRoleCreate(ctx context.Context, d *schema.ResourceData, m inte roleType := d.Get("role_type").(string) client := getOktaClientFromMetadata(m) logger(m).Info("assigning role to group", "group_id", groupID, "role_type", roleType) - role, _, err := client.Group.AssignRoleToGroup(ctx, groupID, &okta.AssignRoleRequest{Type: roleType}, + role, _, err := client.Group.AssignRoleToGroup(ctx, groupID, okta.AssignRoleRequest{Type: roleType}, &query.Params{DisableNotifications: boolPtr(d.Get("disable_notifications").(bool))}) if err != nil { return diag.Errorf("failed to assign role %s to group %s: %v", roleType, groupID, err) @@ -173,7 +173,7 @@ func resourceGroupRoleUpdate(ctx context.Context, d *schema.ResourceData, m inte roleType := d.Get("role_type").(string) client := getOktaClientFromMetadata(m) if d.HasChange("disable_notifications") { - _, _, err := client.Group.AssignRoleToGroup(ctx, groupID, nil, + _, _, err := client.Group.AssignRoleToGroup(ctx, groupID, okta.AssignRoleRequest{}, &query.Params{DisableNotifications: boolPtr(d.Get("disable_notifications").(bool))}) if err != nil { return diag.Errorf("failed to update group's '%s' notification settings: %v", groupID, err) diff --git a/okta/resource_okta_group_roles.go b/okta/resource_okta_group_roles.go index 5839a11ca..29bb05a45 100644 --- a/okta/resource_okta_group_roles.go +++ b/okta/resource_okta_group_roles.go @@ -46,7 +46,7 @@ func resourceGroupRolesCreate(ctx context.Context, d *schema.ResourceData, m int groupID := d.Get("group_id").(string) adminRoles := convertInterfaceToStringSet(d.Get("admin_roles")) for _, role := range adminRoles { - _, _, err := getOktaClientFromMetadata(m).Group.AssignRoleToGroup(ctx, groupID, &okta.AssignRoleRequest{Type: role}, nil) + _, _, err := getOktaClientFromMetadata(m).Group.AssignRoleToGroup(ctx, groupID, okta.AssignRoleRequest{Type: role}, nil) if err != nil { return diag.Errorf("failed to assign role %s to group %s: %v", role, groupID, err) } @@ -79,7 +79,7 @@ func resourceGroupRolesUpdate(ctx context.Context, d *schema.ResourceData, m int adminRoles := convertInterfaceToStringSet(d.Get("admin_roles")) rolesToAdd, rolesToRemove := splitRoles(existingRoles, adminRoles) for _, role := range rolesToAdd { - _, _, err := client.Group.AssignRoleToGroup(ctx, groupID, &okta.AssignRoleRequest{Type: role}, nil) + _, _, err := client.Group.AssignRoleToGroup(ctx, groupID, okta.AssignRoleRequest{Type: role}, nil) if err != nil { return diag.Errorf("failed to assign role %s to group %s: %v", role, groupID, err) } diff --git a/okta/resource_okta_idp_oidc.go b/okta/resource_okta_idp_oidc.go index 6f4f94089..cfb1fe808 100644 --- a/okta/resource_okta_idp_oidc.go +++ b/okta/resource_okta_idp_oidc.go @@ -126,12 +126,12 @@ func resourceIdpRead(ctx context.Context, d *schema.ResourceData, m interface{}) if idp.IssuerMode != "" { _ = d.Set("issuer_mode", idp.IssuerMode) } - mapping, _, err := getSupplementFromMetadata(m).GetProfileMappingBySourceID(ctx, idp.Id, "") + mapping, _, err := getProfileMappingBySourceID(ctx, idp.Id, "", m) if err != nil { return diag.Errorf("failed to get identity provider profile mapping: %v", err) } if mapping != nil { - _ = d.Set("user_type_id", mapping.Target.ID) + _ = d.Set("user_type_id", mapping.Target.Id) } setMap := map[string]interface{}{ "scopes": convertStringSliceToSet(idp.Protocol.Scopes), diff --git a/okta/resource_okta_idp_saml.go b/okta/resource_okta_idp_saml.go index 071530264..91c3e5078 100644 --- a/okta/resource_okta_idp_saml.go +++ b/okta/resource_okta_idp_saml.go @@ -140,12 +140,12 @@ func resourceIdpSamlRead(ctx context.Context, d *schema.ResourceData, m interfac if idp.IssuerMode != "" { _ = d.Set("issuer_mode", idp.IssuerMode) } - mapping, _, err := getSupplementFromMetadata(m).GetProfileMappingBySourceID(ctx, idp.Id, "") + mapping, _, err := getProfileMappingBySourceID(ctx, idp.Id, "", m) if err != nil { return diag.Errorf("failed to get SAML identity provider profile mapping: %v", err) } if mapping != nil { - _ = d.Set("user_type_id", mapping.Target.ID) + _ = d.Set("user_type_id", mapping.Target.Id) } setMap := map[string]interface{}{ "subject_format": convertStringSliceToSet(idp.Policy.Subject.Format), diff --git a/okta/resource_okta_idp_social.go b/okta/resource_okta_idp_social.go index c34ecfd16..db52c5cf2 100644 --- a/okta/resource_okta_idp_social.go +++ b/okta/resource_okta_idp_social.go @@ -199,12 +199,12 @@ func buildIdPSocial(d *schema.ResourceData) okta.IdentityProvider { } if idp.Type == "APPLE" { idp.Protocol.Credentials.Signing = &okta.IdentityProviderCredentialsSigning{ - Kid: nil, + Kid: "", PrivateKey: d.Get("apple_private_key").(string), TeamId: d.Get("apple_team_id").(string), } if kid, ok := d.GetOk("apple_kid"); ok { - idp.Protocol.Credentials.Signing.Kid = stringPtr(kid.(string)) + idp.Protocol.Credentials.Signing.Kid = kid.(string) } } return idp diff --git a/okta/resource_okta_idp_social_test.go b/okta/resource_okta_idp_social_test.go index 93297ab7d..2b412beaa 100644 --- a/okta/resource_okta_idp_social_test.go +++ b/okta/resource_okta_idp_social_test.go @@ -42,7 +42,7 @@ func TestAccOktaIdpSocial_crud(t *testing.T) { resource.TestCheckResourceAttr(microName, "groups_assignment.#", "1"), resource.TestCheckResourceAttr(googleName, "type", "GOOGLE"), - resource.TestCheckResourceAttr(googleName, "protocol_type", "OAUTH2"), + resource.TestCheckResourceAttr(googleName, "protocol_type", "OIDC"), resource.TestCheckResourceAttr(googleName, "name", fmt.Sprintf("testAcc_google_%d", ri)), resource.TestCheckResourceAttr(googleName, "client_id", "abcd123"), resource.TestCheckResourceAttr(googleName, "client_secret", "abcd123"), @@ -53,7 +53,7 @@ func TestAccOktaIdpSocial_crud(t *testing.T) { Config: disabledConf, Check: resource.ComposeTestCheckFunc( resource.TestCheckResourceAttr(googleName, "type", "GOOGLE"), - resource.TestCheckResourceAttr(googleName, "protocol_type", "OAUTH2"), + resource.TestCheckResourceAttr(googleName, "protocol_type", "OIDC"), resource.TestCheckResourceAttr(googleName, "name", fmt.Sprintf("testAcc_google_%d", ri)), resource.TestCheckResourceAttr(googleName, "client_id", "abcd123"), resource.TestCheckResourceAttr(googleName, "client_secret", "abcd123"), diff --git a/okta/resource_okta_link_definition.go b/okta/resource_okta_link_definition.go index 0c932d2a0..f8583efbf 100644 --- a/okta/resource_okta_link_definition.go +++ b/okta/resource_okta_link_definition.go @@ -5,7 +5,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/okta/terraform-provider-okta/sdk" + "github.com/okta/okta-sdk-golang/v2/okta" ) func resourceLinkDefinition() *schema.Resource { @@ -56,21 +56,21 @@ func resourceLinkDefinition() *schema.Resource { } func resourceLinkDefinitionCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - linkedObject := sdk.LinkedObject{ - Primary: &sdk.LinkedObjectPart{ + linkedObject := okta.LinkedObject{ + Primary: &okta.LinkedObjectDetails{ Name: d.Get("primary_name").(string), Title: d.Get("primary_title").(string), Description: d.Get("primary_description").(string), Type: "USER", }, - Associated: &sdk.LinkedObjectPart{ + Associated: &okta.LinkedObjectDetails{ Name: d.Get("associated_name").(string), Title: d.Get("associated_title").(string), Description: d.Get("associated_description").(string), Type: "USER", }, } - _, _, err := getSupplementFromMetadata(m).CreateLinkedObject(ctx, linkedObject) + _, _, err := getOktaClientFromMetadata(m).LinkedObject.AddLinkedObjectDefinition(ctx, linkedObject) if err != nil { return diag.Errorf("failed to create linked object: %v", err) } @@ -79,7 +79,7 @@ func resourceLinkDefinitionCreate(ctx context.Context, d *schema.ResourceData, m } func resourceLinkDefinitionRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - linkedObject, resp, err := getSupplementFromMetadata(m).GetLinkedObject(ctx, d.Id()) + linkedObject, resp, err := getOktaClientFromMetadata(m).LinkedObject.GetLinkedObjectDefinition(ctx, d.Id()) if err := suppressErrorOn404(resp, err); err != nil { return diag.Errorf("failed to get linked object: %v", err) } @@ -100,7 +100,7 @@ func resourceLinkDefinitionRead(ctx context.Context, d *schema.ResourceData, m i } func resourceLinkDefinitionDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - resp, err := getSupplementFromMetadata(m).DeleteLinkedObject(ctx, d.Id()) + resp, err := getOktaClientFromMetadata(m).LinkedObject.DeleteLinkedObjectDefinition(ctx, d.Id()) if err := suppressErrorOn404(resp, err); err != nil { return diag.Errorf("failed to remove linked object: %v", err) } diff --git a/okta/resource_okta_link_definition_test.go b/okta/resource_okta_link_definition_test.go index bfdcaf8bb..16e8e4786 100644 --- a/okta/resource_okta_link_definition_test.go +++ b/okta/resource_okta_link_definition_test.go @@ -12,13 +12,13 @@ import ( func sweepLinkDefinitions(client *testClient) error { var errorList []error - linkedObjects, _, err := client.apiSupplement.ListLinkedObjects(context.Background()) + linkedObjects, _, err := getOktaClientFromMetadata(testAccProvider.Meta()).LinkedObject.ListLinkedObjectDefinitions(context.Background()) if err != nil { return err } for _, object := range linkedObjects { if strings.HasPrefix(object.Primary.Name, testResourcePrefix) { - if _, err := client.apiSupplement.DeleteLinkedObject(context.Background(), object.Primary.Name); err != nil { + if _, err := getOktaClientFromMetadata(testAccProvider.Meta()).LinkedObject.DeleteLinkedObjectDefinition(context.Background(), object.Primary.Name); err != nil { errorList = append(errorList, err) } } @@ -52,6 +52,6 @@ func TestAccOktaLinkDefinition(t *testing.T) { } func doesLinkDefinitionExist(id string) (bool, error) { - _, response, err := getSupplementFromMetadata(testAccProvider.Meta()).GetLinkedObject(context.Background(), id) + _, response, err := getOktaClientFromMetadata(testAccProvider.Meta()).LinkedObject.GetLinkedObjectDefinition(context.Background(), id) return doesResourceExist(response, err) } diff --git a/okta/resource_okta_link_value.go b/okta/resource_okta_link_value.go index 283b9ffa5..9cda0b496 100644 --- a/okta/resource_okta_link_value.go +++ b/okta/resource_okta_link_value.go @@ -41,8 +41,8 @@ func resourceLinkValue() *schema.Resource { } func resourceLinkValueCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - client := getSupplementFromMetadata(m) - lo, _, err := client.GetLinkedObject(ctx, d.Get("primary_name").(string)) + client := getOktaClientFromMetadata(m) + lo, _, err := client.LinkedObject.GetLinkedObjectDefinition(ctx, d.Get("primary_name").(string)) if err != nil { return diag.Errorf("failed to get linked object by primary name: %v", err) } @@ -53,7 +53,7 @@ func resourceLinkValueCreate(ctx context.Context, d *schema.ResourceData, m inte d.SetId(fmt.Sprintf("%s/%s", lo.Primary.Name, puID)) associatedUsers := convertInterfaceToStringSetNullable(d.Get("associated_user_ids")) for _, associatedUser := range associatedUsers { - _, err := client.SetLinkedObjectValueForPrimary(ctx, associatedUser, lo.Primary.Name, puID) + _, err := client.User.SetLinkedObjectForUser(ctx, associatedUser, lo.Primary.Name, puID) if err != nil { return diag.Errorf("failed to set linked object value for primary name: "+ "associatedUser: %s, primaryName: %s, primaryUser: %s, err: %v", associatedUser, lo.Primary.Name, puID, err) @@ -63,8 +63,8 @@ func resourceLinkValueCreate(ctx context.Context, d *schema.ResourceData, m inte } func resourceLinkValueRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - client := getSupplementFromMetadata(m) - lo, resp, err := client.GetLinkedObject(ctx, d.Get("primary_name").(string)) + client := getOktaClientFromMetadata(m) + lo, resp, err := client.LinkedObject.GetLinkedObjectDefinition(ctx, d.Get("primary_name").(string)) if err := suppressErrorOn404(resp, err); err != nil { return diag.Errorf("failed to get linked object by primary name: %v", err) } @@ -76,7 +76,7 @@ func resourceLinkValueRead(ctx context.Context, d *schema.ResourceData, m interf return diag.Errorf("primary name should be provided instead of associated one") } puID := d.Get("primary_user_id").(string) - los, resp, err := client.GetLinkedObjectValues(ctx, puID, lo.Associated.Name) + los, resp, err := client.User.GetLinkedObjectsForUser(ctx, puID, lo.Associated.Name, nil) if resp != nil && resp.StatusCode == http.StatusNotFound { d.SetId("") return nil @@ -92,21 +92,20 @@ func resourceLinkValueRead(ctx context.Context, d *schema.ResourceData, m interf } func resourceLinkValueUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - client := getSupplementFromMetadata(m) oldUsers, newUsers := d.GetChange("associated_user_ids") oldSet := oldUsers.(*schema.Set) newSet := newUsers.(*schema.Set) usersToAdd := convertInterfaceArrToStringArr(newSet.Difference(oldSet).List()) usersToRemove := convertInterfaceArrToStringArr(oldSet.Difference(newSet).List()) for _, u := range usersToAdd { - _, err := client.SetLinkedObjectValueForPrimary(ctx, u, d.Get("primary_name").(string), d.Get("primary_user_id").(string)) + _, err := getOktaClientFromMetadata(m).User.SetLinkedObjectForUser(ctx, u, d.Get("primary_name").(string), d.Get("primary_user_id").(string)) if err != nil { return diag.Errorf("failed to set relationship: associatedUser: %s, primaryName: %s, primaryUser: %s, "+ "err: %v", u, d.Get("primary_name").(string), d.Get("primary_user_id").(string), err) } } for _, u := range usersToRemove { - _, err := client.DeleteLinkedObjectValue(ctx, u, d.Get("primary_name").(string)) + _, err := getOktaClientFromMetadata(m).User.RemoveLinkedObjectForUser(ctx, u, d.Get("primary_name").(string)) if err != nil { return diag.Errorf("failed to remove relationship: associatedUser: %s, primaryName: %s, err: %v", u, d.Get("primary_name"), err) } @@ -116,9 +115,8 @@ func resourceLinkValueUpdate(ctx context.Context, d *schema.ResourceData, m inte func resourceLinkValueDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { associatedUsers := convertInterfaceToStringSetNullable(d.Get("associated_user_ids")) - client := getSupplementFromMetadata(m) for _, u := range associatedUsers { - resp, err := client.DeleteLinkedObjectValue(ctx, u, d.Get("primary_name").(string)) + resp, err := getOktaClientFromMetadata(m).User.RemoveLinkedObjectForUser(ctx, u, d.Get("primary_name").(string)) if resp != nil && resp.StatusCode == http.StatusNotFound { continue } diff --git a/okta/resource_okta_link_value_test.go b/okta/resource_okta_link_value_test.go index e6b5d7171..292c62cf7 100644 --- a/okta/resource_okta_link_value_test.go +++ b/okta/resource_okta_link_value_test.go @@ -43,15 +43,14 @@ func checkLinkValueDestroy(s *terraform.State) error { if rs.Type != linkValue { continue } - client := getSupplementFromMetadata(testAccProvider.Meta()) - lo, resp, err := client.GetLinkedObject(context.Background(), rs.Primary.Attributes["primary_name"]) + lo, resp, err := getOktaClientFromMetadata(testAccProvider.Meta()).LinkedObject.GetLinkedObjectDefinition(context.Background(), rs.Primary.Attributes["primary_name"]) if resp != nil && resp.StatusCode == http.StatusNotFound { return nil } else if err != nil { return err } puID := rs.Primary.Attributes["primary_user_id"] - los, resp, err := client.GetLinkedObjectValues(context.Background(), puID, lo.Associated.Name) + los, resp, err := getOktaClientFromMetadata(testAccProvider.Meta()).User.GetLinkedObjectsForUser(context.Background(), puID, lo.Associated.Name, nil) if resp != nil && resp.StatusCode == http.StatusNotFound { return nil } else if err != nil { diff --git a/okta/resource_okta_policy_password.go b/okta/resource_okta_policy_password.go index 783a963c0..a6beb4969 100644 --- a/okta/resource_okta_policy_password.go +++ b/okta/resource_okta_policy_password.go @@ -107,10 +107,11 @@ func resourcePolicyPassword() *schema.Resource { Default: 0, }, "password_max_lockout_attempts": { - Type: schema.TypeInt, - Optional: true, - Description: "Number of unsuccessful login attempts allowed before lockout: 0 = no limit.", - Default: 10, + Type: schema.TypeInt, + Optional: true, + Description: "Number of unsuccessful login attempts allowed before lockout: 0 = no limit.", + Default: 10, + DiffSuppressFunc: createValueDiffSuppression("0"), // default from Okta can be set to other than 10 }, "password_auto_unlock_minutes": { Type: schema.TypeInt, @@ -289,14 +290,14 @@ func buildPasswordPolicy(d *schema.ResourceData) sdk.Policy { // Okta defaults // we add the defaults here & not in the schema map to avoid defaults appearing in the terraform plan diff template.Settings = &sdk.PolicySettings{ - Password: &sdk.PasswordPolicyPasswordSettings{ - Age: &sdk.PasswordPolicyPasswordSettingsAge{ + Password: &okta.PasswordPolicyPasswordSettings{ + Age: &okta.PasswordPolicyPasswordSettingsAge{ ExpireWarnDays: int64(d.Get("password_expire_warn_days").(int)), HistoryCount: int64(d.Get("password_history_count").(int)), MaxAgeDays: int64(d.Get("password_max_age_days").(int)), MinAgeMinutes: int64(d.Get("password_min_age_minutes").(int)), }, - Complexity: &sdk.PasswordPolicyPasswordSettingsComplexity{ + Complexity: &okta.PasswordPolicyPasswordSettingsComplexity{ Dictionary: &okta.PasswordDictionary{ Common: &okta.PasswordDictionaryCommon{ Exclude: boolPtr(d.Get("password_dictionary_lookup").(bool)), @@ -310,32 +311,32 @@ func buildPasswordPolicy(d *schema.ResourceData) sdk.Policy { MinSymbol: int64(d.Get("password_min_symbol").(int)), MinUpperCase: int64(d.Get("password_min_uppercase").(int)), }, - Lockout: &sdk.PasswordPolicyPasswordSettingsLockout{ + Lockout: &okta.PasswordPolicyPasswordSettingsLockout{ AutoUnlockMinutes: int64(d.Get("password_auto_unlock_minutes").(int)), MaxAttempts: int64(d.Get("password_max_lockout_attempts").(int)), ShowLockoutFailures: boolPtr(d.Get("password_show_lockout_failures").(bool)), UserLockoutNotificationChannels: convertInterfaceToStringSet(d.Get("password_lockout_notification_channels")), }, }, - Recovery: &sdk.PasswordPolicyRecoverySettings{ - Factors: &sdk.PasswordPolicyRecoveryFactors{ + Recovery: &okta.PasswordPolicyRecoverySettings{ + Factors: &okta.PasswordPolicyRecoveryFactors{ OktaCall: &okta.PasswordPolicyRecoveryFactorSettings{ Status: d.Get("call_recovery").(string), }, OktaSms: &okta.PasswordPolicyRecoveryFactorSettings{ Status: d.Get("sms_recovery").(string), }, - OktaEmail: &sdk.PasswordPolicyRecoveryEmail{ - Properties: &sdk.PasswordPolicyRecoveryEmailProperties{ - RecoveryToken: &sdk.PasswordPolicyRecoveryEmailRecoveryToken{ + OktaEmail: &okta.PasswordPolicyRecoveryEmail{ + Properties: &okta.PasswordPolicyRecoveryEmailProperties{ + RecoveryToken: &okta.PasswordPolicyRecoveryEmailRecoveryToken{ TokenLifetimeMinutes: int64(d.Get("recovery_email_token").(int)), }, }, Status: d.Get("email_recovery").(string), }, - RecoveryQuestion: &sdk.PasswordPolicyRecoveryQuestion{ - Properties: &sdk.PasswordPolicyRecoveryQuestionProperties{ - Complexity: &sdk.PasswordPolicyRecoveryQuestionComplexity{ + RecoveryQuestion: &okta.PasswordPolicyRecoveryQuestion{ + Properties: &okta.PasswordPolicyRecoveryQuestionProperties{ + Complexity: &okta.PasswordPolicyRecoveryQuestionComplexity{ MinLength: int64(d.Get("question_min_length").(int)), }, }, diff --git a/okta/resource_okta_policy_password_default.go b/okta/resource_okta_policy_password_default.go index 999633bd8..35fa99a97 100644 --- a/okta/resource_okta_policy_password_default.go +++ b/okta/resource_okta_policy_password_default.go @@ -106,10 +106,11 @@ func resourcePolicyPasswordDefault() *schema.Resource { Default: 0, }, "password_history_count": { - Type: schema.TypeInt, - Optional: true, - Description: "Number of distinct passwords that must be created before they can be reused: 0 = none.", - Default: 0, + Type: schema.TypeInt, + Optional: true, + Description: "Number of distinct passwords that must be created before they can be reused: 0 = none.", + Default: 0, + DiffSuppressFunc: createValueDiffSuppression("0"), // default from Okta can be set to other than 0 }, "password_max_lockout_attempts": { Type: schema.TypeInt, @@ -273,14 +274,14 @@ func buildDefaultPasswordPolicy(d *schema.ResourceData) sdk.Policy { // Okta defaults // we add the defaults here & not in the schema map to avoid defaults appearing in the terraform plan diff policy.Settings = &sdk.PolicySettings{ - Password: &sdk.PasswordPolicyPasswordSettings{ - Age: &sdk.PasswordPolicyPasswordSettingsAge{ + Password: &okta.PasswordPolicyPasswordSettings{ + Age: &okta.PasswordPolicyPasswordSettingsAge{ ExpireWarnDays: int64(d.Get("password_expire_warn_days").(int)), HistoryCount: int64(d.Get("password_history_count").(int)), MaxAgeDays: int64(d.Get("password_max_age_days").(int)), MinAgeMinutes: int64(d.Get("password_min_age_minutes").(int)), }, - Complexity: &sdk.PasswordPolicyPasswordSettingsComplexity{ + Complexity: &okta.PasswordPolicyPasswordSettingsComplexity{ Dictionary: &okta.PasswordDictionary{ Common: &okta.PasswordDictionaryCommon{ Exclude: boolPtr(d.Get("password_dictionary_lookup").(bool)), @@ -294,32 +295,32 @@ func buildDefaultPasswordPolicy(d *schema.ResourceData) sdk.Policy { MinSymbol: int64(d.Get("password_min_symbol").(int)), MinUpperCase: int64(d.Get("password_min_uppercase").(int)), }, - Lockout: &sdk.PasswordPolicyPasswordSettingsLockout{ + Lockout: &okta.PasswordPolicyPasswordSettingsLockout{ AutoUnlockMinutes: int64(d.Get("password_auto_unlock_minutes").(int)), MaxAttempts: int64(d.Get("password_max_lockout_attempts").(int)), ShowLockoutFailures: boolPtr(d.Get("password_show_lockout_failures").(bool)), UserLockoutNotificationChannels: convertInterfaceToStringSet(d.Get("password_lockout_notification_channels")), }, }, - Recovery: &sdk.PasswordPolicyRecoverySettings{ - Factors: &sdk.PasswordPolicyRecoveryFactors{ + Recovery: &okta.PasswordPolicyRecoverySettings{ + Factors: &okta.PasswordPolicyRecoveryFactors{ OktaCall: &okta.PasswordPolicyRecoveryFactorSettings{ Status: d.Get("call_recovery").(string), }, OktaSms: &okta.PasswordPolicyRecoveryFactorSettings{ Status: d.Get("sms_recovery").(string), }, - OktaEmail: &sdk.PasswordPolicyRecoveryEmail{ - Properties: &sdk.PasswordPolicyRecoveryEmailProperties{ - RecoveryToken: &sdk.PasswordPolicyRecoveryEmailRecoveryToken{ + OktaEmail: &okta.PasswordPolicyRecoveryEmail{ + Properties: &okta.PasswordPolicyRecoveryEmailProperties{ + RecoveryToken: &okta.PasswordPolicyRecoveryEmailRecoveryToken{ TokenLifetimeMinutes: int64(d.Get("recovery_email_token").(int)), }, }, Status: d.Get("email_recovery").(string), }, - RecoveryQuestion: &sdk.PasswordPolicyRecoveryQuestion{ - Properties: &sdk.PasswordPolicyRecoveryQuestionProperties{ - Complexity: &sdk.PasswordPolicyRecoveryQuestionComplexity{ + RecoveryQuestion: &okta.PasswordPolicyRecoveryQuestion{ + Properties: &okta.PasswordPolicyRecoveryQuestionProperties{ + Complexity: &okta.PasswordPolicyRecoveryQuestionComplexity{ MinLength: int64(d.Get("question_min_length").(int)), }, }, diff --git a/okta/resource_okta_policy_password_test.go b/okta/resource_okta_policy_password_test.go index 3c617108d..3210e9017 100644 --- a/okta/resource_okta_policy_password_test.go +++ b/okta/resource_okta_policy_password_test.go @@ -10,6 +10,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/okta/okta-sdk-golang/v2/okta" "github.com/okta/okta-sdk-golang/v2/okta/query" "github.com/okta/terraform-provider-okta/sdk" ) @@ -24,7 +25,8 @@ func deletePolicyByType(t string, client *testClient) error { if err != nil { return fmt.Errorf("failed to list policies in order to properly destroy: %v", err) } - for _, policy := range policies { + for _, _policy := range policies { + policy := _policy.(*okta.Policy) if strings.HasPrefix(policy.Name, testResourcePrefix) { _, err = client.oktaClient.Policy.DeletePolicy(ctx, policy.Id) if err != nil { @@ -75,7 +77,7 @@ func TestAccOktaPolicyPassword_crud(t *testing.T) { resource.TestCheckResourceAttr(resourceName, "password_expire_warn_days", "15"), resource.TestCheckResourceAttr(resourceName, "password_min_age_minutes", "60"), resource.TestCheckResourceAttr(resourceName, "password_history_count", "5"), - resource.TestCheckResourceAttr(resourceName, "password_max_lockout_attempts", "0"), + // resource.TestCheckResourceAttr(resourceName, "password_max_lockout_attempts", "0"), // this default value can be overwritten on the org, don't test the default resource.TestCheckResourceAttr(resourceName, "password_auto_unlock_minutes", "2"), resource.TestCheckResourceAttr(resourceName, "password_show_lockout_failures", "true"), resource.TestCheckResourceAttr(resourceName, "password_lockout_notification_channels.#", "1"), diff --git a/okta/resource_okta_policy_rule_password_test.go b/okta/resource_okta_policy_rule_password_test.go index b0ab97daa..fb2a1ab4b 100644 --- a/okta/resource_okta_policy_rule_password_test.go +++ b/okta/resource_okta_policy_rule_password_test.go @@ -11,6 +11,7 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/okta/okta-sdk-golang/v2/okta" "github.com/okta/okta-sdk-golang/v2/okta/query" "github.com/okta/terraform-provider-okta/sdk" ) @@ -25,7 +26,8 @@ func deletePolicyRulesByType(ruleType string, client *testClient) error { if err != nil { return fmt.Errorf("failed to list policies in order to properly destroy rules: %v", err) } - for _, policy := range policies { + for _, _policy := range policies { + policy := _policy.(*okta.Policy) rules, _, err := client.apiSupplement.ListPolicyRules(ctx, policy.Id) if err != nil { return err diff --git a/okta/resource_okta_policy_rule_sign_on.go b/okta/resource_okta_policy_rule_sign_on.go index 94367bdc0..270e248b3 100644 --- a/okta/resource_okta_policy_rule_sign_on.go +++ b/okta/resource_okta_policy_rule_sign_on.go @@ -135,6 +135,7 @@ func resourcePolicySignOnRule() *schema.Resource { Optional: true, ValidateDiagFunc: elemInSlice([]string{"ANY", "OKTA", "SPECIFIC_IDP"}), Description: "Apply rule based on the IdP used: ANY, OKTA or SPECIFIC_IDP.", + Default: "ANY", }, "identity_provider_ids": { // identity_provider must be SPECIFIC_IDP Type: schema.TypeList, diff --git a/okta/resource_okta_profile_mapping.go b/okta/resource_okta_profile_mapping.go index 1708f1ff5..8d9d7a6b4 100644 --- a/okta/resource_okta_profile_mapping.go +++ b/okta/resource_okta_profile_mapping.go @@ -7,7 +7,8 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" - "github.com/okta/terraform-provider-okta/sdk" + "github.com/okta/okta-sdk-golang/v2/okta" + "github.com/okta/okta-sdk-golang/v2/okta/query" ) const ( @@ -89,22 +90,21 @@ var mappingResource = &schema.Resource{ } func resourceProfileMappingCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - client := getSupplementFromMetadata(m) sourceID := d.Get("source_id").(string) targetID := d.Get("target_id").(string) - mapping, resp, err := client.GetProfileMappingBySourceID(ctx, sourceID, targetID) + mapping, resp, err := getProfileMappingBySourceID(ctx, sourceID, targetID, m) if err := suppressErrorOn404(resp, err); err != nil { return diag.Errorf("failed to get profile mapping: %v", err) } if mapping == nil { return diag.Errorf("no profile mappings found for source ID '%s' and target ID '%s'", sourceID, targetID) } - d.SetId(mapping.ID) + d.SetId(mapping.Id) newMapping := buildMapping(d) if d.Get("delete_when_absent").(bool) { newMapping.Properties = mergeProperties(newMapping.Properties, getDeleteProperties(d, mapping.Properties)) } - _, _, err = client.UpdateMapping(ctx, mapping.ID, newMapping, nil) + _, _, err = getOktaClientFromMetadata(m).ProfileMapping.UpdateProfileMapping(ctx, mapping.Id, newMapping) if err != nil { return diag.Errorf("failed to create profile mapping: %v", err) } @@ -116,7 +116,7 @@ func resourceProfileMappingCreate(ctx context.Context, d *schema.ResourceData, m } func resourceProfileMappingRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - mapping, resp, err := getSupplementFromMetadata(m).GetProfileMappingByID(ctx, d.Id()) + mapping, resp, err := getOktaClientFromMetadata(m).ProfileMapping.GetProfileMapping(ctx, d.Id()) if err := suppressErrorOn404(resp, err); err != nil { return diag.Errorf("failed to get profile mapping: %v", err) } @@ -127,7 +127,7 @@ func resourceProfileMappingRead(ctx context.Context, d *schema.ResourceData, m i _ = d.Set("source_type", mapping.Source.Type) _ = d.Set("source_name", mapping.Source.Name) _ = d.Set("target_type", mapping.Target.Type) - _ = d.Set("target_id", mapping.Target.ID) + _ = d.Set("target_id", mapping.Target.Id) _ = d.Set("target_name", mapping.Target.Name) if !d.Get("delete_when_absent").(bool) { current := buildMappingProperties(d.Get("mappings").(*schema.Set)) @@ -142,10 +142,9 @@ func resourceProfileMappingRead(ctx context.Context, d *schema.ResourceData, m i } func resourceProfileMappingUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - client := getSupplementFromMetadata(m) sourceID := d.Get("source_id").(string) targetID := d.Get("target_id").(string) - mapping, resp, err := client.GetProfileMappingBySourceID(ctx, sourceID, targetID) + mapping, resp, err := getOktaClientFromMetadata(m).ProfileMapping.GetProfileMapping(ctx, d.Id()) if err := suppressErrorOn404(resp, err); err != nil { return diag.Errorf("failed to get profile mapping: %v", err) } @@ -156,7 +155,7 @@ func resourceProfileMappingUpdate(ctx context.Context, d *schema.ResourceData, m if d.Get("delete_when_absent").(bool) { newMapping.Properties = mergeProperties(newMapping.Properties, getDeleteProperties(d, mapping.Properties)) } - _, _, err = client.UpdateMapping(ctx, mapping.ID, newMapping, nil) + _, _, err = getOktaClientFromMetadata(m).ProfileMapping.UpdateProfileMapping(ctx, mapping.Id, newMapping) if err != nil { return diag.Errorf("failed to update profile mapping: %v", err) } @@ -168,10 +167,9 @@ func resourceProfileMappingUpdate(ctx context.Context, d *schema.ResourceData, m } func resourceProfileMappingDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - client := getSupplementFromMetadata(m) sourceID := d.Get("source_id").(string) targetID := d.Get("target_id").(string) - mapping, resp, err := client.GetProfileMappingBySourceID(ctx, sourceID, targetID) + mapping, resp, err := getOktaClientFromMetadata(m).ProfileMapping.GetProfileMapping(ctx, d.Id()) if err := suppressErrorOn404(resp, err); err != nil { return diag.Errorf("failed to get profile mapping: %v", err) } @@ -184,15 +182,15 @@ func resourceProfileMappingDelete(ctx context.Context, d *schema.ResourceData, m } mapping.Properties[k] = nil } - _, _, err = client.UpdateMapping(ctx, mapping.ID, *mapping, nil) + _, _, err = getOktaClientFromMetadata(m).ProfileMapping.UpdateProfileMapping(ctx, mapping.Id, *mapping) if err != nil { return diag.Errorf("failed to delete profile mapping: %v", err) } return nil } -func getDeleteProperties(d *schema.ResourceData, actual map[string]*sdk.MappingProperty) map[string]*sdk.MappingProperty { - toDelete := map[string]*sdk.MappingProperty{} +func getDeleteProperties(d *schema.ResourceData, actual map[string]*okta.ProfileMappingProperty) map[string]*okta.ProfileMappingProperty { + toDelete := map[string]*okta.ProfileMappingProperty{} config := buildMappingProperties(d.Get("mappings").(*schema.Set)) for key := range actual { if _, ok := config[key]; !ok { @@ -202,14 +200,14 @@ func getDeleteProperties(d *schema.ResourceData, actual map[string]*sdk.MappingP return toDelete } -func mergeProperties(target, b map[string]*sdk.MappingProperty) map[string]*sdk.MappingProperty { +func mergeProperties(target, b map[string]*okta.ProfileMappingProperty) map[string]*okta.ProfileMappingProperty { for k, v := range b { target[k] = v } return target } -func flattenMappingProperties(src map[string]*sdk.MappingProperty) *schema.Set { +func flattenMappingProperties(src map[string]*okta.ProfileMappingProperty) *schema.Set { var arr []interface{} for k, v := range src { arr = append(arr, map[string]interface{}{ @@ -221,13 +219,13 @@ func flattenMappingProperties(src map[string]*sdk.MappingProperty) *schema.Set { return schema.NewSet(schema.HashResource(mappingResource), arr) } -func buildMappingProperties(set *schema.Set) map[string]*sdk.MappingProperty { - res := map[string]*sdk.MappingProperty{} +func buildMappingProperties(set *schema.Set) map[string]*okta.ProfileMappingProperty { + res := map[string]*okta.ProfileMappingProperty{} for _, rawMap := range set.List() { if m, ok := rawMap.(map[string]interface{}); ok { k := m["id"].(string) - res[k] = &sdk.MappingProperty{ + res[k] = &okta.ProfileMappingProperty{ Expression: m["expression"].(string), PushStatus: m["push_status"].(string), } @@ -236,14 +234,14 @@ func buildMappingProperties(set *schema.Set) map[string]*sdk.MappingProperty { return res } -func buildMapping(d *schema.ResourceData) sdk.Mapping { - return sdk.Mapping{ - ID: d.Id(), +func buildMapping(d *schema.ResourceData) okta.ProfileMapping { + return okta.ProfileMapping{ + Id: d.Id(), Properties: buildMappingProperties(d.Get("mappings").(*schema.Set)), } } -func applyMapping(ctx context.Context, d *schema.ResourceData, m interface{}, mapping *sdk.Mapping) error { +func applyMapping(ctx context.Context, d *schema.ResourceData, m interface{}, mapping *okta.ProfileMapping) error { if !d.Get("always_apply").(bool) { return nil } @@ -251,10 +249,10 @@ func applyMapping(ctx context.Context, d *schema.ResourceData, m interface{}, ma target := d.Get("target_id").(string) var appID string if mapping.Source.Type == "appuser" { - appID = mapping.Source.ID + appID = mapping.Source.Id } if mapping.Target.Type == "appuser" { - appID = mapping.Target.ID + appID = mapping.Target.Id } appUserTypes, _, err := getSupplementFromMetadata(m).GetAppUserTypes(ctx, appID) if err != nil { @@ -269,9 +267,36 @@ func applyMapping(ctx context.Context, d *schema.ResourceData, m interface{}, ma } else { target = appUserTypes[0].Id } + // FIXME uses internal api _, err = getSupplementFromMetadata(m).ApplyMappings(ctx, source, target) if err != nil { return fmt.Errorf("failed to apply mappings for source '%s' and target '%s': %v", source, target, err) } return nil } + +func getProfileMappingBySourceID(ctx context.Context, sourceId, targetId string, m interface{}) (*okta.ProfileMapping, *okta.Response, error) { + qp := query.Params{ + Limit: defaultPaginationLimit, + } + if sourceId != "" { + qp.SourceId = sourceId + } + if targetId != "" { + qp.TargetId = targetId + } + + client := getOktaClientFromMetadata(m) + mappings, resp, err := client.ProfileMapping.ListProfileMappings(ctx, &qp) + if err != nil { + return nil, resp, err + } + + for _, mapping := range mappings { + if mapping.Source.Id == sourceId { + return client.ProfileMapping.GetProfileMapping(ctx, mapping.Id) + } + } + + return nil, resp, err +} diff --git a/okta/resource_okta_role_subscription.go b/okta/resource_okta_role_subscription.go index f4576303b..b005afbd3 100644 --- a/okta/resource_okta_role_subscription.go +++ b/okta/resource_okta_role_subscription.go @@ -64,15 +64,15 @@ func resourceRoleSubscriptionCreate(ctx context.Context, d *schema.ResourceData, if !ok { return resourceRoleSubscriptionRead(ctx, d, m) } - subscription, _, err := getSupplementFromMetadata(m).GetRoleTypeSubscription(ctx, d.Get("role_type").(string), d.Get("notification_type").(string)) + subscription, _, err := getOktaClientFromMetadata(m).Subscription.GetRoleSubscriptionByNotificationType(ctx, d.Get("role_type").(string), d.Get("notification_type").(string)) if err != nil { return diag.Errorf("failed get subscription: %v", err) } if subscription.Status != status.(string) { if status == "subscribed" { - _, err = getSupplementFromMetadata(m).RoleTypeSubscribe(ctx, d.Get("role_type").(string), d.Get("notification_type").(string)) + _, err = getOktaClientFromMetadata(m).Subscription.SubscribeRoleSubscriptionByNotificationType(ctx, d.Get("role_type").(string), d.Get("notification_type").(string)) } else { - _, err = getSupplementFromMetadata(m).RoleTypeUnsubscribe(ctx, d.Get("role_type").(string), d.Get("notification_type").(string)) + _, err = getOktaClientFromMetadata(m).Subscription.UnsubscribeRoleSubscriptionByNotificationType(ctx, d.Get("role_type").(string), d.Get("notification_type").(string)) } if err != nil { return diag.Errorf("failed to change subscription: %v", err) @@ -83,7 +83,7 @@ func resourceRoleSubscriptionCreate(ctx context.Context, d *schema.ResourceData, } func resourceRoleSubscriptionRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { - subscription, _, err := getSupplementFromMetadata(m).GetRoleTypeSubscription(ctx, d.Get("role_type").(string), d.Get("notification_type").(string)) + subscription, _, err := getOktaClientFromMetadata(m).Subscription.GetRoleSubscriptionByNotificationType(ctx, d.Get("role_type").(string), d.Get("notification_type").(string)) if err != nil { return diag.Errorf("failed get subscription: %v", err) } @@ -105,9 +105,9 @@ func resourceRoleSubscriptionUpdate(ctx context.Context, d *schema.ResourceData, return nil } if newStatus == "subscribed" { - _, err = getSupplementFromMetadata(m).RoleTypeSubscribe(ctx, d.Get("role_type").(string), d.Get("notification_type").(string)) + _, err = getOktaClientFromMetadata(m).Subscription.SubscribeRoleSubscriptionByNotificationType(ctx, d.Get("role_type").(string), d.Get("notification_type").(string)) } else { - _, err = getSupplementFromMetadata(m).RoleTypeUnsubscribe(ctx, d.Get("role_type").(string), d.Get("notification_type").(string)) + _, err = getOktaClientFromMetadata(m).Subscription.UnsubscribeRoleSubscriptionByNotificationType(ctx, d.Get("role_type").(string), d.Get("notification_type").(string)) } if err != nil { return diag.Errorf("failed to change subscription: %v", err) diff --git a/okta/resource_okta_user_factor_question.go b/okta/resource_okta_user_factor_question.go index e2c699e6e..58dac81f0 100644 --- a/okta/resource_okta_user_factor_question.go +++ b/okta/resource_okta_user_factor_question.go @@ -9,7 +9,6 @@ import ( "github.com/hashicorp/terraform-plugin-sdk/v2/diag" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/okta/okta-sdk-golang/v2/okta" - "github.com/okta/terraform-provider-okta/sdk" ) func resourceUserFactorQuestion() *schema.Resource { @@ -59,7 +58,8 @@ func resourceUserFactorQuestionCreate(ctx context.Context, d *schema.ResourceDat return diag.FromErr(err) } sq := buildUserFactorQuestion(d) - _, err = getSupplementFromMetadata(m).EnrollUserFactor(ctx, d.Get("user_id").(string), sq, nil) + _, _, err = getOktaClientFromMetadata(m).UserFactor.EnrollFactor(ctx, d.Get("user_id").(string), sq, nil) + if err != nil { return diag.Errorf("failed to enroll user question factor: %v", err) } @@ -69,10 +69,11 @@ func resourceUserFactorQuestionCreate(ctx context.Context, d *schema.ResourceDat func resourceUserFactorQuestionRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics { var uf okta.SecurityQuestionUserFactor - resp, err := getSupplementFromMetadata(m).GetUserFactor(ctx, d.Get("user_id").(string), d.Id(), &uf) + _, resp, err := getOktaClientFromMetadata(m).UserFactor.GetFactor(ctx, d.Get("user_id").(string), d.Id(), &uf) if err := suppressErrorOn404(resp, err); err != nil { return diag.Errorf("failed to get user question factor: %v", err) } + if uf.Id == "" { d.SetId("") return nil @@ -88,7 +89,7 @@ func resourceUserFactorQuestionUpdate(ctx context.Context, d *schema.ResourceDat if err != nil { return diag.FromErr(err) } - sq := &sdk.SecurityQuestionUserFactor{ + sq := &okta.SecurityQuestionUserFactor{ Profile: &okta.SecurityQuestionUserFactorProfile{ Answer: d.Get("answer").(string), Question: d.Get("key").(string), @@ -113,8 +114,8 @@ func resourceUserFactorQuestionDelete(ctx context.Context, d *schema.ResourceDat return nil } -func buildUserFactorQuestion(d *schema.ResourceData) *sdk.SecurityQuestionUserFactor { - return &sdk.SecurityQuestionUserFactor{ +func buildUserFactorQuestion(d *schema.ResourceData) *okta.SecurityQuestionUserFactor { + return &okta.SecurityQuestionUserFactor{ FactorType: "question", Provider: "OKTA", Profile: &okta.SecurityQuestionUserFactorProfile{ diff --git a/okta/user.go b/okta/user.go index 730b292ff..c8b85a198 100644 --- a/okta/user.go +++ b/okta/user.go @@ -190,7 +190,7 @@ func assignAdminRolesToUser(ctx context.Context, userID string, roles []string, if role == "CUSTOM" { continue } - _, _, err := client.User.AssignRoleToUser(ctx, userID, &okta.AssignRoleRequest{Type: role}, + _, _, err := client.User.AssignRoleToUser(ctx, userID, okta.AssignRoleRequest{Type: role}, &query.Params{DisableNotifications: boolPtr(disableNotifications)}) if err != nil { return fmt.Errorf("failed to assign role '%s' to user '%s': %w", role, userID, err) diff --git a/okta/user_schema_property.go b/okta/user_schema_property.go index 697c47ffe..3220ba4cc 100644 --- a/okta/user_schema_property.go +++ b/okta/user_schema_property.go @@ -4,7 +4,6 @@ import ( "encoding/json" "errors" "fmt" - "strconv" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" "github.com/okta/okta-sdk-golang/v2/okta" @@ -175,10 +174,10 @@ func syncCustomUserSchema(d *schema.ResourceData, subschema *okta.UserSchemaAttr if subschema.Items != nil { _ = d.Set("array_type", subschema.Items.Type) _ = d.Set("array_one_of", flattenOneOf(subschema.Items.OneOf)) - _ = d.Set("array_enum", flattenEnum(subschema.Items.Enum)) + _ = d.Set("array_enum", subschema.Items.Enum) } if len(subschema.Enum) > 0 { - _ = d.Set("enum", flattenEnum(subschema.Enum)) + _ = d.Set("enum", subschema.Enum) } return setNonPrimitives(d, map[string]interface{}{ "one_of": flattenOneOf(subschema.OneOf), @@ -249,10 +248,7 @@ func buildNullableItems(d *schema.ResourceData) (*okta.UserSchemaAttributeItems, return u, nil } if okArrayEnum { - enum, err := buildEnum(arrayEnum.([]interface{}), u.Type) - if err != nil { - return nil, err - } + enum := buildStringSlice(arrayEnum.([]interface{})) u.Enum = enum } if okArrayOneOf { @@ -273,38 +269,25 @@ func buildOneOf(ae []interface{}, elemType string) ([]*okta.UserSchemaAttributeE Title: valueMap["title"].(string), } c := valueMap["const"].(string) - switch elemType { - case "number": - f, err := strconv.ParseFloat(c, 64) - if err != nil { - return nil, errInvalidElemFormat - } - oneOf[i].Const = f - case "integer": - f, err := strconv.Atoi(c) - if err != nil { - return nil, errInvalidElemFormat - } - oneOf[i].Const = f - default: - oneOf[i].Const = c - } + oneOf[i].Const = c } return oneOf, nil } -func flattenEnum(enum []interface{}) []interface{} { +func buildStringSlice(enum []interface{}) []string { + result := make([]string, len(enum)) + for i := range enum { + result[i] = enum[i].(string) + } + return result +} + +func strToInterfaceSlice(enum []string) []interface{} { result := make([]interface{}, len(enum)) for i := range enum { - switch enum[i].(type) { - case int: - result[i] = strconv.Itoa(enum[i].(int)) - case float64: - result[i] = strconv.FormatFloat(enum[i].(float64), 'g', -1, 64) - default: - result[i] = enum[i] - } + result[i] = enum[i] } + return result } @@ -313,14 +296,7 @@ func flattenOneOf(oneOf []*okta.UserSchemaAttributeEnum) []interface{} { for i, v := range oneOf { of := map[string]interface{}{ "title": v.Title, - } - switch v.Const.(type) { - case int: - of["const"] = strconv.Itoa(v.Const.(int)) - case float64: - of["const"] = strconv.FormatFloat(v.Const.(float64), 'g', -1, 64) - default: - of["const"] = v.Const + "const": v.Const, } result[i] = of } @@ -339,12 +315,9 @@ func buildUserCustomSchemaAttribute(d *schema.ResourceData) (*okta.UserSchemaAtt return nil, err } } - var enum []interface{} + var enum []string if rawEnum, ok := d.GetOk("enum"); ok { - enum, err = buildEnum(rawEnum.([]interface{}), d.Get("type").(string)) - if err != nil { - return nil, err - } + enum = buildStringSlice(rawEnum.([]interface{})) } return &okta.UserSchemaAttribute{ Title: d.Get("title").(string), diff --git a/okta/utils.go b/okta/utils.go index 9d1d699c0..feb20fc12 100644 --- a/okta/utils.go +++ b/okta/utils.go @@ -5,6 +5,7 @@ import ( "encoding/json" "errors" "fmt" + "io" "net/http" "strconv" "strings" @@ -252,6 +253,18 @@ func doesResourceExist(response *okta.Response, err error) (bool, error) { if err != nil { return false, responseErr(response, err) } + + defer response.Body.Close() + b, err := io.ReadAll(response.Body) + if err != nil { + return false, responseErr(response, err) + } + // some of the API response can be 200 and return an empty object or list meaning nothing was found + body := string(b) + if body == "{}" || body == "[]" { + return false, nil + } + return true, nil } diff --git a/sdk/app_logo.go b/sdk/app_logo.go deleted file mode 100644 index 0e061b959..000000000 --- a/sdk/app_logo.go +++ /dev/null @@ -1,40 +0,0 @@ -package sdk - -import ( - "bytes" - "context" - "fmt" - "io" - "mime/multipart" - "net/http" - "os" - - "github.com/okta/okta-sdk-golang/v2/okta" -) - -// UploadAppLogo uploads app's logo -func (m *APISupplement) UploadAppLogo(ctx context.Context, appID, filename string) (*okta.Response, error) { - file, err := os.Open(filename) - if err != nil { - return nil, err - } - defer file.Close() - body := &bytes.Buffer{} - writer := multipart.NewWriter(body) - fw, err := writer.CreateFormFile("file", filename) - if err != nil { - return nil, err - } - _, err = io.Copy(fw, file) - if err != nil { - return nil, err - } - _ = writer.Close() - url := fmt.Sprintf("/api/v1/apps/%s/logo", appID) - re := m.cloneRequestExecutor() - req, err := re.WithContentType(writer.FormDataContentType()).NewRequest(http.MethodPost, url, body) - if err != nil { - return nil, err - } - return re.Do(ctx, req, nil) -} diff --git a/sdk/authenticator.go b/sdk/authenticator.go deleted file mode 100644 index 2d14f0cf4..000000000 --- a/sdk/authenticator.go +++ /dev/null @@ -1,141 +0,0 @@ -package sdk - -import ( - "context" - "fmt" - "net/http" - - "github.com/okta/okta-sdk-golang/v2/okta" -) - -type Authenticator struct { - Type string `json:"type,omitempty"` - ID string `json:"id,omitempty"` - Key string `json:"key,omitempty"` - Status string `json:"status,omitempty"` - Name string `json:"name,omitempty"` - Settings *AuthenticatorSettings `json:"settings,omitempty"` - Provider *AuthenticatorProvider `json:"provider,omitempty"` -} - -type AuthenticatorSettings struct { - AllowedFor string `json:"allowedFor,omitempty"` - TokenLifetimeInMinutes int `json:"tokenLifetimeInMinutes,omitempty"` - Compliance *AuthenticatorSettingsCompliance `json:"compliance,omitempty"` - ChannelBinding *AuthenticatorSettingsChannelBinding `json:"channelBinding,omitempty"` - UserVerification string `json:"userVerification,omitempty"` - AppInstanceID string `json:"appInstanceId,omitempty"` -} - -type AuthenticatorSettingsCompliance struct { - Fips string `json:"fips,omitempty"` -} - -type AuthenticatorSettingsChannelBinding struct { - Style string `json:"style,omitempty"` - Required string `json:"required,omitempty"` -} - -type AuthenticatorProvider struct { - Type string `json:"type,omitempty"` - Configuration *AuthenticatorProviderConfiguration `json:"configuration,omitempty"` -} - -type AuthenticatorProviderConfiguration struct { - HostName string `json:"hostName,omitempty"` - AuthPort int `json:"authPort,omitempty"` - InstanceID string `json:"instanceId,omitempty"` - SharedSecret string `json:"sharedSecret,omitempty"` - UserNameTemplate *AuthenticatorProviderConfigurationUserNameTemplate `json:"userNameTemplate,omitempty"` -} - -type AuthenticatorProviderConfigurationUserNameTemplate struct { - Template string `json:"template,omitempty"` -} - -func (m *APISupplement) ListAuthenticators(ctx context.Context) ([]*Authenticator, *okta.Response, error) { - url := `/api/v1/authenticators` - - re := m.cloneRequestExecutor() - - req, err := re.WithAccept("application/json").WithContentType("application/json").NewRequest("GET", url, nil) - if err != nil { - return nil, nil, err - } - - var authenticator []*Authenticator - - resp, err := re.Do(ctx, req, &authenticator) - if err != nil { - return nil, resp, err - } - - return authenticator, resp, nil -} - -func (m *APISupplement) GetAuthenticator(ctx context.Context, authenticatorId string) (*Authenticator, *okta.Response, error) { - url := fmt.Sprintf("/api/v1/authenticators/%v", authenticatorId) - - re := m.cloneRequestExecutor() - - req, err := re.WithAccept("application/json").WithContentType("application/json").NewRequest("GET", url, nil) - if err != nil { - return nil, nil, err - } - - var authenticator *Authenticator - - resp, err := re.Do(ctx, req, &authenticator) - if err != nil { - return nil, resp, err - } - - return authenticator, resp, nil -} - -func (m *APISupplement) UpdateAuthenticator(ctx context.Context, authenticatorId string, body Authenticator) (*Authenticator, *okta.Response, error) { - url := fmt.Sprintf("/api/v1/authenticators/%v", authenticatorId) - - re := m.cloneRequestExecutor() - - req, err := re.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodPut, url, body) - if err != nil { - return nil, nil, err - } - - var authenticator *Authenticator - - resp, err := re.Do(ctx, req, &authenticator) - if err != nil { - return nil, resp, err - } - - return authenticator, resp, nil -} - -func (m *APISupplement) ActivateAuthenticator(ctx context.Context, authenticatorId string) (*Authenticator, *okta.Response, error) { - return m.lifecycleChangeAuthenticator(ctx, authenticatorId, "activate") -} - -func (m *APISupplement) DeactivateAuthenticator(ctx context.Context, authenticatorId string) (*Authenticator, *okta.Response, error) { - return m.lifecycleChangeAuthenticator(ctx, authenticatorId, "deactivate") -} - -func (m *APISupplement) lifecycleChangeAuthenticator(ctx context.Context, authenticatorId, action string) (*Authenticator, *okta.Response, error) { - url := fmt.Sprintf("/api/v1/authenticators/%v/lifecycle/%s", authenticatorId, action) - re := m.cloneRequestExecutor() - - req, err := re.WithAccept("application/json").WithContentType("application/json").NewRequest("POST", url, nil) - if err != nil { - return nil, nil, err - } - - var authenticator *Authenticator - - resp, err := re.Do(ctx, req, &authenticator) - if err != nil { - return nil, resp, err - } - - return authenticator, resp, nil -} diff --git a/sdk/link_definition.go b/sdk/link_definition.go deleted file mode 100644 index ee0bcaee6..000000000 --- a/sdk/link_definition.go +++ /dev/null @@ -1,76 +0,0 @@ -package sdk - -import ( - "context" - "fmt" - "net/http" - - "github.com/okta/okta-sdk-golang/v2/okta" -) - -type LinkedObject struct { - Primary *LinkedObjectPart `json:"primary"` - Associated *LinkedObjectPart `json:"associated"` -} - -type LinkedObjectPart struct { - Name string `json:"name"` - Title string `json:"title"` - Description string `json:"description"` - Type string `json:"type"` -} - -func (m *APISupplement) ListLinkedObjects(ctx context.Context) ([]*LinkedObject, *okta.Response, error) { - url := "/api/v1/meta/schemas/user/linkedObjects" - re := m.cloneRequestExecutor() - req, err := re.NewRequest(http.MethodGet, url, nil) - if err != nil { - return nil, nil, err - } - var linkedObjects []*LinkedObject - resp, err := re.Do(ctx, req, &linkedObjects) - if err != nil { - return nil, resp, err - } - return linkedObjects, resp, nil -} - -func (m *APISupplement) CreateLinkedObject(ctx context.Context, body LinkedObject) (*LinkedObject, *okta.Response, error) { - url := "/api/v1/meta/schemas/user/linkedObjects" - re := m.cloneRequestExecutor() - req, err := re.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodPost, url, body) - if err != nil { - return nil, nil, err - } - var linkedObject *LinkedObject - resp, err := re.Do(ctx, req, &linkedObject) - if err != nil { - return nil, resp, err - } - return linkedObject, resp, nil -} - -func (m *APISupplement) GetLinkedObject(ctx context.Context, name string) (*LinkedObject, *okta.Response, error) { - url := fmt.Sprintf("/api/v1/meta/schemas/user/linkedObjects/%s", name) - re := m.cloneRequestExecutor() - req, err := re.NewRequest(http.MethodGet, url, nil) - if err != nil { - return nil, nil, err - } - var linkedObject *LinkedObject - resp, err := re.Do(ctx, req, &linkedObject) - if err != nil { - return nil, resp, err - } - return linkedObject, resp, nil -} - -func (m *APISupplement) DeleteLinkedObject(ctx context.Context, name string) (*okta.Response, error) { - url := fmt.Sprintf("/api/v1/meta/schemas/user/linkedObjects/%s", name) - re := m.cloneRequestExecutor() - req, err := re.NewRequest(http.MethodDelete, url, nil) - if err != nil { - return nil, err - } - return re.Do(ctx, req, nil) -} diff --git a/sdk/link_value.go b/sdk/link_value.go deleted file mode 100644 index e05d2c499..000000000 --- a/sdk/link_value.go +++ /dev/null @@ -1,48 +0,0 @@ -package sdk - -import ( - "context" - "fmt" - "net/http" - - "github.com/okta/okta-sdk-golang/v2/okta" -) - -type LinkedObjectValues struct { - Links interface{} `json:"_links,omitempty"` -} - -func (m *APISupplement) SetLinkedObjectValueForPrimary(ctx context.Context, associatedUserId, primaryName, primaryUserId string) (*okta.Response, error) { - url := fmt.Sprintf("/api/v1/users/%s/linkedObjects/%s/%s", associatedUserId, primaryName, primaryUserId) - re := m.cloneRequestExecutor() - req, err := re.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodPut, url, nil) - if err != nil { - return nil, err - } - return re.Do(ctx, req, nil) -} - -func (m *APISupplement) GetLinkedObjectValues(ctx context.Context, userId, primaryOrAssociatedName string) ([]*LinkedObjectValues, *okta.Response, error) { - url := fmt.Sprintf("/api/v1/users/%s/linkedObjects/%s", userId, primaryOrAssociatedName) - re := m.cloneRequestExecutor() - req, err := re.NewRequest(http.MethodGet, url, nil) - if err != nil { - return nil, nil, err - } - var linkedObjectValues []*LinkedObjectValues - resp, err := re.Do(ctx, req, &linkedObjectValues) - if err != nil { - return nil, resp, err - } - return linkedObjectValues, resp, nil -} - -func (m *APISupplement) DeleteLinkedObjectValue(ctx context.Context, userId, primaryName string) (*okta.Response, error) { - url := fmt.Sprintf("/api/v1/users/%s/linkedObjects/%s", userId, primaryName) - re := m.cloneRequestExecutor() - req, err := re.NewRequest(http.MethodDelete, url, nil) - if err != nil { - return nil, err - } - return re.Do(ctx, req, nil) -} diff --git a/sdk/mappings.go b/sdk/mappings.go index 260b9d354..c807d97eb 100644 --- a/sdk/mappings.go +++ b/sdk/mappings.go @@ -2,130 +2,13 @@ package sdk import ( "context" - "errors" "fmt" "net/http" "github.com/okta/okta-sdk-golang/v2/okta" - "github.com/okta/okta-sdk-golang/v2/okta/query" ) -type ( - MappingProperty struct { - Expression string `json:"expression"` - PushStatus string `json:"pushStatus"` - } - - MappingSource struct { - ID string `json:"id"` - Name string `json:"name"` - Type string `json:"type"` - } - - Mapping struct { - ID string `json:"id"` - Source *MappingSource `json:"source,omitempty"` - Target *MappingSource `json:"target,omitempty"` - Properties map[string]*MappingProperty `json:"properties,omitempty"` - } -) - -func (m *APISupplement) GetProfileMappingBySourceID(ctx context.Context, sourceId, targetId string) (*Mapping, *okta.Response, error) { - var url string - if sourceId != "" && targetId != "" { - url = fmt.Sprintf("/api/v1/mappings?sourceId=%s&targetId=%s", sourceId, targetId) - } else if sourceId != "" { - url = fmt.Sprintf("/api/v1/mappings?sourceId=%s", sourceId) - } else if targetId != "" { - url = fmt.Sprintf("/api/v1/mappings?targetId=%s", targetId) - } else { - return nil, nil, errors.New("at least targetId of sourceId should not be empty") - } - - req, err := m.RequestExecutor.NewRequest(http.MethodGet, url, nil) - if err != nil { - return nil, nil, err - } - var mappings []*Mapping - resp, err := m.RequestExecutor.Do(ctx, req, &mappings) - if err != nil { - return nil, resp, err - } - for _, mapping := range mappings { - if mapping.Source.ID == sourceId { - return m.GetProfileMappingByID(ctx, mapping.ID) - } - } - return nil, resp, err -} - -func (m *APISupplement) GetProfileMappingByID(ctx context.Context, mappingId string) (*Mapping, *okta.Response, error) { - url := fmt.Sprintf("/api/v1/mappings/%s", mappingId) - req, err := m.RequestExecutor.NewRequest(http.MethodGet, url, nil) - if err != nil { - return nil, nil, err - } - var mapping *Mapping - resp, err := m.RequestExecutor.Do(ctx, req, &mapping) - if err != nil { - return nil, resp, err - } - return mapping, resp, err -} - -func (m *APISupplement) UpdateMapping(ctx context.Context, mappingId string, body Mapping, qp *query.Params) (*Mapping, *okta.Response, error) { - url := fmt.Sprintf("/api/v1/mappings/%s", mappingId) - if qp != nil { - url += qp.String() - } - req, err := m.RequestExecutor.NewRequest(http.MethodPost, url, body) - if err != nil { - return nil, nil, err - } - mapping := body - resp, err := m.RequestExecutor.Do(ctx, req, &mapping) - if err != nil { - return nil, resp, err - } - return &mapping, resp, nil -} - -// FindProfileMappingSource retrieves profile mapping source/target via name -func (m *APISupplement) FindProfileMappingSource(ctx context.Context, name, typ string, qp *query.Params) (*MappingSource, error) { - uri := "/api/v1/mappings" - if qp != nil { - uri += qp.String() - } - req, err := m.RequestExecutor.NewRequest(http.MethodGet, uri, nil) - if err != nil { - return nil, err - } - var mappings []*Mapping - resp, err := m.RequestExecutor.Do(ctx, req, &mappings) - if err != nil { - return nil, err - } - for { - for _, m := range mappings { - if m.Target.Name == name && m.Target.Type == typ { - return m.Target, nil - } else if m.Source.Name == name && m.Source.Type == typ { - return m.Source, nil - } - } - if resp.HasNextPage() { - resp, err = resp.Next(ctx, &mappings) - if err != nil { - return nil, err - } - continue - } else { - break - } - } - return nil, fmt.Errorf("could not locate profile mapping source with name '%s' and type '%s'", name, typ) -} - +// FIXME uses internal api func (m *APISupplement) ApplyMappings(ctx context.Context, sourceID, targetID string) (*okta.Response, error) { url := fmt.Sprintf("/api/internal/v1/mappings/reapply?source=%s&target=%s", sourceID, targetID) re := m.cloneRequestExecutor() diff --git a/sdk/policy.go b/sdk/policy.go index 50aa3c61c..20d10d6d3 100644 --- a/sdk/policy.go +++ b/sdk/policy.go @@ -4,7 +4,6 @@ import ( "context" "fmt" "net/http" - "time" "github.com/okta/okta-sdk-golang/v2/okta" ) @@ -23,118 +22,54 @@ const ( // PasswordPolicy returns policy of PASSWORD type func PasswordPolicy() Policy { // Initialize a policy with password data - return Policy{Type: PasswordPolicyType} + p := Policy{} + p.Type = PasswordPolicyType + return p } // SignOnPolicy returns policy of OKTA_SIGN_ON type func SignOnPolicy() Policy { - return Policy{Type: SignOnPolicyType} + p := Policy{} + p.Type = SignOnPolicyType + return p } // MfaPolicy returns policy of MFA_ENROLL type func MfaPolicy() Policy { - return Policy{Type: MfaPolicyType} + p := Policy{} + p.Type = MfaPolicyType + return p } // ProfileEnrollmentPolicy returns policy of PROFILE_ENROLLMENT type func ProfileEnrollmentPolicy() Policy { - return Policy{Type: ProfileEnrollmentPolicyType} + p := Policy{} + p.Type = ProfileEnrollmentPolicyType + return p } +// Policy wrapper over okta.Policy until all of the public properties are fully supported type Policy struct { - Embedded interface{} `json:"_embedded,omitempty"` - Links interface{} `json:"_links,omitempty"` - Conditions *okta.PolicyRuleConditions `json:"conditions,omitempty"` - Created *time.Time `json:"created,omitempty"` - Description string `json:"description,omitempty"` - Id string `json:"id,omitempty"` - LastUpdated *time.Time `json:"lastUpdated,omitempty"` - Name string `json:"name,omitempty"` - Priority int64 `json:"priority,omitempty"` - Status string `json:"status,omitempty"` - System *bool `json:"system,omitempty"` - Type string `json:"type,omitempty"` - Settings *PolicySettings `json:"settings,omitempty"` + // TODO + okta.Policy + + Settings *PolicySettings `json:"settings,omitempty"` } +// PolicySettings missing from okta-sdk-golang. However, there is a subset okta.PasswordPolicySettings. type PolicySettings struct { + // TODO Authenticators []*PolicyAuthenticator `json:"authenticators,omitempty"` Delegation *okta.PasswordPolicyDelegationSettings `json:"delegation,omitempty"` Factors *PolicyFactorsSettings `json:"factors,omitempty"` - Password *PasswordPolicyPasswordSettings `json:"password,omitempty"` - Recovery *PasswordPolicyRecoverySettings `json:"recovery,omitempty"` + Password *okta.PasswordPolicyPasswordSettings `json:"password,omitempty"` + Recovery *okta.PasswordPolicyRecoverySettings `json:"recovery,omitempty"` Type string `json:"type,omitempty"` } -type PasswordPolicyPasswordSettings struct { - Age *PasswordPolicyPasswordSettingsAge `json:"age,omitempty"` - Complexity *PasswordPolicyPasswordSettingsComplexity `json:"complexity,omitempty"` - Lockout *PasswordPolicyPasswordSettingsLockout `json:"lockout,omitempty"` -} - -type PasswordPolicyPasswordSettingsAge struct { - ExpireWarnDays int64 `json:"expireWarnDays"` - HistoryCount int64 `json:"historyCount"` - MaxAgeDays int64 `json:"maxAgeDays"` - MinAgeMinutes int64 `json:"minAgeMinutes"` -} - -type PasswordPolicyPasswordSettingsComplexity struct { - Dictionary *okta.PasswordDictionary `json:"dictionary,omitempty"` - ExcludeAttributes []string `json:"excludeAttributes,omitempty"` - ExcludeUsername *bool `json:"excludeUsername,omitempty"` - MinLength int64 `json:"minLength"` - MinLowerCase int64 `json:"minLowerCase"` - MinNumber int64 `json:"minNumber"` - MinSymbol int64 `json:"minSymbol"` - MinUpperCase int64 `json:"minUpperCase"` -} - -type PasswordPolicyRecoverySettings struct { - Factors *PasswordPolicyRecoveryFactors `json:"factors,omitempty"` -} - -type PasswordPolicyRecoveryFactors struct { - OktaCall *okta.PasswordPolicyRecoveryFactorSettings `json:"okta_call,omitempty"` - OktaSms *okta.PasswordPolicyRecoveryFactorSettings `json:"okta_sms,omitempty"` - OktaEmail *PasswordPolicyRecoveryEmail `json:"okta_email,omitempty"` - RecoveryQuestion *PasswordPolicyRecoveryQuestion `json:"recovery_question,omitempty"` -} - -type PasswordPolicyRecoveryEmail struct { - Properties *PasswordPolicyRecoveryEmailProperties `json:"properties,omitempty"` - Status string `json:"status,omitempty"` -} - -type PasswordPolicyRecoveryEmailProperties struct { - RecoveryToken *PasswordPolicyRecoveryEmailRecoveryToken `json:"recoveryToken,omitempty"` -} - -type PasswordPolicyRecoveryEmailRecoveryToken struct { - TokenLifetimeMinutes int64 `json:"tokenLifetimeMinutes"` -} - -type PasswordPolicyRecoveryQuestion struct { - Properties *PasswordPolicyRecoveryQuestionProperties `json:"properties,omitempty"` - Status string `json:"status,omitempty"` -} - -type PasswordPolicyRecoveryQuestionProperties struct { - Complexity *PasswordPolicyRecoveryQuestionComplexity `json:"complexity,omitempty"` -} - -type PasswordPolicyPasswordSettingsLockout struct { - AutoUnlockMinutes int64 `json:"autoUnlockMinutes"` - MaxAttempts int64 `json:"maxAttempts"` - ShowLockoutFailures *bool `json:"showLockoutFailures,omitempty"` - UserLockoutNotificationChannels []string `json:"userLockoutNotificationChannels,omitempty"` -} - -type PasswordPolicyRecoveryQuestionComplexity struct { - MinLength int64 `json:"minLength"` -} - +// PolicyFactorsSettings is not expressed in the okta-sdk-golang yet type PolicyFactorsSettings struct { + // TODO Duo *PolicyFactor `json:"duo,omitempty"` FidoU2f *PolicyFactor `json:"fido_u2f,omitempty"` FidoWebauthn *PolicyFactor `json:"fido_webauthn,omitempty"` diff --git a/sdk/subscription.go b/sdk/subscription.go deleted file mode 100644 index a8026d7eb..000000000 --- a/sdk/subscription.go +++ /dev/null @@ -1,51 +0,0 @@ -package sdk - -import ( - "context" - "fmt" - "net/http" - - "github.com/okta/okta-sdk-golang/v2/okta" -) - -type Subscription struct { - NotificationType string `json:"notificationType"` - Channels []string `json:"channels"` - Status string `json:"status"` - Links interface{} `json:"links"` -} - -func (m *APISupplement) GetRoleTypeSubscription(ctx context.Context, roleType, notificationType string) (*Subscription, *okta.Response, error) { - url := fmt.Sprintf("/api/v1/roles/%s/subscriptions/%s", roleType, notificationType) - re := m.cloneRequestExecutor() - req, err := re.WithAccept("application/json").WithContentType("application/json").NewRequest("GET", url, nil) - if err != nil { - return nil, nil, err - } - var subscription *Subscription - resp, err := re.Do(ctx, req, &subscription) - if err != nil { - return nil, resp, err - } - return subscription, resp, nil -} - -func (m *APISupplement) RoleTypeSubscribe(ctx context.Context, roleType, notificationType string) (*okta.Response, error) { - url := fmt.Sprintf("/api/v1/roles/%s/subscriptions/%s/subscribe", roleType, notificationType) - re := m.cloneRequestExecutor() - req, err := re.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodPost, url, nil) - if err != nil { - return nil, err - } - return re.Do(ctx, req, nil) -} - -func (m *APISupplement) RoleTypeUnsubscribe(ctx context.Context, roleType, notificationType string) (*okta.Response, error) { - url := fmt.Sprintf("/api/v1/roles/%s/subscriptions/%s/unsubscribe", roleType, notificationType) - re := m.cloneRequestExecutor() - req, err := re.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodPost, url, nil) - if err != nil { - return nil, err - } - return re.Do(ctx, req, nil) -} diff --git a/sdk/user_factor.go b/sdk/user_factor.go index b636b0823..e702d9f78 100644 --- a/sdk/user_factor.go +++ b/sdk/user_factor.go @@ -4,60 +4,12 @@ import ( "context" "fmt" "net/http" - "time" "github.com/okta/okta-sdk-golang/v2/okta" - "github.com/okta/okta-sdk-golang/v2/okta/query" ) -type Factor interface { - IsUserFactorInstance() bool -} - -type SecurityQuestionUserFactor struct { - Embedded interface{} `json:"_embedded,omitempty"` - Links interface{} `json:"_links,omitempty"` - Created *time.Time `json:"created,omitempty"` - FactorType string `json:"factorType,omitempty"` - Id string `json:"id,omitempty"` - LastUpdated *time.Time `json:"lastUpdated,omitempty"` - Provider string `json:"provider,omitempty"` - Status string `json:"status,omitempty"` - Verify *okta.VerifyFactorRequest `json:"verify,omitempty"` - Profile *okta.SecurityQuestionUserFactorProfile `json:"profile,omitempty"` -} - -func (a *SecurityQuestionUserFactor) IsUserFactorInstance() bool { - return true -} - -// EnrollUserFactor enrolls a user with a supported factor. -func (m *APISupplement) EnrollUserFactor(ctx context.Context, userId string, factorInstance Factor, qp *query.Params) (*okta.Response, error) { - url := fmt.Sprintf("/api/v1/users/%v/factors", userId) - if qp != nil { - url += qp.String() - } - req, err := m.RequestExecutor. - WithAccept("application/json"). - WithContentType("application/json"). - NewRequest(http.MethodPost, url, factorInstance) - if err != nil { - return nil, err - } - return m.RequestExecutor.Do(ctx, req, factorInstance) -} - -// GetUserFactor fetches a factor for the specified user -func (m *APISupplement) GetUserFactor(ctx context.Context, userId, factorId string, factorInstance Factor) (*okta.Response, error) { - url := fmt.Sprintf("/api/v1/users/%v/factors/%v", userId, factorId) - req, err := m.RequestExecutor.NewRequest(http.MethodGet, url, nil) - if err != nil { - return nil, err - } - return m.RequestExecutor.Do(ctx, req, factorInstance) -} - -func (m *APISupplement) UpdateUserFactor(ctx context.Context, userId, factorId string, factorInstance Factor) (*okta.Response, error) { +// FIXME calling undocumented public API +func (m *APISupplement) UpdateUserFactor(ctx context.Context, userId, factorId string, factorInstance okta.Factor) (*okta.Response, error) { url := fmt.Sprintf("/api/v1/users/%v/factors/%v", userId, factorId) req, err := m.RequestExecutor. WithAccept("application/json"). diff --git a/website/docs/r/app_saml.html.markdown b/website/docs/r/app_saml.html.markdown index 83cbd7afb..a6f42b35a 100644 --- a/website/docs/r/app_saml.html.markdown +++ b/website/docs/r/app_saml.html.markdown @@ -157,9 +157,9 @@ The following arguments are supported: - `accessibility_login_redirect_url` - (Optional) Custom login page for this application. -- `accessibility_self_service` - (Optional) Enable self-service. By default, it is `false`. +- `accessibility_self_service` - (Optional) Enable self-service. Default is: `false`. -- `acs_endpoints` - An array of ACS endpoints. You can configure a maximum of 100 endpoints. +- `acs_endpoints` - (Optional) An array of ACS endpoints. You can configure a maximum of 100 endpoints. - `admin_note` - (Optional) Application notes for admins. @@ -181,7 +181,7 @@ The following arguments are supported: - `authn_context_class_ref` - (Optional) Identifies the SAML authentication context class for the assertion’s authentication statement. -- `auto_submit_toolbar` - (Optional) Display auto submit toolbar. +- `auto_submit_toolbar` - (Optional) Display auto submit toolbar. Default is: `false` - `default_relay_state` - (Optional) Identifies a specific application resource in an IDP initiated SSO scenario. @@ -196,11 +196,11 @@ The following arguments are supported: - `groups` - (Optional) Groups associated with the application. - `DEPRECATED`: Please replace usage with the `okta_app_group_assignments` (or `okta_app_group_assignment`) resource. -- `hide_ios` - (Optional) Do not display application icon on mobile app. +- `hide_ios` - (Optional) Do not display application icon on mobile app. Default is: `false` -- `hide_web` - (Optional) Do not display application icon to users +- `hide_web` - (Optional) Do not display application icon to users. Default is: `false` -- `honor_force_authn` - (Optional) Prompt user to re-authenticate if SP asks for it. +- `honor_force_authn` - (Optional) Prompt user to re-authenticate if SP asks for it. Default is: `false` - `idp_issuer` - (Optional) SAML issuer ID. @@ -216,7 +216,17 @@ The following arguments are supported: - `logo` - (Optional) Local file path to the logo. The file must be in PNG, JPG, or GIF format, and less than 1 MB in size. -- `preconfigured_app` - (Optional) name of application from the Okta Integration Network, if not included a custom app will be created. +- `preconfigured_app` - (Optional) name of application from the Okta Integration Network, if not included a custom app will be created. + If not provided the following arguments are required: + - `sso_url` + - `recipient` + - `destination` + - `audience` + - `subject_name_id_template` + - `subject_name_id_format` + - `signature_algorithm` + - `digest_algorithm` + - `authn_context_class_ref` - `recipient` - (Optional) The location where the app may present the SAML assertion. @@ -235,9 +245,9 @@ The following arguments are supported: - `single_logout_url` - (Optional) The location where the logout response is sent. -- `skip_groups` - (Optional) Indicator that allows the app to skip `groups` sync (it's also can be provided during import). Default is `false`. +- `skip_groups` - (Optional) Indicator that allows the app to skip `groups` sync (it can also be provided during import). Default is `false`. -- `skip_users` - (Optional) Indicator that allows the app to skip `users` sync (it's also can be provided during import). Default is `false`. +- `skip_users` - (Optional) Indicator that allows the app to skip `users` sync (it can also be provided during import). Default is `false`. - `sp_issuer` - (Optional) SAML service provider issuer. @@ -249,13 +259,13 @@ The following arguments are supported: - `subject_name_id_template` - (Optional) Template for app user's username when a user is assigned to the app. -- `user_name_template` - (Optional) Username template. Default: `"${source.login}"` +- `user_name_template` - (Optional) Username template. Default is: `"${source.login}"` - `user_name_template_push_status` - (Optional) Push username on update. Valid values: `"PUSH"` and `"DONT_PUSH"`. - `user_name_template_suffix` - (Optional) Username template suffix. -- `user_name_template_type` - (Optional) Username template type. Default: `"BUILT_IN"`. +- `user_name_template_type` - (Optional) Username template type. Default is: `"BUILT_IN"`. - `users` - (Optional) Users associated with the application. - `DEPRECATED`: Please replace usage with the `okta_app_user` resource.