Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

okta_brand resource brand_id = default and okta_auth_server_default name = default #1570

Merged
merged 3 commits into from
Jun 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion examples/okta_auth_server_default/basic.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
resource "okta_auth_server_default" "sun_also_rises" {
name = "default"
audiences = ["api://default"]
description = "Default Authorization Server for your Applications"
}
5 changes: 5 additions & 0 deletions examples/okta_auth_server_default/basic_legacy.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
resource "okta_auth_server_default" "sun_also_rises" {
name = "default"
audiences = ["api://default"]
description = "Default Authorization Server for your Applications"
}
1 change: 0 additions & 1 deletion examples/okta_auth_server_default/basic_updated.tf
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
resource "okta_auth_server_default" "sun_also_rises" {
name = "default"
audiences = ["whatever.rise.zone"]
description = "Default Authorization Server"
status = "ACTIVE"
Expand Down
6 changes: 6 additions & 0 deletions examples/okta_auth_server_default/basic_updated_legacy.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
resource "okta_auth_server_default" "sun_also_rises" {
name = "default"
audiences = ["whatever.rise.zone"]
description = "Default Authorization Server"
status = "ACTIVE"
}
4 changes: 4 additions & 0 deletions examples/okta_brand/datasource.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@ data "okta_brands" "test" {
data "okta_brand" "example" {
brand_id = tolist(data.okta_brands.test.brands)[0].id
}

data "okta_brand" "default" {
brand_id = "default"
}
8 changes: 8 additions & 0 deletions examples/okta_brand/import.tf
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,12 @@ data "okta_brands" "test" {

resource "okta_brand" "example" {
brand_id = tolist(data.okta_brands.test.brands)[0].id

lifecycle {
ignore_changes = [
agree_to_custom_privacy_policy,
custom_privacy_policy_url,
remove_powered_by_okta
]
}
}
17 changes: 17 additions & 0 deletions okta/brand.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package okta

import (
"context"
"encoding/json"
"errors"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/okta/okta-sdk-golang/v3/okta"
Expand Down Expand Up @@ -105,3 +107,18 @@ func flattenBrand(brand *okta.Brand) map[string]interface{} {

return attrs
}

func getDefaultBrand(ctx context.Context, m interface{}) (*okta.Brand, error) {
brands, _, err := getOktaV3ClientFromMetadata(m).CustomizationApi.ListBrands(ctx).Execute()
if err != nil {
return nil, err
}

for _, brand := range brands {
if *brand.IsDefault {
return &brand, nil
}
}

return nil, errors.New("failed to get default brand")
}
15 changes: 11 additions & 4 deletions okta/data_source_okta_brand.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,21 @@ func dataSourceBrand() *schema.Resource {
func dataSourceBrandRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
var brand *okta.Brand
var err error
brandID, ok := d.GetOk("brand_id")
if ok {
logger(m).Info("reading brand by ID", "id", brandID.(string))
brand, _, err = getOktaV3ClientFromMetadata(m).CustomizationApi.GetBrand(ctx, brandID.(string)).Execute()
brandID := d.Get("brand_id").(string)

if brandID == "default" {
brand, err = getDefaultBrand(ctx, m)
if err != nil {
return diag.Errorf("failed to get default brand for org: %v", err)
}
} else {
logger(m).Info("reading brand by ID", "id", brandID)
brand, _, err = getOktaV3ClientFromMetadata(m).CustomizationApi.GetBrand(ctx, brandID).Execute()
if err != nil {
return diag.Errorf("failed to get brand: %v", err)
}
}

d.SetId(brand.GetId())
rawMap := flattenBrand(brand)
err = setNonPrimitives(d, rawMap)
Expand Down
2 changes: 2 additions & 0 deletions okta/data_source_okta_brand_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ func TestAccDataSourceOktaBrand_read(t *testing.T) {
resource.TestCheckResourceAttrSet("data.okta_brand.example", "id"),
resource.TestCheckResourceAttrSet("data.okta_brand.example", "name"),
resource.TestCheckResourceAttrSet("data.okta_brand.example", "links"),
resource.TestCheckResourceAttrSet("data.okta_brand.default", "id"),
resource.TestCheckResourceAttrSet("data.okta_brand.default", "links"),
),
},
},
Expand Down
27 changes: 20 additions & 7 deletions okta/resource_okta_brand.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,27 @@ func resourceBrand() *schema.Resource {
}

func resourceBrandCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
brandId := d.Get("brand_id").(string)
// check that the brand exists, create is short circuited as a reader
brand, resp, err := getOktaV3ClientFromMetadata(m).CustomizationApi.GetBrand(ctx, brandId).Execute()
if err := v3suppressErrorOn404(resp, err); err != nil {
return diag.Errorf("failed to get brand %q: %v", brandId, err)
brandID := d.Get("brand_id").(string)

var brand *okta.Brand
var resp *okta.APIResponse
var err error

if brandID == "default" {
brand, err = getDefaultBrand(ctx, m)
if err != nil {
return diag.Errorf("failed to get default brand for org: %v", err)
}
} else {
// check that the brand exists, create is short circuited as a reader
brand, resp, err = getOktaV3ClientFromMetadata(m).CustomizationApi.GetBrand(ctx, brandID).Execute()
if err := v3suppressErrorOn404(resp, err); err != nil {
return diag.Errorf("failed to get brand %q: %v", brandID, err)
}
}
logger(m).Info("setting brand id", "id", brandId)
d.SetId(brandId)

logger(m).Info("setting brand id", "id", brandID)
d.SetId(brandID)
rawMap := flattenBrand(brand)
err = setNonPrimitives(d, rawMap)
if err != nil {
Expand Down
35 changes: 35 additions & 0 deletions okta/resource_okta_brand_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,38 @@ func TestAccResourceOktaBrand_import_update(t *testing.T) {
},
})
}

func TestAccResourceOktaBrand_default_brand(t *testing.T) {
config := `
resource "okta_brand" "example" {
brand_id = "default"
lifecycle {
ignore_changes = [
agree_to_custom_privacy_policy,
custom_privacy_policy_url,
remove_powered_by_okta
]
}
}
`
oktaResourceTest(t, resource.TestCase{
PreCheck: testAccPreCheck(t),
ErrorCheck: testAccErrorChecks(t),
ProviderFactories: testAccProvidersFactories,
CheckDestroy: func(s *terraform.State) error {
// brand api doens't have real delete for a brand
return nil
},
Steps: []resource.TestStep{
{
Config: config,
Destroy: false,
ExpectNonEmptyPlan: true,
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrSet("okta_brand.example", "id"),
resource.TestCheckResourceAttr("okta_brand.example", "brand_id", "default"),
),
},
},
})
}
54 changes: 50 additions & 4 deletions okta/resource_okta_default_auth_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ package okta

import (
"context"
"fmt"

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

func resourceAuthServerDefault() *schema.Resource {
Expand Down Expand Up @@ -52,7 +54,8 @@ func resourceAuthServerDefault() *schema.Resource {
},
"name": {
Type: schema.TypeString,
Required: true,
Optional: true,
Default: "default",
},
"issuer": {
Type: schema.TypeString,
Expand Down Expand Up @@ -101,15 +104,51 @@ func resourceAuthServerDefaultRead(ctx context.Context, d *schema.ResourceData,
return nil
}

func getDefaultAuthServer(ctx context.Context, m interface{}, serverID string) (authServer *sdk.AuthorizationServer, err error) {
if serverID != "" {
authServer, _, err = getOktaClientFromMetadata(m).AuthorizationServer.GetAuthorizationServer(ctx, serverID)
return
}

authServers, _, err := getOktaClientFromMetadata(m).AuthorizationServer.ListAuthorizationServers(ctx, nil)
if err != nil {
return nil, err
}
for _, server := range authServers {
if *server.Default {
authServer = server
return
}
}

return nil, fmt.Errorf("failed to find default authorization server")
}

func resourceAuthServerDefaultUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
id := d.Id()

// when id is blank this is the create case as this function is used for
// both create and update
if id == "" {
id = d.Get("name").(string)
name := d.Get("name").(string)
if name != "" {
id = name
// Legacy implementation allowed name to be set to something other
// than "default" which was to loose of a constraint. In order to
// not have breaking changes to existing configurations we will warn
// when we find this situation.
if name != "default" {
logger(m).Warn("\"name\" argument is not \"default\". Allowing this legacy behavior.")
}
}
}
authServer, _, err := getOktaClientFromMetadata(m).AuthorizationServer.GetAuthorizationServer(ctx, id)

authServer, err := getDefaultAuthServer(ctx, m, id)
if err != nil {
return diag.Errorf("failed to get default authorization server: %v", err)
}
id = authServer.Id

if status, ok := d.GetOk("status"); ok {
client := getOktaClientFromMetadata(m)
if status.(string) == statusActive && authServer.Status != statusActive {
Expand All @@ -125,10 +164,17 @@ func resourceAuthServerDefaultUpdate(ctx context.Context, d *schema.ResourceData
}
}
}

_name, ok := d.GetOk("name")
if ok {
authServer.Name = _name.(string)
}
if *authServer.Default && authServer.Name == "" {
authServer.Name = "default"
}
authServer.Audiences = convertInterfaceToStringSet(d.Get("audiences"))
authServer.Credentials.Signing.RotationMode = d.Get("credentials_rotation_mode").(string)
authServer.Description = d.Get("description").(string)
authServer.Name = d.Get("name").(string)
authServer.IssuerMode = d.Get("issuer_mode").(string)
_, _, err = getOktaClientFromMetadata(m).AuthorizationServer.UpdateAuthorizationServer(ctx, id, *authServer)
if err != nil {
Expand Down
47 changes: 47 additions & 0 deletions okta/resource_okta_default_auth_server_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,50 @@ func TestAccOktaAuthServerDefault_crud(t *testing.T) {
},
})
}

func TestAccOktaAuthServerDefault_legacy_crud(t *testing.T) {
resourceName := fmt.Sprintf("%s.sun_also_rises", authServerDefault)
mgr := newFixtureManager(authServerDefault, t.Name())
config := mgr.GetFixtures("basic_legacy.tf", t)
updatedConfig := mgr.GetFixtures("basic_updated_legacy.tf", t)

oktaResourceTest(t, resource.TestCase{
PreCheck: testAccPreCheck(t),
ErrorCheck: testAccErrorChecks(t),
ProviderFactories: testAccProvidersFactories,
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: config,
Check: resource.ComposeTestCheckFunc(
ensureResourceExists(resourceName, authServerExists),
resource.TestCheckResourceAttr(resourceName, "description", "Default Authorization Server for your Applications"),
resource.TestCheckResourceAttr(resourceName, "name", "default"),
resource.TestCheckResourceAttr(resourceName, "audiences.#", "1"),
resource.TestCheckResourceAttr(resourceName, "credentials_rotation_mode", "MANUAL"),
),
},
{
Config: updatedConfig,
Check: resource.ComposeTestCheckFunc(
ensureResourceExists(resourceName, authServerExists),
resource.TestCheckResourceAttr(resourceName, "description", "Default Authorization Server"),
resource.TestCheckResourceAttr(resourceName, "name", "default"),
resource.TestCheckResourceAttr(resourceName, "status", "ACTIVE"),
resource.TestCheckResourceAttr(resourceName, "audiences.#", "1"),
resource.TestCheckResourceAttr(resourceName, "credentials_rotation_mode", "MANUAL"),
),
},
{
Config: config,
Check: resource.ComposeTestCheckFunc(
ensureResourceExists(resourceName, authServerExists),
resource.TestCheckResourceAttr(resourceName, "description", "Default Authorization Server for your Applications"),
resource.TestCheckResourceAttr(resourceName, "name", "default"),
resource.TestCheckResourceAttr(resourceName, "audiences.#", "1"),
resource.TestCheckResourceAttr(resourceName, "credentials_rotation_mode", "MANUAL"),
),
},
},
})
}
Loading