Skip to content

Commit a0e28a7

Browse files
Add access restrictions field for google_iam_workforce_pool resource (#9490) (#16580)
[upstream:05e14a25287adfa933db8be44f4da737dfe38197] Signed-off-by: Modular Magician <[email protected]>
1 parent 35fce45 commit a0e28a7

File tree

5 files changed

+230
-22
lines changed

5 files changed

+230
-22
lines changed

.changelog/9490.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
iam: added `allowedServices`, `disableProgrammaticSignin` fields to `google_iam_workforce_pool` resource
3+
```

google/services/iamworkforcepool/resource_iam_workforce_pool.go

+140
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,40 @@ func ResourceIAMWorkforcePoolWorkforcePool() *schema.Resource {
9191
digits, or hyphens. It must start with a letter, and cannot have a trailing hyphen.
9292
The prefix 'gcp-' is reserved for use by Google, and may not be specified.`,
9393
},
94+
"access_restrictions": {
95+
Type: schema.TypeList,
96+
Optional: true,
97+
ForceNew: true,
98+
Description: `Configure access restrictions on the workforce pool users. This is an optional field. If specified web
99+
sign-in can be restricted to given set of services or programmatic sign-in can be disabled for pool users.`,
100+
MaxItems: 1,
101+
Elem: &schema.Resource{
102+
Schema: map[string]*schema.Schema{
103+
"allowed_services": {
104+
Type: schema.TypeList,
105+
Optional: true,
106+
Description: `Services allowed for web sign-in with the workforce pool.
107+
If not set by default there are no restrictions.`,
108+
Elem: &schema.Resource{
109+
Schema: map[string]*schema.Schema{
110+
"domain": {
111+
Type: schema.TypeString,
112+
Optional: true,
113+
Description: `Domain name of the service.
114+
Example: console.cloud.google`,
115+
},
116+
},
117+
},
118+
},
119+
"disable_programmatic_signin": {
120+
Type: schema.TypeBool,
121+
Optional: true,
122+
Description: `Disable programmatic sign-in by disabling token issue via the Security Token API endpoint.
123+
See [Security Token Service API](https://cloud.google.com/iam/docs/reference/sts/rest).`,
124+
},
125+
},
126+
},
127+
},
94128
"description": {
95129
Type: schema.TypeString,
96130
Optional: true,
@@ -180,6 +214,12 @@ func resourceIAMWorkforcePoolWorkforcePoolCreate(d *schema.ResourceData, meta in
180214
} else if v, ok := d.GetOkExists("session_duration"); !tpgresource.IsEmptyValue(reflect.ValueOf(sessionDurationProp)) && (ok || !reflect.DeepEqual(v, sessionDurationProp)) {
181215
obj["sessionDuration"] = sessionDurationProp
182216
}
217+
accessRestrictionsProp, err := expandIAMWorkforcePoolWorkforcePoolAccessRestrictions(d.Get("access_restrictions"), d, config)
218+
if err != nil {
219+
return err
220+
} else if v, ok := d.GetOkExists("access_restrictions"); !tpgresource.IsEmptyValue(reflect.ValueOf(accessRestrictionsProp)) && (ok || !reflect.DeepEqual(v, accessRestrictionsProp)) {
221+
obj["accessRestrictions"] = accessRestrictionsProp
222+
}
183223

184224
url, err := tpgresource.ReplaceVars(d, config, "{{IAMWorkforcePoolBasePath}}locations/{{location}}/workforcePools?workforcePoolId={{workforce_pool_id}}")
185225
if err != nil {
@@ -292,6 +332,9 @@ func resourceIAMWorkforcePoolWorkforcePoolRead(d *schema.ResourceData, meta inte
292332
if err := d.Set("session_duration", flattenIAMWorkforcePoolWorkforcePoolSessionDuration(res["sessionDuration"], d, config)); err != nil {
293333
return fmt.Errorf("Error reading WorkforcePool: %s", err)
294334
}
335+
if err := d.Set("access_restrictions", flattenIAMWorkforcePoolWorkforcePoolAccessRestrictions(res["accessRestrictions"], d, config)); err != nil {
336+
return fmt.Errorf("Error reading WorkforcePool: %s", err)
337+
}
295338

296339
return nil
297340
}
@@ -490,6 +533,47 @@ func flattenIAMWorkforcePoolWorkforcePoolSessionDuration(v interface{}, d *schem
490533
return v
491534
}
492535

536+
func flattenIAMWorkforcePoolWorkforcePoolAccessRestrictions(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
537+
if v == nil {
538+
return nil
539+
}
540+
original := v.(map[string]interface{})
541+
if len(original) == 0 {
542+
return nil
543+
}
544+
transformed := make(map[string]interface{})
545+
transformed["allowed_services"] =
546+
flattenIAMWorkforcePoolWorkforcePoolAccessRestrictionsAllowedServices(original["allowedServices"], d, config)
547+
transformed["disable_programmatic_signin"] =
548+
flattenIAMWorkforcePoolWorkforcePoolAccessRestrictionsDisableProgrammaticSignin(original["disableProgrammaticSignin"], d, config)
549+
return []interface{}{transformed}
550+
}
551+
func flattenIAMWorkforcePoolWorkforcePoolAccessRestrictionsAllowedServices(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
552+
if v == nil {
553+
return v
554+
}
555+
l := v.([]interface{})
556+
transformed := make([]interface{}, 0, len(l))
557+
for _, raw := range l {
558+
original := raw.(map[string]interface{})
559+
if len(original) < 1 {
560+
// Do not include empty json objects coming back from the api
561+
continue
562+
}
563+
transformed = append(transformed, map[string]interface{}{
564+
"domain": flattenIAMWorkforcePoolWorkforcePoolAccessRestrictionsAllowedServicesDomain(original["domain"], d, config),
565+
})
566+
}
567+
return transformed
568+
}
569+
func flattenIAMWorkforcePoolWorkforcePoolAccessRestrictionsAllowedServicesDomain(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
570+
return v
571+
}
572+
573+
func flattenIAMWorkforcePoolWorkforcePoolAccessRestrictionsDisableProgrammaticSignin(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
574+
return v
575+
}
576+
493577
func expandIAMWorkforcePoolWorkforcePoolParent(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
494578
return v, nil
495579
}
@@ -510,6 +594,62 @@ func expandIAMWorkforcePoolWorkforcePoolSessionDuration(v interface{}, d tpgreso
510594
return v, nil
511595
}
512596

597+
func expandIAMWorkforcePoolWorkforcePoolAccessRestrictions(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
598+
l := v.([]interface{})
599+
if len(l) == 0 || l[0] == nil {
600+
return nil, nil
601+
}
602+
raw := l[0]
603+
original := raw.(map[string]interface{})
604+
transformed := make(map[string]interface{})
605+
606+
transformedAllowedServices, err := expandIAMWorkforcePoolWorkforcePoolAccessRestrictionsAllowedServices(original["allowed_services"], d, config)
607+
if err != nil {
608+
return nil, err
609+
} else if val := reflect.ValueOf(transformedAllowedServices); val.IsValid() && !tpgresource.IsEmptyValue(val) {
610+
transformed["allowedServices"] = transformedAllowedServices
611+
}
612+
613+
transformedDisableProgrammaticSignin, err := expandIAMWorkforcePoolWorkforcePoolAccessRestrictionsDisableProgrammaticSignin(original["disable_programmatic_signin"], d, config)
614+
if err != nil {
615+
return nil, err
616+
} else if val := reflect.ValueOf(transformedDisableProgrammaticSignin); val.IsValid() && !tpgresource.IsEmptyValue(val) {
617+
transformed["disableProgrammaticSignin"] = transformedDisableProgrammaticSignin
618+
}
619+
620+
return transformed, nil
621+
}
622+
623+
func expandIAMWorkforcePoolWorkforcePoolAccessRestrictionsAllowedServices(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
624+
l := v.([]interface{})
625+
req := make([]interface{}, 0, len(l))
626+
for _, raw := range l {
627+
if raw == nil {
628+
continue
629+
}
630+
original := raw.(map[string]interface{})
631+
transformed := make(map[string]interface{})
632+
633+
transformedDomain, err := expandIAMWorkforcePoolWorkforcePoolAccessRestrictionsAllowedServicesDomain(original["domain"], d, config)
634+
if err != nil {
635+
return nil, err
636+
} else if val := reflect.ValueOf(transformedDomain); val.IsValid() && !tpgresource.IsEmptyValue(val) {
637+
transformed["domain"] = transformedDomain
638+
}
639+
640+
req = append(req, transformed)
641+
}
642+
return req, nil
643+
}
644+
645+
func expandIAMWorkforcePoolWorkforcePoolAccessRestrictionsAllowedServicesDomain(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
646+
return v, nil
647+
}
648+
649+
func expandIAMWorkforcePoolWorkforcePoolAccessRestrictionsDisableProgrammaticSignin(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
650+
return v, nil
651+
}
652+
513653
func resourceIAMWorkforcePoolWorkforcePoolDecoder(d *schema.ResourceData, meta interface{}, res map[string]interface{}) (map[string]interface{}, error) {
514654
if v := res["state"]; v == "DELETED" {
515655
return nil, nil

google/services/iamworkforcepool/resource_iam_workforce_pool_generated_test.go

+13-7
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,19 @@ func TestAccIAMWorkforcePoolWorkforcePool_iamWorkforcePoolFullExample(t *testing
9696
func testAccIAMWorkforcePoolWorkforcePool_iamWorkforcePoolFullExample(context map[string]interface{}) string {
9797
return acctest.Nprintf(`
9898
resource "google_iam_workforce_pool" "example" {
99-
workforce_pool_id = "tf-test-example-pool%{random_suffix}"
100-
parent = "organizations/%{org_id}"
101-
location = "global"
102-
display_name = "Display name"
103-
description = "A sample workforce pool."
104-
disabled = false
105-
session_duration = "7200s"
99+
workforce_pool_id = "tf-test-example-pool%{random_suffix}"
100+
parent = "organizations/%{org_id}"
101+
location = "global"
102+
display_name = "Display name"
103+
description = "A sample workforce pool."
104+
disabled = false
105+
session_duration = "7200s"
106+
access_restrictions {
107+
allowed_services {
108+
domain = "backstory.chronicle.security"
109+
}
110+
disable_programmatic_signin = false
111+
}
106112
}
107113
`, context)
108114
}

google/services/iamworkforcepool/resource_iam_workforce_pool_test.go

+34-8
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ func TestAccIAMWorkforcePoolWorkforcePool_full(t *testing.T) {
3131
ImportStateVerify: true,
3232
},
3333
{
34-
Config: testAccIAMWorkforcePoolWorkforcePool_update(context),
34+
Config: testAccIAMWorkforcePoolWorkforcePool_full_update(context),
3535
},
3636
{
3737
ResourceName: "google_iam_workforce_pool.my_pool",
@@ -64,7 +64,7 @@ func TestAccIAMWorkforcePoolWorkforcePool_minimal(t *testing.T) {
6464
ImportStateVerify: true,
6565
},
6666
{
67-
Config: testAccIAMWorkforcePoolWorkforcePool_update(context),
67+
Config: testAccIAMWorkforcePoolWorkforcePool_minimal_update(context),
6868
},
6969
{
7070
ResourceName: "google_iam_workforce_pool.my_pool",
@@ -77,29 +77,55 @@ func TestAccIAMWorkforcePoolWorkforcePool_minimal(t *testing.T) {
7777

7878
func testAccIAMWorkforcePoolWorkforcePool_full(context map[string]interface{}) string {
7979
return acctest.Nprintf(`
80+
resource "google_iam_workforce_pool" "my_pool" {
81+
workforce_pool_id = "my-pool-%{random_suffix}"
82+
parent = "organizations/%{org_id}"
83+
location = "global"
84+
display_name = "Display name"
85+
description = "A sample workforce pool."
86+
disabled = false
87+
session_duration = "7200s"
88+
access_restrictions {
89+
allowed_services {
90+
domain = "backstory.chronicle.security"
91+
}
92+
disable_programmatic_signin = false
93+
}
94+
}
95+
`, context)
96+
}
97+
98+
func testAccIAMWorkforcePoolWorkforcePool_minimal(context map[string]interface{}) string {
99+
return acctest.Nprintf(`
80100
resource "google_iam_workforce_pool" "my_pool" {
81101
workforce_pool_id = "my-pool-%{random_suffix}"
82102
parent = "organizations/%{org_id}"
83103
location = "global"
84-
display_name = "Display name"
85-
description = "A sample workforce pool."
86-
disabled = false
87-
session_duration = "7200s"
88104
}
89105
`, context)
90106
}
91107

92-
func testAccIAMWorkforcePoolWorkforcePool_minimal(context map[string]interface{}) string {
108+
func testAccIAMWorkforcePoolWorkforcePool_full_update(context map[string]interface{}) string {
93109
return acctest.Nprintf(`
94110
resource "google_iam_workforce_pool" "my_pool" {
95111
workforce_pool_id = "my-pool-%{random_suffix}"
96112
parent = "organizations/%{org_id}"
97113
location = "global"
114+
display_name = "New display name"
115+
description = "A sample workforce pool with updated description."
116+
disabled = true
117+
session_duration = "3600s"
118+
access_restrictions {
119+
allowed_services {
120+
domain = "backstory.chronicle.security"
121+
}
122+
disable_programmatic_signin = false
123+
}
98124
}
99125
`, context)
100126
}
101127

102-
func testAccIAMWorkforcePoolWorkforcePool_update(context map[string]interface{}) string {
128+
func testAccIAMWorkforcePoolWorkforcePool_minimal_update(context map[string]interface{}) string {
103129
return acctest.Nprintf(`
104130
resource "google_iam_workforce_pool" "my_pool" {
105131
workforce_pool_id = "my-pool-%{random_suffix}"

website/docs/r/iam_workforce_pool.html.markdown

+40-7
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,19 @@ resource "google_iam_workforce_pool" "example" {
4747

4848
```hcl
4949
resource "google_iam_workforce_pool" "example" {
50-
workforce_pool_id = "example-pool"
51-
parent = "organizations/123456789"
52-
location = "global"
53-
display_name = "Display name"
54-
description = "A sample workforce pool."
55-
disabled = false
56-
session_duration = "7200s"
50+
workforce_pool_id = "example-pool"
51+
parent = "organizations/123456789"
52+
location = "global"
53+
display_name = "Display name"
54+
description = "A sample workforce pool."
55+
disabled = false
56+
session_duration = "7200s"
57+
access_restrictions {
58+
allowed_services {
59+
domain = "backstory.chronicle.security"
60+
}
61+
disable_programmatic_signin = false
62+
}
5763
}
5864
```
5965

@@ -101,6 +107,33 @@ The following arguments are supported:
101107
If `sessionDuration` is not configured, minted credentials have a default duration of one hour (3600s).
102108
A duration in seconds with up to nine fractional digits, ending with '`s`'. Example: "`3.5s`".
103109

110+
* `access_restrictions` -
111+
(Optional)
112+
Configure access restrictions on the workforce pool users. This is an optional field. If specified web
113+
sign-in can be restricted to given set of services or programmatic sign-in can be disabled for pool users.
114+
Structure is [documented below](#nested_access_restrictions).
115+
116+
117+
<a name="nested_access_restrictions"></a>The `access_restrictions` block supports:
118+
119+
* `allowed_services` -
120+
(Optional)
121+
Services allowed for web sign-in with the workforce pool.
122+
If not set by default there are no restrictions.
123+
Structure is [documented below](#nested_allowed_services).
124+
125+
* `disable_programmatic_signin` -
126+
(Optional)
127+
Disable programmatic sign-in by disabling token issue via the Security Token API endpoint.
128+
See [Security Token Service API](https://cloud.google.com/iam/docs/reference/sts/rest).
129+
130+
131+
<a name="nested_allowed_services"></a>The `allowed_services` block supports:
132+
133+
* `domain` -
134+
(Optional)
135+
Domain name of the service.
136+
Example: console.cloud.google
104137

105138
## Attributes Reference
106139

0 commit comments

Comments
 (0)