Skip to content

Commit 47243ee

Browse files
Add allowlistedCertificates field to TrustConfig (#10906) (#18587)
[upstream:0b9e2683dd1750ec04a869d4ffe54ff7fe0ad292] Signed-off-by: Modular Magician <[email protected]>
1 parent 5c2b80d commit 47243ee

5 files changed

+181
-7
lines changed

.changelog/10906.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
certificatemanager: added `allowlisted_certificates` to `google_certificate_manager_trust_config`
3+
```

google/services/certificatemanager/resource_certificate_manager_trust_config.go

+84-5
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,21 @@ func ResourceCertificateManagerTrustConfig() *schema.Resource {
6666
ForceNew: true,
6767
Description: `A user-defined name of the trust config. Trust config names must be unique globally.`,
6868
},
69+
"allowlisted_certificates": {
70+
Type: schema.TypeList,
71+
Optional: true,
72+
Description: `Allowlisted PEM-encoded certificates. A certificate matching an allowlisted certificate is always considered valid as long as
73+
the certificate is parseable, proof of private key possession is established, and constraints on the certificate's SAN field are met.`,
74+
Elem: &schema.Resource{
75+
Schema: map[string]*schema.Schema{
76+
"pem_certificate": {
77+
Type: schema.TypeString,
78+
Required: true,
79+
Description: `PEM certificate that is allowlisted. The certificate can be up to 5k bytes, and must be a parseable X.509 certificate.`,
80+
},
81+
},
82+
},
83+
},
6984
"description": {
7085
Type: schema.TypeString,
7186
Optional: true,
@@ -134,7 +149,6 @@ Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z".`,
134149
"effective_labels": {
135150
Type: schema.TypeMap,
136151
Computed: true,
137-
ForceNew: true,
138152
Description: `All of labels (key/value pairs) present on the resource in GCP, including the labels configured through Terraform, other clients and services.`,
139153
Elem: &schema.Schema{Type: schema.TypeString},
140154
},
@@ -184,6 +198,12 @@ func resourceCertificateManagerTrustConfigCreate(d *schema.ResourceData, meta in
184198
} else if v, ok := d.GetOkExists("trust_stores"); !tpgresource.IsEmptyValue(reflect.ValueOf(trustStoresProp)) && (ok || !reflect.DeepEqual(v, trustStoresProp)) {
185199
obj["trustStores"] = trustStoresProp
186200
}
201+
allowlistedCertificatesProp, err := expandCertificateManagerTrustConfigAllowlistedCertificates(d.Get("allowlisted_certificates"), d, config)
202+
if err != nil {
203+
return err
204+
} else if v, ok := d.GetOkExists("allowlisted_certificates"); !tpgresource.IsEmptyValue(reflect.ValueOf(allowlistedCertificatesProp)) && (ok || !reflect.DeepEqual(v, allowlistedCertificatesProp)) {
205+
obj["allowlistedCertificates"] = allowlistedCertificatesProp
206+
}
187207
labelsProp, err := expandCertificateManagerTrustConfigEffectiveLabels(d.Get("effective_labels"), d, config)
188208
if err != nil {
189209
return err
@@ -304,6 +324,9 @@ func resourceCertificateManagerTrustConfigRead(d *schema.ResourceData, meta inte
304324
if err := d.Set("trust_stores", flattenCertificateManagerTrustConfigTrustStores(res["trustStores"], d, config)); err != nil {
305325
return fmt.Errorf("Error reading TrustConfig: %s", err)
306326
}
327+
if err := d.Set("allowlisted_certificates", flattenCertificateManagerTrustConfigAllowlistedCertificates(res["allowlistedCertificates"], d, config)); err != nil {
328+
return fmt.Errorf("Error reading TrustConfig: %s", err)
329+
}
307330
if err := d.Set("terraform_labels", flattenCertificateManagerTrustConfigTerraformLabels(res["labels"], d, config)); err != nil {
308331
return fmt.Errorf("Error reading TrustConfig: %s", err)
309332
}
@@ -342,6 +365,18 @@ func resourceCertificateManagerTrustConfigUpdate(d *schema.ResourceData, meta in
342365
} else if v, ok := d.GetOkExists("trust_stores"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, trustStoresProp)) {
343366
obj["trustStores"] = trustStoresProp
344367
}
368+
allowlistedCertificatesProp, err := expandCertificateManagerTrustConfigAllowlistedCertificates(d.Get("allowlisted_certificates"), d, config)
369+
if err != nil {
370+
return err
371+
} else if v, ok := d.GetOkExists("allowlisted_certificates"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, allowlistedCertificatesProp)) {
372+
obj["allowlistedCertificates"] = allowlistedCertificatesProp
373+
}
374+
labelsProp, err := expandCertificateManagerTrustConfigEffectiveLabels(d.Get("effective_labels"), d, config)
375+
if err != nil {
376+
return err
377+
} else if v, ok := d.GetOkExists("effective_labels"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, labelsProp)) {
378+
obj["labels"] = labelsProp
379+
}
345380

346381
url, err := tpgresource.ReplaceVars(d, config, "{{CertificateManagerBasePath}}projects/{{project}}/locations/{{location}}/trustConfigs/{{name}}")
347382
if err != nil {
@@ -350,10 +385,6 @@ func resourceCertificateManagerTrustConfigUpdate(d *schema.ResourceData, meta in
350385

351386
log.Printf("[DEBUG] Updating TrustConfig %q: %#v", d.Id(), obj)
352387
headers := make(http.Header)
353-
url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": "*"})
354-
if err != nil {
355-
return err
356-
}
357388

358389
// err == nil indicates that the billing_project value was found
359390
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {
@@ -554,6 +585,28 @@ func flattenCertificateManagerTrustConfigTrustStoresIntermediateCasPemCertificat
554585
return v
555586
}
556587

588+
func flattenCertificateManagerTrustConfigAllowlistedCertificates(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
589+
if v == nil {
590+
return v
591+
}
592+
l := v.([]interface{})
593+
transformed := make([]interface{}, 0, len(l))
594+
for _, raw := range l {
595+
original := raw.(map[string]interface{})
596+
if len(original) < 1 {
597+
// Do not include empty json objects coming back from the api
598+
continue
599+
}
600+
transformed = append(transformed, map[string]interface{}{
601+
"pem_certificate": flattenCertificateManagerTrustConfigAllowlistedCertificatesPemCertificate(original["pemCertificate"], d, config),
602+
})
603+
}
604+
return transformed
605+
}
606+
func flattenCertificateManagerTrustConfigAllowlistedCertificatesPemCertificate(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
607+
return v
608+
}
609+
557610
func flattenCertificateManagerTrustConfigTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
558611
if v == nil {
559612
return v
@@ -658,6 +711,32 @@ func expandCertificateManagerTrustConfigTrustStoresIntermediateCasPemCertificate
658711
return v, nil
659712
}
660713

714+
func expandCertificateManagerTrustConfigAllowlistedCertificates(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
715+
l := v.([]interface{})
716+
req := make([]interface{}, 0, len(l))
717+
for _, raw := range l {
718+
if raw == nil {
719+
continue
720+
}
721+
original := raw.(map[string]interface{})
722+
transformed := make(map[string]interface{})
723+
724+
transformedPemCertificate, err := expandCertificateManagerTrustConfigAllowlistedCertificatesPemCertificate(original["pem_certificate"], d, config)
725+
if err != nil {
726+
return nil, err
727+
} else if val := reflect.ValueOf(transformedPemCertificate); val.IsValid() && !tpgresource.IsEmptyValue(val) {
728+
transformed["pemCertificate"] = transformedPemCertificate
729+
}
730+
731+
req = append(req, transformed)
732+
}
733+
return req, nil
734+
}
735+
736+
func expandCertificateManagerTrustConfigAllowlistedCertificatesPemCertificate(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
737+
return v, nil
738+
}
739+
661740
func expandCertificateManagerTrustConfigEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
662741
if v == nil {
663742
return map[string]string{}, nil

google/services/certificatemanager/resource_certificate_manager_trust_config_generated_test.go

+46
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,52 @@ resource "google_certificate_manager_trust_config" "default" {
7878
`, context)
7979
}
8080

81+
func TestAccCertificateManagerTrustConfig_certificateManagerTrustConfigAllowlistedCertificatesExample(t *testing.T) {
82+
t.Parallel()
83+
84+
context := map[string]interface{}{
85+
"random_suffix": acctest.RandString(t, 10),
86+
}
87+
88+
acctest.VcrTest(t, resource.TestCase{
89+
PreCheck: func() { acctest.AccTestPreCheck(t) },
90+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
91+
CheckDestroy: testAccCheckCertificateManagerTrustConfigDestroyProducer(t),
92+
Steps: []resource.TestStep{
93+
{
94+
Config: testAccCertificateManagerTrustConfig_certificateManagerTrustConfigAllowlistedCertificatesExample(context),
95+
},
96+
{
97+
ResourceName: "google_certificate_manager_trust_config.default",
98+
ImportState: true,
99+
ImportStateVerify: true,
100+
ImportStateVerifyIgnore: []string{"labels", "location", "name", "terraform_labels"},
101+
},
102+
},
103+
})
104+
}
105+
106+
func testAccCertificateManagerTrustConfig_certificateManagerTrustConfigAllowlistedCertificatesExample(context map[string]interface{}) string {
107+
return acctest.Nprintf(`
108+
resource "google_certificate_manager_trust_config" "default" {
109+
name = "tf-test-trust-config%{random_suffix}"
110+
description = "A sample trust config resource with allowlisted certificates"
111+
location = "global"
112+
113+
allowlisted_certificates {
114+
pem_certificate = file("test-fixtures/cert.pem")
115+
}
116+
allowlisted_certificates {
117+
pem_certificate = file("test-fixtures/cert2.pem")
118+
}
119+
120+
labels = {
121+
foo = "bar"
122+
}
123+
}
124+
`, context)
125+
}
126+
81127
func testAccCheckCertificateManagerTrustConfigDestroyProducer(t *testing.T) func(s *terraform.State) error {
82128
return func(s *terraform.State) error {
83129
for name, rs := range s.RootModule().Resources {

google/services/certificatemanager/resource_certificate_manager_trust_config_test.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ func testAccCertificateManagerTrustConfig_update0(context map[string]interface{}
4848
resource "google_certificate_manager_trust_config" "default" {
4949
name = "tf-test-trust-config%{random_suffix}"
5050
description = "sample description for the trust config"
51-
location = "us-central1"
51+
location = "global"
5252
5353
trust_stores {
5454
trust_anchors {
@@ -59,6 +59,10 @@ resource "google_certificate_manager_trust_config" "default" {
5959
}
6060
}
6161
62+
allowlisted_certificates {
63+
pem_certificate = file("test-fixtures/cert.pem")
64+
}
65+
6266
labels = {
6367
"foo" = "bar"
6468
}
@@ -71,7 +75,7 @@ func testAccCertificateManagerTrustConfig_update1(context map[string]interface{}
7175
resource "google_certificate_manager_trust_config" "default" {
7276
name = "tf-test-trust-config%{random_suffix}"
7377
description = "sample description for the trust config 2"
74-
location = "us-central1"
78+
location = "global"
7579
7680
trust_stores {
7781
trust_anchors {
@@ -82,6 +86,10 @@ resource "google_certificate_manager_trust_config" "default" {
8286
}
8387
}
8488
89+
allowlisted_certificates {
90+
pem_certificate = file("test-fixtures/cert.pem")
91+
}
92+
8593
labels = {
8694
"bar" = "foo"
8795
}

website/docs/r/certificate_manager_trust_config.html.markdown

+38
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,32 @@ resource "google_certificate_manager_trust_config" "default" {
6060
}
6161
}
6262
```
63+
<div class = "oics-button" style="float: right; margin: 0 0 -15px">
64+
<a href="https://console.cloud.google.com/cloudshell/open?cloudshell_git_repo=https%3A%2F%2Fgithub.jpy.wang%2Fterraform-google-modules%2Fdocs-examples.git&cloudshell_image=gcr.io%2Fcloudshell-images%2Fcloudshell%3Alatest&cloudshell_print=.%2Fmotd&cloudshell_tutorial=.%2Ftutorial.md&cloudshell_working_dir=certificate_manager_trust_config_allowlisted_certificates&open_in_editor=main.tf" target="_blank">
65+
<img alt="Open in Cloud Shell" src="//gstatic.com/cloudssh/images/open-btn.svg" style="max-height: 44px; margin: 32px auto; max-width: 100%;">
66+
</a>
67+
</div>
68+
## Example Usage - Certificate Manager Trust Config Allowlisted Certificates
69+
70+
71+
```hcl
72+
resource "google_certificate_manager_trust_config" "default" {
73+
name = "trust-config"
74+
description = "A sample trust config resource with allowlisted certificates"
75+
location = "global"
76+
77+
allowlisted_certificates {
78+
pem_certificate = file("test-fixtures/cert.pem")
79+
}
80+
allowlisted_certificates {
81+
pem_certificate = file("test-fixtures/cert2.pem")
82+
}
83+
84+
labels = {
85+
foo = "bar"
86+
}
87+
}
88+
```
6389

6490
## Argument Reference
6591

@@ -94,6 +120,12 @@ The following arguments are supported:
94120
This field is supported when TrustConfig is configured with Load Balancers, currently not supported for SPIFFE certificate validation.
95121
Structure is [documented below](#nested_trust_stores).
96122

123+
* `allowlisted_certificates` -
124+
(Optional)
125+
Allowlisted PEM-encoded certificates. A certificate matching an allowlisted certificate is always considered valid as long as
126+
the certificate is parseable, proof of private key possession is established, and constraints on the certificate's SAN field are met.
127+
Structure is [documented below](#nested_allowlisted_certificates).
128+
97129
* `project` - (Optional) The ID of the project in which the resource belongs.
98130
If it is not provided, the provider project is used.
99131

@@ -128,6 +160,12 @@ The following arguments are supported:
128160
Each certificate provided in PEM format may occupy up to 5kB.
129161
**Note**: This property is sensitive and will not be displayed in the plan.
130162

163+
<a name="nested_allowlisted_certificates"></a>The `allowlisted_certificates` block supports:
164+
165+
* `pem_certificate` -
166+
(Required)
167+
PEM certificate that is allowlisted. The certificate can be up to 5k bytes, and must be a parseable X.509 certificate.
168+
131169
## Attributes Reference
132170

133171
In addition to the arguments listed above, the following computed attributes are exported:

0 commit comments

Comments
 (0)