Skip to content

Commit e03b1f8

Browse files
add deletion protection for CA (#5932) (#11551)
Signed-off-by: Modular Magician <[email protected]>
1 parent 54f8c65 commit e03b1f8

9 files changed

+63
-11
lines changed

.changelog/5932.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
```release-note:enhancement
2+
privateca: add `deletion_protection` for CertificateAuthority.
3+
```
4+
```release-note:note
5+
`google_privateca_certificate_authority` resources now cannot be destroyed unless `deletion_protection = false` is set in state for the resource.
6+
```

google/data_source_certificate_authority_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ resource "google_privateca_certificate_authority" "default" {
3939
certificate_authority_id = "tf-test-my-certificate-authority%{random_suffix}"
4040
location = "%{pool_location}"
4141
type = "SUBORDINATE"
42+
deletion_protection = false
4243
config {
4344
subject_config {
4445
subject {

google/resource_privateca_certificate_authority.go

+19
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,11 @@ CertificateAuthority's certificate.`,
596596
A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine
597597
fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z".`,
598598
},
599+
"deletion_protection": {
600+
Type: schema.TypeBool,
601+
Optional: true,
602+
Default: true,
603+
},
599604
"project": {
600605
Type: schema.TypeString,
601606
Optional: true,
@@ -782,6 +787,12 @@ func resourcePrivatecaCertificateAuthorityRead(d *schema.ResourceData, meta inte
782787
return nil
783788
}
784789

790+
// Explicitly set virtual fields to default values if unset
791+
if _, ok := d.GetOkExists("deletion_protection"); !ok {
792+
if err := d.Set("deletion_protection", true); err != nil {
793+
return fmt.Errorf("Error setting deletion_protection: %s", err)
794+
}
795+
}
785796
if err := d.Set("project", project); err != nil {
786797
return fmt.Errorf("Error reading CertificateAuthority: %s", err)
787798
}
@@ -912,6 +923,10 @@ func resourcePrivatecaCertificateAuthorityDelete(d *schema.ResourceData, meta in
912923
}
913924

914925
var obj map[string]interface{}
926+
if d.Get("deletion_protection").(bool) {
927+
return fmt.Errorf("cannot destroy CertificateAuthority without setting deletion_protection=false and running `terraform apply`")
928+
}
929+
915930
if d.Get("state").(string) == "ENABLED" {
916931
disableUrl, err := replaceVars(d, config, "{{PrivatecaBasePath}}projects/{{project}}/locations/{{location}}/caPools/{{pool}}/certificateAuthorities/{{certificate_authority_id}}:disable")
917932
if err != nil {
@@ -974,6 +989,10 @@ func resourcePrivatecaCertificateAuthorityImport(d *schema.ResourceData, meta in
974989
}
975990
d.SetId(id)
976991

992+
// Explicitly set virtual fields to default values on import
993+
if err := d.Set("deletion_protection", true); err != nil {
994+
return nil, fmt.Errorf("Error setting deletion_protection: %s", err)
995+
}
977996
if err := d.Set("ignore_active_certificates_on_deletion", false); err != nil {
978997
return nil, err
979998
}

google/resource_privateca_certificate_authority_generated_test.go

+12-8
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityBasicExam
2727
t.Parallel()
2828

2929
context := map[string]interface{}{
30-
"pool_name": BootstrapSharedCaPoolInLocation(t, "us-central1"),
31-
"pool_location": "us-central1",
32-
"random_suffix": randString(t, 10),
30+
"pool_name": BootstrapSharedCaPoolInLocation(t, "us-central1"),
31+
"pool_location": "us-central1",
32+
"deletion_protection": false,
33+
"random_suffix": randString(t, 10),
3334
}
3435

3536
vcrTest(t, resource.TestCase{
@@ -44,7 +45,7 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityBasicExam
4445
ResourceName: "google_privateca_certificate_authority.default",
4546
ImportState: true,
4647
ImportStateVerify: true,
47-
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool"},
48+
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection"},
4849
},
4950
},
5051
})
@@ -58,6 +59,7 @@ resource "google_privateca_certificate_authority" "default" {
5859
pool = "%{pool_name}"
5960
certificate_authority_id = "tf-test-my-certificate-authority%{random_suffix}"
6061
location = "%{pool_location}"
62+
deletion_protection = "%{deletion_protection}"
6163
config {
6264
subject_config {
6365
subject {
@@ -106,9 +108,10 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthoritySubordina
106108
t.Parallel()
107109

108110
context := map[string]interface{}{
109-
"pool_name": BootstrapSharedCaPoolInLocation(t, "us-central1"),
110-
"pool_location": "us-central1",
111-
"random_suffix": randString(t, 10),
111+
"pool_name": BootstrapSharedCaPoolInLocation(t, "us-central1"),
112+
"pool_location": "us-central1",
113+
"deletion_protection": false,
114+
"random_suffix": randString(t, 10),
112115
}
113116

114117
vcrTest(t, resource.TestCase{
@@ -123,7 +126,7 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthoritySubordina
123126
ResourceName: "google_privateca_certificate_authority.default",
124127
ImportState: true,
125128
ImportStateVerify: true,
126-
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool"},
129+
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection"},
127130
},
128131
},
129132
})
@@ -137,6 +140,7 @@ resource "google_privateca_certificate_authority" "default" {
137140
pool = "%{pool_name}"
138141
certificate_authority_id = "tf-test-my-certificate-authority%{random_suffix}"
139142
location = "%{pool_location}"
143+
deletion_protection = "%{deletion_protection}"
140144
config {
141145
subject_config {
142146
subject {

google/resource_privateca_certificate_authority_test.go

+5-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityUpdate(t
2828
ResourceName: "google_privateca_certificate_authority.default",
2929
ImportState: true,
3030
ImportStateVerify: true,
31-
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool"},
31+
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection"},
3232
},
3333
{
3434
Config: testAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityEnd(context),
@@ -37,7 +37,7 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityUpdate(t
3737
ResourceName: "google_privateca_certificate_authority.default",
3838
ImportState: true,
3939
ImportStateVerify: true,
40-
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool"},
40+
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection"},
4141
},
4242
{
4343
Config: testAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityStart(context),
@@ -46,7 +46,7 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityUpdate(t
4646
ResourceName: "google_privateca_certificate_authority.default",
4747
ImportState: true,
4848
ImportStateVerify: true,
49-
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool"},
49+
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection"},
5050
},
5151
},
5252
})
@@ -60,6 +60,7 @@ resource "google_privateca_certificate_authority" "default" {
6060
pool = "%{pool_name}"
6161
certificate_authority_id = "tf-test-my-certificate-authority-%{random_suffix}"
6262
location = "%{pool_location}"
63+
deletion_protection = false
6364
config {
6465
subject_config {
6566
subject {
@@ -112,6 +113,7 @@ resource "google_privateca_certificate_authority" "default" {
112113
pool = "%{pool_name}"
113114
certificate_authority_id = "tf-test-my-certificate-authority-%{random_suffix}"
114115
location = "%{pool_location}"
116+
deletion_protection = false
115117
config {
116118
subject_config {
117119
subject {

google/resource_privateca_certificate_generated_test.go

+4
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ resource "google_privateca_certificate_authority" "test-ca" {
5757
location = "us-central1"
5858
pool = "%{pool}"
5959
ignore_active_certificates_on_deletion = true
60+
deletion_protection = false
6061
config {
6162
subject_config {
6263
subject {
@@ -241,6 +242,7 @@ resource "google_privateca_certificate_authority" "test-ca" {
241242
pool = "%{pool}"
242243
certificate_authority_id = "tf-test-my-certificate-authority%{random_suffix}"
243244
location = "us-central1"
245+
deletion_protection = false
244246
config {
245247
subject_config {
246248
subject {
@@ -319,6 +321,7 @@ resource "google_privateca_certificate_authority" "test-ca" {
319321
pool = "%{pool}"
320322
certificate_authority_id = "tf-test-my-certificate-authority%{random_suffix}"
321323
location = "us-central1"
324+
deletion_protection = false
322325
config {
323326
subject_config {
324327
subject {
@@ -398,6 +401,7 @@ resource "google_privateca_certificate_authority" "authority" {
398401
pool = "%{pool}"
399402
certificate_authority_id = "tf-test-my-authority%{random_suffix}"
400403
location = "us-central1"
404+
deletion_protection = false
401405
config {
402406
subject_config {
403407
subject {

google/resource_privateca_certificate_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ resource "google_privateca_certificate_authority" "default" {
6060
pool = "%{pool_name}"
6161
certificate_authority_id = "tf-test-my-certificate-authority-%{random_suffix}"
6262
location = "%{pool_location}"
63+
deletion_protection = false
6364
config {
6465
subject_config {
6566
subject {
@@ -137,6 +138,7 @@ resource "google_privateca_certificate_authority" "default" {
137138
pool = "%{pool_name}"
138139
certificate_authority_id = "tf-test-my-certificate-authority-%{random_suffix}"
139140
location = "%{pool_location}"
141+
deletion_protection = false
140142
config {
141143
subject_config {
142144
subject {

website/docs/r/privateca_certificate.html.markdown

+4
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ resource "google_privateca_certificate_authority" "test-ca" {
3939
location = "us-central1"
4040
pool = ""
4141
ignore_active_certificates_on_deletion = true
42+
deletion_protection = false
4243
config {
4344
subject_config {
4445
subject {
@@ -196,6 +197,7 @@ resource "google_privateca_certificate_authority" "test-ca" {
196197
pool = ""
197198
certificate_authority_id = "my-certificate-authority"
198199
location = "us-central1"
200+
deletion_protection = false
199201
config {
200202
subject_config {
201203
subject {
@@ -247,6 +249,7 @@ resource "google_privateca_certificate_authority" "test-ca" {
247249
pool = ""
248250
certificate_authority_id = "my-certificate-authority"
249251
location = "us-central1"
252+
deletion_protection = false
250253
config {
251254
subject_config {
252255
subject {
@@ -299,6 +302,7 @@ resource "google_privateca_certificate_authority" "authority" {
299302
pool = ""
300303
certificate_authority_id = "my-authority"
301304
location = "us-central1"
305+
deletion_protection = false
302306
config {
303307
subject_config {
304308
subject {

website/docs/r/privateca_certificate_authority.html.markdown

+10
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ To get more information about CertificateAuthority, see:
3232
* How-to Guides
3333
* [Official Documentation](https://cloud.google.com/certificate-authority-service)
3434

35+
~> **Warning:** On newer versions of the provider, you must explicitly set `deletion_protection=false`
36+
(and run `terraform apply` to write the field to state) in order to destroy a CertificateAuthority.
37+
It is recommended to not set this field (or set it to true) until you're ready to destroy.
38+
3539
<div class = "oics-button" style="float: right; margin: 0 0 -15px">
3640
<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_working_dir=privateca_certificate_authority_basic&cloudshell_image=gcr.io%2Fgraphite-cloud-shell-images%2Fterraform%3Alatest&open_in_editor=main.tf&cloudshell_print=.%2Fmotd&cloudshell_tutorial=.%2Ftutorial.md" target="_blank">
3741
<img alt="Open in Cloud Shell" src="//gstatic.com/cloudssh/images/open-btn.svg" style="max-height: 44px; margin: 32px auto; max-width: 100%;">
@@ -47,6 +51,7 @@ resource "google_privateca_certificate_authority" "default" {
4751
pool = "ca-pool"
4852
certificate_authority_id = "my-certificate-authority"
4953
location = "us-central1"
54+
deletion_protection = "true"
5055
config {
5156
subject_config {
5257
subject {
@@ -104,6 +109,7 @@ resource "google_privateca_certificate_authority" "default" {
104109
pool = "ca-pool"
105110
certificate_authority_id = "my-certificate-authority"
106111
location = "us-central1"
112+
deletion_protection = "true"
107113
config {
108114
subject_config {
109115
subject {
@@ -179,6 +185,7 @@ resource "google_privateca_certificate_authority" "default" {
179185
pool = "ca-pool"
180186
certificate_authority_id = "my-certificate-authority"
181187
location = "us-central1"
188+
deletion_protection = "true"
182189
key_spec {
183190
cloud_kms_key_version = "projects/keys-project/locations/us-central1/keyRings/key-ring/cryptoKeys/crypto-key/cryptoKeyVersions/1"
184191
}
@@ -545,6 +552,9 @@ The following arguments are supported:
545552
* `project` - (Optional) The ID of the project in which the resource belongs.
546553
If it is not provided, the provider project is used.
547554

555+
* `deletion_protection` - (Optional) Whether or not to allow Terraform to destroy the CertificateAuthority. Unless this field is set to false
556+
in Terraform state, a `terraform destroy` or `terraform apply` that would delete the instance will fail.
557+
548558

549559
## Attributes Reference
550560

0 commit comments

Comments
 (0)