Skip to content

Commit c31431d

Browse files
GH-1834 | okta_event_hook_verification Not Re-Verifying After an Update (#2723)
1 parent 58ac7d8 commit c31431d

7 files changed

Lines changed: 1276 additions & 3 deletions

File tree

docs/resources/event_hook_verification.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,6 @@ resource "okta_event_hook_verification" "example" {
4646
### Read-Only
4747

4848
- `id` (String) The ID of this resource.
49+
- `verification_status` (String) The verification status of the event hook.
4950

5051

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
resource "okta_event_hook" "example" {
2+
name = "testAcc_replace_with_uuid"
3+
events = [
4+
"user.lifecycle.create",
5+
"user.lifecycle.delete.initiated",
6+
]
7+
8+
channel = {
9+
type = "HTTP"
10+
version = "1.0.0"
11+
uri = "https://eoj5lz4z8m0m1jk.m.pipedream.net"
12+
}
13+
14+
auth = {
15+
type = "HEADER"
16+
key = "Authorization"
17+
value = "value"
18+
}
19+
}
20+
21+
resource "okta_event_hook_verification" "user_assigned" {
22+
event_hook_id = okta_event_hook.example.id
23+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
resource "okta_event_hook" "example" {
2+
name = "testAcc_replace_with_uuid"
3+
events = [
4+
"user.lifecycle.create",
5+
"user.lifecycle.delete.initiated",
6+
]
7+
8+
channel = {
9+
type = "HTTP"
10+
version = "1.0.0"
11+
uri = "https://eo4afyqp3adkxpk.m.pipedream.net"
12+
}
13+
14+
auth = {
15+
type = "HEADER"
16+
key = "Authorization"
17+
value = "value"
18+
}
19+
}
20+
21+
resource "okta_event_hook_verification" "user_assigned" {
22+
event_hook_id = okta_event_hook.example.id
23+
}

okta/services/idaas/resource_okta_event_hook_verification.go

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,26 +11,64 @@ import (
1111
func resourceEventHookVerification() *schema.Resource {
1212
return &schema.Resource{
1313
CreateContext: resourceEventHookVerificationCreate,
14-
ReadContext: utils.ResourceFuncNoOp,
14+
ReadContext: resourceEventHookVerificationRead,
15+
UpdateContext: resourceEventHookVerificationUpdate,
1516
DeleteContext: utils.ResourceFuncNoOp,
1617
Importer: nil,
1718
Description: "Verifies the Event Hook. The resource won't be created unless the URI provided in the event hook returns a valid JSON object with verification. See [Event Hooks](https://developer.okta.com/docs/concepts/event-hooks/#one-time-verification-request) documentation for details.",
19+
CustomizeDiff: func(ctx context.Context, d *schema.ResourceDiff, meta interface{}) error {
20+
// When the API reports the hook as UNVERIFIED, force a planned diff so that
21+
// UpdateContext is invoked on the next apply to re-trigger verification.
22+
if d.Id() != "" && d.Get("verification_status").(string) == "UNVERIFIED" {
23+
return d.SetNew("verification_status", "VERIFIED")
24+
}
25+
return nil
26+
},
1827
Schema: map[string]*schema.Schema{
1928
"event_hook_id": {
2029
Type: schema.TypeString,
2130
Required: true,
22-
ForceNew: true,
2331
Description: "Event hook ID",
2432
},
33+
"verification_status": {
34+
Type: schema.TypeString,
35+
Computed: true,
36+
Description: "Verification status of the Event hook",
37+
},
2538
},
2639
}
2740
}
2841

2942
func resourceEventHookVerificationCreate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
30-
_, _, err := getOktaClientFromMetadata(meta).EventHook.VerifyEventHook(ctx, d.Get("event_hook_id").(string))
43+
hook, _, err := getOktaV6ClientFromMetadata(meta).EventHookAPI.VerifyEventHook(ctx, d.Get("event_hook_id").(string)).Execute()
44+
if err != nil {
45+
return diag.Errorf("failed to verify event hook sender: %v", err)
46+
}
47+
d.SetId(d.Get("event_hook_id").(string))
48+
_ = d.Set("verification_status", hook.VerificationStatus)
49+
return nil
50+
}
51+
52+
func resourceEventHookVerificationRead(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
53+
hook, resp, err := getOktaV6ClientFromMetadata(meta).EventHookAPI.GetEventHook(ctx, d.Id()).Execute()
54+
if err := utils.SuppressErrorOn404_V6(resp, err); err != nil {
55+
return diag.Errorf("failed to get event hook: %v", err)
56+
}
57+
if hook == nil {
58+
d.SetId("")
59+
return nil
60+
}
61+
d.SetId(d.Get("event_hook_id").(string))
62+
_ = d.Set("verification_status", hook.VerificationStatus)
63+
return nil
64+
}
65+
66+
func resourceEventHookVerificationUpdate(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.Diagnostics {
67+
hook, _, err := getOktaV6ClientFromMetadata(meta).EventHookAPI.VerifyEventHook(ctx, d.Get("event_hook_id").(string)).Execute()
3168
if err != nil {
3269
return diag.Errorf("failed to verify event hook sender: %v", err)
3370
}
3471
d.SetId(d.Get("event_hook_id").(string))
72+
_ = d.Set("verification_status", hook.VerificationStatus)
3573
return nil
3674
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package idaas_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
7+
"github.com/okta/terraform-provider-okta/okta/acctest"
8+
"github.com/okta/terraform-provider-okta/okta/resources"
9+
)
10+
11+
func TestAccResourceOktaEventHookVerification_crud(t *testing.T) {
12+
resourceName := "okta_event_hook_verification.user_assigned"
13+
mgr := newFixtureManager("resources", resources.OktaIDaaSEventHookVerification, t.Name())
14+
config := mgr.GetFixtures("basic.tf", t)
15+
updatedConfig := mgr.GetFixtures("basic_updated.tf", t)
16+
17+
acctest.OktaResourceTest(t, resource.TestCase{
18+
PreCheck: acctest.AccPreCheck(t),
19+
ErrorCheck: testAccErrorChecks(t),
20+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactoriesForTestAcc(t),
21+
CheckDestroy: nil,
22+
Steps: []resource.TestStep{
23+
{
24+
Config: config,
25+
Check: resource.ComposeTestCheckFunc(
26+
resource.TestCheckResourceAttr(resourceName, "verification_status", "VERIFIED"),
27+
),
28+
},
29+
{
30+
Config: updatedConfig,
31+
Check: resource.ComposeTestCheckFunc(
32+
resource.TestCheckResourceAttr(resourceName, "verification_status", "VERIFIED"),
33+
),
34+
// After apply, ReadContext fetches UNVERIFIED from the API and
35+
// CustomizeDiff forces the plan to VERIFIED, so a non-empty plan
36+
// is expected on the post-step refresh.
37+
ExpectNonEmptyPlan: true,
38+
},
39+
{
40+
// ReadContext fetches the hook and sets verification_status=UNVERIFIED
41+
// in state (e.g. the hook was reset externally between applies).
42+
// CustomizeDiff then detects UNVERIFIED and calls
43+
// d.SetNew("verification_status", "VERIFIED"), so the plan must show ...
44+
Config: updatedConfig,
45+
PlanOnly: true,
46+
ExpectNonEmptyPlan: true, // ... at least one change — Terraform will schedule an Update to re-verify.
47+
},
48+
},
49+
})
50+
}

0 commit comments

Comments
 (0)