Skip to content
This repository has been archived by the owner on Jun 14, 2021. It is now read-only.

Commit

Permalink
Require target_id on profile mapping
Browse files Browse the repository at this point in the history
Also add data source to allow users to determine target/source ids

Update CHANGELOG

Update new data source to be more specific

All other profile mapping sources are do not have unique names

Update find profile mapping source to take type as well

Update docs
  • Loading branch information
quantumew committed Nov 19, 2019
1 parent 32a26c7 commit 4d83e21
Show file tree
Hide file tree
Showing 15 changed files with 173 additions and 45 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,3 +257,13 @@ FEATURES:
BUG FIXES:

* Policy values could not be set to 0. Doing so resulted in the SDK omitting them, resulting in Okta resetting the values to default.

## 3.0.35

ENHANCEMENT:

* Require target_id on `okta_profile_mapping` to avoid ambiguity

FEATURES:

* **New Data Source:** `okta_user_profile_mapping_source` [GH-340]
3 changes: 3 additions & 0 deletions examples/okta_profile_mapping/basic.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
resource okta_profile_mapping test {
source_id = "${okta_idp_social.google.id}"
target_id = "${data.okta_user_profile_mapping_source.user.id}"
delete_when_absent = true

mappings {
Expand Down Expand Up @@ -38,3 +39,5 @@ resource okta_idp_social google {
client_secret = "abcd123"
username_template = "idpuser.email"
}

data okta_user_profile_mapping_source user {}
3 changes: 3 additions & 0 deletions examples/okta_profile_mapping/prevent_delete.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
resource okta_profile_mapping test {
source_id = "${okta_idp_social.google.id}"
target_id = "${data.okta_user_profile_mapping_source.user.id}"
delete_when_absent = false

mappings {
Expand Down Expand Up @@ -63,3 +64,5 @@ resource okta_idp_social google {
client_secret = "abcd123"
username_template = "idpuser.email"
}

data okta_user_profile_mapping_source user {}
3 changes: 3 additions & 0 deletions examples/okta_profile_mapping/updated.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
resource okta_profile_mapping test {
source_id = "${okta_idp_social.google.id}"
target_id = "${data.okta_user_profile_mapping_source.user.id}"
delete_when_absent = true

mappings {
Expand Down Expand Up @@ -43,3 +44,5 @@ resource okta_idp_social google {
client_secret = "abcd123"
username_template = "idpuser.email"
}

data okta_user_profile_mapping_source user {}
5 changes: 3 additions & 2 deletions okta/app_filter.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"strings"

"github.com/articulate/terraform-provider-okta/sdk"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/okta/okta-sdk-golang/okta"
"github.com/okta/okta-sdk-golang/okta/query"
Expand Down Expand Up @@ -58,7 +59,7 @@ func collectApps(reqExe *okta.RequestExecutor, filters *appFilters, results *sea

results.Apps = append(results.Apps, filterApp(appList, filters)...)

if after := getAfterParam(res); after != "" && !filters.shouldShortCircuit(results.Apps) {
if after := sdk.GetAfterParam(res); after != "" && !filters.shouldShortCircuit(results.Apps) {
qp.After = after
return collectApps(reqExe, filters, results, qp)
}
Expand Down Expand Up @@ -124,7 +125,7 @@ func collectSamlApps(reqExe *okta.RequestExecutor, filters *appFilters, results

results.SamlApps = append(results.SamlApps, filterSamlApp(appList, filters)...)

if after := getAfterParam(res); after != "" && !filters.shouldShortCircuit(results.Apps) {
if after := sdk.GetAfterParam(res); after != "" && !filters.shouldShortCircuit(results.Apps) {
qp.After = after
return collectApps(reqExe, filters, results, qp)
}
Expand Down
40 changes: 40 additions & 0 deletions okta/data_source_okta_user_profile_mapping_source.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
package okta

import (
"fmt"

"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/okta/okta-sdk-golang/okta/query"
)

func dataSourceUserProfileMappingSource() *schema.Resource {
return &schema.Resource{
Read: dataSourceUserProfileMappingSourceRead,

Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Computed: true,
},
"type": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func dataSourceUserProfileMappingSourceRead(d *schema.ResourceData, m interface{}) error {
client := getSupplementFromMetadata(m)

mapping, _, err := client.FindProfileMappingSource("user", "user", &query.Params{})
if err != nil {
return fmt.Errorf("Error Listing User Profile Mapping Source in Okta: %v", err)
}

d.SetId(mapping.ID)
d.Set("type", mapping.Type)
d.Set("name", mapping.Name)

return nil
}
3 changes: 2 additions & 1 deletion okta/data_source_okta_users.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package okta
import (
"fmt"

"github.com/articulate/terraform-provider-okta/sdk"
"github.com/hashicorp/terraform-plugin-sdk/helper/hashcode"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
"github.com/okta/okta-sdk-golang/okta"
Expand Down Expand Up @@ -58,7 +59,7 @@ func collectUsers(client *okta.Client, results *searchResults, qp *query.Params)

results.Users = append(results.Users, users...)

if after := getAfterParam(res); after != "" {
if after := sdk.GetAfterParam(res); after != "" {
qp.After = after
return collectUsers(client, results, qp)
}
Expand Down
27 changes: 14 additions & 13 deletions okta/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,19 +179,20 @@ func Provider() terraform.ResourceProvider {
"okta_mfa_policy_rule": deprecateIncorrectNaming(resourcePolicyMfaRule(), policyRuleMfa),
},
DataSourcesMap: map[string]*schema.Resource{
"okta_app": dataSourceApp(),
"okta_app_saml": dataSourceAppSaml(),
"okta_app_metadata_saml": dataSourceAppMetadataSaml(),
"okta_default_policies": deprecatedPolicies,
"okta_default_policy": dataSourceDefaultPolicies(),
"okta_everyone_group": dataSourceEveryoneGroup(),
"okta_group": dataSourceGroup(),
"okta_idp_metadata_saml": dataSourceIdpMetadataSaml(),
"okta_idp_saml": dataSourceIdpSaml(),
"okta_policy": dataSourcePolicy(),
"okta_user": dataSourceUser(),
"okta_users": dataSourceUsers(),
authServer: dataSourceAuthServer(),
"okta_app": dataSourceApp(),
"okta_app_saml": dataSourceAppSaml(),
"okta_app_metadata_saml": dataSourceAppMetadataSaml(),
"okta_default_policies": deprecatedPolicies,
"okta_default_policy": dataSourceDefaultPolicies(),
"okta_everyone_group": dataSourceEveryoneGroup(),
"okta_group": dataSourceGroup(),
"okta_idp_metadata_saml": dataSourceIdpMetadataSaml(),
"okta_idp_saml": dataSourceIdpSaml(),
"okta_policy": dataSourcePolicy(),
"okta_user_profile_mapping_source": dataSourceUserProfileMappingSource(),
"okta_user": dataSourceUser(),
"okta_users": dataSourceUsers(),
authServer: dataSourceAuthServer(),
},

ConfigureFunc: providerConfigure,
Expand Down
9 changes: 5 additions & 4 deletions okta/resource_okta_profile_mapping.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,9 @@ func resourceOktaProfileMapping() *schema.Resource {
Computed: true,
},
"target_id": &schema.Schema{
Type: schema.TypeString,
Computed: true,
Type: schema.TypeString,
Required: true,
Description: "The target id of the mapping to manage.",
},
"target_type": &schema.Schema{
Type: schema.TypeString,
Expand Down Expand Up @@ -120,7 +121,7 @@ func getProfileMapping(d *schema.ResourceData, m interface{}) (*sdk.Mapping, err

func resourceProfileMappingCreate(d *schema.ResourceData, m interface{}) error {
client := getSupplementFromMetadata(m)
mapping, _, err := client.GetProfileMappingBySourceId(d.Get("source_id").(string))
mapping, _, err := client.GetProfileMappingBySourceId(d.Get("source_id").(string), d.Get("target_id").(string))

if err != nil || mapping == nil {
return fmt.Errorf("failed to retrieve source, which is required to track mappings in state, error: %v", err)
Expand Down Expand Up @@ -213,7 +214,7 @@ func resourceProfileMappingUpdate(d *schema.ResourceData, m interface{}) error {
client := getSupplementFromMetadata(m)
newMapping := buildMapping(d)

mapping, _, err := client.GetProfileMappingBySourceId(d.Get("source_id").(string))
mapping, _, err := client.GetProfileMappingBySourceId(d.Get("source_id").(string), d.Get("target_id").(string))

if err != nil || mapping == nil {
return fmt.Errorf("failed to retrieve source, which is required to track mappings in state, error: %v", err)
Expand Down
23 changes: 0 additions & 23 deletions okta/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,12 @@ import (
"errors"
"fmt"
"net/http"
"net/url"
"regexp"
"strings"
"unicode"

sdk "github.com/articulate/terraform-provider-okta/sdk"
"github.com/okta/okta-sdk-golang/okta"
"github.com/peterhellberg/link"

articulateOkta "github.com/articulate/oktasdk-go/okta"
"github.com/hashicorp/terraform-plugin-sdk/helper/schema"
Expand Down Expand Up @@ -250,27 +248,6 @@ func ensureNotDefault(d *schema.ResourceData, t string) error {
return nil
}

// Grabs after link from link headers if it exists
func getAfterParam(res *okta.Response) string {
if res == nil {
return ""
}

linkList := link.ParseHeader(res.Header)
for _, l := range linkList {
if l.Rel == "next" {
parsedURL, err := url.Parse(l.URI)
if err != nil {
continue
}
q := parsedURL.Query()
return q.Get("after")
}
}

return ""
}

func getMapString(m map[string]interface{}, key string) string {
if v, ok := m[key]; ok {
return v.(string)
Expand Down
23 changes: 23 additions & 0 deletions sdk/api_supplement.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import (
"fmt"
"io/ioutil"
"net/http"
"net/url"

"github.com/okta/okta-sdk-golang/okta"
"github.com/peterhellberg/link"
)

// ApiSupplement not all APIs are supported by okta-sdk-golang, this will act as a supplement to the Okta SDK
Expand Down Expand Up @@ -47,3 +49,24 @@ func (m *ApiSupplement) GetXml(url string) ([]byte, *http.Response, error) {

return data, res, err
}

// GetAfterParam grabs after link from link headers if it exists
func GetAfterParam(res *okta.Response) string {
if res == nil {
return ""
}

linkList := link.ParseHeader(res.Header)
for _, l := range linkList {
if l.Rel == "next" {
parsedURL, err := url.Parse(l.URI)
if err != nil {
continue
}
q := parsedURL.Query()
return q.Get("after")
}
}

return ""
}
38 changes: 36 additions & 2 deletions sdk/mappings.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ func (m *ApiSupplement) RemovePropertyMapping(mappingId, id string) (*okta.Respo
return m.RequestExecutor.Do(req, nil)
}

func (m *ApiSupplement) GetProfileMappingBySourceId(sourceId string) (*Mapping, *okta.Response, error) {
url := fmt.Sprintf("/api/v1/mappings?sourceId=%s", sourceId)
func (m *ApiSupplement) GetProfileMappingBySourceId(sourceId, targetId string) (*Mapping, *okta.Response, error) {
url := fmt.Sprintf("/api/v1/mappings?sourceId=%s&targetId=%s", sourceId, targetId)
req, err := m.RequestExecutor.NewRequest("GET", url, nil)

if err != nil {
Expand Down Expand Up @@ -101,3 +101,37 @@ func (m *ApiSupplement) UpdateMapping(mappingId string, body Mapping, qp *query.
}
return &mapping, resp, nil
}

// FindProfileMappingSource retrieves profile mapping source/target via name
func (m *ApiSupplement) FindProfileMappingSource(name, typ string, qp *query.Params) (*MappingSource, *okta.Response, error) {
uri := "/api/v1/mappings"

if qp != nil {
uri += qp.String()
}

req, err := m.RequestExecutor.NewRequest("GET", uri, nil)

if err != nil {
return nil, nil, err
}

mappings := []*Mapping{}
res, err := m.RequestExecutor.Do(req, &mappings)

for _, m := range mappings {
if m.Target.Name == name && m.Target.Type == typ {
return m.Target, res, nil
} else if m.Source.Name == name && m.Source.Type == typ {
return m.Source, res, nil
}
}

if after := GetAfterParam(res); after != "" {
qp.After = after

return m.FindProfileMappingSource(name, typ, qp)
}

return nil, res, fmt.Errorf("could not locate profile mapping source with name %s", name)
}
25 changes: 25 additions & 0 deletions website/docs/d/user_profile_mapping_source.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
layout: "okta"
page_title: "Okta: okta_user_profile_mapping_source"
sidebar_current: "docs-okta-datasource-user-profile-mapping-source"
description: |-
Get the base user Profile Mapping source or target from Okta.
---

# okta_user_profile_mapping_source

Use this data source to retrieve the base user Profile Mapping source or target from Okta.

## Example Usage

```hcl
data "okta_user_profile_mapping_source" "example" {}
```

## Attributes Reference

* `id` - id of the source.

* `name` - name of source.

* `type` - type of source.
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@ This resource allows you to manage a profile mapping by source id.
## Example Usage

```hcl
data "okta_user_profile_mapping_source" "user" {}
resource "okta_profile_mapping" "example" {
source_id = "<source id>"
target_id = "${data.okta_user_profile_mapping_source.user.id}"
delete_when_absent = true
mappings {
Expand Down
3 changes: 3 additions & 0 deletions website/okta.erb
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
<li<%= sidebar_current("docs-okta-datasource-policy") %>>
<a href="/docs/providers/okta/d/policy.html">okta_policy</a>
</li>
<li<%= sidebar_current("docs-okta-datasource-user-profile-mapping-source") %>>
<a href="/docs/providers/okta/d/user_profile_mapping_source.html">okta_user_profile_mapping_source</a>
</li>
<li<%= sidebar_current("docs-okta-datasource-user") %>>
<a href="/docs/providers/okta/d/user.html">okta_user</a>
</li>
Expand Down

0 comments on commit 4d83e21

Please # to comment.