Skip to content

Commit 7c4bfb5

Browse files
authored
Merge pull request #266 from philips-software/chore/workaround-iam-bugfix
IAM: conditionally check IAM Device/User mixups #265
2 parents 2592a6f + be4a8c0 commit 7c4bfb5

File tree

4 files changed

+116
-10
lines changed

4 files changed

+116
-10
lines changed

docs/resources/iam_group.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ The following arguments are supported:
5959
opt-in for IAM Groups due to insufficient IAM API capabilities to perform this operation efficiently.
6060
A future version might change this to be always-on. When enabled, the provider will perform additional API calls
6161
to determine if any changes were made outside of Terraform to user and service assignments of this Group. Default: `false`
62+
* `iam_device_bug_workaround` - (Optional, bool) Work around an IAM bug that returns both user and device entities in the API.
63+
Do not enable this unless you are using IAM Devices in your infrastructure. Default: `false`
6264

6365
## Attributes Reference
6466

internal/services/iam/group/resource_iam_group.go

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ func ResourceIAMGroup() *schema.Resource {
1818
Importer: &schema.ResourceImporter{
1919
StateContext: schema.ImportStatePassthroughContext,
2020
},
21-
SchemaVersion: 2,
21+
SchemaVersion: 3,
2222
CreateContext: resourceIAMGroupCreate,
2323
ReadContext: resourceIAMGroupRead,
2424
UpdateContext: resourceIAMGroupUpdate,
@@ -34,6 +34,11 @@ func ResourceIAMGroup() *schema.Resource {
3434
Upgrade: patchIAMGroupV1,
3535
Version: 1,
3636
},
37+
{
38+
Type: ResourceIAMGroupV2().CoreConfigSchema().ImpliedType(),
39+
Upgrade: patchIAMGroupV2,
40+
Version: 2,
41+
},
3742
},
3843

3944
Schema: map[string]*schema.Schema{
@@ -82,6 +87,11 @@ func ResourceIAMGroup() *schema.Resource {
8287
Optional: true,
8388
Default: false,
8489
},
90+
"iam_device_bug_workaround": {
91+
Type: schema.TypeBool,
92+
Optional: true,
93+
Default: false,
94+
},
8595
},
8696
}
8797
}
@@ -224,6 +234,7 @@ func resourceIAMGroupRead(_ context.Context, d *schema.ResourceData, m interface
224234

225235
id := d.Id()
226236
driftDetection := d.Get("drift_detection").(bool)
237+
iamDeviceBugWorkaround := d.Get("iam_device_bug_workaround").(bool)
227238

228239
group, resp, err := client.Groups.GetGroupByID(id)
229240
if err != nil {
@@ -254,15 +265,19 @@ func resourceIAMGroupRead(_ context.Context, d *schema.ResourceData, m interface
254265
if err != nil {
255266
return diag.FromErr(fmt.Errorf("error retrieving users from group: %v", err))
256267
}
257-
// Unfortunately Users must now be verified as the GetAllUsers query also returns IAM Devices
258-
var verifiedUsers []string
259-
for _, u := range users {
260-
_, _, err := client.Users.GetUserByID(u)
261-
if err == nil {
262-
verifiedUsers = append(verifiedUsers, u)
268+
_ = d.Set("users", tools.SchemaSetStrings(users))
269+
270+
if iamDeviceBugWorkaround {
271+
// IAM Devices could be mixed in the GetUser results, this is an IAM BUG
272+
var verifiedUsers []string
273+
for _, u := range users {
274+
_, _, err := client.Users.GetUserByID(u) // This call could FAIL if the IAM entity does not have broad access
275+
if err == nil {
276+
verifiedUsers = append(verifiedUsers, u)
277+
}
263278
}
279+
_ = d.Set("users", tools.SchemaSetStrings(verifiedUsers))
264280
}
265-
_ = d.Set("users", tools.SchemaSetStrings(verifiedUsers))
266281

267282
// Services
268283
// We only deal with services we know

internal/services/iam/group/resource_iam_group_test.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,20 @@ resource "hsdp_iam_role" "test" {
119119
managing_organization = hsdp_iam_org.test.id
120120
}
121121
122+
resource "hsdp_iam_group" "user_test" {
123+
name = "%s1"
124+
description = "Acceptance Test Group %s1"
125+
126+
roles = [hsdp_iam_role.test.id]
127+
users = [hsdp_iam_user.test.id]
128+
services = [hsdp_iam_service.test.id]
129+
130+
managing_organization = hsdp_iam_org.test.id
131+
132+
drift_detection = true
133+
iam_device_bug_workaround = false
134+
}
135+
122136
resource "hsdp_iam_group" "test" {
123137
name = "%s"
124138
description = "Acceptance Test Group %s"
@@ -130,8 +144,11 @@ resource "hsdp_iam_group" "test" {
130144
131145
managing_organization = hsdp_iam_org.test.id
132146
133-
drift_detection = true
134-
}`,
147+
drift_detection = true
148+
iam_device_bug_workaround = true
149+
}
150+
151+
`,
135152
// ORG
136153
upperName,
137154
name,
@@ -155,6 +172,9 @@ resource "hsdp_iam_group" "test" {
155172
// ROLE
156173
upperName,
157174
name,
175+
// USER GROUP
176+
name,
177+
name,
158178
// GROUP
159179
name,
160180
name)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package group
2+
3+
import (
4+
"context"
5+
6+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
7+
"github.com/philips-software/terraform-provider-hsdp/internal/tools"
8+
)
9+
10+
// Upgrades an IAM Group resource from v2 to v3
11+
func patchIAMGroupV2(_ context.Context, rawState map[string]interface{}, _ interface{}) (map[string]interface{}, error) {
12+
if rawState == nil {
13+
rawState = map[string]interface{}{}
14+
}
15+
rawState["iam_device_bug_workaround"] = false
16+
return rawState, nil
17+
}
18+
19+
func ResourceIAMGroupV2() *schema.Resource {
20+
return &schema.Resource{
21+
Schema: map[string]*schema.Schema{
22+
"name": {
23+
Type: schema.TypeString,
24+
Required: true,
25+
ForceNew: true,
26+
DiffSuppressFunc: tools.SuppressCaseDiffs,
27+
},
28+
"description": {
29+
Type: schema.TypeString,
30+
Optional: true,
31+
DiffSuppressFunc: tools.SuppressWhenGenerated,
32+
},
33+
"managing_organization": {
34+
Type: schema.TypeString,
35+
Required: true,
36+
ForceNew: true,
37+
},
38+
"roles": {
39+
Type: schema.TypeSet,
40+
MaxItems: 1000,
41+
Required: true,
42+
Elem: tools.StringSchema(),
43+
},
44+
"users": {
45+
Type: schema.TypeSet,
46+
MaxItems: 2000,
47+
Optional: true,
48+
Elem: tools.StringSchema(),
49+
},
50+
"services": {
51+
Type: schema.TypeSet,
52+
MaxItems: 2000,
53+
Optional: true,
54+
Elem: tools.StringSchema(),
55+
},
56+
"devices": {
57+
Type: schema.TypeSet,
58+
MaxItems: 2000,
59+
Optional: true,
60+
Elem: tools.StringSchema(),
61+
},
62+
"drift_detection": {
63+
Type: schema.TypeBool,
64+
Optional: true,
65+
Default: false,
66+
},
67+
},
68+
}
69+
}

0 commit comments

Comments
 (0)