Skip to content

Commit

Permalink
add deletion protection for CA (#5932) (#11551)
Browse files Browse the repository at this point in the history
Signed-off-by: Modular Magician <magic-modules@google.com>
  • Loading branch information
modular-magician authored Apr 20, 2022
1 parent 54f8c65 commit e03b1f8
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 11 deletions.
6 changes: 6 additions & 0 deletions .changelog/5932.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
```release-note:enhancement
privateca: add `deletion_protection` for CertificateAuthority.
```
```release-note:note
`google_privateca_certificate_authority` resources now cannot be destroyed unless `deletion_protection = false` is set in state for the resource.
```
1 change: 1 addition & 0 deletions google/data_source_certificate_authority_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ resource "google_privateca_certificate_authority" "default" {
certificate_authority_id = "tf-test-my-certificate-authority%{random_suffix}"
location = "%{pool_location}"
type = "SUBORDINATE"
deletion_protection = false
config {
subject_config {
subject {
Expand Down
19 changes: 19 additions & 0 deletions google/resource_privateca_certificate_authority.go
Original file line number Diff line number Diff line change
Expand Up @@ -596,6 +596,11 @@ CertificateAuthority's certificate.`,
A timestamp in RFC3339 UTC "Zulu" format, with nanosecond resolution and up to nine
fractional digits. Examples: "2014-10-02T15:01:23Z" and "2014-10-02T15:01:23.045123456Z".`,
},
"deletion_protection": {
Type: schema.TypeBool,
Optional: true,
Default: true,
},
"project": {
Type: schema.TypeString,
Optional: true,
Expand Down Expand Up @@ -782,6 +787,12 @@ func resourcePrivatecaCertificateAuthorityRead(d *schema.ResourceData, meta inte
return nil
}

// Explicitly set virtual fields to default values if unset
if _, ok := d.GetOkExists("deletion_protection"); !ok {
if err := d.Set("deletion_protection", true); err != nil {
return fmt.Errorf("Error setting deletion_protection: %s", err)
}
}
if err := d.Set("project", project); err != nil {
return fmt.Errorf("Error reading CertificateAuthority: %s", err)
}
Expand Down Expand Up @@ -912,6 +923,10 @@ func resourcePrivatecaCertificateAuthorityDelete(d *schema.ResourceData, meta in
}

var obj map[string]interface{}
if d.Get("deletion_protection").(bool) {
return fmt.Errorf("cannot destroy CertificateAuthority without setting deletion_protection=false and running `terraform apply`")
}

if d.Get("state").(string) == "ENABLED" {
disableUrl, err := replaceVars(d, config, "{{PrivatecaBasePath}}projects/{{project}}/locations/{{location}}/caPools/{{pool}}/certificateAuthorities/{{certificate_authority_id}}:disable")
if err != nil {
Expand Down Expand Up @@ -974,6 +989,10 @@ func resourcePrivatecaCertificateAuthorityImport(d *schema.ResourceData, meta in
}
d.SetId(id)

// Explicitly set virtual fields to default values on import
if err := d.Set("deletion_protection", true); err != nil {
return nil, fmt.Errorf("Error setting deletion_protection: %s", err)
}
if err := d.Set("ignore_active_certificates_on_deletion", false); err != nil {
return nil, err
}
Expand Down
20 changes: 12 additions & 8 deletions google/resource_privateca_certificate_authority_generated_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityBasicExam
t.Parallel()

context := map[string]interface{}{
"pool_name": BootstrapSharedCaPoolInLocation(t, "us-central1"),
"pool_location": "us-central1",
"random_suffix": randString(t, 10),
"pool_name": BootstrapSharedCaPoolInLocation(t, "us-central1"),
"pool_location": "us-central1",
"deletion_protection": false,
"random_suffix": randString(t, 10),
}

vcrTest(t, resource.TestCase{
Expand All @@ -44,7 +45,7 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityBasicExam
ResourceName: "google_privateca_certificate_authority.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool"},
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection"},
},
},
})
Expand All @@ -58,6 +59,7 @@ resource "google_privateca_certificate_authority" "default" {
pool = "%{pool_name}"
certificate_authority_id = "tf-test-my-certificate-authority%{random_suffix}"
location = "%{pool_location}"
deletion_protection = "%{deletion_protection}"
config {
subject_config {
subject {
Expand Down Expand Up @@ -106,9 +108,10 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthoritySubordina
t.Parallel()

context := map[string]interface{}{
"pool_name": BootstrapSharedCaPoolInLocation(t, "us-central1"),
"pool_location": "us-central1",
"random_suffix": randString(t, 10),
"pool_name": BootstrapSharedCaPoolInLocation(t, "us-central1"),
"pool_location": "us-central1",
"deletion_protection": false,
"random_suffix": randString(t, 10),
}

vcrTest(t, resource.TestCase{
Expand All @@ -123,7 +126,7 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthoritySubordina
ResourceName: "google_privateca_certificate_authority.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool"},
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection"},
},
},
})
Expand All @@ -137,6 +140,7 @@ resource "google_privateca_certificate_authority" "default" {
pool = "%{pool_name}"
certificate_authority_id = "tf-test-my-certificate-authority%{random_suffix}"
location = "%{pool_location}"
deletion_protection = "%{deletion_protection}"
config {
subject_config {
subject {
Expand Down
8 changes: 5 additions & 3 deletions google/resource_privateca_certificate_authority_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityUpdate(t
ResourceName: "google_privateca_certificate_authority.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool"},
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection"},
},
{
Config: testAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityEnd(context),
Expand All @@ -37,7 +37,7 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityUpdate(t
ResourceName: "google_privateca_certificate_authority.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool"},
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection"},
},
{
Config: testAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityStart(context),
Expand All @@ -46,7 +46,7 @@ func TestAccPrivatecaCertificateAuthority_privatecaCertificateAuthorityUpdate(t
ResourceName: "google_privateca_certificate_authority.default",
ImportState: true,
ImportStateVerify: true,
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool"},
ImportStateVerifyIgnore: []string{"ignore_active_certificates_on_deletion", "location", "certificate_authority_id", "pool", "deletion_protection"},
},
},
})
Expand All @@ -60,6 +60,7 @@ resource "google_privateca_certificate_authority" "default" {
pool = "%{pool_name}"
certificate_authority_id = "tf-test-my-certificate-authority-%{random_suffix}"
location = "%{pool_location}"
deletion_protection = false
config {
subject_config {
subject {
Expand Down Expand Up @@ -112,6 +113,7 @@ resource "google_privateca_certificate_authority" "default" {
pool = "%{pool_name}"
certificate_authority_id = "tf-test-my-certificate-authority-%{random_suffix}"
location = "%{pool_location}"
deletion_protection = false
config {
subject_config {
subject {
Expand Down
4 changes: 4 additions & 0 deletions google/resource_privateca_certificate_generated_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ resource "google_privateca_certificate_authority" "test-ca" {
location = "us-central1"
pool = "%{pool}"
ignore_active_certificates_on_deletion = true
deletion_protection = false
config {
subject_config {
subject {
Expand Down Expand Up @@ -241,6 +242,7 @@ resource "google_privateca_certificate_authority" "test-ca" {
pool = "%{pool}"
certificate_authority_id = "tf-test-my-certificate-authority%{random_suffix}"
location = "us-central1"
deletion_protection = false
config {
subject_config {
subject {
Expand Down Expand Up @@ -319,6 +321,7 @@ resource "google_privateca_certificate_authority" "test-ca" {
pool = "%{pool}"
certificate_authority_id = "tf-test-my-certificate-authority%{random_suffix}"
location = "us-central1"
deletion_protection = false
config {
subject_config {
subject {
Expand Down Expand Up @@ -398,6 +401,7 @@ resource "google_privateca_certificate_authority" "authority" {
pool = "%{pool}"
certificate_authority_id = "tf-test-my-authority%{random_suffix}"
location = "us-central1"
deletion_protection = false
config {
subject_config {
subject {
Expand Down
2 changes: 2 additions & 0 deletions google/resource_privateca_certificate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ resource "google_privateca_certificate_authority" "default" {
pool = "%{pool_name}"
certificate_authority_id = "tf-test-my-certificate-authority-%{random_suffix}"
location = "%{pool_location}"
deletion_protection = false
config {
subject_config {
subject {
Expand Down Expand Up @@ -137,6 +138,7 @@ resource "google_privateca_certificate_authority" "default" {
pool = "%{pool_name}"
certificate_authority_id = "tf-test-my-certificate-authority-%{random_suffix}"
location = "%{pool_location}"
deletion_protection = false
config {
subject_config {
subject {
Expand Down
4 changes: 4 additions & 0 deletions website/docs/r/privateca_certificate.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ resource "google_privateca_certificate_authority" "test-ca" {
location = "us-central1"
pool = ""
ignore_active_certificates_on_deletion = true
deletion_protection = false
config {
subject_config {
subject {
Expand Down Expand Up @@ -196,6 +197,7 @@ resource "google_privateca_certificate_authority" "test-ca" {
pool = ""
certificate_authority_id = "my-certificate-authority"
location = "us-central1"
deletion_protection = false
config {
subject_config {
subject {
Expand Down Expand Up @@ -247,6 +249,7 @@ resource "google_privateca_certificate_authority" "test-ca" {
pool = ""
certificate_authority_id = "my-certificate-authority"
location = "us-central1"
deletion_protection = false
config {
subject_config {
subject {
Expand Down Expand Up @@ -299,6 +302,7 @@ resource "google_privateca_certificate_authority" "authority" {
pool = ""
certificate_authority_id = "my-authority"
location = "us-central1"
deletion_protection = false
config {
subject_config {
subject {
Expand Down
10 changes: 10 additions & 0 deletions website/docs/r/privateca_certificate_authority.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ To get more information about CertificateAuthority, see:
* How-to Guides
* [Official Documentation](https://cloud.google.com/certificate-authority-service)

~> **Warning:** On newer versions of the provider, you must explicitly set `deletion_protection=false`
(and run `terraform apply` to write the field to state) in order to destroy a CertificateAuthority.
It is recommended to not set this field (or set it to true) until you're ready to destroy.

<div class = "oics-button" style="float: right; margin: 0 0 -15px">
<a href="https://console.cloud.google.com/cloudshell/open?cloudshell_git_repo=https%3A%2F%2Fgit.luolix.top%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">
<img alt="Open in Cloud Shell" src="//gstatic.com/cloudssh/images/open-btn.svg" style="max-height: 44px; margin: 32px auto; max-width: 100%;">
Expand All @@ -47,6 +51,7 @@ resource "google_privateca_certificate_authority" "default" {
pool = "ca-pool"
certificate_authority_id = "my-certificate-authority"
location = "us-central1"
deletion_protection = "true"
config {
subject_config {
subject {
Expand Down Expand Up @@ -104,6 +109,7 @@ resource "google_privateca_certificate_authority" "default" {
pool = "ca-pool"
certificate_authority_id = "my-certificate-authority"
location = "us-central1"
deletion_protection = "true"
config {
subject_config {
subject {
Expand Down Expand Up @@ -179,6 +185,7 @@ resource "google_privateca_certificate_authority" "default" {
pool = "ca-pool"
certificate_authority_id = "my-certificate-authority"
location = "us-central1"
deletion_protection = "true"
key_spec {
cloud_kms_key_version = "projects/keys-project/locations/us-central1/keyRings/key-ring/cryptoKeys/crypto-key/cryptoKeyVersions/1"
}
Expand Down Expand Up @@ -545,6 +552,9 @@ The following arguments are supported:
* `project` - (Optional) The ID of the project in which the resource belongs.
If it is not provided, the provider project is used.

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


## Attributes Reference

Expand Down

0 comments on commit e03b1f8

Please sign in to comment.