Make sure KMS key "deletion" disables rotation (#3624)

Signed-off-by: Modular Magician <magic-modules@google.com>
This commit is contained in:
The Magician 2019-05-15 10:25:09 -07:00 committed by emily
parent 0149d37fc3
commit f306b84d31
2 changed files with 57 additions and 21 deletions

View File

@ -224,12 +224,24 @@ func clearCryptoKeyVersions(cryptoKeyId *kmsCryptoKeyId, config *Config) error {
return nil return nil
} }
/* func disableCryptoKeyRotation(cryptoKeyId *kmsCryptoKeyId, config *Config) error {
Because KMS CryptoKey resources cannot be deleted on GCP, we are only going to remove it from state keyClient := config.clientKms.Projects.Locations.KeyRings.CryptoKeys
and destroy all its versions, rendering the key useless for encryption and decryption of data. _, err := keyClient.Patch(cryptoKeyId.cryptoKeyId(), &cloudkms.CryptoKey{
Re-creation of this resource through Terraform will produce an error. NullFields: []string{"rotationPeriod", "nextRotationTime"},
*/ }).
UpdateMask("rotationPeriod,nextRotationTime").Do()
return err
}
// Because KMS CryptoKey keys cannot be deleted (in GCP proper), we "delete"
// the key ring by
// a) marking all key versions for destruction (24hr soft-delete)
// b) disabling rotation of the key
// c) removing it from state
// This disables all usage of previous versions of the key and makes it
// generally useless for encryption and decryption of data.
// Re-creation of this resource through Terraform will produce an error.
func resourceKmsCryptoKeyDelete(d *schema.ResourceData, meta interface{}) error { func resourceKmsCryptoKeyDelete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config) config := meta.(*Config)
@ -242,12 +254,18 @@ func resourceKmsCryptoKeyDelete(d *schema.ResourceData, meta interface{}) error
[WARNING] KMS CryptoKey resources cannot be deleted from GCP. The CryptoKey %s will be removed from Terraform state, [WARNING] KMS CryptoKey resources cannot be deleted from GCP. The CryptoKey %s will be removed from Terraform state,
and all its CryptoKeyVersions will be destroyed, but it will still be present on the server.`, cryptoKeyId.cryptoKeyId()) and all its CryptoKeyVersions will be destroyed, but it will still be present on the server.`, cryptoKeyId.cryptoKeyId())
err = clearCryptoKeyVersions(cryptoKeyId, config) // Delete all versions of the key
if err := clearCryptoKeyVersions(cryptoKeyId, config); err != nil {
if err != nil {
return err return err
} }
// Make sure automatic key rotation is disabled.
if err := disableCryptoKeyRotation(cryptoKeyId, config); err != nil {
return fmt.Errorf(
"While cryptoKeyVersions were cleared, Terraform was unable to disable automatic rotation of key due to an error: %s."+
"Please retry or manually disable automatic rotation to prevent creation of a new version of this key.", err)
}
d.SetId("") d.SetId("")
return nil return nil
} }

View File

@ -137,6 +137,7 @@ func TestAccKmsCryptoKey_basic(t *testing.T) {
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleKmsCryptoKeyWasRemovedFromState("google_kms_crypto_key.crypto_key"), testAccCheckGoogleKmsCryptoKeyWasRemovedFromState("google_kms_crypto_key.crypto_key"),
testAccCheckGoogleKmsCryptoKeyVersionsDestroyed(projectId, location, keyRingName, cryptoKeyName), testAccCheckGoogleKmsCryptoKeyVersionsDestroyed(projectId, location, keyRingName, cryptoKeyName),
testAccCheckGoogleKmsCryptoKeyRotationDisabled(projectId, location, keyRingName, cryptoKeyName),
), ),
}, },
}, },
@ -189,16 +190,15 @@ func TestAccKmsCryptoKey_rotation(t *testing.T) {
Check: resource.ComposeTestCheckFunc( Check: resource.ComposeTestCheckFunc(
testAccCheckGoogleKmsCryptoKeyWasRemovedFromState("google_kms_crypto_key.crypto_key"), testAccCheckGoogleKmsCryptoKeyWasRemovedFromState("google_kms_crypto_key.crypto_key"),
testAccCheckGoogleKmsCryptoKeyVersionsDestroyed(projectId, location, keyRingName, cryptoKeyName), testAccCheckGoogleKmsCryptoKeyVersionsDestroyed(projectId, location, keyRingName, cryptoKeyName),
testAccCheckGoogleKmsCryptoKeyRotationDisabled(projectId, location, keyRingName, cryptoKeyName),
), ),
}, },
}, },
}) })
} }
/* // KMS KeyRings cannot be deleted. This ensures that the CryptoKey resource was removed from state,
KMS KeyRings cannot be deleted. This ensures that the CryptoKey resource was removed from state, // even though the server-side resource was not removed.
even though the server-side resource was not removed.
*/
func testAccCheckGoogleKmsCryptoKeyWasRemovedFromState(resourceName string) resource.TestCheckFunc { func testAccCheckGoogleKmsCryptoKeyWasRemovedFromState(resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error { return func(s *terraform.State) error {
_, ok := s.RootModule().Resources[resourceName] _, ok := s.RootModule().Resources[resourceName]
@ -211,11 +211,8 @@ func testAccCheckGoogleKmsCryptoKeyWasRemovedFromState(resourceName string) reso
} }
} }
/* // KMS KeyRings cannot be deleted. This ensures that the CryptoKey resource's CryptoKeyVersion
KMS KeyRings cannot be deleted. This ensures that the CryptoKey resource's CryptoKeyVersion // sub-resources were scheduled to be destroyed, rendering the key itself inoperable.
sub-resources were scheduled to be destroyed, rendering the key itself inoperable.
*/
func testAccCheckGoogleKmsCryptoKeyVersionsDestroyed(projectId, location, keyRingName, cryptoKeyName string) resource.TestCheckFunc { func testAccCheckGoogleKmsCryptoKeyVersionsDestroyed(projectId, location, keyRingName, cryptoKeyName string) resource.TestCheckFunc {
return func(_ *terraform.State) error { return func(_ *terraform.State) error {
config := testAccProvider.Meta().(*Config) config := testAccProvider.Meta().(*Config)
@ -239,10 +236,31 @@ func testAccCheckGoogleKmsCryptoKeyVersionsDestroyed(projectId, location, keyRin
} }
} }
/* // KMS KeyRings cannot be deleted. This ensures that the CryptoKey autorotation
This test runs in its own project, otherwise the test project would start to get filled // was disabled to prevent more versions of the key from being created.
with undeletable resources func testAccCheckGoogleKmsCryptoKeyRotationDisabled(projectId, location, keyRingName, cryptoKeyName string) resource.TestCheckFunc {
*/ return func(_ *terraform.State) error {
config := testAccProvider.Meta().(*Config)
gcpResourceUri := fmt.Sprintf("projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s", projectId, location, keyRingName, cryptoKeyName)
response, err := config.clientKms.Projects.Locations.KeyRings.CryptoKeys.Get(gcpResourceUri).Do()
if err != nil {
return fmt.Errorf("Unexpected failure while verifying 'deleted' crypto key: %s", err)
}
if response.NextRotationTime != "" {
return fmt.Errorf("Expected empty nextRotationTime for 'deleted' crypto key, got %s", response.NextRotationTime)
}
if response.RotationPeriod != "" {
return fmt.Errorf("Expected empty RotationPeriod for 'deleted' crypto key, got %s", response.RotationPeriod)
}
return nil
}
}
// This test runs in its own project, otherwise the test project would start to get filled
// with undeletable resources
func testGoogleKmsCryptoKey_basic(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName string) string { func testGoogleKmsCryptoKey_basic(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName string) string {
return fmt.Sprintf(` return fmt.Sprintf(`
resource "google_project" "acceptance" { resource "google_project" "acceptance" {