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

Commit

Permalink
Merge pull request #341 from articulate/feature/support-target-id
Browse files Browse the repository at this point in the history
Require target_id on profile mapping
  • Loading branch information
quantumew committed Nov 19, 2019
2 parents 32a26c7 + 4d83e21 commit 5e9b6bf
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 5e9b6bf

Please sign in to comment.