diff --git a/mmv1/products/alloydb/Cluster.yaml b/mmv1/products/alloydb/Cluster.yaml index 86fe6c11a9b5..45f376ec2562 100644 --- a/mmv1/products/alloydb/Cluster.yaml +++ b/mmv1/products/alloydb/Cluster.yaml @@ -89,6 +89,36 @@ properties: - !ruby/object:Api::Type::KeyValuePairs name: 'labels' description: 'User-defined labels for the alloydb cluster.' + - !ruby/object:Api::Type::NestedObject + name: "encryptionConfig" + description: | + EncryptionConfig describes the encryption config of a cluster or a backup that is encrypted with a CMEK (customer-managed encryption key). + properties: + - !ruby/object:Api::Type::String + name: "kmsKeyName" + description: | + The fully-qualified resource name of the KMS key. Each Cloud KMS key is regionalized and has the following format: projects/[PROJECT]/locations/[REGION]/keyRings/[RING]/cryptoKeys/[KEY_NAME]. + immutable: true + - !ruby/object:Api::Type::NestedObject + name: "encryptionInfo" + description: | + EncryptionInfo describes the encryption information of a cluster or a backup. + output: true + properties: + - !ruby/object:Api::Type::Enum + name: 'encryptionType' + description: "Output only. Type of encryption." + values: + - :TYPE_UNSPECIFIED + - :GOOGLE_DEFAULT_ENCRYPTION + - :CUSTOMER_MANAGED_ENCRYPTION + output: true + - !ruby/object:Api::Type::Array + name: kmsKeyVersions + item_type: Api::Type::String + description: | + Output only. Cloud KMS key versions that are being used to protect the database or the backup. + output: true - !ruby/object:Api::Type::String name: 'network' required: true @@ -147,6 +177,15 @@ properties: name: 'labels' description: 'Labels to apply to backups created using this configuration.' + - !ruby/object:Api::Type::NestedObject + name: "encryptionConfig" + description: | + EncryptionConfig describes the encryption config of a cluster or a backup that is encrypted with a CMEK (customer-managed encryption key). + properties: + - !ruby/object:Api::Type::String + name: "kmsKeyName" + description: | + The fully-qualified resource name of the KMS key. Each Cloud KMS key is regionalized and has the following format: projects/[PROJECT]/locations/[REGION]/keyRings/[RING]/cryptoKeys/[KEY_NAME]. - !ruby/object:Api::Type::NestedObject name: 'weeklySchedule' description: 'Weekly schedule for the Backup.' diff --git a/mmv1/third_party/terraform/tests/resource_alloydb_cluster_test.go b/mmv1/third_party/terraform/tests/resource_alloydb_cluster_test.go index c1b2d57869ca..061a368f2a8e 100644 --- a/mmv1/third_party/terraform/tests/resource_alloydb_cluster_test.go +++ b/mmv1/third_party/terraform/tests/resource_alloydb_cluster_test.go @@ -460,3 +460,284 @@ resource "google_compute_network" "default" { } `, context) } +func TestAccAlloydbCluster_usingCMEK(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": RandString(t, 10), + "key_name": "tf-test-key-" + RandString(t, 10), + } + + VcrTest(t, resource.TestCase{ + PreCheck: func() { AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckAlloydbClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccAlloydbCluster_usingCMEK(context), + }, + { + ResourceName: "google_alloydb_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"cluster_id", "location"}, + }, + }, + }) +} + +func testAccAlloydbCluster_usingCMEK(context map[string]interface{}) string { + return Nprintf(` +resource "google_alloydb_cluster" "default" { + cluster_id = "tf-test-alloydb-cluster%{random_suffix}" + location = "us-central1" + network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}" + encryption_config { + kms_key_name = google_kms_crypto_key.key.id + } + depends_on = [google_kms_crypto_key_iam_binding.crypto_key] +} +resource "google_compute_network" "default" { + name = "tf-test-alloydb-cluster%{random_suffix}" +} +data "google_project" "project" {} +resource "google_kms_key_ring" "keyring" { + name = "%{key_name}" + location = "us-central1" +} +resource "google_kms_crypto_key" "key" { + name = "%{key_name}" + key_ring = google_kms_key_ring.keyring.id +} +resource "google_kms_crypto_key_iam_binding" "crypto_key" { + crypto_key_id = google_kms_crypto_key.key.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", + ] +} +`, context) +} + +func TestAccAlloydbCluster_CMEKInAutomatedBackupIsUpdatable(t *testing.T) { + t.Parallel() + + context := map[string]interface{}{ + "random_suffix": RandString(t, 10), + "key_name": "tf-test-key-" + RandString(t, 10), + } + + VcrTest(t, resource.TestCase{ + PreCheck: func() { AccTestPreCheck(t) }, + ProtoV5ProviderFactories: ProtoV5ProviderFactories(t), + CheckDestroy: testAccCheckAlloydbClusterDestroyProducer(t), + Steps: []resource.TestStep{ + { + Config: testAccAlloydbCluster_usingCMEKInClusterAndAutomatedBackup(context), + }, + { + ResourceName: "google_alloydb_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"cluster_id", "location"}, + }, + { + Config: testAccAlloydbCluster_updateCMEKInAutomatedBackup(context), + }, + { + ResourceName: "google_alloydb_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"cluster_id", "location"}, + }, + { + Config: testAccAlloydbCluster_usingCMEKallowDeletion(context), + }, + { + ResourceName: "google_alloydb_cluster.default", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"cluster_id", "location"}, + }, + }, + }) +} + +func testAccAlloydbCluster_usingCMEKInClusterAndAutomatedBackup(context map[string]interface{}) string { + return Nprintf(` +resource "google_alloydb_cluster" "default" { + cluster_id = "tf-test-alloydb-cluster%{random_suffix}" + location = "us-central1" + network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}" + encryption_config { + kms_key_name = google_kms_crypto_key.key.id + } + automated_backup_policy { + location = "us-central1" + backup_window = "1800s" + enabled = true + encryption_config { + kms_key_name = google_kms_crypto_key.key.id + } + time_based_retention { + retention_period = "510s" + } + } + lifecycle { + prevent_destroy = true + } + depends_on = [google_kms_crypto_key_iam_binding.crypto_key] +} + +resource "google_compute_network" "default" { + name = "tf-test-alloydb-cluster%{random_suffix}" +} + +data "google_project" "project" {} + +resource "google_kms_key_ring" "keyring" { + name = "%{key_name}" + location = "us-central1" +} + +resource "google_kms_crypto_key" "key" { + name = "%{key_name}" + key_ring = google_kms_key_ring.keyring.id +} + +resource "google_kms_crypto_key_iam_binding" "crypto_key" { + crypto_key_id = google_kms_crypto_key.key.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", + ] +} +`, context) +} + +func testAccAlloydbCluster_updateCMEKInAutomatedBackup(context map[string]interface{}) string { + return Nprintf(` +resource "google_alloydb_cluster" "default" { + cluster_id = "tf-test-alloydb-cluster%{random_suffix}" + location = "us-central1" + network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}" + encryption_config { + kms_key_name = google_kms_crypto_key.key.id + } + automated_backup_policy { + location = "us-central1" + backup_window = "1800s" + enabled = true + encryption_config { + kms_key_name = google_kms_crypto_key.key2.id + } + time_based_retention { + retention_period = "510s" + } + } + lifecycle { + prevent_destroy = true + } + depends_on = [google_kms_crypto_key_iam_binding.crypto_key] +} + +resource "google_compute_network" "default" { + name = "tf-test-alloydb-cluster%{random_suffix}" +} + +data "google_project" "project" {} + +resource "google_kms_key_ring" "keyring" { + name = "%{key_name}" + location = "us-central1" +} + +resource "google_kms_crypto_key" "key" { + name = "%{key_name}" + key_ring = google_kms_key_ring.keyring.id +} + +resource "google_kms_crypto_key" "key2" { + name = "%{key_name}-2" + key_ring = google_kms_key_ring.keyring.id +} + +resource "google_kms_crypto_key_iam_binding" "crypto_key" { + crypto_key_id = google_kms_crypto_key.key.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", + ] +} + +resource "google_kms_crypto_key_iam_binding" "crypto_key2" { + crypto_key_id = google_kms_crypto_key.key2.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", + ] +} +`, context) +} + +func testAccAlloydbCluster_usingCMEKallowDeletion(context map[string]interface{}) string { + return Nprintf(` +resource "google_alloydb_cluster" "default" { + cluster_id = "tf-test-alloydb-cluster%{random_suffix}" + location = "us-central1" + network = "projects/${data.google_project.project.number}/global/networks/${google_compute_network.default.name}" + encryption_config { + kms_key_name = google_kms_crypto_key.key.id + } + automated_backup_policy { + location = "us-central1" + backup_window = "1800s" + enabled = true + encryption_config { + kms_key_name = google_kms_crypto_key.key2.id + } + time_based_retention { + retention_period = "510s" + } + } + depends_on = [google_kms_crypto_key_iam_binding.crypto_key] +} + +resource "google_compute_network" "default" { + name = "tf-test-alloydb-cluster%{random_suffix}" +} + +data "google_project" "project" {} + +resource "google_kms_key_ring" "keyring" { + name = "%{key_name}" + location = "us-central1" +} + +resource "google_kms_crypto_key" "key" { + name = "%{key_name}" + key_ring = google_kms_key_ring.keyring.id +} + +resource "google_kms_crypto_key" "key2" { + name = "%{key_name}-2" + key_ring = google_kms_key_ring.keyring.id +} + +resource "google_kms_crypto_key_iam_binding" "crypto_key" { + crypto_key_id = google_kms_crypto_key.key.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", + ] +} + +resource "google_kms_crypto_key_iam_binding" "crypto_key2" { + crypto_key_id = google_kms_crypto_key.key2.id + role = "roles/cloudkms.cryptoKeyEncrypterDecrypter" + members = [ + "serviceAccount:service-${data.google_project.project.number}@gcp-sa-alloydb.iam.gserviceaccount.com", + ] +} +`, context) +}