Skip to content

Commit

Permalink
Added support for CMEK in alloydb cluster and automated backup (Googl…
Browse files Browse the repository at this point in the history
…eCloudPlatform#7781)

* Added validation for "type" in cloud_sql_user_resource for preventing user from setting "password" or "host" for CLOUD_IAM_USER and CLOUD_IAM_SERVICE_ACCOUNT user types.

* Removed validation and added documentation to prevent setting of host or password field for CLOUD_IAM_USER and CLOUD_IAM_SERVICE_ACCOUNT

* Added support for CMEK in alloydb cluster and automated backup.
  • Loading branch information
ravisiddhu authored and Madhura Phadnis committed Apr 27, 2023
1 parent 1272fb2 commit 3e36b85
Show file tree
Hide file tree
Showing 2 changed files with 320 additions and 0 deletions.
39 changes: 39 additions & 0 deletions mmv1/products/alloydb/Cluster.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.'
Expand Down
281 changes: 281 additions & 0 deletions mmv1/third_party/terraform/tests/resource_alloydb_cluster_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}

0 comments on commit 3e36b85

Please sign in to comment.