From d29b614eb23d613a15c6c5bb6914fe01506b98fb Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Thu, 21 Sep 2023 01:39:51 -0500 Subject: [PATCH 01/17] create sdk custom API functions for client role assignment, including custom structs for operations --- sdk/client_role_assignment.go | 76 +++++++++++++++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 sdk/client_role_assignment.go diff --git a/sdk/client_role_assignment.go b/sdk/client_role_assignment.go new file mode 100644 index 000000000..fae13dc06 --- /dev/null +++ b/sdk/client_role_assignment.go @@ -0,0 +1,76 @@ +package sdk + +import ( + "context" + "fmt" + "net/http" + "time" +) + +// Regular roles struct is missing `resource-set` and `role` fields, from CUSTOM role response. +type ClientRole struct { + Embedded interface{} `json:"_embedded,omitempty"` + Links interface{} `json:"_links,omitempty"` + AssignmentType string `json:"assignmentType,omitempty"` + Created *time.Time `json:"created,omitempty"` + Description string `json:"description,omitempty"` + Id string `json:"id,omitempty"` + Label string `json:"label,omitempty"` + LastUpdated *time.Time `json:"lastUpdated,omitempty"` + Status string `json:"status,omitempty"` + Type string `json:"type,omitempty"` + ResourceSet string `json:"resource-set,omitempty"` + Role string `json:"role,omitempty"` +} + +func (m *APISupplement) ListClientRoles(ctx context.Context, clientID string) ([]*ClientRole, *Response, error) { + var roles []*ClientRole + + url := fmt.Sprintf("/oauth2/v1/clients/%s/roles", clientID) + req, err := m.RequestExecutor.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodGet, url, nil) + if err != nil { + return nil, nil, err + } + resp, err := m.RequestExecutor.Do(ctx, req, &roles) + return roles, resp, err +} + +type ClientRoleAssignment struct { + ResourceSet string `json:"resource-set,omitempty"` + Role string `json:"role,omitempty"` + Type string `json:"type"` +} + +func (m *APISupplement) AssignClientRole(ctx context.Context, clientID string, assignment *ClientRoleAssignment) (*ClientRole, *Response, error) { + var role *ClientRole + + url := fmt.Sprintf("/oauth2/v1/clients/%s/roles", clientID) + req, err := m.RequestExecutor.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodPost, url, assignment) + if err != nil { + return nil, nil, err + } + resp, err := m.RequestExecutor.Do(ctx, req, &role) + return role, resp, err +} + +func (m *APISupplement) GetClientRole(ctx context.Context, clientID, roleID string) (*ClientRole, *Response, error) { + var role *ClientRole + + url := fmt.Sprintf("/oauth2/v1/clients/%s/roles/%s", clientID, roleID) + req, err := m.RequestExecutor.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodGet, url, nil) + if err != nil { + return nil, nil, err + } + resp, err := m.RequestExecutor.Do(ctx, req, &role) + return role, resp, err +} + +func (m *APISupplement) UnassignClientRole(ctx context.Context, clientID, roleID string) (*Response, error) { + url := fmt.Sprintf("/oauth2/v1/clients/%s/roles/%s", clientID, roleID) + req, err := m.RequestExecutor.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodDelete, url, nil) + if err != nil { + return nil, err + } + resp, err := m.RequestExecutor.Do(ctx, req, nil) + return resp, err +} From 750bac65683e7907ffdd56535d1177cf05462e29 Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Thu, 21 Sep 2023 12:55:00 -0500 Subject: [PATCH 02/17] use cloned request executor --- sdk/client_role_assignment.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/sdk/client_role_assignment.go b/sdk/client_role_assignment.go index fae13dc06..8a13ef4fc 100644 --- a/sdk/client_role_assignment.go +++ b/sdk/client_role_assignment.go @@ -27,11 +27,12 @@ func (m *APISupplement) ListClientRoles(ctx context.Context, clientID string) ([ var roles []*ClientRole url := fmt.Sprintf("/oauth2/v1/clients/%s/roles", clientID) - req, err := m.RequestExecutor.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodGet, url, nil) + re := m.cloneRequestExecutor() + req, err := re.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodGet, url, nil) if err != nil { return nil, nil, err } - resp, err := m.RequestExecutor.Do(ctx, req, &roles) + resp, err := re.Do(ctx, req, &roles) return roles, resp, err } @@ -45,11 +46,12 @@ func (m *APISupplement) AssignClientRole(ctx context.Context, clientID string, a var role *ClientRole url := fmt.Sprintf("/oauth2/v1/clients/%s/roles", clientID) - req, err := m.RequestExecutor.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodPost, url, assignment) + re := m.cloneRequestExecutor() + req, err := re.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodPost, url, assignment) if err != nil { return nil, nil, err } - resp, err := m.RequestExecutor.Do(ctx, req, &role) + resp, err := re.Do(ctx, req, &role) return role, resp, err } @@ -57,20 +59,22 @@ func (m *APISupplement) GetClientRole(ctx context.Context, clientID, roleID stri var role *ClientRole url := fmt.Sprintf("/oauth2/v1/clients/%s/roles/%s", clientID, roleID) - req, err := m.RequestExecutor.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodGet, url, nil) + re := m.cloneRequestExecutor() + req, err := re.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodGet, url, nil) if err != nil { return nil, nil, err } - resp, err := m.RequestExecutor.Do(ctx, req, &role) + resp, err := re.Do(ctx, req, &role) return role, resp, err } func (m *APISupplement) UnassignClientRole(ctx context.Context, clientID, roleID string) (*Response, error) { url := fmt.Sprintf("/oauth2/v1/clients/%s/roles/%s", clientID, roleID) - req, err := m.RequestExecutor.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodDelete, url, nil) + re := m.cloneRequestExecutor() + req, err := re.WithAccept("application/json").WithContentType("application/json").NewRequest(http.MethodDelete, url, nil) if err != nil { return nil, err } - resp, err := m.RequestExecutor.Do(ctx, req, nil) + resp, err := re.Do(ctx, req, nil) return resp, err } From 17613d9e377c4913e8405c9a52c6eb2f4eb5169c Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Thu, 21 Sep 2023 17:21:33 -0500 Subject: [PATCH 03/17] add code for AppOAuthRoleAssignment resource --- ...resource_okta_app_oauth_role_assignment.go | 201 ++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 okta/resource_okta_app_oauth_role_assignment.go diff --git a/okta/resource_okta_app_oauth_role_assignment.go b/okta/resource_okta_app_oauth_role_assignment.go new file mode 100644 index 000000000..9455737b5 --- /dev/null +++ b/okta/resource_okta_app_oauth_role_assignment.go @@ -0,0 +1,201 @@ +package okta + +import ( + "context" + + "github.com/hashicorp/terraform-plugin-framework/path" + "github.com/hashicorp/terraform-plugin-framework/resource" + "github.com/hashicorp/terraform-plugin-framework/resource/schema" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier" + "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier" + "github.com/hashicorp/terraform-plugin-framework/types" + "github.com/okta/terraform-provider-okta/sdk" +) + +var _ resource.ResourceWithValidateConfig = &appOAuthRoleAssignmentResource{} + +func NewAppOAuthRoleAssignmentResource() resource.Resource { + return &appOAuthRoleAssignmentResource{} +} + +type appOAuthRoleAssignmentResource struct { + *Config +} + +type OAuthRoleAssignmentResourceModel struct { + ID types.String `tfsdk:"id"` + ClientID types.String `tfsdk:"client_id"` + Type types.String `tfsdk:"type"` + ResourceSet types.String `tfsdk:"resource_set"` + Role types.String `tfsdk:"role"` + Status types.String `tfsdk:"status"` + Label types.String `tfsdk:"label"` +} + +func (r *appOAuthRoleAssignmentResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) { + resp.TypeName = req.ProviderTypeName + "_app_oauth_role_assignment" +} + +// func (r *appOAuthRoleAssignmentResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { +// if req.ProviderData == nil { +// return +// } + +// config, ok := req.ProviderData.(*Config) +// if !ok { +// resp.Diagnostics.AddError( +// "Unexpected Resource Configure Type", +// fmt.Sprintf("Expected *Config, got: %T. Please report this issue to the provider developers.", req.ProviderData), +// ) +// return +// } +// r.Config = config +// } + +func (r *appOAuthRoleAssignmentResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { + resp.Schema = schema.Schema{ + Description: "Manages assignment of OAuth Role to an Application", + MarkdownDescription: "Manages assignment of OAuth Role to an Application", + Attributes: map[string]schema.Attribute{ + "id": schema.StringAttribute{ + Description: "Role Assignment ID", + MarkdownDescription: "Role Assignment ID", + Computed: true, + }, + "client_id": schema.StringAttribute{ + Description: "Client ID for the role to be assigned to", + MarkdownDescription: "Client ID for the role to be assigned to", + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "type": schema.StringAttribute{ + Description: "Role type to assign. This can be one of the standard Okta roles, such as `HELP_DESK_ADMIN` or `CUSTOM`. Using custom requires the `resource_set` and `role` attributes to be set.", + MarkdownDescription: "Role type to assign. This can be one of the standard Okta roles, such as `HELP_DESK_ADMIN` or `CUSTOM`. Using custom requires the `resource_set` and `role` attributes to be set.", + Required: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "resource_set": schema.StringAttribute{ + Description: "Resource set for the custom role to assign, must be the ID of the created resource set.", + MarkdownDescription: "Resource set for the custom role to assign, must be the ID of the created resource set.", + Optional: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "role": schema.StringAttribute{ + Description: "Custom Role ID", + MarkdownDescription: "Custom Role ID", + Optional: true, + PlanModifiers: []planmodifier.String{ + stringplanmodifier.RequiresReplace(), + }, + }, + "status": schema.StringAttribute{ + Description: "Status of the role assignment", + MarkdownDescription: "Status of the role assignment", + Computed: true, + }, + "label": schema.StringAttribute{ + Description: "Label of the role assignment", + MarkdownDescription: "Label of the role assignment", + Computed: true, + }, + }, + } +} + +func (r *appOAuthRoleAssignmentResource) ValidateConfig(ctx context.Context, req resource.ValidateConfigRequest, resp *resource.ValidateConfigResponse) { + var data *OAuthRoleAssignmentResourceModel + + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + if data.Type.ValueString() == "CUSTOM" && (data.ResourceSet.ValueString() == "" || data.Role.ValueString() == "") { + resp.Diagnostics.AddAttributeError( + path.Root("type"), + "Missing attribute configuration", + "When type is set to 'CUSTOM', the resource_set and role attributes must be set.", + ) + } +} + +func (r *appOAuthRoleAssignmentResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) { + var data *OAuthRoleAssignmentResourceModel + + resp.Diagnostics.Append(req.Config.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + roleAssignmentRequest := &sdk.ClientRoleAssignment{ + Type: data.Type.ValueString(), + ResourceSet: data.ResourceSet.ValueString(), + Role: data.Role.ValueString(), + } + + role, _, err := r.Config.oktaSDKsupplementClient.AssignClientRole(ctx, data.ClientID.ValueString(), roleAssignmentRequest) + if err != nil { + resp.Diagnostics.AddError("Unable to assign role to client", err.Error()) + return + } + + data.ID = types.StringValue(role.Id) + data.Status = types.StringValue(role.Status) + data.Label = types.StringValue(role.Label) + data.Type = types.StringValue(role.Type) + data.ResourceSet = types.StringValue(role.ResourceSet) + data.Role = types.StringValue(role.Role) + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *appOAuthRoleAssignmentResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) { + var data *OAuthRoleAssignmentResourceModel + + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + role, _, err := r.Config.oktaSDKsupplementClient.GetClientRole(ctx, data.ClientID.ValueString(), data.ID.ValueString()) + if err != nil { + resp.Diagnostics.AddError("Unable to read role assignment", err.Error()) + return + } + + data.ID = types.StringValue(role.Id) + data.Status = types.StringValue(role.Status) + data.Label = types.StringValue(role.Label) + data.Type = types.StringValue(role.Type) + data.ResourceSet = types.StringValue(role.ResourceSet) + data.Role = types.StringValue(role.Role) + + resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) +} + +func (r *appOAuthRoleAssignmentResource) Update(_ context.Context, _ resource.UpdateRequest, resp *resource.UpdateResponse) { + resp.Diagnostics.AddError( + "Update not supported", + "OAuth Role Assignments cannot be updated. If you get to this contact the provider maintainers as this should not be hit.", + ) +} + +func (r *appOAuthRoleAssignmentResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { + var data *OAuthRoleAssignmentResourceModel + + resp.Diagnostics.Append(req.State.Get(ctx, &data)...) + if resp.Diagnostics.HasError() { + return + } + + _, err := r.Config.oktaSDKsupplementClient.UnassignClientRole(ctx, data.ClientID.ValueString(), data.ID.ValueString()) + if err != nil { + resp.Diagnostics.AddError("Unable to delete role assignment", err.Error()) + return + } +} From 225cb325f25430d81e3ace370900c87ac553d40b Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Thu, 21 Sep 2023 17:22:06 -0500 Subject: [PATCH 04/17] add resource to provider and sort list --- okta/framework_provider.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/okta/framework_provider.go b/okta/framework_provider.go index 55604a8b6..3526c1ef3 100644 --- a/okta/framework_provider.go +++ b/okta/framework_provider.go @@ -249,10 +249,11 @@ func (p *FrameworkProvider) DataSources(_ context.Context) []func() datasource.D func (p *FrameworkProvider) Resources(_ context.Context) []func() resource.Resource { return []func() resource.Resource{ NewAppAccessPolicyAssignmentResource, + NewAppOAuthRoleAssignmentResource, NewBrandResource, NewPolicyDeviceAssuranceAndroidResource, - NewPolicyDeviceAssuranceIOSResource, NewPolicyDeviceAssuranceChromeOSResource, + NewPolicyDeviceAssuranceIOSResource, NewPolicyDeviceAssuranceMacOSResource, NewPolicyDeviceAssuranceWindowsResource, } From cbb7acc99c4201c53492bee2a74f2fcc2a093976 Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Thu, 21 Sep 2023 17:32:19 -0500 Subject: [PATCH 05/17] start adding test code --- ...rce_okta_app_oauth_role_assignment_test.go | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 okta/resource_okta_app_oauth_role_assignment_test.go diff --git a/okta/resource_okta_app_oauth_role_assignment_test.go b/okta/resource_okta_app_oauth_role_assignment_test.go new file mode 100644 index 000000000..a286fedd6 --- /dev/null +++ b/okta/resource_okta_app_oauth_role_assignment_test.go @@ -0,0 +1,50 @@ +package okta + +import ( + "context" + "errors" + "fmt" + "strings" + "testing" + + "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" + "github.com/okta/terraform-provider-okta/sdk" + "github.com/okta/terraform-provider-okta/sdk/query" +) + +func TestAccResourceOktaAppOAuthRoleAssignment_basic(t *testing.T) { + mgr := newFixtureManager("okta_app_oauth_role_assignment", t.Name()) + + oktaResourceTest(t, resource.TestCase{ + PreCheck: testAccPreCheck(t), + ErrorCheck: testAccErrorChecks(t), + ProtoV5ProviderFactories: testAccMergeProvidersFactories, + Steps: []resource.TestStep{ + { + Config: mgr.GetFixtures("basic.tf"), + }, + { + Config: mgr.GetFixtures("basic_updated.tf"), + } + } + }) +} + +func TestAccResourceOktaAppOAuthRoleAssignment_custom(t *testing.T) { + mgr := newFixtureManager("okta_app_oauth_role_assignment", t.Name()) + + oktaResourceTest(t, resource.TestCase{ + PreCheck: testAccPreCheck(t), + ErrorCheck: testAccErrorChecks(t), + ProtoV5ProviderFactories: testAccMergeProvidersFactories, + Steps: []resource.TestStep{ + { + Config: mgr.GetFixtures("custom.tf"), + }, + { + Config: mgr.GetFixtures("custom_updated.tf"), + } + } + }) +} From 2fa4484036a15dbf0056b366f03d15dbaa2d7fd2 Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Thu, 21 Sep 2023 23:24:21 -0500 Subject: [PATCH 06/17] add basic fixtures --- .../okta_app_oauth_role_assignment/basic.tf | 12 ++++++++++ .../basic_updated.tf | 12 ++++++++++ ...rce_okta_app_oauth_role_assignment_test.go | 23 +++++++------------ 3 files changed, 32 insertions(+), 15 deletions(-) create mode 100644 examples/okta_app_oauth_role_assignment/basic.tf create mode 100644 examples/okta_app_oauth_role_assignment/basic_updated.tf diff --git a/examples/okta_app_oauth_role_assignment/basic.tf b/examples/okta_app_oauth_role_assignment/basic.tf new file mode 100644 index 000000000..f5ac31ce3 --- /dev/null +++ b/examples/okta_app_oauth_role_assignment/basic.tf @@ -0,0 +1,12 @@ +resource "okta_app_oauth" "test" { + label = "testAcc_replace_with_uuid" + type = "service" + response_types = ["token"] + grant_types = ["client_credentials"] + jwks_uri = "https://example.com" +} + +resource "okta_app_oauth_role_assignment" "test" { + client_id = okta_app_oauth.test.client_id + type = "HELP_DESK_ADMIN" +} diff --git a/examples/okta_app_oauth_role_assignment/basic_updated.tf b/examples/okta_app_oauth_role_assignment/basic_updated.tf new file mode 100644 index 000000000..c246b6479 --- /dev/null +++ b/examples/okta_app_oauth_role_assignment/basic_updated.tf @@ -0,0 +1,12 @@ +resource "okta_app_oauth" "test" { + label = "testAcc_replace_with_uuid" + type = "service" + response_types = ["token"] + grant_types = ["client_credentials"] + jwks_uri = "https://example.com" +} + +resource "okta_app_oauth_role_assignment" "test" { + client_id = okta_app_oauth.test.client_id + type = "GROUP_MEMBERSHIP_ADMIN" +} diff --git a/okta/resource_okta_app_oauth_role_assignment_test.go b/okta/resource_okta_app_oauth_role_assignment_test.go index a286fedd6..d5ad56b05 100644 --- a/okta/resource_okta_app_oauth_role_assignment_test.go +++ b/okta/resource_okta_app_oauth_role_assignment_test.go @@ -1,16 +1,9 @@ package okta import ( - "context" - "errors" - "fmt" - "strings" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" - "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" - "github.com/okta/terraform-provider-okta/sdk" - "github.com/okta/terraform-provider-okta/sdk/query" ) func TestAccResourceOktaAppOAuthRoleAssignment_basic(t *testing.T) { @@ -22,12 +15,12 @@ func TestAccResourceOktaAppOAuthRoleAssignment_basic(t *testing.T) { ProtoV5ProviderFactories: testAccMergeProvidersFactories, Steps: []resource.TestStep{ { - Config: mgr.GetFixtures("basic.tf"), + Config: mgr.GetFixtures("basic.tf", t), }, { - Config: mgr.GetFixtures("basic_updated.tf"), - } - } + Config: mgr.GetFixtures("basic_updated.tf", t), + }, + }, }) } @@ -40,11 +33,11 @@ func TestAccResourceOktaAppOAuthRoleAssignment_custom(t *testing.T) { ProtoV5ProviderFactories: testAccMergeProvidersFactories, Steps: []resource.TestStep{ { - Config: mgr.GetFixtures("custom.tf"), + Config: mgr.GetFixtures("custom.tf", t), }, { - Config: mgr.GetFixtures("custom_updated.tf"), - } - } + Config: mgr.GetFixtures("custom_updated.tf", t), + }, + }, }) } From 4e3d801a1c19efadb816dd2a4a39f711073d3e2b Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Thu, 21 Sep 2023 23:28:10 -0500 Subject: [PATCH 07/17] add test checks --- ...resource_okta_app_oauth_role_assignment_test.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/okta/resource_okta_app_oauth_role_assignment_test.go b/okta/resource_okta_app_oauth_role_assignment_test.go index d5ad56b05..48dab4a0c 100644 --- a/okta/resource_okta_app_oauth_role_assignment_test.go +++ b/okta/resource_okta_app_oauth_role_assignment_test.go @@ -16,9 +16,23 @@ func TestAccResourceOktaAppOAuthRoleAssignment_basic(t *testing.T) { Steps: []resource.TestStep{ { Config: mgr.GetFixtures("basic.tf", t), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("okta_app_oauth_role_assignment.test", "type", "HELP_DESK_ADMIN"), + resource.TestCheckResourceAttr("okta_app_oauth_role_assignment.test", "status", "ACTIVE"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "id"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "client_id"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "label"), + ), }, { Config: mgr.GetFixtures("basic_updated.tf", t), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("okta_app_oauth_role_assignment.test", "type", "GROUP_MEMBERSHIP_ADMIN"), + resource.TestCheckResourceAttr("okta_app_oauth_role_assignment.test", "status", "ACTIVE"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "id"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "client_id"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "label"), + ), }, }, }) From 95892568d544d54dc9892044520830e38fe46d0e Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Thu, 21 Sep 2023 23:42:13 -0500 Subject: [PATCH 08/17] add back Configure function, switch optional fields in the JSON to pointers to ensure proper null handling --- ...resource_okta_app_oauth_role_assignment.go | 59 ++++++++++--------- sdk/client_role_assignment.go | 22 +++---- 2 files changed, 41 insertions(+), 40 deletions(-) diff --git a/okta/resource_okta_app_oauth_role_assignment.go b/okta/resource_okta_app_oauth_role_assignment.go index 9455737b5..5739b78f6 100644 --- a/okta/resource_okta_app_oauth_role_assignment.go +++ b/okta/resource_okta_app_oauth_role_assignment.go @@ -2,6 +2,7 @@ package okta import ( "context" + "fmt" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -36,21 +37,21 @@ func (r *appOAuthRoleAssignmentResource) Metadata(_ context.Context, req resourc resp.TypeName = req.ProviderTypeName + "_app_oauth_role_assignment" } -// func (r *appOAuthRoleAssignmentResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { -// if req.ProviderData == nil { -// return -// } - -// config, ok := req.ProviderData.(*Config) -// if !ok { -// resp.Diagnostics.AddError( -// "Unexpected Resource Configure Type", -// fmt.Sprintf("Expected *Config, got: %T. Please report this issue to the provider developers.", req.ProviderData), -// ) -// return -// } -// r.Config = config -// } +func (r *appOAuthRoleAssignmentResource) Configure(_ context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) { + if req.ProviderData == nil { + return + } + + config, ok := req.ProviderData.(*Config) + if !ok { + resp.Diagnostics.AddError( + "Unexpected Resource Configure Type", + fmt.Sprintf("Expected *Config, got: %T. Please report this issue to the provider developers.", req.ProviderData), + ) + return + } + r.Config = config +} func (r *appOAuthRoleAssignmentResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ @@ -134,8 +135,8 @@ func (r *appOAuthRoleAssignmentResource) Create(ctx context.Context, req resourc roleAssignmentRequest := &sdk.ClientRoleAssignment{ Type: data.Type.ValueString(), - ResourceSet: data.ResourceSet.ValueString(), - Role: data.Role.ValueString(), + ResourceSet: data.ResourceSet.ValueStringPointer(), + Role: data.Role.ValueStringPointer(), } role, _, err := r.Config.oktaSDKsupplementClient.AssignClientRole(ctx, data.ClientID.ValueString(), roleAssignmentRequest) @@ -144,12 +145,12 @@ func (r *appOAuthRoleAssignmentResource) Create(ctx context.Context, req resourc return } - data.ID = types.StringValue(role.Id) - data.Status = types.StringValue(role.Status) - data.Label = types.StringValue(role.Label) - data.Type = types.StringValue(role.Type) - data.ResourceSet = types.StringValue(role.ResourceSet) - data.Role = types.StringValue(role.Role) + data.ID = types.StringPointerValue(role.Id) + data.Status = types.StringPointerValue(role.Status) + data.Label = types.StringPointerValue(role.Label) + data.Type = types.StringPointerValue(role.Type) + data.ResourceSet = types.StringPointerValue(role.ResourceSet) + data.Role = types.StringPointerValue(role.Role) resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) } @@ -168,12 +169,12 @@ func (r *appOAuthRoleAssignmentResource) Read(ctx context.Context, req resource. return } - data.ID = types.StringValue(role.Id) - data.Status = types.StringValue(role.Status) - data.Label = types.StringValue(role.Label) - data.Type = types.StringValue(role.Type) - data.ResourceSet = types.StringValue(role.ResourceSet) - data.Role = types.StringValue(role.Role) + data.ID = types.StringPointerValue(role.Id) + data.Status = types.StringPointerValue(role.Status) + data.Label = types.StringPointerValue(role.Label) + data.Type = types.StringPointerValue(role.Type) + data.ResourceSet = types.StringPointerValue(role.ResourceSet) + data.Role = types.StringPointerValue(role.Role) resp.Diagnostics.Append(resp.State.Set(ctx, &data)...) } diff --git a/sdk/client_role_assignment.go b/sdk/client_role_assignment.go index 8a13ef4fc..edc642877 100644 --- a/sdk/client_role_assignment.go +++ b/sdk/client_role_assignment.go @@ -11,16 +11,16 @@ import ( type ClientRole struct { Embedded interface{} `json:"_embedded,omitempty"` Links interface{} `json:"_links,omitempty"` - AssignmentType string `json:"assignmentType,omitempty"` + AssignmentType *string `json:"assignmentType,omitempty"` Created *time.Time `json:"created,omitempty"` - Description string `json:"description,omitempty"` - Id string `json:"id,omitempty"` - Label string `json:"label,omitempty"` + Description *string `json:"description,omitempty"` + Id *string `json:"id,omitempty"` + Label *string `json:"label,omitempty"` LastUpdated *time.Time `json:"lastUpdated,omitempty"` - Status string `json:"status,omitempty"` - Type string `json:"type,omitempty"` - ResourceSet string `json:"resource-set,omitempty"` - Role string `json:"role,omitempty"` + Status *string `json:"status,omitempty"` + Type *string `json:"type,omitempty"` + ResourceSet *string `json:"resource-set,omitempty"` + Role *string `json:"role,omitempty"` } func (m *APISupplement) ListClientRoles(ctx context.Context, clientID string) ([]*ClientRole, *Response, error) { @@ -37,9 +37,9 @@ func (m *APISupplement) ListClientRoles(ctx context.Context, clientID string) ([ } type ClientRoleAssignment struct { - ResourceSet string `json:"resource-set,omitempty"` - Role string `json:"role,omitempty"` - Type string `json:"type"` + ResourceSet *string `json:"resource-set,omitempty"` + Role *string `json:"role,omitempty"` + Type string `json:"type"` } func (m *APISupplement) AssignClientRole(ctx context.Context, clientID string, assignment *ClientRoleAssignment) (*ClientRole, *Response, error) { From b8bdea32179aa6f88f5e54c6be3930679bb0ef72 Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Thu, 21 Sep 2023 23:47:14 -0500 Subject: [PATCH 09/17] add test fixtures for CUSTOM --- .../okta_app_oauth_role_assignment/custom.tf | 37 +++++++++++++++++++ .../custom_updated.tf | 37 +++++++++++++++++++ ...rce_okta_app_oauth_role_assignment_test.go | 18 +++++++++ 3 files changed, 92 insertions(+) create mode 100644 examples/okta_app_oauth_role_assignment/custom.tf create mode 100644 examples/okta_app_oauth_role_assignment/custom_updated.tf diff --git a/examples/okta_app_oauth_role_assignment/custom.tf b/examples/okta_app_oauth_role_assignment/custom.tf new file mode 100644 index 000000000..4f12e0242 --- /dev/null +++ b/examples/okta_app_oauth_role_assignment/custom.tf @@ -0,0 +1,37 @@ +resource "okta_app_oauth" "test" { + label = "testAcc_replace_with_uuid" + type = "service" + response_types = ["token"] + grant_types = ["client_credentials"] + jwks_uri = "https://example.com" +} + +variable "hostname" { + type = string +} + +locals { + org_url = "https://${var.hostname}" +} + +resource "okta_admin_role_custom" "test" { + label = "testAcc_replace_with_uuid" + description = "testing, testing" + permissions = ["okta.apps.assignment.manage", "okta.users.manage", "okta.apps.manage"] +} + +resource "okta_resource_set" "test" { + label = "testAcc_replace_with_uuid" + description = "testing, testing" + resources = [ + format("%s/api/v1/users", local.org_url), + format("%s/api/v1/apps", local.org_url) + ] +} + +resource "okta_app_oauth_role_assignment" "test" { + client_id = okta_app_oauth.test.client_id + type = "CUSTOM" + role = okta_admin_role_custom.test.id + resource_set = okta_resource_set.test.id +} diff --git a/examples/okta_app_oauth_role_assignment/custom_updated.tf b/examples/okta_app_oauth_role_assignment/custom_updated.tf new file mode 100644 index 000000000..ead9a558e --- /dev/null +++ b/examples/okta_app_oauth_role_assignment/custom_updated.tf @@ -0,0 +1,37 @@ +resource "okta_app_oauth" "test" { + label = "testAcc_replace_with_uuid" + type = "service" + response_types = ["token"] + grant_types = ["client_credentials"] + jwks_uri = "https://example.com" +} + +variable "hostname" { + type = string +} + +locals { + org_url = "https://${var.hostname}" +} + +resource "okta_admin_role_custom" "test" { + label = "testAcc_replace_with_uuid" + description = "testing, testing" + permissions = ["okta.apps.assignment.manage", "okta.users.read"] +} + +resource "okta_resource_set" "test" { + label = "testAcc_replace_with_uuid" + description = "testing, testing" + resources = [ + format("%s/api/v1/users", local.org_url), + format("%s/api/v1/apps", local.org_url), + ] +} + +resource "okta_app_oauth_role_assignment" "test" { + client_id = okta_app_oauth.test.client_id + type = "CUSTOM" + role = okta_admin_role_custom.test.id + resource_set = okta_resource_set.test.id +} diff --git a/okta/resource_okta_app_oauth_role_assignment_test.go b/okta/resource_okta_app_oauth_role_assignment_test.go index 48dab4a0c..7165ba044 100644 --- a/okta/resource_okta_app_oauth_role_assignment_test.go +++ b/okta/resource_okta_app_oauth_role_assignment_test.go @@ -48,9 +48,27 @@ func TestAccResourceOktaAppOAuthRoleAssignment_custom(t *testing.T) { Steps: []resource.TestStep{ { Config: mgr.GetFixtures("custom.tf", t), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("okta_app_oauth_role_assignment.test", "type", "CUSTOM"), + resource.TestCheckResourceAttr("okta_app_oauth_role_assignment.test", "status", "ACTIVE"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "id"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "client_id"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "label"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "role"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "resource_set"), + ), }, { Config: mgr.GetFixtures("custom_updated.tf", t), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("okta_app_oauth_role_assignment.test", "type", "CUSTOM"), + resource.TestCheckResourceAttr("okta_app_oauth_role_assignment.test", "status", "ACTIVE"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "id"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "client_id"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "label"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "role"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "resource_set"), + ), }, }, }) From e9ca9231df0244fb0631a34dfde87318e0f264cd Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Thu, 21 Sep 2023 23:50:59 -0500 Subject: [PATCH 10/17] fix the validation handler check --- okta/resource_okta_app_oauth_role_assignment.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/okta/resource_okta_app_oauth_role_assignment.go b/okta/resource_okta_app_oauth_role_assignment.go index 5739b78f6..e7d9c0930 100644 --- a/okta/resource_okta_app_oauth_role_assignment.go +++ b/okta/resource_okta_app_oauth_role_assignment.go @@ -116,7 +116,7 @@ func (r *appOAuthRoleAssignmentResource) ValidateConfig(ctx context.Context, req if resp.Diagnostics.HasError() { return } - if data.Type.ValueString() == "CUSTOM" && (data.ResourceSet.ValueString() == "" || data.Role.ValueString() == "") { + if data.Type.ValueString() == "CUSTOM" && (data.ResourceSet.IsNull() || data.Role.IsNull()) { resp.Diagnostics.AddAttributeError( path.Root("type"), "Missing attribute configuration", From 82cf0ec76d85e97df194f60a076f09cc2f1046a7 Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Thu, 21 Sep 2023 23:59:38 -0500 Subject: [PATCH 11/17] add website docs and fix test --- ...resource_okta_app_oauth_role_assignment.go | 4 +- .../r/app_oauth_role_assignment.html.markdown | 90 +++++++++++++++++++ 2 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 website/docs/r/app_oauth_role_assignment.html.markdown diff --git a/okta/resource_okta_app_oauth_role_assignment.go b/okta/resource_okta_app_oauth_role_assignment.go index e7d9c0930..1a522c661 100644 --- a/okta/resource_okta_app_oauth_role_assignment.go +++ b/okta/resource_okta_app_oauth_role_assignment.go @@ -55,8 +55,8 @@ func (r *appOAuthRoleAssignmentResource) Configure(_ context.Context, req resour func (r *appOAuthRoleAssignmentResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) { resp.Schema = schema.Schema{ - Description: "Manages assignment of OAuth Role to an Application", - MarkdownDescription: "Manages assignment of OAuth Role to an Application", + Description: "Manages assignment of an admin role to an OAuth application", + MarkdownDescription: "Manages assignment of an admin role to an OAuth application", Attributes: map[string]schema.Attribute{ "id": schema.StringAttribute{ Description: "Role Assignment ID", diff --git a/website/docs/r/app_oauth_role_assignment.html.markdown b/website/docs/r/app_oauth_role_assignment.html.markdown new file mode 100644 index 000000000..47a1d729e --- /dev/null +++ b/website/docs/r/app_oauth_role_assignment.html.markdown @@ -0,0 +1,90 @@ +--- +layout: 'okta' +page_title: 'Okta: okta_app_oauth_role_assignment' +sidebar_current: 'docs-okta-resource-okta-app-oauth-role-assignment' +description: |- + Manages assignment of an admin role to an OAuth application +--- + +# okta_app_oauth_role_assignment + +Manages assignment of an admin role to an OAuth application. + +This resource allows you to assign an Okta admin role to a OAuth service application. This requires the Okta tenant feature flag for this function to be enabled. + +## Example Usage + +Standard Role: + +```hcl +resource "okta_app_oauth" "test" { + label = "test" + type = "service" + response_types = ["token"] + grant_types = ["client_credentials"] + jwks_uri = "https://example.com" +} + +resource "okta_app_oauth_role_assignment" "test" { + client_id = okta_app_oauth.test.client_id + type = "HELP_DESK_ADMIN" +} +``` + +Custom Role: + +```hcl +resource "okta_app_oauth" "test" { + label = "test" + type = "service" + response_types = ["token"] + grant_types = ["client_credentials"] + jwks_uri = "https://example.com" +} + +resource "okta_admin_role_custom" "test" { + label = "test" + description = "testing, testing" + permissions = ["okta.apps.assignment.manage", "okta.users.manage", "okta.apps.manage"] +} + +resource "okta_resource_set" "test" { + label = "test" + description = "testing, testing" + resources = [ + format("%s/api/v1/users", "https://example.okta.com"), + format("%s/api/v1/apps", "https://example.okta.com") + ] +} + +resource "okta_app_oauth_role_assignment" "test" { + client_id = okta_app_oauth.test.client_id + type = "CUSTOM" + role = okta_admin_role_custom.test.id + resource_set = okta_resource_set.test.id +} +``` + +## Argument Reference + +The following arguments are supported: + +- `client_id` - (Required) Client ID for the role to be assigned to + +- `type` - (Required) Role type to assign. This can be one of the standard Okta roles, such as `HELP_DESK_ADMIN` or `CUSTOM`. Using custom requires the `resource_set` and `role` attributes to be set. + +- `resource_set` - (Optional) Resource set for the custom role to assign, must be the ID of the created resource set. + +- `role` - (Optional) Custom Role ID + +## Attribute Reference + +- `id` - Role Assignment ID + +- `status` - Status of the role assignment + +- `label` - Label of the role assignment + +## Import + +Not implemented From e1b95567fe8f0c3667b9e4dfeca49daf35e65206 Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Fri, 22 Sep 2023 00:04:31 -0500 Subject: [PATCH 12/17] fix test --- okta/resource_okta_app_oauth_role_assignment.go | 4 ++-- website/docs/r/app_oauth_role_assignment.html.markdown | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/okta/resource_okta_app_oauth_role_assignment.go b/okta/resource_okta_app_oauth_role_assignment.go index 1a522c661..9c9be94d4 100644 --- a/okta/resource_okta_app_oauth_role_assignment.go +++ b/okta/resource_okta_app_oauth_role_assignment.go @@ -72,8 +72,8 @@ func (r *appOAuthRoleAssignmentResource) Schema(_ context.Context, _ resource.Sc }, }, "type": schema.StringAttribute{ - Description: "Role type to assign. This can be one of the standard Okta roles, such as `HELP_DESK_ADMIN` or `CUSTOM`. Using custom requires the `resource_set` and `role` attributes to be set.", - MarkdownDescription: "Role type to assign. This can be one of the standard Okta roles, such as `HELP_DESK_ADMIN` or `CUSTOM`. Using custom requires the `resource_set` and `role` attributes to be set.", + Description: "Role type to assign. This can be one of the standard Okta roles, such as `HELP_DESK_ADMIN`, or `CUSTOM`. Using custom requires the `resource_set` and `role` attributes to be set.", + MarkdownDescription: "Role type to assign. This can be one of the standard Okta roles, such as `HELP_DESK_ADMIN`, or `CUSTOM`. Using custom requires the `resource_set` and `role` attributes to be set.", Required: true, PlanModifiers: []planmodifier.String{ stringplanmodifier.RequiresReplace(), diff --git a/website/docs/r/app_oauth_role_assignment.html.markdown b/website/docs/r/app_oauth_role_assignment.html.markdown index 47a1d729e..743db831c 100644 --- a/website/docs/r/app_oauth_role_assignment.html.markdown +++ b/website/docs/r/app_oauth_role_assignment.html.markdown @@ -71,7 +71,7 @@ The following arguments are supported: - `client_id` - (Required) Client ID for the role to be assigned to -- `type` - (Required) Role type to assign. This can be one of the standard Okta roles, such as `HELP_DESK_ADMIN` or `CUSTOM`. Using custom requires the `resource_set` and `role` attributes to be set. +- `type` - (Required) Role type to assign. This can be one of the standard Okta roles, such as `HELP_DESK_ADMIN`, or `CUSTOM`. Using custom requires the `resource_set` and `role` attributes to be set. - `resource_set` - (Optional) Resource set for the custom role to assign, must be the ID of the created resource set. From 057985d3aaf0607ea19ba68c83afe2b9872f34e7 Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Fri, 22 Sep 2023 13:34:22 -0500 Subject: [PATCH 13/17] add import test --- ...rce_okta_app_oauth_role_assignment_test.go | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/okta/resource_okta_app_oauth_role_assignment_test.go b/okta/resource_okta_app_oauth_role_assignment_test.go index 7165ba044..a26d23ea6 100644 --- a/okta/resource_okta_app_oauth_role_assignment_test.go +++ b/okta/resource_okta_app_oauth_role_assignment_test.go @@ -73,3 +73,30 @@ func TestAccResourceOktaAppOAuthRoleAssignment_custom(t *testing.T) { }, }) } + +func TestAccResourceOktaAppOAuthRoleAssignment_import(t *testing.T) { + mgr := newFixtureManager("okta_app_oauth_role_assignment", t.Name()) + + oktaResourceTest(t, resource.TestCase{ + PreCheck: testAccPreCheck(t), + ErrorCheck: testAccErrorChecks(t), + ProtoV5ProviderFactories: testAccMergeProvidersFactories, + Steps: []resource.TestStep{ + { + Config: mgr.GetFixtures("basic.tf", t), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("okta_app_oauth_role_assignment.test", "type", "HELP_DESK_ADMIN"), + resource.TestCheckResourceAttr("okta_app_oauth_role_assignment.test", "status", "ACTIVE"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "id"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "client_id"), + resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "label"), + ), + }, + { + ResourceName: "okta_app_oauth_role_assignment.test", + ImportState: true, + ImportStateVerify: true, + }, + }, + }) +} From 17893bfb20652725f97a95602f3f6a5e8c2662e5 Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Fri, 22 Sep 2023 13:38:07 -0500 Subject: [PATCH 14/17] consolidate test --- ...rce_okta_app_oauth_role_assignment_test.go | 32 +++---------------- 1 file changed, 5 insertions(+), 27 deletions(-) diff --git a/okta/resource_okta_app_oauth_role_assignment_test.go b/okta/resource_okta_app_oauth_role_assignment_test.go index a26d23ea6..1f525f3e5 100644 --- a/okta/resource_okta_app_oauth_role_assignment_test.go +++ b/okta/resource_okta_app_oauth_role_assignment_test.go @@ -24,6 +24,11 @@ func TestAccResourceOktaAppOAuthRoleAssignment_basic(t *testing.T) { resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "label"), ), }, + { + ResourceName: "okta_app_oauth_role_assignment.test", + ImportState: true, + ImportStateVerify: true, + }, { Config: mgr.GetFixtures("basic_updated.tf", t), Check: resource.ComposeTestCheckFunc( @@ -73,30 +78,3 @@ func TestAccResourceOktaAppOAuthRoleAssignment_custom(t *testing.T) { }, }) } - -func TestAccResourceOktaAppOAuthRoleAssignment_import(t *testing.T) { - mgr := newFixtureManager("okta_app_oauth_role_assignment", t.Name()) - - oktaResourceTest(t, resource.TestCase{ - PreCheck: testAccPreCheck(t), - ErrorCheck: testAccErrorChecks(t), - ProtoV5ProviderFactories: testAccMergeProvidersFactories, - Steps: []resource.TestStep{ - { - Config: mgr.GetFixtures("basic.tf", t), - Check: resource.ComposeTestCheckFunc( - resource.TestCheckResourceAttr("okta_app_oauth_role_assignment.test", "type", "HELP_DESK_ADMIN"), - resource.TestCheckResourceAttr("okta_app_oauth_role_assignment.test", "status", "ACTIVE"), - resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "id"), - resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "client_id"), - resource.TestCheckResourceAttrSet("okta_app_oauth_role_assignment.test", "label"), - ), - }, - { - ResourceName: "okta_app_oauth_role_assignment.test", - ImportState: true, - ImportStateVerify: true, - }, - }, - }) -} From 1346623c5a8a07412a5936e65c4be9fa75a042e6 Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Fri, 22 Sep 2023 13:53:37 -0500 Subject: [PATCH 15/17] implement ImportState --- okta/resource_okta_app_oauth_role_assignment.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/okta/resource_okta_app_oauth_role_assignment.go b/okta/resource_okta_app_oauth_role_assignment.go index 9c9be94d4..7dc47ac0f 100644 --- a/okta/resource_okta_app_oauth_role_assignment.go +++ b/okta/resource_okta_app_oauth_role_assignment.go @@ -3,6 +3,7 @@ package okta import ( "context" "fmt" + "strings" "github.com/hashicorp/terraform-plugin-framework/path" "github.com/hashicorp/terraform-plugin-framework/resource" @@ -14,6 +15,7 @@ import ( ) var _ resource.ResourceWithValidateConfig = &appOAuthRoleAssignmentResource{} +var _ resource.ResourceWithImportState = &appOAuthRoleAssignmentResource{} func NewAppOAuthRoleAssignmentResource() resource.Resource { return &appOAuthRoleAssignmentResource{} @@ -200,3 +202,16 @@ func (r *appOAuthRoleAssignmentResource) Delete(ctx context.Context, req resourc return } } + +func (r *appOAuthRoleAssignmentResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) { + idParts := strings.Split(req.ID, "/") + + if len(idParts) != 2 || idParts[0] == "" || idParts[1] == "" { + resp.Diagnostics.AddError("Unexpected Import Identifier", "Expected import identifier with format /") + return + } + resp.Diagnostics.Append(resp.State.Set(ctx, &OAuthRoleAssignmentResourceModel{ + ClientID: types.StringValue(idParts[0]), + ID: types.StringValue(idParts[1]), + })...) +} From c8ebc6b4f1ea127dfc719ea1c316b13c999bc0d8 Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Fri, 22 Sep 2023 14:00:57 -0500 Subject: [PATCH 16/17] fix ID setup for import test --- okta/resource_okta_app_oauth_role_assignment_test.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/okta/resource_okta_app_oauth_role_assignment_test.go b/okta/resource_okta_app_oauth_role_assignment_test.go index 1f525f3e5..a39bd1e3f 100644 --- a/okta/resource_okta_app_oauth_role_assignment_test.go +++ b/okta/resource_okta_app_oauth_role_assignment_test.go @@ -1,9 +1,11 @@ package okta import ( + "fmt" "testing" "github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource" + "github.com/hashicorp/terraform-plugin-sdk/v2/terraform" ) func TestAccResourceOktaAppOAuthRoleAssignment_basic(t *testing.T) { @@ -28,6 +30,13 @@ func TestAccResourceOktaAppOAuthRoleAssignment_basic(t *testing.T) { ResourceName: "okta_app_oauth_role_assignment.test", ImportState: true, ImportStateVerify: true, + ImportStateIdFunc: func(s *terraform.State) (string, error) { + r, ok := s.RootModule().Resources["okta_app_oauth_role_assignment.test"] + if !ok { + return "", fmt.Errorf("Unable to find resource: %s:", "okta_app_oauth_role_assignment.test") + } + return fmt.Sprintf("%s/%s", r.Primary.Attributes["client_id"], r.Primary.Attributes["id"]), nil + }, }, { Config: mgr.GetFixtures("basic_updated.tf", t), From 4af36332f2eb0d38edf33dfea95fda9eae6fc51c Mon Sep 17 00:00:00 2001 From: Tom Goodsell <56050072+tgoodsell-tempus@users.noreply.github.com> Date: Fri, 22 Sep 2023 14:03:03 -0500 Subject: [PATCH 17/17] add docs for import --- website/docs/r/app_oauth_role_assignment.html.markdown | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/website/docs/r/app_oauth_role_assignment.html.markdown b/website/docs/r/app_oauth_role_assignment.html.markdown index 743db831c..2938eaccf 100644 --- a/website/docs/r/app_oauth_role_assignment.html.markdown +++ b/website/docs/r/app_oauth_role_assignment.html.markdown @@ -87,4 +87,6 @@ The following arguments are supported: ## Import -Not implemented +OAuth Role assignment can be imported by passing the Client ID and Role Assignment ID for the specific client role. + +`$ terraform import okta_app_oauth_role_assignment.test /`