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

Add access restrictions field for google_iam_workforce_pool resource #6666

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
3 changes: 3 additions & 0 deletions .changelog/9490.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
iam: added `allowedServices`, `disableProgrammaticSignin` fields to `google_iam_workforce_pool` resource
```
140 changes: 140 additions & 0 deletions google-beta/services/iamworkforcepool/resource_iam_workforce_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,40 @@ func ResourceIAMWorkforcePoolWorkforcePool() *schema.Resource {
digits, or hyphens. It must start with a letter, and cannot have a trailing hyphen.
The prefix 'gcp-' is reserved for use by Google, and may not be specified.`,
},
"access_restrictions": {
Type: schema.TypeList,
Optional: true,
ForceNew: true,
Description: `Configure access restrictions on the workforce pool users. This is an optional field. If specified web
sign-in can be restricted to given set of services or programmatic sign-in can be disabled for pool users.`,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"allowed_services": {
Type: schema.TypeList,
Optional: true,
Description: `Services allowed for web sign-in with the workforce pool.
If not set by default there are no restrictions.`,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"domain": {
Type: schema.TypeString,
Optional: true,
Description: `Domain name of the service.
Example: console.cloud.google`,
},
},
},
},
"disable_programmatic_signin": {
Type: schema.TypeBool,
Optional: true,
Description: `Disable programmatic sign-in by disabling token issue via the Security Token API endpoint.
See [Security Token Service API](https://cloud.google.com/iam/docs/reference/sts/rest).`,
},
},
},
},
"description": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -180,6 +214,12 @@ func resourceIAMWorkforcePoolWorkforcePoolCreate(d *schema.ResourceData, meta in
} else if v, ok := d.GetOkExists("session_duration"); !tpgresource.IsEmptyValue(reflect.ValueOf(sessionDurationProp)) && (ok || !reflect.DeepEqual(v, sessionDurationProp)) {
obj["sessionDuration"] = sessionDurationProp
}
accessRestrictionsProp, err := expandIAMWorkforcePoolWorkforcePoolAccessRestrictions(d.Get("access_restrictions"), d, config)
if err != nil {
return err
} else if v, ok := d.GetOkExists("access_restrictions"); !tpgresource.IsEmptyValue(reflect.ValueOf(accessRestrictionsProp)) && (ok || !reflect.DeepEqual(v, accessRestrictionsProp)) {
obj["accessRestrictions"] = accessRestrictionsProp
}

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

return nil
}
Expand Down Expand Up @@ -490,6 +533,47 @@ func flattenIAMWorkforcePoolWorkforcePoolSessionDuration(v interface{}, d *schem
return v
}

func flattenIAMWorkforcePoolWorkforcePoolAccessRestrictions(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return nil
}
original := v.(map[string]interface{})
if len(original) == 0 {
return nil
}
transformed := make(map[string]interface{})
transformed["allowed_services"] =
flattenIAMWorkforcePoolWorkforcePoolAccessRestrictionsAllowedServices(original["allowedServices"], d, config)
transformed["disable_programmatic_signin"] =
flattenIAMWorkforcePoolWorkforcePoolAccessRestrictionsDisableProgrammaticSignin(original["disableProgrammaticSignin"], d, config)
return []interface{}{transformed}
}
func flattenIAMWorkforcePoolWorkforcePoolAccessRestrictionsAllowedServices(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
if v == nil {
return v
}
l := v.([]interface{})
transformed := make([]interface{}, 0, len(l))
for _, raw := range l {
original := raw.(map[string]interface{})
if len(original) < 1 {
// Do not include empty json objects coming back from the api
continue
}
transformed = append(transformed, map[string]interface{}{
"domain": flattenIAMWorkforcePoolWorkforcePoolAccessRestrictionsAllowedServicesDomain(original["domain"], d, config),
})
}
return transformed
}
func flattenIAMWorkforcePoolWorkforcePoolAccessRestrictionsAllowedServicesDomain(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func flattenIAMWorkforcePoolWorkforcePoolAccessRestrictionsDisableProgrammaticSignin(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
return v
}

func expandIAMWorkforcePoolWorkforcePoolParent(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}
Expand All @@ -510,6 +594,62 @@ func expandIAMWorkforcePoolWorkforcePoolSessionDuration(v interface{}, d tpgreso
return v, nil
}

func expandIAMWorkforcePoolWorkforcePoolAccessRestrictions(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
if len(l) == 0 || l[0] == nil {
return nil, nil
}
raw := l[0]
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedAllowedServices, err := expandIAMWorkforcePoolWorkforcePoolAccessRestrictionsAllowedServices(original["allowed_services"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedAllowedServices); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["allowedServices"] = transformedAllowedServices
}

transformedDisableProgrammaticSignin, err := expandIAMWorkforcePoolWorkforcePoolAccessRestrictionsDisableProgrammaticSignin(original["disable_programmatic_signin"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedDisableProgrammaticSignin); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["disableProgrammaticSignin"] = transformedDisableProgrammaticSignin
}

return transformed, nil
}

func expandIAMWorkforcePoolWorkforcePoolAccessRestrictionsAllowedServices(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
l := v.([]interface{})
req := make([]interface{}, 0, len(l))
for _, raw := range l {
if raw == nil {
continue
}
original := raw.(map[string]interface{})
transformed := make(map[string]interface{})

transformedDomain, err := expandIAMWorkforcePoolWorkforcePoolAccessRestrictionsAllowedServicesDomain(original["domain"], d, config)
if err != nil {
return nil, err
} else if val := reflect.ValueOf(transformedDomain); val.IsValid() && !tpgresource.IsEmptyValue(val) {
transformed["domain"] = transformedDomain
}

req = append(req, transformed)
}
return req, nil
}

func expandIAMWorkforcePoolWorkforcePoolAccessRestrictionsAllowedServicesDomain(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func expandIAMWorkforcePoolWorkforcePoolAccessRestrictionsDisableProgrammaticSignin(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
return v, nil
}

func resourceIAMWorkforcePoolWorkforcePoolDecoder(d *schema.ResourceData, meta interface{}, res map[string]interface{}) (map[string]interface{}, error) {
if v := res["state"]; v == "DELETED" {
return nil, nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,19 @@ func TestAccIAMWorkforcePoolWorkforcePool_iamWorkforcePoolFullExample(t *testing
func testAccIAMWorkforcePoolWorkforcePool_iamWorkforcePoolFullExample(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_iam_workforce_pool" "example" {
workforce_pool_id = "tf-test-example-pool%{random_suffix}"
parent = "organizations/%{org_id}"
location = "global"
display_name = "Display name"
description = "A sample workforce pool."
disabled = false
session_duration = "7200s"
workforce_pool_id = "tf-test-example-pool%{random_suffix}"
parent = "organizations/%{org_id}"
location = "global"
display_name = "Display name"
description = "A sample workforce pool."
disabled = false
session_duration = "7200s"
access_restrictions {
allowed_services {
domain = "backstory.chronicle.security"
}
disable_programmatic_signin = false
}
}
`, context)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func TestAccIAMWorkforcePoolWorkforcePool_full(t *testing.T) {
ImportStateVerify: true,
},
{
Config: testAccIAMWorkforcePoolWorkforcePool_update(context),
Config: testAccIAMWorkforcePoolWorkforcePool_full_update(context),
},
{
ResourceName: "google_iam_workforce_pool.my_pool",
Expand Down Expand Up @@ -64,7 +64,7 @@ func TestAccIAMWorkforcePoolWorkforcePool_minimal(t *testing.T) {
ImportStateVerify: true,
},
{
Config: testAccIAMWorkforcePoolWorkforcePool_update(context),
Config: testAccIAMWorkforcePoolWorkforcePool_minimal_update(context),
},
{
ResourceName: "google_iam_workforce_pool.my_pool",
Expand All @@ -77,29 +77,55 @@ func TestAccIAMWorkforcePoolWorkforcePool_minimal(t *testing.T) {

func testAccIAMWorkforcePoolWorkforcePool_full(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_iam_workforce_pool" "my_pool" {
workforce_pool_id = "my-pool-%{random_suffix}"
parent = "organizations/%{org_id}"
location = "global"
display_name = "Display name"
description = "A sample workforce pool."
disabled = false
session_duration = "7200s"
access_restrictions {
allowed_services {
domain = "backstory.chronicle.security"
}
disable_programmatic_signin = false
}
}
`, context)
}

func testAccIAMWorkforcePoolWorkforcePool_minimal(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_iam_workforce_pool" "my_pool" {
workforce_pool_id = "my-pool-%{random_suffix}"
parent = "organizations/%{org_id}"
location = "global"
display_name = "Display name"
description = "A sample workforce pool."
disabled = false
session_duration = "7200s"
}
`, context)
}

func testAccIAMWorkforcePoolWorkforcePool_minimal(context map[string]interface{}) string {
func testAccIAMWorkforcePoolWorkforcePool_full_update(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_iam_workforce_pool" "my_pool" {
workforce_pool_id = "my-pool-%{random_suffix}"
parent = "organizations/%{org_id}"
location = "global"
display_name = "New display name"
description = "A sample workforce pool with updated description."
disabled = true
session_duration = "3600s"
access_restrictions {
allowed_services {
domain = "backstory.chronicle.security"
}
disable_programmatic_signin = false
}
}
`, context)
}

func testAccIAMWorkforcePoolWorkforcePool_update(context map[string]interface{}) string {
func testAccIAMWorkforcePoolWorkforcePool_minimal_update(context map[string]interface{}) string {
return acctest.Nprintf(`
resource "google_iam_workforce_pool" "my_pool" {
workforce_pool_id = "my-pool-%{random_suffix}"
Expand Down
47 changes: 40 additions & 7 deletions website/docs/r/iam_workforce_pool.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -47,13 +47,19 @@ resource "google_iam_workforce_pool" "example" {

```hcl
resource "google_iam_workforce_pool" "example" {
workforce_pool_id = "example-pool"
parent = "organizations/123456789"
location = "global"
display_name = "Display name"
description = "A sample workforce pool."
disabled = false
session_duration = "7200s"
workforce_pool_id = "example-pool"
parent = "organizations/123456789"
location = "global"
display_name = "Display name"
description = "A sample workforce pool."
disabled = false
session_duration = "7200s"
access_restrictions {
allowed_services {
domain = "backstory.chronicle.security"
}
disable_programmatic_signin = false
}
}
```

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

* `access_restrictions` -
(Optional)
Configure access restrictions on the workforce pool users. This is an optional field. If specified web
sign-in can be restricted to given set of services or programmatic sign-in can be disabled for pool users.
Structure is [documented below](#nested_access_restrictions).


<a name="nested_access_restrictions"></a>The `access_restrictions` block supports:

* `allowed_services` -
(Optional)
Services allowed for web sign-in with the workforce pool.
If not set by default there are no restrictions.
Structure is [documented below](#nested_allowed_services).

* `disable_programmatic_signin` -
(Optional)
Disable programmatic sign-in by disabling token issue via the Security Token API endpoint.
See [Security Token Service API](https://cloud.google.com/iam/docs/reference/sts/rest).


<a name="nested_allowed_services"></a>The `allowed_services` block supports:

* `domain` -
(Optional)
Domain name of the service.
Example: console.cloud.google

## Attributes Reference

Expand Down