Skip to content

Commit

Permalink
feat!: Add import flags (#133)
Browse files Browse the repository at this point in the history
  • Loading branch information
romanini-ciandt authored Apr 8, 2024
1 parent f553b67 commit 70d2718
Show file tree
Hide file tree
Showing 11 changed files with 226 additions and 17 deletions.
4 changes: 3 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ Functional examples are included in the
| crypto\_key\_backend | (Optional) The resource name of the backend environment associated with all CryptoKeyVersions within this CryptoKey. The resource name is in the format 'projects//locations//ekmConnections/*' and only applies to 'EXTERNAL\_VPC' keys. | `string` | `null` | no |
| decrypters | List of comma-separated owners for each key declared in set\_decrypters\_for. | `list(string)` | `[]` | no |
| encrypters | List of comma-separated owners for each key declared in set\_encrypters\_for. | `list(string)` | `[]` | no |
| import\_only | Whether these keys may contain imported versions only. | `bool` | `false` | no |
| key\_algorithm | The algorithm to use when creating a version based on this template. See the https://cloud.google.com/kms/docs/reference/rest/v1/CryptoKeyVersionAlgorithm for possible inputs. | `string` | `"GOOGLE_SYMMETRIC_ENCRYPTION"` | no |
| key\_destroy\_scheduled\_duration | Set the period of time that versions of keys spend in the DESTROY\_SCHEDULED state before transitioning to DESTROYED. | `string` | `null` | no |
| key\_protection\_level | The protection level to use when creating a version based on this template. Default value: "SOFTWARE" Possible values: ["SOFTWARE", "HSM", "EXTERNAL", "EXTERNAL\_VPC"] | `string` | `"SOFTWARE"` | no |
Expand All @@ -58,10 +59,11 @@ Functional examples are included in the
| owners | List of comma-separated owners for each key declared in set\_owners\_for. | `list(string)` | `[]` | no |
| prevent\_destroy | Set the prevent\_destroy lifecycle attribute on keys. | `bool` | `true` | no |
| project\_id | Project id where the keyring will be created. | `string` | n/a | yes |
| purpose | The immutable purpose of the CryptoKey. Possible values are ENCRYPT\_DECRYPT, ASYMMETRIC\_SIGN, and ASYMMETRIC\_DECRYPT. | `string` | `"ENCRYPT_DECRYPT"` | no |
| purpose | The immutable purpose of the CryptoKey. Default value is ENCRYPT\_DECRYPT. See purpose reference (https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings.cryptoKeys#CryptoKeyPurpose) for possible inputs. | `string` | `"ENCRYPT_DECRYPT"` | no |
| set\_decrypters\_for | Name of keys for which decrypters will be set. | `list(string)` | `[]` | no |
| set\_encrypters\_for | Name of keys for which encrypters will be set. | `list(string)` | `[]` | no |
| set\_owners\_for | Name of keys for which owners will be set. | `list(string)` | `[]` | no |
| skip\_initial\_version\_creation | If set to true, the request will create CryptoKeys without any CryptoKeyVersions. | `bool` | `false` | no |

## Outputs

Expand Down
27 changes: 27 additions & 0 deletions examples/import_only_example/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Import Only Example

This example illustrates how to use the `kms` module when you want to create a CryptoKey with no CryptoKeyVersion in order to import the key material.

<!-- BEGINNING OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
## Inputs

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| project\_id | The ID of the project in which to provision resources. | `string` | n/a | yes |

## Outputs

| Name | Description |
|------|-------------|
| keyring | The name of the keyring. |
| keys | List of created kkey names. |
| location | The location of the keyring. |
| project\_id | The ID of the project in which resources are provisioned. |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->

To provision this example, run the following from within this directory:
- `terraform init` to get the plugins
- `terraform plan` to see the infrastructure plan
- `terraform apply` to apply the infrastructure build
- `terraform destroy` to destroy the built infrastructure
37 changes: 37 additions & 0 deletions examples/import_only_example/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/**
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

resource "random_pet" "main" {
length = 1
prefix = "simple-example"
separator = "-"
}

module "kms" {
source = "../.."

project_id = var.project_id
keyring = random_pet.main.id
location = "global"
keys = ["one", "two"]
# keys can be destroyed by Terraform
prevent_destroy = false
import_only = true
skip_initial_version_creation = true
key_rotation_period = ""
purpose = "RAW_ENCRYPT_DECRYPT"
key_algorithm = "AES_256_GCM"
}
35 changes: 35 additions & 0 deletions examples/import_only_example/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

output "keyring" {
description = "The name of the keyring."
value = module.kms.keyring_resource.name
}

output "location" {
description = "The location of the keyring."
value = module.kms.keyring_resource.location
}

output "keys" {
description = "List of created kkey names."
value = keys(module.kms.keys)
}

output "project_id" {
description = "The ID of the project in which resources are provisioned."
value = var.project_id
}
20 changes: 20 additions & 0 deletions examples/import_only_example/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

variable "project_id" {
description = "The ID of the project in which to provision resources."
type = string
}
24 changes: 24 additions & 0 deletions examples/import_only_example/versions.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/**
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

terraform {
required_providers {
google = {
source = "hashicorp/google"
}
}
required_version = ">= 0.13"
}
28 changes: 16 additions & 12 deletions main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ resource "google_kms_key_ring" "key_ring" {
}

resource "google_kms_crypto_key" "key" {
count = var.prevent_destroy ? length(var.keys) : 0
name = var.keys[count.index]
key_ring = google_kms_key_ring.key_ring.id
rotation_period = var.key_rotation_period
purpose = var.purpose
crypto_key_backend = var.crypto_key_backend
count = var.prevent_destroy ? length(var.keys) : 0
name = var.keys[count.index]
key_ring = google_kms_key_ring.key_ring.id
rotation_period = var.key_rotation_period
purpose = var.purpose
import_only = var.import_only
skip_initial_version_creation = var.skip_initial_version_creation
crypto_key_backend = var.crypto_key_backend

lifecycle {
prevent_destroy = true
Expand All @@ -47,12 +49,14 @@ resource "google_kms_crypto_key" "key" {
}

resource "google_kms_crypto_key" "key_ephemeral" {
count = var.prevent_destroy ? 0 : length(var.keys)
name = var.keys[count.index]
key_ring = google_kms_key_ring.key_ring.id
rotation_period = var.key_rotation_period
purpose = var.purpose
crypto_key_backend = var.crypto_key_backend
count = var.prevent_destroy ? 0 : length(var.keys)
name = var.keys[count.index]
key_ring = google_kms_key_ring.key_ring.id
rotation_period = var.key_rotation_period
purpose = var.purpose
import_only = var.import_only
skip_initial_version_creation = var.skip_initial_version_creation
crypto_key_backend = var.crypto_key_backend

lifecycle {
prevent_destroy = false
Expand Down
47 changes: 47 additions & 0 deletions test/integration/import_only_example/import_only_example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package simple_example

import (
"fmt"
"testing"

"github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/gcloud"
"github.com/GoogleCloudPlatform/cloud-foundation-toolkit/infra/blueprint-test/pkg/tft"
"github.com/stretchr/testify/assert"
)

func TestImportOnlyExample(t *testing.T) {
bpt := tft.NewTFBlueprintTest(t)
bpt.DefineVerify(func(assert *assert.Assertions) {
bpt.DefaultVerify(assert)

projectId := bpt.GetStringOutput("project_id")
keyring := bpt.GetStringOutput("keyring")
location := bpt.GetStringOutput("location")
keys := [2]string{"one", "two"}

op := gcloud.Runf(t, "--project=%s kms keyrings list --location %s --filter name:%s", projectId, location, keyring).Array()[0].Get("name")
assert.Contains(op.String(), fmt.Sprintf("projects/%s/locations/%s/keyRings/%s", projectId, location, keyring), "Contains KeyRing")

op1 := gcloud.Runf(t, "kms keys list --project=%s --keyring %s --location %s", projectId, keyring, location).Array()
for index, element := range op1 {
assert.Equal(element.Get("name").String(), fmt.Sprintf("projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s", projectId, location, keyring, keys[index]), "Contains Keys")
assert.True(element.Get("importOnly").Bool(), "ImportOnly flag")
}
})

bpt.Test()
}
5 changes: 3 additions & 2 deletions test/integration/simple_example/simple_example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,13 @@ func TestSimpleExample(t *testing.T) {
location := bpt.GetStringOutput("location")
keys := [2]string{"one", "two"}

op := gcloud.Runf(t, "--project=%s kms keyrings list --location %s", projectId, location).Array()[0].Get("name")
op := gcloud.Runf(t, "--project=%s kms keyrings list --location %s --filter name:%s", projectId, location, keyring).Array()[0].Get("name")
assert.Contains(op.String(), fmt.Sprintf("projects/%s/locations/%s/keyRings/%s", projectId, location, keyring), "Contains KeyRing")

op1 := gcloud.Runf(t, "kms keys list --project=%s --keyring %s --location %s", projectId, keyring, location).Array()
for index, element := range op1 {
assert.Contains(element.Get("name").String(), fmt.Sprintf("projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s", projectId, location, keyring, keys[index]), "Contains Keys")
assert.Equal(element.Get("primary").Map()["name"].Str, fmt.Sprintf("projects/%s/locations/%s/keyRings/%s/cryptoKeys/%s/cryptoKeyVersions/1", projectId, location, keyring, keys[index]), "Contains Keys")
assert.False(element.Get("importOnly").Bool(), "ImportOnly flag")
}
})

Expand Down
14 changes: 13 additions & 1 deletion variables.tf
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ variable "key_destroy_scheduled_duration" {

variable "purpose" {
type = string
description = "The immutable purpose of the CryptoKey. Possible values are ENCRYPT_DECRYPT, ASYMMETRIC_SIGN, and ASYMMETRIC_DECRYPT."
description = "The immutable purpose of the CryptoKey. Default value is ENCRYPT_DECRYPT. See purpose reference (https://cloud.google.com/kms/docs/reference/rest/v1/projects.locations.keyRings.cryptoKeys#CryptoKeyPurpose) for possible inputs."
default = "ENCRYPT_DECRYPT"
}

Expand Down Expand Up @@ -114,6 +114,18 @@ variable "labels" {
default = {}
}

variable "import_only" {
type = bool
description = "Whether these keys may contain imported versions only."
default = false
}

variable "skip_initial_version_creation" {
type = bool
description = "If set to true, the request will create CryptoKeys without any CryptoKeyVersions."
default = false
}

variable "crypto_key_backend" {
type = string
description = "(Optional) The resource name of the backend environment associated with all CryptoKeyVersions within this CryptoKey. The resource name is in the format 'projects//locations//ekmConnections/*' and only applies to 'EXTERNAL_VPC' keys."
Expand Down
2 changes: 1 addition & 1 deletion versions.tf
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ terraform {

google = {
source = "hashicorp/google"
version = ">= 3.53, < 6"
version = ">= 3.87, < 6"
}
}

Expand Down

0 comments on commit 70d2718

Please sign in to comment.