Skip to content

Commit 74d86d6

Browse files
authored
Add CIG Policy List API support in Terraform (#15812)
1 parent 3bf5651 commit 74d86d6

File tree

4 files changed

+324
-0
lines changed

4 files changed

+324
-0
lines changed

mmv1/third_party/terraform/provider/provider_mmv1_resources.go.tmpl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ var handwrittenDatasources = map[string]*schema.Resource{
8080
"google_cloud_identity_group_memberships": cloudidentity.DataSourceGoogleCloudIdentityGroupMemberships(),
8181
"google_cloud_identity_group_transitive_memberships": cloudidentity.DataSourceGoogleCloudIdentityGroupTransitiveMemberships(),
8282
"google_cloud_identity_group_lookup": cloudidentity.DataSourceGoogleCloudIdentityGroupLookup(),
83+
"google_cloud_identity_policies": cloudidentity.DataSourceGoogleCloudIdentityPolicies(),
8384
"google_cloud_identity_policy": cloudidentity.DataSourceGoogleCloudIdentityPolicy(),
8485
"google_cloud_quotas_quota_info": cloudquotas.DataSourceGoogleCloudQuotasQuotaInfo(),
8586
"google_cloud_quotas_quota_infos": cloudquotas.DataSourceGoogleCloudQuotasQuotaInfos(),
Lines changed: 170 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,170 @@
1+
package cloudidentity
2+
3+
import (
4+
"encoding/json"
5+
"fmt"
6+
7+
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
8+
"github.com/hashicorp/terraform-provider-google/google/tpgresource"
9+
transport_tpg "github.com/hashicorp/terraform-provider-google/google/transport"
10+
)
11+
12+
func DataSourceGoogleCloudIdentityPolicies() *schema.Resource {
13+
return &schema.Resource{
14+
Read: dataSourceGoogleCloudIdentityPoliciesRead,
15+
Schema: map[string]*schema.Schema{
16+
"filter": {
17+
Type: schema.TypeString,
18+
Optional: true,
19+
Description: `Filter expression for listing policies, as documented in the Cloud Identity Policy API policies.list method`,
20+
},
21+
"policies": {
22+
Type: schema.TypeList,
23+
Computed: true,
24+
Description: `List of Cloud Identity policies that match the filter (or all policies if no filter is provided).`,
25+
Elem: &schema.Resource{
26+
Schema: map[string]*schema.Schema{
27+
"name": {
28+
Type: schema.TypeString,
29+
Computed: true,
30+
Description: `The resource name of the policy.`,
31+
},
32+
"customer": {
33+
Type: schema.TypeString,
34+
Computed: true,
35+
Description: `The customer that the policy belongs to.`,
36+
},
37+
"policy_query": {
38+
Type: schema.TypeList,
39+
Computed: true,
40+
Description: `The CEL query that defines which entities the policy applies to.`,
41+
Elem: &schema.Resource{
42+
Schema: map[string]*schema.Schema{
43+
"query": {
44+
Type: schema.TypeString,
45+
Computed: true,
46+
Description: "The query that defines which entities the policy applies to.",
47+
},
48+
"group": {
49+
Type: schema.TypeString,
50+
Computed: true,
51+
Description: "The group that the policy applies to.",
52+
},
53+
"org_unit": {
54+
Type: schema.TypeString,
55+
Computed: true,
56+
Description: "The org unit that the policy applies to.",
57+
},
58+
"sort_order": {
59+
Type: schema.TypeFloat,
60+
Computed: true,
61+
Description: "The sort order of the policy.",
62+
},
63+
},
64+
},
65+
},
66+
"setting": {
67+
Type: schema.TypeString,
68+
Computed: true,
69+
Description: `The setting configured by this policy.`,
70+
},
71+
"type": {
72+
Type: schema.TypeString,
73+
Computed: true,
74+
Description: `The type of the policy.`,
75+
},
76+
},
77+
},
78+
},
79+
},
80+
}
81+
}
82+
83+
func dataSourceGoogleCloudIdentityPoliciesRead(d *schema.ResourceData, meta interface{}) error {
84+
config := meta.(*transport_tpg.Config)
85+
userAgent, err := tpgresource.GenerateUserAgentString(d, config.UserAgent)
86+
if err != nil {
87+
return err
88+
}
89+
90+
policiesListCall := config.NewCloudIdentityClient(userAgent).Policies.List()
91+
92+
if filter, ok := d.GetOk("filter"); ok {
93+
policiesListCall = policiesListCall.Filter(filter.(string))
94+
}
95+
96+
if config.UserProjectOverride {
97+
billingProject := ""
98+
// err may be nil - project isn't required for this resource
99+
if project, err := tpgresource.GetProject(d, config); err == nil {
100+
billingProject = project
101+
}
102+
103+
// err == nil indicates that the billing_project value was found
104+
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
105+
billingProject = bp
106+
}
107+
108+
if billingProject != "" {
109+
policiesListCall.Header().Set("X-Goog-User-Project", billingProject)
110+
}
111+
}
112+
113+
var allPolicies []map[string]interface{}
114+
115+
for {
116+
resp, err := policiesListCall.Do()
117+
if err != nil {
118+
return transport_tpg.HandleDataSourceNotFoundError(err, d, "CloudIdentityListPolicies", "Policies")
119+
}
120+
121+
if resp.Policies != nil {
122+
for _, p := range resp.Policies {
123+
policyMap := map[string]interface{}{
124+
"name": p.Name,
125+
"customer": p.Customer,
126+
}
127+
128+
if p.PolicyQuery != nil {
129+
pq := map[string]interface{}{
130+
"query": p.PolicyQuery.Query,
131+
"group": p.PolicyQuery.Group,
132+
"org_unit": p.PolicyQuery.OrgUnit,
133+
"sort_order": p.PolicyQuery.SortOrder,
134+
}
135+
policyMap["policy_query"] = []interface{}{pq}
136+
}
137+
138+
if p.Setting != nil {
139+
settingBytes, err := json.Marshal(p.Setting)
140+
if err != nil {
141+
return fmt.Errorf("error marshalling policy setting: %s", err)
142+
}
143+
policyMap["setting"] = string(settingBytes)
144+
}
145+
146+
policyMap["type"] = p.Type
147+
148+
allPolicies = append(allPolicies, policyMap)
149+
}
150+
}
151+
152+
if resp.NextPageToken == "" {
153+
break
154+
}
155+
156+
policiesListCall = policiesListCall.PageToken(resp.NextPageToken)
157+
}
158+
159+
if err := d.Set("policies", allPolicies); err != nil {
160+
return fmt.Errorf("error setting policies: %s", err)
161+
}
162+
163+
if filter, ok := d.GetOk("filter"); ok {
164+
d.SetId(fmt.Sprintf("cloud-identity-policies-%s", filter.(string)))
165+
} else {
166+
d.SetId(fmt.Sprintf("cloud-identity-policies-%d", len(allPolicies)))
167+
}
168+
169+
return nil
170+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package cloudidentity_test
2+
3+
import (
4+
"context"
5+
"testing"
6+
7+
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
8+
"github.com/hashicorp/terraform-provider-google/google/acctest"
9+
"google.golang.org/api/cloudidentity/v1"
10+
)
11+
12+
// This test uses the ListPolicies API directly in the precheck to ensure that
13+
// the Cloud Identity Policies API is reachable and that at least one policy
14+
// exists. Once CreatePolicy becomes GA and is supported, this test can be
15+
// updated to create a dedicated policy instead.
16+
func TestAccDataSourceGoogleCloudIdentityPolicies(t *testing.T) {
17+
acctest.VcrTest(t, resource.TestCase{
18+
PreCheck: func() {
19+
acctest.AccTestPreCheck(t)
20+
21+
ctx := context.Background()
22+
ci, err := cloudidentity.NewService(ctx)
23+
if err != nil {
24+
t.Skipf("Cloud Identity service not available in this env: %v", err)
25+
}
26+
lst, err := ci.Policies.List().Context(ctx).PageSize(1).Do()
27+
if err != nil {
28+
t.Skipf("Cloud Identity Policies API not accessible in this env: %v", err)
29+
}
30+
if lst == nil || len(lst.Policies) == 0 {
31+
t.Skip("No Cloud Identity policies found in this customer; skipping data source test.")
32+
}
33+
},
34+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
35+
Steps: []resource.TestStep{
36+
{
37+
Config: `
38+
data "google_cloud_identity_policies" "test" {
39+
}
40+
`,
41+
Check: resource.ComposeTestCheckFunc(
42+
// We know at least one policy exists from the precheck, so we can
43+
// assert that at least the first element in the list is populated.
44+
resource.TestCheckResourceAttrSet("data.google_cloud_identity_policies.test", "policies.#"),
45+
resource.TestCheckResourceAttrSet("data.google_cloud_identity_policies.test", "policies.0.name"),
46+
resource.TestCheckResourceAttrSet("data.google_cloud_identity_policies.test", "policies.0.customer"),
47+
resource.TestCheckResourceAttrSet("data.google_cloud_identity_policies.test", "policies.0.type"),
48+
),
49+
},
50+
},
51+
})
52+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
---
2+
subcategory: "Cloud Identity"
3+
layout: "google"
4+
page_title: "Google: google_cloud_identity_policies"
5+
sidebar_current: "docs-google-data-cloud-identity-list-policies"
6+
description: |-
7+
Use this data source to list Cloud Identity policies.
8+
---
9+
10+
# google_cloud_identity_policies
11+
12+
Use this data source to list Cloud Identity policies.
13+
14+
## Example Usage
15+
16+
```hcl
17+
data "google_cloud_identity_policies" "all" {
18+
# Example filter (optional)"
19+
# filter = "customer == \"customers/my_customer\" &&
20+
# setting.type.matches('^settings/gmail\\..*$')"
21+
}
22+
23+
// The name of the first policy in the list of policies
24+
output "first_policy_name" {
25+
value = data.google_cloud_identity_policies.all.policies[0].name
26+
}
27+
28+
// The customer to whom the first policy belongs to. This will always be the
29+
// same across multiple policies as well.
30+
output "first_policy_customer" {
31+
value = data.google_cloud_identity_policies.all.policies[0].customer
32+
}
33+
34+
// The CEL query of the first policy
35+
output "policy_query_query" {
36+
value = data.google_cloud_identity_policies.all.policies[0].policy_query[0].query
37+
}
38+
39+
// The org unit the first policy applies to
40+
output "policy_query_org_unit" {
41+
value = data.google_cloud_identity_policies.all.policies[0].policy_query[0].org_unit
42+
}
43+
44+
// The group the first policy applies to
45+
output "policy_query_group" {
46+
value = data.google_cloud_identity_policies.all.policies[0].policy_query[0].group
47+
}
48+
49+
// The sort order of the first policy
50+
output "policy_query_sort_order" {
51+
value = data.google_cloud_identity_policies.all.policies[0].policy_query[0].sort_order
52+
}
53+
54+
// The setting of the first policy as a JSON string
55+
output "policy_setting" {
56+
value = data.google_cloud_identity_policies.all.policies[0].setting
57+
}
58+
59+
// The type of policy - ADMIN/SYSTEM
60+
output "policy_type" {
61+
value = data.google_cloud_identity_policies.all.policies[0].type
62+
}
63+
```
64+
65+
## Argument Reference
66+
67+
The following arguments are supported:
68+
69+
* `filter` - (Optional) Filter expression for listing policies, as documented in the Cloud Identity Policy API policies.list method.
70+
71+
## Attributes Reference
72+
73+
In addition to the arguments listed above, the following computed attributes are exported:
74+
75+
* `policies` - List of Cloud Identity policies that match the filter (or all policies if no filter is provided). Structure is documented below.
76+
77+
---
78+
79+
The `policies` block contains:
80+
81+
* `name` - The resource name of the policy.
82+
83+
* `customer` - The customer that the policy belongs to.
84+
85+
* `policy_query` - A list containing the CEL query that defines which entities the policy applies to. Structure is documented below.
86+
87+
* `setting` - The setting configured by this policy, represented as a JSON string.
88+
89+
* `type` - The type of the policy.
90+
91+
---
92+
93+
The `policy_query` block contains:
94+
95+
* `query` - The query that defines which entities the policy applies to.
96+
97+
* `group` - The group that the policy applies to.
98+
99+
* `org_unit` - The org unit that the policy applies to.
100+
101+
* `sort_order` - The sort order of the policy.

0 commit comments

Comments
 (0)