Skip to content

Commit cd33ad7

Browse files
Feat add cas custom cdp aia support (#12452) (#9221)
[upstream:47cf9528aec3da430af249968b438905b44c14b4] Signed-off-by: Modular Magician <[email protected]>
1 parent 38af12f commit cd33ad7

5 files changed

+247
-0
lines changed

.changelog/12452.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
privateca: added `userDefinedAccessUrls` fields to `CertificateAuthority` resource to add support for custom CDP AIA URLs
3+
```

google-beta/services/privateca/resource_privateca_certificate_authority.go

+103
Original file line numberDiff line numberDiff line change
@@ -757,6 +757,33 @@ but not pem certificate for this CA itself.`,
757757
be activated before they can issue certificates. Default value: "SELF_SIGNED" Possible values: ["SELF_SIGNED", "SUBORDINATE"]`,
758758
Default: "SELF_SIGNED",
759759
},
760+
"user_defined_access_urls": {
761+
Type: schema.TypeList,
762+
Optional: true,
763+
Description: `Custom URLs for accessing content published by this CA, such as the CA certificate and CRLs,
764+
that can be specified by users.`,
765+
MaxItems: 1,
766+
Elem: &schema.Resource{
767+
Schema: map[string]*schema.Schema{
768+
"aia_issuing_certificate_urls": {
769+
Type: schema.TypeList,
770+
Optional: true,
771+
Description: `A list of URLs where this CertificateAuthority's CA certificate is published that is specified by users.`,
772+
Elem: &schema.Schema{
773+
Type: schema.TypeString,
774+
},
775+
},
776+
"crl_access_urls": {
777+
Type: schema.TypeList,
778+
Optional: true,
779+
Description: `A list of URLs where this CertificateAuthority's CRLs are published that is specified by users.`,
780+
Elem: &schema.Schema{
781+
Type: schema.TypeString,
782+
},
783+
},
784+
},
785+
},
786+
},
760787
"access_urls": {
761788
Type: schema.TypeList,
762789
Computed: true,
@@ -902,6 +929,12 @@ func resourcePrivatecaCertificateAuthorityCreate(d *schema.ResourceData, meta in
902929
} else if v, ok := d.GetOkExists("gcs_bucket"); !tpgresource.IsEmptyValue(reflect.ValueOf(gcsBucketProp)) && (ok || !reflect.DeepEqual(v, gcsBucketProp)) {
903930
obj["gcsBucket"] = gcsBucketProp
904931
}
932+
userDefinedAccessUrlsProp, err := expandPrivatecaCertificateAuthorityUserDefinedAccessUrls(d.Get("user_defined_access_urls"), d, config)
933+
if err != nil {
934+
return err
935+
} else if v, ok := d.GetOkExists("user_defined_access_urls"); !tpgresource.IsEmptyValue(reflect.ValueOf(userDefinedAccessUrlsProp)) && (ok || !reflect.DeepEqual(v, userDefinedAccessUrlsProp)) {
936+
obj["userDefinedAccessUrls"] = userDefinedAccessUrlsProp
937+
}
905938
labelsProp, err := expandPrivatecaCertificateAuthorityEffectiveLabels(d.Get("effective_labels"), d, config)
906939
if err != nil {
907940
return err
@@ -1112,6 +1145,9 @@ func resourcePrivatecaCertificateAuthorityRead(d *schema.ResourceData, meta inte
11121145
if err := d.Set("labels", flattenPrivatecaCertificateAuthorityLabels(res["labels"], d, config)); err != nil {
11131146
return fmt.Errorf("Error reading CertificateAuthority: %s", err)
11141147
}
1148+
if err := d.Set("user_defined_access_urls", flattenPrivatecaCertificateAuthorityUserDefinedAccessUrls(res["userDefinedAccessUrls"], d, config)); err != nil {
1149+
return fmt.Errorf("Error reading CertificateAuthority: %s", err)
1150+
}
11151151
if err := d.Set("terraform_labels", flattenPrivatecaCertificateAuthorityTerraformLabels(res["labels"], d, config)); err != nil {
11161152
return fmt.Errorf("Error reading CertificateAuthority: %s", err)
11171153
}
@@ -1144,6 +1180,12 @@ func resourcePrivatecaCertificateAuthorityUpdate(d *schema.ResourceData, meta in
11441180
} else if v, ok := d.GetOkExists("subordinate_config"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, subordinateConfigProp)) {
11451181
obj["subordinateConfig"] = subordinateConfigProp
11461182
}
1183+
userDefinedAccessUrlsProp, err := expandPrivatecaCertificateAuthorityUserDefinedAccessUrls(d.Get("user_defined_access_urls"), d, config)
1184+
if err != nil {
1185+
return err
1186+
} else if v, ok := d.GetOkExists("user_defined_access_urls"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, userDefinedAccessUrlsProp)) {
1187+
obj["userDefinedAccessUrls"] = userDefinedAccessUrlsProp
1188+
}
11471189
labelsProp, err := expandPrivatecaCertificateAuthorityEffectiveLabels(d.Get("effective_labels"), d, config)
11481190
if err != nil {
11491191
return err
@@ -1164,6 +1206,10 @@ func resourcePrivatecaCertificateAuthorityUpdate(d *schema.ResourceData, meta in
11641206
updateMask = append(updateMask, "subordinateConfig")
11651207
}
11661208

1209+
if d.HasChange("user_defined_access_urls") {
1210+
updateMask = append(updateMask, "userDefinedAccessUrls")
1211+
}
1212+
11671213
if d.HasChange("effective_labels") {
11681214
updateMask = append(updateMask, "labels")
11691215
}
@@ -1675,6 +1721,29 @@ func flattenPrivatecaCertificateAuthorityLabels(v interface{}, d *schema.Resourc
16751721
return transformed
16761722
}
16771723

1724+
func flattenPrivatecaCertificateAuthorityUserDefinedAccessUrls(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1725+
if v == nil {
1726+
return nil
1727+
}
1728+
original := v.(map[string]interface{})
1729+
if len(original) == 0 {
1730+
return nil
1731+
}
1732+
transformed := make(map[string]interface{})
1733+
transformed["aia_issuing_certificate_urls"] =
1734+
flattenPrivatecaCertificateAuthorityUserDefinedAccessUrlsAiaIssuingCertificateUrls(original["aiaIssuingCertificateUrls"], d, config)
1735+
transformed["crl_access_urls"] =
1736+
flattenPrivatecaCertificateAuthorityUserDefinedAccessUrlsCrlAccessUrls(original["crlAccessUrls"], d, config)
1737+
return []interface{}{transformed}
1738+
}
1739+
func flattenPrivatecaCertificateAuthorityUserDefinedAccessUrlsAiaIssuingCertificateUrls(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1740+
return v
1741+
}
1742+
1743+
func flattenPrivatecaCertificateAuthorityUserDefinedAccessUrlsCrlAccessUrls(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
1744+
return v
1745+
}
1746+
16781747
func flattenPrivatecaCertificateAuthorityTerraformLabels(v interface{}, d *schema.ResourceData, config *transport_tpg.Config) interface{} {
16791748
if v == nil {
16801749
return v
@@ -2084,6 +2153,40 @@ func expandPrivatecaCertificateAuthorityGcsBucket(v interface{}, d tpgresource.T
20842153
return v, nil
20852154
}
20862155

2156+
func expandPrivatecaCertificateAuthorityUserDefinedAccessUrls(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
2157+
l := v.([]interface{})
2158+
if len(l) == 0 || l[0] == nil {
2159+
return nil, nil
2160+
}
2161+
raw := l[0]
2162+
original := raw.(map[string]interface{})
2163+
transformed := make(map[string]interface{})
2164+
2165+
transformedAiaIssuingCertificateUrls, err := expandPrivatecaCertificateAuthorityUserDefinedAccessUrlsAiaIssuingCertificateUrls(original["aia_issuing_certificate_urls"], d, config)
2166+
if err != nil {
2167+
return nil, err
2168+
} else if val := reflect.ValueOf(transformedAiaIssuingCertificateUrls); val.IsValid() && !tpgresource.IsEmptyValue(val) {
2169+
transformed["aiaIssuingCertificateUrls"] = transformedAiaIssuingCertificateUrls
2170+
}
2171+
2172+
transformedCrlAccessUrls, err := expandPrivatecaCertificateAuthorityUserDefinedAccessUrlsCrlAccessUrls(original["crl_access_urls"], d, config)
2173+
if err != nil {
2174+
return nil, err
2175+
} else if val := reflect.ValueOf(transformedCrlAccessUrls); val.IsValid() && !tpgresource.IsEmptyValue(val) {
2176+
transformed["crlAccessUrls"] = transformedCrlAccessUrls
2177+
}
2178+
2179+
return transformed, nil
2180+
}
2181+
2182+
func expandPrivatecaCertificateAuthorityUserDefinedAccessUrlsAiaIssuingCertificateUrls(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
2183+
return v, nil
2184+
}
2185+
2186+
func expandPrivatecaCertificateAuthorityUserDefinedAccessUrlsCrlAccessUrls(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (interface{}, error) {
2187+
return v, nil
2188+
}
2189+
20872190
func expandPrivatecaCertificateAuthorityEffectiveLabels(v interface{}, d tpgresource.TerraformResourceData, config *transport_tpg.Config) (map[string]string, error) {
20882191
if v == nil {
20892192
return map[string]string{}, nil

google-beta/services/privateca/resource_privateca_certificate_authority_generated_meta.yaml

+2
Original file line numberDiff line numberDiff line change
@@ -89,3 +89,5 @@ fields:
8989
provider_only: true
9090
- field: 'type'
9191
- field: 'update_time'
92+
- field: 'user_defined_access_urls.aia_issuing_certificate_urls'
93+
- field: 'user_defined_access_urls.crl_access_urls'

google-beta/services/privateca/resource_privateca_certificate_authority_generated_test.go

+73
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,79 @@ resource "google_privateca_certificate_authority" "default" {
213213
`, context)
214214
}
215215

216+
func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityBasicWithCustomCdpAiaUrlsExample(t *testing.T) {
217+
t.Parallel()
218+
219+
context := map[string]interface{}{
220+
"deletion_protection": false,
221+
"pool_location": "us-central1",
222+
"pool_name": acctest.BootstrapSharedCaPoolInLocation(t, "us-central1"),
223+
"random_suffix": acctest.RandString(t, 10),
224+
}
225+
226+
acctest.VcrTest(t, resource.TestCase{
227+
PreCheck: func() { acctest.AccTestPreCheck(t) },
228+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
229+
CheckDestroy: testAccCheckPrivatecaCertificateAuthorityDestroyProducer(t),
230+
Steps: []resource.TestStep{
231+
{
232+
Config: testAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityBasicWithCustomCdpAiaUrlsExample(context),
233+
},
234+
{
235+
ResourceName: "google_privateca_certificate_authority.default",
236+
ImportState: true,
237+
ImportStateVerify: true,
238+
ImportStateVerifyIgnore: []string{"certificate_authority_id", "deletion_protection", "ignore_active_certificates_on_deletion", "labels", "location", "pem_ca_certificate", "pool", "skip_grace_period", "terraform_labels"},
239+
},
240+
},
241+
})
242+
}
243+
244+
func testAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityBasicWithCustomCdpAiaUrlsExample(context map[string]interface{}) string {
245+
return acctest.Nprintf(`
246+
resource "google_privateca_certificate_authority" "default" {
247+
// This example assumes this pool already exists.
248+
// Pools cannot be deleted in normal test circumstances, so we depend on static pools
249+
pool = "%{pool_name}"
250+
certificate_authority_id = "tf-test-my-certificate-authority%{random_suffix}"
251+
location = "%{pool_location}"
252+
deletion_protection = %{deletion_protection}
253+
config {
254+
subject_config {
255+
subject {
256+
organization = "ACME"
257+
common_name = "my-certificate-authority"
258+
}
259+
}
260+
x509_config {
261+
ca_options {
262+
# is_ca *MUST* be true for certificate authorities
263+
is_ca = true
264+
}
265+
key_usage {
266+
base_key_usage {
267+
# cert_sign and crl_sign *MUST* be true for certificate authorities
268+
cert_sign = true
269+
crl_sign = true
270+
}
271+
extended_key_usage {
272+
}
273+
}
274+
}
275+
}
276+
# valid for 10 years
277+
lifetime = "${10 * 365 * 24 * 3600}s"
278+
key_spec {
279+
algorithm = "RSA_PKCS1_4096_SHA256"
280+
}
281+
user_defined_access_urls {
282+
aia_issuing_certificate_urls = ["http://example.com/ca.crt", "http://example.com/anotherca.crt"]
283+
crl_access_urls = ["http://example.com/crl1.crt", "http://example.com/crl2.crt"]
284+
}
285+
}
286+
`, context)
287+
}
288+
216289
func testAccCheckPrivatecaCertificateAuthorityDestroyProducer(t *testing.T) func(s *terraform.State) error {
217290
return func(s *terraform.State) error {
218291
for name, rs := range s.RootModule().Resources {

website/docs/r/privateca_certificate_authority.html.markdown

+66
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,56 @@ resource "google_privateca_certificate_authority" "default" {
284284
}
285285
}
286286
```
287+
<div class = "oics-button" style="float: right; margin: 0 0 -15px">
288+
<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=privateca_certificate_authority_basic_with_custom_cdp_aia_urls&open_in_editor=main.tf" target="_blank">
289+
<img alt="Open in Cloud Shell" src="//gstatic.com/cloudssh/images/open-btn.svg" style="max-height: 44px; margin: 32px auto; max-width: 100%;">
290+
</a>
291+
</div>
292+
## Example Usage - Privateca Certificate Authority Basic With Custom Cdp Aia Urls
293+
294+
295+
```hcl
296+
resource "google_privateca_certificate_authority" "default" {
297+
// This example assumes this pool already exists.
298+
// Pools cannot be deleted in normal test circumstances, so we depend on static pools
299+
pool = "ca-pool"
300+
certificate_authority_id = "my-certificate-authority"
301+
location = "us-central1"
302+
deletion_protection = true
303+
config {
304+
subject_config {
305+
subject {
306+
organization = "ACME"
307+
common_name = "my-certificate-authority"
308+
}
309+
}
310+
x509_config {
311+
ca_options {
312+
# is_ca *MUST* be true for certificate authorities
313+
is_ca = true
314+
}
315+
key_usage {
316+
base_key_usage {
317+
# cert_sign and crl_sign *MUST* be true for certificate authorities
318+
cert_sign = true
319+
crl_sign = true
320+
}
321+
extended_key_usage {
322+
}
323+
}
324+
}
325+
}
326+
# valid for 10 years
327+
lifetime = "${10 * 365 * 24 * 3600}s"
328+
key_spec {
329+
algorithm = "RSA_PKCS1_4096_SHA256"
330+
}
331+
user_defined_access_urls {
332+
aia_issuing_certificate_urls = ["http://example.com/ca.crt", "http://example.com/anotherca.crt"]
333+
crl_access_urls = ["http://example.com/crl1.crt", "http://example.com/crl2.crt"]
334+
}
335+
}
336+
```
287337

288338
## Argument Reference
289339

@@ -709,6 +759,12 @@ The following arguments are supported:
709759
**Note**: This field is non-authoritative, and will only manage the labels present in your configuration.
710760
Please refer to the field `effective_labels` for all of the labels present on the resource.
711761

762+
* `user_defined_access_urls` -
763+
(Optional)
764+
Custom URLs for accessing content published by this CA, such as the CA certificate and CRLs,
765+
that can be specified by users.
766+
Structure is [documented below](#nested_user_defined_access_urls).
767+
712768
* `project` - (Optional) The ID of the project in which the resource belongs.
713769
If it is not provided, the provider project is used.
714770

@@ -743,6 +799,16 @@ Possible values: ENABLED, DISABLED, STAGED.
743799
(Optional)
744800
Expected to be in leaf-to-root order according to RFC 5246.
745801

802+
<a name="nested_user_defined_access_urls"></a>The `user_defined_access_urls` block supports:
803+
804+
* `aia_issuing_certificate_urls` -
805+
(Optional)
806+
A list of URLs where this CertificateAuthority's CA certificate is published that is specified by users.
807+
808+
* `crl_access_urls` -
809+
(Optional)
810+
A list of URLs where this CertificateAuthority's CRLs are published that is specified by users.
811+
746812
## Attributes Reference
747813

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

0 commit comments

Comments
 (0)