Skip to content

Commit 8fe9a7e

Browse files
authored
fix!: fix count invalid argument on simple bucket (#355)
1 parent 81e870a commit 8fe9a7e

File tree

6 files changed

+131
-21
lines changed

6 files changed

+131
-21
lines changed

docs/upgrading_to_v8.0.md

+78
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Upgrading to v8.0
2+
3+
The v8.0 release of the terraform-google-cloud-storage module is a backwards incompatible release, due to the following breaking change:
4+
5+
- The fix for the issue [Error when using simple bucket with kms created in the same configuration](https://github.com/terraform-google-modules/terraform-google-cloud-storage/issues/339) in the [Simple Bucket](../modules/simple_bucket/README.md) module replaced the creation of an internal KMS key based in the variable `encryption.default_kms_key_name` having a `null` value with an explicit control flag `internal_encryption_config.create_encryption_key`.
6+
7+
## Migration Instructions
8+
9+
To migrate from 5.x or 6.0.0 no change is necessary for the Simple Bucket module.
10+
11+
To migrate from 6.1.0 or 7.x:
12+
13+
- If the feature to auto create KMS keys was not used no change is necessary for the Simple Bucket module
14+
- If the feature to auto create KMS keys was used, a migration from 7.x to 8.x for the Simple Bucket module as showcased below
15+
16+
```diff
17+
module "simple_bucket" {
18+
source = "terraform-google-modules/cloud-storage/google//modules/simple_bucket"
19+
- version = "~> 7.0"
20+
+ version = "~> 8.0"
21+
```
22+
23+
will produce the following output during a `terraform plan`:
24+
25+
```
26+
27+
Error: Missing required argument
28+
29+
with module.simple_bucket.google_storage_bucket.bucket,
30+
on .terraform/modules/simple_bucket/main.tf line 22, in resource "google_storage_bucket" "bucket":
31+
22: resource "google_storage_bucket" "bucket" {
32+
33+
The argument "encryption.0.default_kms_key_name" is required, but no definition was found.
34+
```
35+
36+
Removing the `null` valued `encryption.default_kms_key_name`
37+
38+
```diff
39+
- -encryption = {
40+
- default_kms_key_name = null
41+
- }
42+
```
43+
44+
will produce the following output during a `terraform plan`:
45+
46+
```
47+
# module.simple_bucket.google_storage_bucket.bucket will be updated in-place
48+
49+
# module.simple_bucket.module.encryption_key[0].google_kms_crypto_key.key_ephemeral[0] will be destroyed
50+
# (because module.simple_bucket.module.encryption_key[0] is not in configuration)
51+
52+
# module.simple_bucket.module.encryption_key[0].google_kms_crypto_key_iam_binding.decrypters[0] will be destroyed
53+
# (because module.simple_bucket.module.encryption_key[0] is not in configuration)
54+
55+
# module.simple_bucket.module.encryption_key[0].google_kms_crypto_key_iam_binding.encrypters[0] will be destroyed
56+
# (because module.simple_bucket.module.encryption_key[0] is not in configuration)
57+
58+
# module.simple_bucket.module.encryption_key[0].google_kms_key_ring.key_ring will be destroyed
59+
# (because module.simple_bucket.module.encryption_key[0] is not in configuration)
60+
61+
Plan: 0 to add, 1 to change, 4 to destroy.
62+
```
63+
64+
To preserve the existing KMS Key, add the following section to your configuration
65+
66+
```diff
67+
+ internal_encryption_config = {
68+
+ create_encryption_key = true
69+
+ }
70+
```
71+
72+
Re-running the plan should show that the Simple Bucket resource is no longer showing a diff.
73+
74+
```
75+
No changes. Your infrastructure matches the configuration.
76+
77+
Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
78+
```

examples/simple_bucket/main.tf

+2-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
module "bucket" {
1818
source = "terraform-google-modules/cloud-storage/google//modules/simple_bucket"
19-
version = "~> 6.0"
19+
version = "~> 7.0"
2020

2121
name = "${var.project_id}-bucket"
2222
project_id = var.project_id
@@ -42,6 +42,5 @@ module "bucket" {
4242
member = "group:[email protected]"
4343
}]
4444

45-
autoclass = true
46-
encryption = { default_kms_key_name = null }
45+
autoclass = true
4746
}

modules/simple_bucket/README.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -42,12 +42,13 @@ Functional examples are included in the
4242
| bucket\_policy\_only | Enables Bucket Policy Only access to a bucket. | `bool` | `true` | no |
4343
| cors | Configuration of CORS for bucket with structure as defined in https://registry.terraform.io/providers/hashicorp/google/latest/docs/resources/storage_bucket#cors. | `any` | `[]` | no |
4444
| custom\_placement\_config | Configuration of the bucket's custom location in a dual-region bucket setup. If the bucket is designated a single or multi-region, the variable are null. | <pre>object({<br> data_locations = list(string)<br> })</pre> | `null` | no |
45-
| encryption | A Cloud KMS key that will be used to encrypt objects inserted into this bucket. If default\_kms\_key\_name is set to 'null' a new keyring and key pair will be created and used to encrypt bucket using CMEK. | <pre>object({<br> default_kms_key_name = string<br> })</pre> | `null` | no |
45+
| encryption | A Cloud KMS key that will be used to encrypt objects inserted into this bucket. To use a Cloud KMS key automatically created by the module use `internal_encryption_config`. | <pre>object({<br> default_kms_key_name = string<br> })</pre> | `null` | no |
4646
| force\_destroy | When deleting a bucket, this boolean option will delete all contained objects. If false, Terraform will fail to delete buckets which contain objects. | `bool` | `false` | no |
4747
| iam\_members | The list of IAM members to grant permissions on the bucket. | <pre>list(object({<br> role = string<br> member = string<br> }))</pre> | `[]` | no |
48+
| internal\_encryption\_config | Configuration for the creation of an internal Google Cloud Key Management Service (KMS) Key for use as Customer-managed encryption key (CMEK) for the GCS Bucket<br> instead of creating one in advance and providing the key in the variable `encryption.default_kms_key_name`.<br> create\_encryption\_key: If `true` a Google Cloud Key Management Service (KMS) KeyRing and a Key will be created<br> prevent\_destroy: Set the prevent\_destroy lifecycle attribute on keys.<br> key\_destroy\_scheduled\_duration: Set the period of time that versions of keys spend in the `DESTROY_SCHEDULED` state before transitioning to `DESTROYED`.<br> key\_rotation\_period: Generate a new key every time this period passes. | <pre>object({<br> create_encryption_key = optional(bool, false)<br> prevent_destroy = optional(bool, false)<br> key_destroy_scheduled_duration = optional(string, null)<br> key_rotation_period = optional(string, "7776000s")<br> })</pre> | `{}` | no |
4849
| labels | A set of key/value label pairs to assign to the bucket. | `map(string)` | `null` | no |
4950
| lifecycle\_rules | The bucket's Lifecycle Rules configuration. | <pre>list(object({<br> # Object with keys:<br> # - type - The type of the action of this Lifecycle Rule. Supported values: Delete and SetStorageClass.<br> # - storage_class - (Required if action type is SetStorageClass) The target Storage Class of objects affected by this Lifecycle Rule.<br> action = any<br><br> # Object with keys:<br> # - age - (Optional) Minimum age of an object in days to satisfy this condition.<br> # - created_before - (Optional) Creation date of an object in RFC 3339 (e.g. 2017-06-13) to satisfy this condition.<br> # - with_state - (Optional) Match to live and/or archived objects. Supported values include: "LIVE", "ARCHIVED", "ANY".<br> # - matches_storage_class - (Optional) Storage Class of objects to satisfy this condition. Supported values include: MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, STANDARD, DURABLE_REDUCED_AVAILABILITY.<br> # - matches_prefix - (Optional) One or more matching name prefixes to satisfy this condition.<br> # - matches_suffix - (Optional) One or more matching name suffixes to satisfy this condition<br> # - num_newer_versions - (Optional) Relevant only for versioned objects. The number of newer versions of an object to satisfy this condition.<br> condition = any<br> }))</pre> | `[]` | no |
50-
| location | The location of the bucket. | `string` | n/a | yes |
51+
| location | The location of the bucket. See https://cloud.google.com/storage/docs/locations. | `string` | n/a | yes |
5152
| log\_bucket | The bucket that will receive log objects. | `string` | `null` | no |
5253
| log\_object\_prefix | The object prefix for log objects. If it's not provided, by default GCS sets this to this bucket's name | `string` | `null` | no |
5354
| name | The name of the bucket. | `string` | n/a | yes |
@@ -64,6 +65,7 @@ Functional examples are included in the
6465
| Name | Description |
6566
|------|-------------|
6667
| bucket | The created storage bucket |
68+
| internal\_kms\_configuration | The intenal KMS Resource. |
6769
| name | Bucket name. |
6870
| url | Bucket URL. |
6971

modules/simple_bucket/main.tf

+22-14
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,11 @@
1414
* limitations under the License.
1515
*/
1616

17+
locals {
18+
internal_encryption = var.internal_encryption_config.create_encryption_key ? { default_kms_key_name = module.encryption_key[0].keys[var.name] } : null
19+
encryption = var.internal_encryption_config.create_encryption_key ? local.internal_encryption : var.encryption
20+
}
21+
1722
resource "google_storage_bucket" "bucket" {
1823
name = var.name
1924
project = var.project_id
@@ -41,9 +46,9 @@ resource "google_storage_bucket" "bucket" {
4146
}
4247

4348
dynamic "encryption" {
44-
for_each = var.encryption == null ? [] : [var.encryption]
49+
for_each = local.encryption == null ? [] : [local.encryption]
4550
content {
46-
default_kms_key_name = var.encryption.default_kms_key_name != null ? var.encryption.default_kms_key_name : module.encryption_key[0].keys[var.name]
51+
default_kms_key_name = local.encryption.default_kms_key_name
4752
}
4853
}
4954

@@ -126,16 +131,19 @@ data "google_storage_project_service_account" "gcs_account" {
126131
}
127132

128133
module "encryption_key" {
129-
count = var.encryption == null ? 0 : (var.encryption.default_kms_key_name == null ? 1 : 0)
130-
source = "terraform-google-modules/kms/google"
131-
version = "~> 3.0"
132-
project_id = var.project_id
133-
location = var.location
134-
keyring = var.name
135-
prevent_destroy = false
136-
keys = [var.name]
137-
set_decrypters_for = [var.name]
138-
set_encrypters_for = [var.name]
139-
decrypters = ["serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}"]
140-
encrypters = ["serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}"]
134+
source = "terraform-google-modules/kms/google"
135+
version = "~> 3.0"
136+
count = var.internal_encryption_config.create_encryption_key ? 1 : 0
137+
138+
project_id = var.project_id
139+
location = lower(var.location)
140+
keyring = var.name
141+
prevent_destroy = var.internal_encryption_config.prevent_destroy
142+
key_destroy_scheduled_duration = var.internal_encryption_config.key_destroy_scheduled_duration
143+
key_rotation_period = var.internal_encryption_config.key_rotation_period
144+
keys = [var.name]
145+
set_decrypters_for = [var.name]
146+
set_encrypters_for = [var.name]
147+
decrypters = ["serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}"]
148+
encrypters = ["serviceAccount:${data.google_storage_project_service_account.gcs_account.email_address}"]
141149
}

modules/simple_bucket/outputs.tf

+5
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,8 @@ output "url" {
2828
description = "Bucket URL."
2929
value = google_storage_bucket.bucket.url
3030
}
31+
32+
output "internal_kms_configuration" {
33+
description = "The intenal KMS Resource."
34+
value = var.internal_encryption_config.create_encryption_key ? module.encryption_key[0] : null
35+
}

modules/simple_bucket/variables.tf

+20-2
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ variable "project_id" {
2525
}
2626

2727
variable "location" {
28-
description = "The location of the bucket."
28+
description = "The location of the bucket. See https://cloud.google.com/storage/docs/locations."
2929
type = string
3030
}
3131

@@ -99,7 +99,7 @@ variable "cors" {
9999
}
100100

101101
variable "encryption" {
102-
description = "A Cloud KMS key that will be used to encrypt objects inserted into this bucket. If default_kms_key_name is set to 'null' a new keyring and key pair will be created and used to encrypt bucket using CMEK."
102+
description = "A Cloud KMS key that will be used to encrypt objects inserted into this bucket. To use a Cloud KMS key automatically created by the module use `internal_encryption_config`."
103103
type = object({
104104
default_kms_key_name = string
105105
})
@@ -158,3 +158,21 @@ variable "soft_delete_policy" {
158158
})
159159
default = {}
160160
}
161+
162+
variable "internal_encryption_config" {
163+
description = <<EOT
164+
Configuration for the creation of an internal Google Cloud Key Management Service (KMS) Key for use as Customer-managed encryption key (CMEK) for the GCS Bucket
165+
instead of creating one in advance and providing the key in the variable `encryption.default_kms_key_name`.
166+
create_encryption_key: If `true` a Google Cloud Key Management Service (KMS) KeyRing and a Key will be created
167+
prevent_destroy: Set the prevent_destroy lifecycle attribute on keys.
168+
key_destroy_scheduled_duration: Set the period of time that versions of keys spend in the `DESTROY_SCHEDULED` state before transitioning to `DESTROYED`.
169+
key_rotation_period: Generate a new key every time this period passes.
170+
EOT
171+
type = object({
172+
create_encryption_key = optional(bool, false)
173+
prevent_destroy = optional(bool, false)
174+
key_destroy_scheduled_duration = optional(string, null)
175+
key_rotation_period = optional(string, "7776000s")
176+
})
177+
default = {}
178+
}

0 commit comments

Comments
 (0)