Skip to content

Commit

Permalink
Added new okta_role_subscription resource and datasource (#746)
Browse files Browse the repository at this point in the history
  • Loading branch information
bogdanprodan-okta authored Oct 25, 2021
1 parent ef78a14 commit 1f39f9f
Show file tree
Hide file tree
Showing 10 changed files with 327 additions and 1 deletion.
5 changes: 5 additions & 0 deletions examples/okta_role_subscription/basic.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resource "okta_role_subscription" "test" {
notification_type = "APP_IMPORT"
role_type = "SUPER_ADMIN"
status = "unsubscribed"
}
44 changes: 44 additions & 0 deletions okta/data_source_okta_role_subscription.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package okta

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func dataSourceRoleSubscription() *schema.Resource {
return &schema.Resource{
ReadContext: dataSourceRoleSubscriptionRead,
Schema: map[string]*schema.Schema{
"role_type": {
Type: schema.TypeString,
Required: true,
ValidateDiagFunc: elemInSlice(validAdminRoles),
Description: "Type of the role",
},
"notification_type": {
Type: schema.TypeString,
Required: true,
ValidateDiagFunc: elemInSlice(validNotificationTypes),
Description: "Type of the notification",
},
"status": {
Type: schema.TypeString,
Computed: true,
Description: "Status of subscription",
},
},
}
}

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))
if err != nil {
return diag.Errorf("failed get subscription: %v", err)
}
d.SetId(fmt.Sprintf("%s/%s", d.Get("role_type").(string), d.Get("notification_type").(string)))
_ = d.Set("status", subscription.Status)
return nil
}
3 changes: 3 additions & 0 deletions okta/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ const (
policySignOn = "okta_policy_signon"
profileMapping = "okta_profile_mapping"
securityNotificationEmails = "okta_security_notification_emails"
roleSubscription = "okta_role_subscription"
templateEmail = "okta_template_email"
templateSms = "okta_template_sms"
threatInsightSettings = "okta_threat_insight_settings"
Expand Down Expand Up @@ -271,6 +272,7 @@ func Provider() *schema.Provider {
policyRuleSignOn: resourcePolicySignOnRule(),
policySignOn: resourcePolicySignOn(),
profileMapping: resourceOktaProfileMapping(),
roleSubscription: resourceRoleSubscription(),
securityNotificationEmails: resourceSecurityNotificationEmails(),
templateEmail: resourceTemplateEmail(),
templateSms: resourceTemplateSms(),
Expand Down Expand Up @@ -335,6 +337,7 @@ func Provider() *schema.Provider {
idpSocial: dataSourceIdpSocial(),
networkZone: dataSourceNetworkZone(),
policy: dataSourcePolicy(),
roleSubscription: dataSourceRoleSubscription(),
user: dataSourceUser(),
userProfileMappingSource: dataSourceUserProfileMappingSource(),
users: dataSourceUsers(),
Expand Down
2 changes: 1 addition & 1 deletion okta/resource_okta_group_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func sweepGroups(client *testClient) error {
func TestAccOktaGroup_crud(t *testing.T) {
ri := acctest.RandInt()
resourceName := fmt.Sprintf("%s.test", group)
mgr := newFixtureManager("okta_group")
mgr := newFixtureManager(group)
config := mgr.GetFixtures("okta_group.tf", ri, t)
updatedConfig := mgr.GetFixtures("okta_group_updated.tf", ri, t)
addUsersConfig := mgr.GetFixtures("okta_group_with_users.tf", ri, t)
Expand Down
106 changes: 106 additions & 0 deletions okta/resource_okta_role_subscription.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package okta

import (
"context"
"fmt"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func resourceRoleSubscription() *schema.Resource {
return &schema.Resource{
CreateContext: resourceRoleSubscriptionCreate,
ReadContext: resourceRoleSubscriptionRead,
UpdateContext: resourceRoleSubscriptionUpdate,
DeleteContext: resourceRoleSubscriptionDelete,
Importer: &schema.ResourceImporter{
StateContext: func(_ context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
parts := strings.Split(d.Id(), "/")
if len(parts) != 2 {
return nil, fmt.Errorf("invalid role subscription specifier, expecting {roleType}/{notificationType}")
}
_ = d.Set("role_type", parts[0])
_ = d.Set("notification_type", parts[1])
d.SetId(parts[1])
return []*schema.ResourceData{d}, nil
},
},
Schema: map[string]*schema.Schema{
"role_type": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateDiagFunc: elemInSlice(validAdminRoles),
Description: "Type of the role",
},
"notification_type": {
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateDiagFunc: elemInSlice(validNotificationTypes),
Description: "Type of the notification",
},
"status": {
Type: schema.TypeString,
Optional: true,
ValidateDiagFunc: elemInSlice([]string{"subscribed", "unsubscribed"}),
Description: "Status of subscription",
},
},
}
}

func resourceRoleSubscriptionCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
status, ok := d.GetOk("status")
if !ok {
return resourceRoleSubscriptionRead(ctx, d, m)
}
subscription, _, err := getSupplementFromMetadata(m).GetRoleTypeSubscription(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))
} else {
_, err = getSupplementFromMetadata(m).RoleTypeUnsubscribe(ctx, d.Get("role_type").(string), d.Get("notification_type").(string))
}
if err != nil {
return diag.Errorf("failed to change subscription: %v", err)
}
}
d.SetId(d.Get("notification_type").(string))
return resourceRoleSubscriptionRead(ctx, d, m)
}

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))
if err != nil {
return diag.Errorf("failed get subscription: %v", err)
}
_ = d.Set("status", subscription.Status)
return nil
}

func resourceRoleSubscriptionUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
var err error
oldStatus, newStatus := d.GetChange("status")
if oldStatus == newStatus {
return nil
}
if newStatus == "subscribed" {
_, err = getSupplementFromMetadata(m).RoleTypeSubscribe(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))
}
if err != nil {
return diag.Errorf("failed to change subscription: %v", err)
}
return nil
}

func resourceRoleSubscriptionDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
return nil
}
29 changes: 29 additions & 0 deletions okta/resource_okta_role_subscription_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package okta

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccOktaRoleSubscription_crud(t *testing.T) {
ri := acctest.RandInt()
resourceName := fmt.Sprintf("%s.test", roleSubscription)
mgr := newFixtureManager(roleSubscription)
config := mgr.GetFixtures("basic.tf", ri, t)

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: testAccProvidersFactories,
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttr(resourceName, "status", "unsubscribed")),
},
},
})
}
7 changes: 7 additions & 0 deletions okta/role_subscription.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package okta

var validNotificationTypes = []string{
"CONNECTOR_AGENT", "USER_LOCKED_OUT", "APP_IMPORT", "LDAP_AGENT",
"AD_AGENT", "OKTA_ANNOUNCEMENT", "OKTA_ISSUE", "OKTA_UPDATE", "IWA_AGENT", "USER_DEPROVISION",
"REPORT_SUSPICIOUS_ACTIVITY", "RATELIMIT_NOTIFICATION",
}
51 changes: 51 additions & 0 deletions sdk/subscription.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
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)
}
36 changes: 36 additions & 0 deletions website/docs/d/role_subscription.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
layout: "okta"
page_title: "Okta: okta_role_subscription"
sidebar_current: "docs-okta-datasource-role-subscription"
description: |-
Get subscriptions of a Role with a specific type
---

# okta_role_subscription

Use this data source to retrieve role subscription with a specific type.

## Example Usage

```hcl
data "okta_role_subscription" "example" {
notification_type = "APP_IMPORT"
role_type = "SUPER_ADMIN"
}
```

## Arguments Reference

- `role_type` - (Required) Type of the role. Valid values: `"SUPER_ADMIN"`, `"ORG_ADMIN"`, `"APP_ADMIN"`, `"USER_ADMIN"`,
`"HELP_DESK_ADMIN"`, `"READ_ONLY_ADMIN"`, `"MOBILE_ADMIN"`, `"API_ACCESS_MANAGEMENT_ADMIN"`, `"REPORT_ADMIN"`,
`"GROUP_MEMBERSHIP_ADMIN"`.

- `notification_type` - (Required) Type of the notification. Valid values: `"CONNECTOR_AGENT"`, `"USER_LOCKED_OUT"`,
`"APP_IMPORT"`, `"LDAP_AGENT"`, `"AD_AGENT"`, `"OKTA_ANNOUNCEMENT"`, `"OKTA_ISSUE"`, `"OKTA_UPDATE"`, `"IWA_AGENT"`,
`"USER_DEPROVISION"`, `"REPORT_SUSPICIOUS_ACTIVITY"`, `"RATELIMIT_NOTIFICATION"`.

## Attributes Reference

- `id` - ID of the resource. Same a `notification_type`.

- `status` - Subscription status.
45 changes: 45 additions & 0 deletions website/docs/r/role_subscription.html.markdown
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
---
layout: 'okta'
page_title: 'Okta: okta_role_subscription'
sidebar_current: 'docs-okta-resource-role-subscription'
description: |-
Manages group subscription.
---

# okta_role_subscription

This resource allows you to configure subscriptions of a Role with a specific type.

## Example Usage

```hcl
resource "okta_role_subscription" "test" {
role_type = "SUPER_ADMIN"
notification_type = "APP_IMPORT"
status = "unsubscribed"
}
```

## Argument Reference

- `role_type` - (Required) Type of the role. Valid values: `"SUPER_ADMIN"`, `"ORG_ADMIN"`, `"APP_ADMIN"`, `"USER_ADMIN"`,
`"HELP_DESK_ADMIN"`, `"READ_ONLY_ADMIN"`, `"MOBILE_ADMIN"`, `"API_ACCESS_MANAGEMENT_ADMIN"`, `"REPORT_ADMIN"`,
`"GROUP_MEMBERSHIP_ADMIN"`.

- `notification_type` - (Required) Type of the notification. Valid values: `"CONNECTOR_AGENT"`, `"USER_LOCKED_OUT"`,
`"APP_IMPORT"`, `"LDAP_AGENT"`, `"AD_AGENT"`, `"OKTA_ANNOUNCEMENT"`, `"OKTA_ISSUE"`, `"OKTA_UPDATE"`, `"IWA_AGENT"`,
`"USER_DEPROVISION"`, `"REPORT_SUSPICIOUS_ACTIVITY"`, `"RATELIMIT_NOTIFICATION"`.

- `status` - (Optional) Subscription status. Valid values: `"subscribed"`, `"unsubscribed"`.

## Attributes Reference

- `id` - ID of the resource. Same a `notification_type`.

## Import

A role subscription can be imported via the Okta ID.

```
$ terraform import okta_role_subscription.example <role_type>/<notification_type>
```

0 comments on commit 1f39f9f

Please sign in to comment.