Skip to content

Commit e394fdd

Browse files
Add new Resource Cryptokeyversions (#6553) (#12926)
* Add new resource cryptokeyVersion, and the tests. * Resource cryptoKeyVersion -- Fix errors that prevent creation * CryptoKeyVersion resource -- [WIP] commit * CryptoKeyVersions -- Fix tests for create and create with skip_initial_version * CryptoKeyVersions -- Fix after running gofmt * CryptoKeyVersions -- modification based on PR feedback, except add update test * CryptoKeyVersion -- Add update test * gofmt fix the test file * Remove unused fields and update tests * Add custom import, yet tests aren't fully passing because of custom_delete * Attempt to fix custom import and delete * Delete kms_crypto_key_version.erb * Fix Custom delete issues * Enable importStateVerify to all tests * Fix make lint problem * Delete go.mod * (1) Remove enum values for output fields (2) fix indentation problems (3) Fix state verify for crypto_Key (4) Add remove test for cryptoKeyVersions (5) WIP Fix custom_delete issues * (1) Call destroy at cryptoKeyVersion deletion (2) Do not destroy cryptoKeyVersion when deleting crypto_key * CryptoKeyVersions Delete, put error handler first * Uncomment clearCryptoKeyVersions when deleting cryptoKey * Align with master branch, check for state before deleting cryptokeyversion * Remove state check in cryptoKeyVersions deletion Signed-off-by: Modular Magician <[email protected]> Signed-off-by: Modular Magician <[email protected]>
1 parent a923a41 commit e394fdd

6 files changed

+915
-2
lines changed

.changelog/6553.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
```release-note:new-resource
2+
kms: Add new resource CryptoKeyVersions
3+
4+
```

google/kms_utils.go

+47
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,19 @@ func (s *kmsCryptoKeyId) terraformId() string {
8585
return fmt.Sprintf("%s/%s", s.KeyRingId.terraformId(), s.Name)
8686
}
8787

88+
type kmsCryptoKeyVersionId struct {
89+
CryptoKeyId kmsCryptoKeyId
90+
Name string
91+
}
92+
93+
func (s *kmsCryptoKeyVersionId) cryptoKeyVersionId() string {
94+
return fmt.Sprintf(s.Name)
95+
}
96+
97+
func (s *kmsCryptoKeyVersionId) terraformId() string {
98+
return fmt.Sprintf("%s/%s", s.CryptoKeyId.terraformId(), s.Name)
99+
}
100+
88101
func validateKmsCryptoKeyRotationPeriod(value interface{}, _ string) (ws []string, errors []error) {
89102
period := value.(string)
90103
pattern := regexp.MustCompile(`^([0-9.]*\d)s$`)
@@ -171,8 +184,27 @@ func parseKmsCryptoKeyId(id string, config *Config) (*kmsCryptoKeyId, error) {
171184
Name: parts[4],
172185
}, nil
173186
}
187+
174188
return nil, fmt.Errorf("Invalid CryptoKey id format, expecting `{projectId}/{locationId}/{KeyringName}/{cryptoKeyName}` or `{locationId}/{keyRingName}/{cryptoKeyName}, got id: %s`", id)
175189
}
190+
func parseKmsCryptoKeyVersionId(id string, config *Config) (*kmsCryptoKeyVersionId, error) {
191+
cryptoKeyVersionRelativeLinkRegex := regexp.MustCompile("^projects/(" + ProjectRegex + ")/locations/([a-z0-9-]+)/keyRings/([a-zA-Z0-9_-]{1,63})/cryptoKeys/([a-zA-Z0-9_-]{1,63})/cryptoKeyVersions/([a-zA-Z0-9_-]{1,63})$")
192+
193+
if parts := cryptoKeyVersionRelativeLinkRegex.FindStringSubmatch(id); parts != nil {
194+
return &kmsCryptoKeyVersionId{
195+
CryptoKeyId: kmsCryptoKeyId{
196+
KeyRingId: kmsKeyRingId{
197+
Project: parts[1],
198+
Location: parts[2],
199+
Name: parts[3],
200+
},
201+
Name: parts[4],
202+
},
203+
Name: "projects/" + parts[1] + "/locations/" + parts[2] + "/keyRings/" + parts[3] + "/cryptoKeys/" + parts[4] + "/cryptoKeyVersions/" + parts[5],
204+
}, nil
205+
}
206+
return nil, fmt.Errorf("Invalid CryptoKeyVersion id format, expecting `{projectId}/{locationId}/{KeyringName}/{cryptoKeyName}/{cryptoKeyVersion}` or `{locationId}/{keyRingName}/{cryptoKeyName}/{cryptoKeyVersion}, got id: %s`", id)
207+
}
176208

177209
func clearCryptoKeyVersions(cryptoKeyId *kmsCryptoKeyId, userAgent string, config *Config) error {
178210
versionsClient := config.NewKmsClient(userAgent).Projects.Locations.KeyRings.CryptoKeys.CryptoKeyVersions
@@ -206,6 +238,21 @@ func clearCryptoKeyVersions(cryptoKeyId *kmsCryptoKeyId, userAgent string, confi
206238
return nil
207239
}
208240

241+
func deleteCryptoKeyVersions(cryptoKeyVersionId *kmsCryptoKeyVersionId, d *schema.ResourceData, userAgent string, config *Config) error {
242+
versionsClient := config.NewKmsClient(userAgent).Projects.Locations.KeyRings.CryptoKeys.CryptoKeyVersions
243+
request := &cloudkms.DestroyCryptoKeyVersionRequest{}
244+
destroyCall := versionsClient.Destroy(cryptoKeyVersionId.Name, request)
245+
if config.UserProjectOverride {
246+
destroyCall.Header().Set("X-Goog-User-Project", cryptoKeyVersionId.CryptoKeyId.KeyRingId.Project)
247+
}
248+
_, err := destroyCall.Do()
249+
if err != nil {
250+
return handleNotFoundError(err, d, fmt.Sprintf("ID %s", cryptoKeyVersionId.Name))
251+
}
252+
253+
return nil
254+
}
255+
209256
func disableCryptoKeyRotation(cryptoKeyId *kmsCryptoKeyId, userAgent string, config *Config) error {
210257
keyClient := config.NewKmsClient(userAgent).Projects.Locations.KeyRings.CryptoKeys
211258
patchCall := keyClient.Patch(cryptoKeyId.cryptoKeyId(), &cloudkms.CryptoKey{

google/provider.go

+3-2
Original file line numberDiff line numberDiff line change
@@ -910,9 +910,9 @@ func Provider() *schema.Provider {
910910
return provider
911911
}
912912

913-
// Generated resources: 243
913+
// Generated resources: 244
914914
// Generated IAM resources: 150
915-
// Total generated resources: 393
915+
// Total generated resources: 394
916916
func ResourceMap() map[string]*schema.Resource {
917917
resourceMap, _ := ResourceMapWithErrors()
918918
return resourceMap
@@ -1205,6 +1205,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) {
12051205
"google_identity_platform_tenant": resourceIdentityPlatformTenant(),
12061206
"google_kms_key_ring": resourceKMSKeyRing(),
12071207
"google_kms_crypto_key": resourceKMSCryptoKey(),
1208+
"google_kms_crypto_key_version": resourceKMSCryptoKeyVersion(),
12081209
"google_kms_key_ring_import_job": resourceKMSKeyRingImportJob(),
12091210
"google_kms_secret_ciphertext": resourceKMSSecretCiphertext(),
12101211
"google_logging_metric": resourceLoggingMetric(),

google/resource_kms_crypto_key_test.go

+264
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,96 @@ func testAccCheckGoogleKmsCryptoKeyRotationDisabled(t *testing.T, projectId, loc
440440
}
441441
}
442442

443+
func TestAccKmsCryptoKeyVersion_basic(t *testing.T) {
444+
t.Parallel()
445+
446+
projectId := fmt.Sprintf("tf-test-%d", randInt(t))
447+
projectOrg := getTestOrgFromEnv(t)
448+
projectBillingAccount := getTestBillingAccountFromEnv(t)
449+
keyRingName := fmt.Sprintf("tf-test-%s", randString(t, 10))
450+
cryptoKeyName := fmt.Sprintf("tf-test-%s", randString(t, 10))
451+
452+
vcrTest(t, resource.TestCase{
453+
PreCheck: func() { testAccPreCheck(t) },
454+
Providers: testAccProviders,
455+
Steps: []resource.TestStep{
456+
{
457+
Config: testGoogleKmsCryptoKeyVersion_basic(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName),
458+
},
459+
{
460+
ResourceName: "google_kms_crypto_key_version.crypto_key_version",
461+
ImportState: true,
462+
ImportStateVerify: true,
463+
},
464+
{
465+
Config: testGoogleKmsCryptoKeyVersion_removed(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName),
466+
},
467+
},
468+
})
469+
}
470+
471+
func TestAccKmsCryptoKeyVersion_skipInitialVersion(t *testing.T) {
472+
t.Parallel()
473+
474+
projectId := fmt.Sprintf("tf-test-%d", randInt(t))
475+
projectOrg := getTestOrgFromEnv(t)
476+
projectBillingAccount := getTestBillingAccountFromEnv(t)
477+
keyRingName := fmt.Sprintf("tf-test-%s", randString(t, 10))
478+
cryptoKeyName := fmt.Sprintf("tf-test-%s", randString(t, 10))
479+
480+
vcrTest(t, resource.TestCase{
481+
PreCheck: func() { testAccPreCheck(t) },
482+
Providers: testAccProviders,
483+
Steps: []resource.TestStep{
484+
{
485+
Config: testGoogleKmsCryptoKeyVersion_skipInitialVersion(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName),
486+
},
487+
{
488+
ResourceName: "google_kms_crypto_key_version.crypto_key_version",
489+
ImportState: true,
490+
ImportStateVerify: true,
491+
},
492+
},
493+
})
494+
}
495+
496+
func TestAccKmsCryptoKeyVersion_patch(t *testing.T) {
497+
t.Parallel()
498+
499+
projectId := fmt.Sprintf("tf-test-%d", randInt(t))
500+
projectOrg := getTestOrgFromEnv(t)
501+
projectBillingAccount := getTestBillingAccountFromEnv(t)
502+
keyRingName := fmt.Sprintf("tf-test-%s", randString(t, 10))
503+
cryptoKeyName := fmt.Sprintf("tf-test-%s", randString(t, 10))
504+
state := "DISABLED"
505+
506+
vcrTest(t, resource.TestCase{
507+
PreCheck: func() { testAccPreCheck(t) },
508+
Providers: testAccProviders,
509+
Steps: []resource.TestStep{
510+
{
511+
Config: testGoogleKmsCryptoKeyVersion_patchInitialize(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName),
512+
},
513+
{
514+
ResourceName: "google_kms_crypto_key_version.crypto_key_version",
515+
ImportState: true,
516+
ImportStateVerify: true,
517+
},
518+
{
519+
Config: testGoogleKmsCryptoKeyVersion_patch("true", projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName, state),
520+
},
521+
{
522+
ResourceName: "google_kms_crypto_key_version.crypto_key_version",
523+
ImportState: true,
524+
ImportStateVerify: true,
525+
},
526+
{
527+
Config: testGoogleKmsCryptoKeyVersion_patch("false", projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName, state),
528+
},
529+
},
530+
})
531+
}
532+
443533
// This test runs in its own project, otherwise the test project would start to get filled
444534
// with undeletable resources
445535
func testGoogleKmsCryptoKey_basic(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName string) string {
@@ -643,3 +733,177 @@ resource "google_kms_crypto_key" "crypto_key" {
643733
}
644734
`, projectId, projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName)
645735
}
736+
737+
func testGoogleKmsCryptoKeyVersion_basic(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName string) string {
738+
return fmt.Sprintf(`
739+
resource "google_project" "acceptance" {
740+
name = "%s"
741+
project_id = "%s"
742+
org_id = "%s"
743+
billing_account = "%s"
744+
}
745+
746+
resource "google_project_service" "acceptance" {
747+
project = google_project.acceptance.project_id
748+
service = "cloudkms.googleapis.com"
749+
}
750+
751+
resource "google_kms_key_ring" "key_ring" {
752+
project = google_project_service.acceptance.project
753+
name = "%s"
754+
location = "us-central1"
755+
}
756+
757+
resource "google_kms_crypto_key" "crypto_key" {
758+
name = "%s"
759+
key_ring = google_kms_key_ring.key_ring.id
760+
labels = {
761+
key = "value"
762+
}
763+
}
764+
765+
resource "google_kms_crypto_key_version" "crypto_key_version" {
766+
crypto_key = google_kms_crypto_key.crypto_key.id
767+
}
768+
`, projectId, projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName)
769+
}
770+
771+
func testGoogleKmsCryptoKeyVersion_removed(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName string) string {
772+
return fmt.Sprintf(`
773+
resource "google_project" "acceptance" {
774+
name = "%s"
775+
project_id = "%s"
776+
org_id = "%s"
777+
billing_account = "%s"
778+
}
779+
780+
resource "google_project_service" "acceptance" {
781+
project = google_project.acceptance.project_id
782+
service = "cloudkms.googleapis.com"
783+
}
784+
785+
resource "google_kms_key_ring" "key_ring" {
786+
project = google_project_service.acceptance.project
787+
name = "%s"
788+
location = "us-central1"
789+
}
790+
791+
resource "google_kms_crypto_key" "crypto_key" {
792+
name = "%s"
793+
key_ring = google_kms_key_ring.key_ring.id
794+
labels = {
795+
key = "value"
796+
}
797+
}
798+
`, projectId, projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName)
799+
}
800+
801+
func testGoogleKmsCryptoKeyVersion_skipInitialVersion(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName string) string {
802+
return fmt.Sprintf(`
803+
resource "google_project" "acceptance" {
804+
name = "%s"
805+
project_id = "%s"
806+
org_id = "%s"
807+
billing_account = "%s"
808+
}
809+
810+
resource "google_project_service" "acceptance" {
811+
project = google_project.acceptance.project_id
812+
service = "cloudkms.googleapis.com"
813+
}
814+
815+
resource "google_kms_key_ring" "key_ring" {
816+
project = google_project_service.acceptance.project
817+
name = "%s"
818+
location = "us-central1"
819+
}
820+
821+
resource "google_kms_crypto_key" "crypto_key" {
822+
name = "%s"
823+
key_ring = google_kms_key_ring.key_ring.id
824+
labels = {
825+
key = "value"
826+
}
827+
skip_initial_version_creation = true
828+
}
829+
830+
resource "google_kms_crypto_key_version" "crypto_key_version" {
831+
crypto_key = google_kms_crypto_key.crypto_key.id
832+
}
833+
`, projectId, projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName)
834+
}
835+
func testGoogleKmsCryptoKeyVersion_patchInitialize(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName string) string {
836+
return fmt.Sprintf(`
837+
resource "google_project" "acceptance" {
838+
name = "%s"
839+
project_id = "%s"
840+
org_id = "%s"
841+
billing_account = "%s"
842+
}
843+
844+
resource "google_project_service" "acceptance" {
845+
project = google_project.acceptance.project_id
846+
service = "cloudkms.googleapis.com"
847+
}
848+
849+
resource "google_kms_key_ring" "key_ring" {
850+
project = google_project_service.acceptance.project
851+
name = "%s"
852+
location = "us-central1"
853+
}
854+
855+
resource "google_kms_crypto_key" "crypto_key" {
856+
name = "%s"
857+
key_ring = google_kms_key_ring.key_ring.id
858+
labels = {
859+
key = "value"
860+
}
861+
}
862+
863+
resource "google_kms_crypto_key_version" "crypto_key_version" {
864+
crypto_key = google_kms_crypto_key.crypto_key.id
865+
lifecycle {
866+
prevent_destroy = true
867+
}
868+
state = "ENABLED"
869+
}
870+
`, projectId, projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName)
871+
}
872+
873+
func testGoogleKmsCryptoKeyVersion_patch(preventDestroy, projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName, state string) string {
874+
return fmt.Sprintf(`
875+
resource "google_project" "acceptance" {
876+
name = "%s"
877+
project_id = "%s"
878+
org_id = "%s"
879+
billing_account = "%s"
880+
}
881+
882+
resource "google_project_service" "acceptance" {
883+
project = google_project.acceptance.project_id
884+
service = "cloudkms.googleapis.com"
885+
}
886+
887+
resource "google_kms_key_ring" "key_ring" {
888+
project = google_project_service.acceptance.project
889+
name = "%s"
890+
location = "us-central1"
891+
}
892+
893+
resource "google_kms_crypto_key" "crypto_key" {
894+
name = "%s"
895+
key_ring = google_kms_key_ring.key_ring.id
896+
labels = {
897+
key = "value"
898+
}
899+
}
900+
901+
resource "google_kms_crypto_key_version" "crypto_key_version" {
902+
crypto_key = google_kms_crypto_key.crypto_key.id
903+
lifecycle {
904+
prevent_destroy = %s
905+
}
906+
state = "%s"
907+
}
908+
`, projectId, projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName, preventDestroy, state)
909+
}

0 commit comments

Comments
 (0)