Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new Resource Cryptokeyversions #12926

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions .changelog/6553.txt
@@ -0,0 +1,4 @@
```release-note:new-resource
kms: Add new resource CryptoKeyVersions

```
47 changes: 47 additions & 0 deletions google/kms_utils.go
Expand Up @@ -85,6 +85,19 @@ func (s *kmsCryptoKeyId) terraformId() string {
return fmt.Sprintf("%s/%s", s.KeyRingId.terraformId(), s.Name)
}

type kmsCryptoKeyVersionId struct {
CryptoKeyId kmsCryptoKeyId
Name string
}

func (s *kmsCryptoKeyVersionId) cryptoKeyVersionId() string {
return fmt.Sprintf(s.Name)
}

func (s *kmsCryptoKeyVersionId) terraformId() string {
return fmt.Sprintf("%s/%s", s.CryptoKeyId.terraformId(), s.Name)
}

func validateKmsCryptoKeyRotationPeriod(value interface{}, _ string) (ws []string, errors []error) {
period := value.(string)
pattern := regexp.MustCompile(`^([0-9.]*\d)s$`)
Expand Down Expand Up @@ -171,8 +184,27 @@ func parseKmsCryptoKeyId(id string, config *Config) (*kmsCryptoKeyId, error) {
Name: parts[4],
}, nil
}

return nil, fmt.Errorf("Invalid CryptoKey id format, expecting `{projectId}/{locationId}/{KeyringName}/{cryptoKeyName}` or `{locationId}/{keyRingName}/{cryptoKeyName}, got id: %s`", id)
}
func parseKmsCryptoKeyVersionId(id string, config *Config) (*kmsCryptoKeyVersionId, error) {
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})$")

if parts := cryptoKeyVersionRelativeLinkRegex.FindStringSubmatch(id); parts != nil {
return &kmsCryptoKeyVersionId{
CryptoKeyId: kmsCryptoKeyId{
KeyRingId: kmsKeyRingId{
Project: parts[1],
Location: parts[2],
Name: parts[3],
},
Name: parts[4],
},
Name: "projects/" + parts[1] + "/locations/" + parts[2] + "/keyRings/" + parts[3] + "/cryptoKeys/" + parts[4] + "/cryptoKeyVersions/" + parts[5],
}, nil
}
return nil, fmt.Errorf("Invalid CryptoKeyVersion id format, expecting `{projectId}/{locationId}/{KeyringName}/{cryptoKeyName}/{cryptoKeyVersion}` or `{locationId}/{keyRingName}/{cryptoKeyName}/{cryptoKeyVersion}, got id: %s`", id)
}

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

func deleteCryptoKeyVersions(cryptoKeyVersionId *kmsCryptoKeyVersionId, d *schema.ResourceData, userAgent string, config *Config) error {
versionsClient := config.NewKmsClient(userAgent).Projects.Locations.KeyRings.CryptoKeys.CryptoKeyVersions
request := &cloudkms.DestroyCryptoKeyVersionRequest{}
destroyCall := versionsClient.Destroy(cryptoKeyVersionId.Name, request)
if config.UserProjectOverride {
destroyCall.Header().Set("X-Goog-User-Project", cryptoKeyVersionId.CryptoKeyId.KeyRingId.Project)
}
_, err := destroyCall.Do()
if err != nil {
return handleNotFoundError(err, d, fmt.Sprintf("ID %s", cryptoKeyVersionId.Name))
}

return nil
}

func disableCryptoKeyRotation(cryptoKeyId *kmsCryptoKeyId, userAgent string, config *Config) error {
keyClient := config.NewKmsClient(userAgent).Projects.Locations.KeyRings.CryptoKeys
patchCall := keyClient.Patch(cryptoKeyId.cryptoKeyId(), &cloudkms.CryptoKey{
Expand Down
5 changes: 3 additions & 2 deletions google/provider.go
Expand Up @@ -910,9 +910,9 @@ func Provider() *schema.Provider {
return provider
}

// Generated resources: 243
// Generated resources: 244
// Generated IAM resources: 150
// Total generated resources: 393
// Total generated resources: 394
func ResourceMap() map[string]*schema.Resource {
resourceMap, _ := ResourceMapWithErrors()
return resourceMap
Expand Down Expand Up @@ -1205,6 +1205,7 @@ func ResourceMapWithErrors() (map[string]*schema.Resource, error) {
"google_identity_platform_tenant": resourceIdentityPlatformTenant(),
"google_kms_key_ring": resourceKMSKeyRing(),
"google_kms_crypto_key": resourceKMSCryptoKey(),
"google_kms_crypto_key_version": resourceKMSCryptoKeyVersion(),
"google_kms_key_ring_import_job": resourceKMSKeyRingImportJob(),
"google_kms_secret_ciphertext": resourceKMSSecretCiphertext(),
"google_logging_metric": resourceLoggingMetric(),
Expand Down
264 changes: 264 additions & 0 deletions google/resource_kms_crypto_key_test.go
Expand Up @@ -440,6 +440,96 @@ func testAccCheckGoogleKmsCryptoKeyRotationDisabled(t *testing.T, projectId, loc
}
}

func TestAccKmsCryptoKeyVersion_basic(t *testing.T) {
t.Parallel()

projectId := fmt.Sprintf("tf-test-%d", randInt(t))
projectOrg := getTestOrgFromEnv(t)
projectBillingAccount := getTestBillingAccountFromEnv(t)
keyRingName := fmt.Sprintf("tf-test-%s", randString(t, 10))
cryptoKeyName := fmt.Sprintf("tf-test-%s", randString(t, 10))

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testGoogleKmsCryptoKeyVersion_basic(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName),
},
{
ResourceName: "google_kms_crypto_key_version.crypto_key_version",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testGoogleKmsCryptoKeyVersion_removed(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName),
},
},
})
}

func TestAccKmsCryptoKeyVersion_skipInitialVersion(t *testing.T) {
t.Parallel()

projectId := fmt.Sprintf("tf-test-%d", randInt(t))
projectOrg := getTestOrgFromEnv(t)
projectBillingAccount := getTestBillingAccountFromEnv(t)
keyRingName := fmt.Sprintf("tf-test-%s", randString(t, 10))
cryptoKeyName := fmt.Sprintf("tf-test-%s", randString(t, 10))

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testGoogleKmsCryptoKeyVersion_skipInitialVersion(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName),
},
{
ResourceName: "google_kms_crypto_key_version.crypto_key_version",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func TestAccKmsCryptoKeyVersion_patch(t *testing.T) {
t.Parallel()

projectId := fmt.Sprintf("tf-test-%d", randInt(t))
projectOrg := getTestOrgFromEnv(t)
projectBillingAccount := getTestBillingAccountFromEnv(t)
keyRingName := fmt.Sprintf("tf-test-%s", randString(t, 10))
cryptoKeyName := fmt.Sprintf("tf-test-%s", randString(t, 10))
state := "DISABLED"

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Config: testGoogleKmsCryptoKeyVersion_patchInitialize(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName),
},
{
ResourceName: "google_kms_crypto_key_version.crypto_key_version",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testGoogleKmsCryptoKeyVersion_patch("true", projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName, state),
},
{
ResourceName: "google_kms_crypto_key_version.crypto_key_version",
ImportState: true,
ImportStateVerify: true,
},
{
Config: testGoogleKmsCryptoKeyVersion_patch("false", projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName, state),
},
},
})
}

// 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 {
Expand Down Expand Up @@ -643,3 +733,177 @@ resource "google_kms_crypto_key" "crypto_key" {
}
`, projectId, projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName)
}

func testGoogleKmsCryptoKeyVersion_basic(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName string) string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
name = "%s"
project_id = "%s"
org_id = "%s"
billing_account = "%s"
}

resource "google_project_service" "acceptance" {
project = google_project.acceptance.project_id
service = "cloudkms.googleapis.com"
}

resource "google_kms_key_ring" "key_ring" {
project = google_project_service.acceptance.project
name = "%s"
location = "us-central1"
}

resource "google_kms_crypto_key" "crypto_key" {
name = "%s"
key_ring = google_kms_key_ring.key_ring.id
labels = {
key = "value"
}
}

resource "google_kms_crypto_key_version" "crypto_key_version" {
crypto_key = google_kms_crypto_key.crypto_key.id
}
`, projectId, projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName)
}

func testGoogleKmsCryptoKeyVersion_removed(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName string) string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
name = "%s"
project_id = "%s"
org_id = "%s"
billing_account = "%s"
}

resource "google_project_service" "acceptance" {
project = google_project.acceptance.project_id
service = "cloudkms.googleapis.com"
}

resource "google_kms_key_ring" "key_ring" {
project = google_project_service.acceptance.project
name = "%s"
location = "us-central1"
}

resource "google_kms_crypto_key" "crypto_key" {
name = "%s"
key_ring = google_kms_key_ring.key_ring.id
labels = {
key = "value"
}
}
`, projectId, projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName)
}

func testGoogleKmsCryptoKeyVersion_skipInitialVersion(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName string) string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
name = "%s"
project_id = "%s"
org_id = "%s"
billing_account = "%s"
}

resource "google_project_service" "acceptance" {
project = google_project.acceptance.project_id
service = "cloudkms.googleapis.com"
}

resource "google_kms_key_ring" "key_ring" {
project = google_project_service.acceptance.project
name = "%s"
location = "us-central1"
}

resource "google_kms_crypto_key" "crypto_key" {
name = "%s"
key_ring = google_kms_key_ring.key_ring.id
labels = {
key = "value"
}
skip_initial_version_creation = true
}

resource "google_kms_crypto_key_version" "crypto_key_version" {
crypto_key = google_kms_crypto_key.crypto_key.id
}
`, projectId, projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName)
}
func testGoogleKmsCryptoKeyVersion_patchInitialize(projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName string) string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
name = "%s"
project_id = "%s"
org_id = "%s"
billing_account = "%s"
}

resource "google_project_service" "acceptance" {
project = google_project.acceptance.project_id
service = "cloudkms.googleapis.com"
}

resource "google_kms_key_ring" "key_ring" {
project = google_project_service.acceptance.project
name = "%s"
location = "us-central1"
}

resource "google_kms_crypto_key" "crypto_key" {
name = "%s"
key_ring = google_kms_key_ring.key_ring.id
labels = {
key = "value"
}
}

resource "google_kms_crypto_key_version" "crypto_key_version" {
crypto_key = google_kms_crypto_key.crypto_key.id
lifecycle {
prevent_destroy = true
}
state = "ENABLED"
}
`, projectId, projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName)
}

func testGoogleKmsCryptoKeyVersion_patch(preventDestroy, projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName, state string) string {
return fmt.Sprintf(`
resource "google_project" "acceptance" {
name = "%s"
project_id = "%s"
org_id = "%s"
billing_account = "%s"
}

resource "google_project_service" "acceptance" {
project = google_project.acceptance.project_id
service = "cloudkms.googleapis.com"
}

resource "google_kms_key_ring" "key_ring" {
project = google_project_service.acceptance.project
name = "%s"
location = "us-central1"
}

resource "google_kms_crypto_key" "crypto_key" {
name = "%s"
key_ring = google_kms_key_ring.key_ring.id
labels = {
key = "value"
}
}

resource "google_kms_crypto_key_version" "crypto_key_version" {
crypto_key = google_kms_crypto_key.crypto_key.id
lifecycle {
prevent_destroy = %s
}
state = "%s"
}
`, projectId, projectId, projectOrg, projectBillingAccount, keyRingName, cryptoKeyName, preventDestroy, state)
}