Skip to content

Commit 3cac604

Browse files
Added support for in-place update for replication.userManaged.replicas.customerManagedEncryption to google_secret_manager_secret resource (#8755) (#15685)
Signed-off-by: Modular Magician <[email protected]>
1 parent 7fa99b6 commit 3cac604

File tree

3 files changed

+226
-2
lines changed

3 files changed

+226
-2
lines changed

.changelog/8755.txt

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
secretmanager: supported in-place update for `replication.user_managed.replicas.customer_managed_encryption` field in `google_secret_manager_secret` resource
3+
```

google/services/secretmanager/resource_secret_manager_secret.go

+18-2
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,13 @@ after the Secret has been created.`,
8989
"customer_managed_encryption": {
9090
Type: schema.TypeList,
9191
Optional: true,
92-
ForceNew: true,
9392
Description: `Customer Managed Encryption for the secret.`,
9493
MaxItems: 1,
9594
Elem: &schema.Resource{
9695
Schema: map[string]*schema.Schema{
9796
"kms_key_name": {
9897
Type: schema.TypeString,
9998
Required: true,
100-
ForceNew: true,
10199
Description: `Describes the Cloud KMS encryption key that will be used to protect destination secret.`,
102100
},
103101
},
@@ -510,6 +508,24 @@ func resourceSecretManagerSecretUpdate(d *schema.ResourceData, meta interface{})
510508
if err != nil {
511509
return err
512510
}
511+
replicationProp, err := expandSecretManagerSecretReplication(d.Get("replication"), d, config)
512+
if err != nil {
513+
return err
514+
} else if v, ok := d.GetOkExists("replication"); !tpgresource.IsEmptyValue(reflect.ValueOf(v)) && (ok || !reflect.DeepEqual(v, replicationProp)) {
515+
obj["replication"] = replicationProp
516+
}
517+
518+
if d.HasChange("replication") {
519+
updateMask = append(updateMask, "replication")
520+
}
521+
522+
// Refreshing updateMask after adding extra schema entries
523+
url, err = transport_tpg.AddQueryParams(url, map[string]string{"updateMask": strings.Join(updateMask, ",")})
524+
if err != nil {
525+
return err
526+
}
527+
528+
log.Printf("[DEBUG] Update URL %q: %v", d.Id(), url)
513529

514530
// err == nil indicates that the billing_project value was found
515531
if bp, err := tpgresource.GetBillingProject(d, config); err == nil {

google/services/secretmanager/resource_secret_manager_secret_test.go

+205
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,64 @@ func TestAccSecretManagerSecret_versionAliasesUpdate(t *testing.T) {
160160
})
161161
}
162162

163+
func TestAccSecretManagerSecret_userManagedCmekUpdate(t *testing.T) {
164+
t.Parallel()
165+
166+
kmscentral := acctest.BootstrapKMSKeyWithPurposeInLocationAndName(t, "ENCRYPT_DECRYPT", "us-central1", "tf-secret-manager-managed-central-key1")
167+
kmseast := acctest.BootstrapKMSKeyWithPurposeInLocationAndName(t, "ENCRYPT_DECRYPT", "us-east1", "tf-secret-manager-managed-east-key1")
168+
kmscentralother := acctest.BootstrapKMSKeyWithPurposeInLocationAndName(t, "ENCRYPT_DECRYPT", "us-central1", "tf-secret-manager-managed-central-key2")
169+
context := map[string]interface{}{
170+
"pid": envvar.GetTestProjectFromEnv(),
171+
"random_suffix": acctest.RandString(t, 10),
172+
"kms_key_name_central": kmscentral.CryptoKey.Name,
173+
"kms_key_name_east": kmseast.CryptoKey.Name,
174+
"kms_key_name_central_other": kmscentralother.CryptoKey.Name,
175+
}
176+
acctest.VcrTest(t, resource.TestCase{
177+
PreCheck: func() { acctest.AccTestPreCheck(t) },
178+
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
179+
CheckDestroy: testAccCheckSecretManagerSecretDestroyProducer(t),
180+
Steps: []resource.TestStep{
181+
{
182+
Config: testAccSecretMangerSecret_userManagedCmekBasic(context),
183+
},
184+
{
185+
ResourceName: "google_secret_manager_secret.secret-basic",
186+
ImportState: true,
187+
ImportStateVerify: true,
188+
ImportStateVerifyIgnore: []string{"ttl"},
189+
},
190+
{
191+
Config: testAccSecretMangerSecret_userManagedCmekUpdate(context),
192+
},
193+
{
194+
ResourceName: "google_secret_manager_secret.secret-basic",
195+
ImportState: true,
196+
ImportStateVerify: true,
197+
ImportStateVerifyIgnore: []string{"ttl"},
198+
},
199+
{
200+
Config: testAccSecretMangerSecret_userManagedCmekUpdate2(context),
201+
},
202+
{
203+
ResourceName: "google_secret_manager_secret.secret-basic",
204+
ImportState: true,
205+
ImportStateVerify: true,
206+
ImportStateVerifyIgnore: []string{"ttl"},
207+
},
208+
{
209+
Config: testAccSecretMangerSecret_userManagedCmekBasic(context),
210+
},
211+
{
212+
ResourceName: "google_secret_manager_secret.secret-basic",
213+
ImportState: true,
214+
ImportStateVerify: true,
215+
ImportStateVerifyIgnore: []string{"ttl"},
216+
},
217+
},
218+
})
219+
}
220+
163221
func testAccSecretManagerSecret_basic(context map[string]interface{}) string {
164222
return acctest.Nprintf(`
165223
resource "google_secret_manager_secret" "secret-basic" {
@@ -427,3 +485,150 @@ resource "google_secret_manager_secret_version" "secret-version-4" {
427485
}
428486
`, context)
429487
}
488+
489+
func testAccSecretMangerSecret_userManagedCmekBasic(context map[string]interface{}) string {
490+
return acctest.Nprintf(`
491+
data "google_project" "project" {
492+
project_id = "%{pid}"
493+
}
494+
resource "google_kms_crypto_key_iam_member" "kms-central-binding-1" {
495+
crypto_key_id = "%{kms_key_name_central}"
496+
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
497+
member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com"
498+
}
499+
resource "google_kms_crypto_key_iam_member" "kms-central-binding-2" {
500+
crypto_key_id = "%{kms_key_name_central_other}"
501+
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
502+
member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com"
503+
}
504+
resource "google_kms_crypto_key_iam_member" "kms-east-binding" {
505+
crypto_key_id = "%{kms_key_name_east}"
506+
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
507+
member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com"
508+
}
509+
resource "google_secret_manager_secret" "secret-basic" {
510+
secret_id = "tf-test-secret-%{random_suffix}"
511+
512+
labels = {
513+
label = "my-label"
514+
}
515+
replication {
516+
user_managed {
517+
replicas {
518+
location = "us-central1"
519+
}
520+
replicas {
521+
location = "us-east1"
522+
}
523+
}
524+
}
525+
depends_on = [
526+
google_kms_crypto_key_iam_member.kms-central-binding-1,
527+
google_kms_crypto_key_iam_member.kms-central-binding-2,
528+
google_kms_crypto_key_iam_member.kms-east-binding,
529+
]
530+
}
531+
`, context)
532+
}
533+
534+
func testAccSecretMangerSecret_userManagedCmekUpdate(context map[string]interface{}) string {
535+
return acctest.Nprintf(`
536+
data "google_project" "project" {
537+
project_id = "%{pid}"
538+
}
539+
resource "google_kms_crypto_key_iam_member" "kms-central-binding-1" {
540+
crypto_key_id = "%{kms_key_name_central}"
541+
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
542+
member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com"
543+
}
544+
resource "google_kms_crypto_key_iam_member" "kms-central-binding-2" {
545+
crypto_key_id = "%{kms_key_name_central_other}"
546+
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
547+
member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com"
548+
}
549+
resource "google_kms_crypto_key_iam_member" "kms-east-binding" {
550+
crypto_key_id = "%{kms_key_name_east}"
551+
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
552+
member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com"
553+
}
554+
resource "google_secret_manager_secret" "secret-basic" {
555+
secret_id = "tf-test-secret-%{random_suffix}"
556+
557+
labels = {
558+
label = "my-label"
559+
}
560+
replication {
561+
user_managed {
562+
replicas {
563+
location = "us-central1"
564+
customer_managed_encryption {
565+
kms_key_name = "%{kms_key_name_central}"
566+
}
567+
}
568+
replicas {
569+
location = "us-east1"
570+
customer_managed_encryption {
571+
kms_key_name = "%{kms_key_name_east}"
572+
}
573+
}
574+
}
575+
}
576+
depends_on = [
577+
google_kms_crypto_key_iam_member.kms-central-binding-1,
578+
google_kms_crypto_key_iam_member.kms-central-binding-2,
579+
google_kms_crypto_key_iam_member.kms-east-binding,
580+
]
581+
}
582+
`, context)
583+
}
584+
585+
func testAccSecretMangerSecret_userManagedCmekUpdate2(context map[string]interface{}) string {
586+
return acctest.Nprintf(`
587+
data "google_project" "project" {
588+
project_id = "%{pid}"
589+
}
590+
resource "google_kms_crypto_key_iam_member" "kms-central-binding-1" {
591+
crypto_key_id = "%{kms_key_name_central}"
592+
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
593+
member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com"
594+
}
595+
resource "google_kms_crypto_key_iam_member" "kms-central-binding-2" {
596+
crypto_key_id = "%{kms_key_name_central_other}"
597+
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
598+
member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com"
599+
}
600+
resource "google_kms_crypto_key_iam_member" "kms-east-binding" {
601+
crypto_key_id = "%{kms_key_name_east}"
602+
role = "roles/cloudkms.cryptoKeyEncrypterDecrypter"
603+
member = "serviceAccount:service-${data.google_project.project.number}@gcp-sa-secretmanager.iam.gserviceaccount.com"
604+
}
605+
resource "google_secret_manager_secret" "secret-basic" {
606+
secret_id = "tf-test-secret-%{random_suffix}"
607+
608+
labels = {
609+
label = "my-label"
610+
}
611+
replication {
612+
user_managed {
613+
replicas {
614+
location = "us-central1"
615+
customer_managed_encryption {
616+
kms_key_name = "%{kms_key_name_central_other}"
617+
}
618+
}
619+
replicas {
620+
location = "us-east1"
621+
customer_managed_encryption {
622+
kms_key_name = "%{kms_key_name_east}"
623+
}
624+
}
625+
}
626+
}
627+
depends_on = [
628+
google_kms_crypto_key_iam_member.kms-central-binding-1,
629+
google_kms_crypto_key_iam_member.kms-central-binding-2,
630+
google_kms_crypto_key_iam_member.kms-east-binding,
631+
]
632+
}
633+
`, context)
634+
}

0 commit comments

Comments
 (0)