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

feat: add autokey plus migration #156

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
fd6ff3d
Introduce autokey feature
romanini-ciandt Aug 29, 2024
fba57c4
Adjusts on setup
romanini-ciandt Aug 29, 2024
8c4df14
Merge branch 'master' of github.com:romanini-ciandt/terraform-google-…
romanini-ciandt Aug 29, 2024
68dc943
Adjust docs
romanini-ciandt Aug 29, 2024
8a94f7e
Adjust permissions
romanini-ciandt Aug 30, 2024
275bed5
Make module more readable
romanini-ciandt Aug 30, 2024
4a018d5
Add tests
romanini-ciandt Aug 30, 2024
b173b10
Add more tests
romanini-ciandt Aug 30, 2024
35b48a9
Turn autokey an independent submodule
romanini-ciandt Sep 5, 2024
f0874c1
README adjusts
romanini-ciandt Sep 5, 2024
f5eb555
Merge branch 'master' into feat/add-autokey
romanini-ciandt Sep 6, 2024
78bddd7
Description updates
romanini-ciandt Sep 9, 2024
ad5d895
Merge branch 'feat/add-autokey' of github.com:romanini-ciandt/terrafo…
romanini-ciandt Sep 9, 2024
8d665de
Adjust tag value
romanini-ciandt Sep 9, 2024
e2598d0
Update output type
romanini-ciandt Sep 9, 2024
b4bd45f
Add autokey README
romanini-ciandt Sep 10, 2024
5c4d195
Fix typo
romanini-ciandt Sep 10, 2024
07c34f5
Hardcode location in tests
romanini-ciandt Sep 10, 2024
2c7e6fd
Add an importing plan README
romanini-ciandt Sep 12, 2024
73bfbba
Add missing init
romanini-ciandt Sep 12, 2024
c6c99a2
Merge branch 'master' into feat/add-autokey-plus-migration
romanini-ciandt Sep 24, 2024
ed14225
Add specific instructions to import existing state
romanini-ciandt Sep 26, 2024
e769c63
Partial working version
romanini-ciandt Sep 27, 2024
e587109
Turn bash commands into scripts
romanini-ciandt Sep 27, 2024
0a3dbda
Remove comments
romanini-ciandt Sep 27, 2024
72efd29
Fix lint errors
romanini-ciandt Sep 27, 2024
91eccaf
Revert an unwanted change
romanini-ciandt Sep 27, 2024
9172091
Fix typo
romanini-ciandt Oct 4, 2024
c44d574
Add comment to explain string op
romanini-ciandt Oct 15, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ terraform.tfstate*
*.pyc
.kitchen
credentials.json
terraform.tfvars

# tf lock file
.terraform.lock.hcl
54 changes: 54 additions & 0 deletions docs/importing_autokey_key_handles.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Importing Autokey Key Handles Guidance

If you have any existing [Autokey Key Handles](https://cloud.google.com/kms/docs/resource-hierarchy#key_handles) previously created using [terraform-google-autokey](https://registry.terraform.io/modules/GoogleCloudPlatform/autokey/google) module, it is recommended to import them to [autokey submodule](../modules/autokey/README.md) Terraform state by following the steps below.

**Note:** You don't need to import the existing state for [Autokey configuration](https://cloud.google.com/kms/docs/enable-autokey#enable-autokey-folder) resource. The [autokey submodule](../modules/autokey/README.md) apply process will handle that automatically.

**Note 2:** These instructions were made using [terraform-google-autokey v1.1.1](https://github.com/GoogleCloudPlatform/terraform-google-autokey/releases/tag/v1.1.1) as reference. Future releases versions might require changes in this document.

**WARNING:** [terraform-google-autokey](https://registry.terraform.io/modules/GoogleCloudPlatform/autokey/google) module can be used to create your Autokey folder, Autokey KMS project, Autokey resource project and additional resources (e.g: a Cloud Storage Bucket configured with Autokey), so **DO NOT RUN** a `terraform destroy` for the existing module, even after the Key Handle import process is completed.

## Getting the existing Autokey state from terraform-google-autokey module
1. Run `cd REPLACE-WITH-YOUR-PATH` to your `terraform-google-autokey/examples/cloud_autokey_example` local module path;
1. If you didn't use `examples/cloud_autokey_example`, make sure you update the output names in the script according your terraform files and the relative path in the command below.
1. Run the following helper script to perform `terraform output` and export the Autokey folder number, Autokey Key project, KeyHandle's names, locations and resource projects as environment variables:
```shell
cp ../../../terraform-google-kms/scripts/export_autokey_env_vars.sh .
chmod +x export_autokey_env_vars.sh
source ./export_autokey_env_vars.sh
```
**Note:** You must see values set for echos: `AUTOKEY_FOLDER_NUMBER` and `AUTOKEY_KMS_PROJECT_ID`.

**Note 2:** You must see values just for the KeyHandles you have deployed. In other words: If you just have a KeyHandle for Bigquery, you'll just see values for: `AUTOKEY_BQ_KEY_HANDLE_PROJECT`, `AUTOKEY_BQ_KEY_HANDLE_LOCATION` and `AUTOKEY_BQ_KEY_HANDLE_NAME` echos.

## Creating the .tfvars file
1. Run `cd` to your [autokey submodule](../modules/autokey/README.md) folder;
1. Run the following helper script to automate the `terraform output` file creation:
```shell
chmod +x ../../scripts/create_autokey_tfvars_file.sh
../../scripts/create_autokey_tfvars_file.sh
```

## Importing the existing Autokey state from terraform-google-autokey module using autokey submodule
1. Run `cd` to your [autokey submodule](../modules/autokey/README.md) folder;
1. Run the following helper script to automate the `terraform import` process:
```shell
chmod +x ../../scripts/import_autokey_state.sh
../../scripts/import_autokey_state.sh
```
1. **Note:** For each import, you should receive the following output:
```
Import successful!

The resources that were imported are shown above. These resources are now in
your Terraform state and will henceforth be managed by Terraform.
```
1. Run `terraform plan`.
1. Run `terraform apply`. **You have successfully imported the Autokey configuration and KeyHandle states**.

## Cleaning your local environment
1. Run the following helper script to unset all the environment variables used in this import process:
```shell
chmod +x ../../scripts/unset_autokey_env_vars.sh
source ../../scripts/unset_autokey_env_vars.sh
```
3 changes: 2 additions & 1 deletion examples/autokey_example/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
*/

module "autokey" {
source = "terraform-google-modules/kms/google//modules/autokey"
source = "terraform-google-modules/kms/google//modules/autokey"
version = "3.1.0"

project_id = var.project_id
autokey_folder_number = var.folder_id
Expand Down
1 change: 1 addition & 0 deletions modules/autokey/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,6 @@ This is a submodule built to make [KMS Autokey](https://cloud.google.com/kms/doc
|------|-------------|
| autokey\_config\_id | An Autokey configuration identifier. |
| autokey\_keyhandles | A map of KeyHandles created. |
| random\_suffix | Random 4 digits suffix used in Autokey submodule. |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
8 changes: 5 additions & 3 deletions modules/autokey/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,6 @@ resource "google_kms_autokey_config" "primary" {
}

resource "random_string" "suffix" {
count = local.create_autokey_key_handles ? 1 : 0

length = 4
special = false
upper = false
Expand All @@ -39,9 +37,13 @@ resource "google_kms_key_handle" "primary" {
provider = google-beta

project = each.value.project
name = "${each.value.name}-${random_string.suffix[0].result}"
name = "${each.value.name}-${random_string.suffix.result}"
location = each.value.location
resource_type_selector = each.value.resource_type_selector

lifecycle {
ignore_changes = [name]
}

Comment on lines +44 to +47
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed because the import script will import the existing keyhandles into TF resources that include the random suffix in the name, but we need to ignore the diffs on apply?

Or is it unrelated and more of a general autokey module improvement, to address what we discussed offline re: users changing the keyhandle name and then running into issues when they try to change it back?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A short answer would be:
It is to address issues on both (when imported or not), but the change was motivated to support the import process. It would impact 100% of the imports and just eventual use cases for not imported.

More context about why:
I added this lifecycle to avoid resource replaces when importing existing key handles. When we import, this submodule will try to append a random suffix and a replacement will be forced.

But also, as we discussed offline, this change would avoid errors even when the user is not importing.
Example: The key Handle for secret manager can not be recreated, just 1 instance per project is allowed by GCP. In this case, if the name is changed in tf, terraform will "destroy" (not actually destroy, but remove it from tf state) and the attempt to create a new resource will raise an error.

So, I chose this lifecycle approach, but I also see two others alternatives:

  1. Add a boolean flag in input variables, so users can control if to append the random suffix into key Handles or not. But the con in this approach is that all the key handles would need to have the same behavior (imported or not), and also we wouldn't be preventing the secret manager issue I mentioned above.
  2. Add a new key handle tf resource specifically for import process. The con in this approach is that, beyond the tf resource duplication, we would need to specify in .tfvars file different variables names for imported and non-imported key handles

Sorry for the length of the comment... but is it clear?
Let me know what you think, or if we should change the approach here :)

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gotcha, thanks for confirming! This all makes sense to me and seems reasonable, I'll defer to the CFT team and see if they disagree :) Thank you!

depends_on = [time_sleep.wait_srv_acc_permissions]
}
5 changes: 5 additions & 0 deletions modules/autokey/outputs.tf
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,8 @@ output "autokey_keyhandles" {
description = "A map of KeyHandles created."
value = local.create_autokey_key_handles ? google_kms_key_handle.primary : {}
}

output "random_suffix" {
description = "Random 4 digits suffix used in Autokey submodule."
value = random_string.suffix.result
}
64 changes: 64 additions & 0 deletions scripts/create_autokey_tfvars_file.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/bin/bash

# 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.

echo ----------------------------------------------
echo Starting terraform.tfvars file creation
echo ----------------------------------------------

echo "
project_id = $AUTOKEY_KMS_PROJECT_ID
autokey_folder_number = \"$AUTOKEY_FOLDER_NUMBER\"
autokey_handles = {
" > terraform.tfvars

if [ -n "$AUTOKEY_BQ_KEY_HANDLE_NAME" ]; then
echo "
bq_dataset = {
name = \"$AUTOKEY_BQ_KEY_HANDLE_NAME\",
project = \"$AUTOKEY_BQ_KEY_HANDLE_PROJECT\",
resource_type_selector = \"bigquery.googleapis.com/Dataset\",
location = \"$AUTOKEY_BQ_KEY_HANDLE_LOCATION\"
},
" >> terraform.tfvars
fi
if [ -n "$AUTOKEY_DISK_KEY_HANDLE_NAME" ]; then
echo "
compute_disk = {
name = \"$AUTOKEY_DISK_KEY_HANDLE_NAME\",
project = \"$AUTOKEY_DISK_KEY_HANDLE_PROJECT\",
resource_type_selector = \"compute.googleapis.com/Disk\",
location = \"$AUTOKEY_DISK_KEY_HANDLE_LOCATION\"
},
" >> terraform.tfvars
fi
if [ -n "$AUTOKEY_GCS_KEY_HANDLE_NAME" ]; then
echo "
gcs_bucket = {
name = \"$AUTOKEY_GCS_KEY_HANDLE_NAME\",
project = \"$AUTOKEY_GCS_KEY_HANDLE_PROJECT\",
resource_type_selector = \"storage.googleapis.com/Bucket\",
location = \"$AUTOKEY_GCS_KEY_HANDLE_LOCATION\"
},
" >> terraform.tfvars
fi

echo "
}
" >> terraform.tfvars

echo ----------------------------------------------
echo terraform.tfvars file created
echo ----------------------------------------------
89 changes: 89 additions & 0 deletions scripts/export_autokey_env_vars.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
#!/bin/bash

# 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.

echo ----------------------------------------------
echo Getting Autokey config and project
echo ----------------------------------------------

# terraform output format: "folders/{FOLDER_NUMBER}/autokeyConfig". That's why we cut just the second element.
AUTOKEY_FOLDER_NUMBER=$(terraform output -raw autokey_config | cut -d'/' -f2)
romanini-ciandt marked this conversation as resolved.
Show resolved Hide resolved
export AUTOKEY_FOLDER_NUMBER

AUTOKEY_KMS_PROJECT_ID=$(echo "module.autokey.key_project_id" | terraform console)
export AUTOKEY_KMS_PROJECT_ID

echo AUTOKEY_FOLDER_NUMBER: "$AUTOKEY_FOLDER_NUMBER"
echo AUTOKEY_KMS_PROJECT_ID: "$AUTOKEY_KMS_PROJECT_ID"

echo ----------------------------------------------
echo Getting Bigquery Dataset KeyHandle
echo ----------------------------------------------

# terraform output format: "projects/{PROJECT_ID}/locations/{LOCATION}/keyHandles/{KEYHANDLE_NAME}".
# That's why we have the cut operation.

AUTOKEY_BQ_KEY_HANDLE_PROJECT=$(terraform output -raw bq_key_handle | cut -d'/' -f2)
export AUTOKEY_BQ_KEY_HANDLE_PROJECT

AUTOKEY_BQ_KEY_HANDLE_LOCATION=$(terraform output -raw bq_key_handle | cut -d'/' -f4)
export AUTOKEY_BQ_KEY_HANDLE_LOCATION

AUTOKEY_BQ_KEY_HANDLE_NAME=$(terraform output -raw bq_key_handle | cut -d'/' -f6)
export AUTOKEY_BQ_KEY_HANDLE_NAME

echo AUTOKEY_BQ_KEY_HANDLE_PROJECT: "$AUTOKEY_BQ_KEY_HANDLE_PROJECT"
echo AUTOKEY_BQ_KEY_HANDLE_LOCATION: "$AUTOKEY_BQ_KEY_HANDLE_LOCATION"
echo AUTOKEY_BQ_KEY_HANDLE_NAME: "$AUTOKEY_BQ_KEY_HANDLE_NAME"

echo ----------------------------------------------
echo Getting Compute Disk KeyHandle
echo ----------------------------------------------

# terraform output format: "projects/{PROJECT_ID}/locations/{LOCATION}/keyHandles/{KEYHANDLE_NAME}".
# That's why we have the cut operation.

AUTOKEY_DISK_KEY_HANDLE_PROJECT=$(terraform output -raw disk_key_handle | cut -d'/' -f2)
export AUTOKEY_DISK_KEY_HANDLE_PROJECT

AUTOKEY_DISK_KEY_HANDLE_LOCATION=$(terraform output -raw disk_key_handle | cut -d'/' -f4)
export AUTOKEY_DISK_KEY_HANDLE_LOCATION

AUTOKEY_DISK_KEY_HANDLE_NAME=$(terraform output -raw disk_key_handle | cut -d'/' -f6)
export AUTOKEY_DISK_KEY_HANDLE_NAME

echo AUTOKEY_DISK_KEY_HANDLE_PROJECT: "$AUTOKEY_DISK_KEY_HANDLE_PROJECT"
echo AUTOKEY_DISK_KEY_HANDLE_LOCATION: "$AUTOKEY_DISK_KEY_HANDLE_LOCATION"
echo AUTOKEY_DISK_KEY_HANDLE_NAME: "$AUTOKEY_DISK_KEY_HANDLE_NAME"

echo ----------------------------------------------
echo Getting Storage Bucket KeyHandle
echo ----------------------------------------------

# terraform output format: "projects/{PROJECT_ID}/locations/{LOCATION}/keyHandles/{KEYHANDLE_NAME}".
# That's why we have the cut operation.

AUTOKEY_GCS_KEY_HANDLE_PROJECT=$(terraform output -raw gcs_key_handle | cut -d'/' -f2)
export AUTOKEY_GCS_KEY_HANDLE_PROJECT

AUTOKEY_GCS_KEY_HANDLE_LOCATION=$(terraform output -raw gcs_key_handle | cut -d'/' -f4)
export AUTOKEY_GCS_KEY_HANDLE_LOCATION

AUTOKEY_GCS_KEY_HANDLE_NAME=$(terraform output -raw gcs_key_handle | cut -d'/' -f6)
export AUTOKEY_GCS_KEY_HANDLE_NAME

echo AUTOKEY_GCS_KEY_HANDLE_PROJECT: "$AUTOKEY_GCS_KEY_HANDLE_PROJECT"
echo AUTOKEY_GCS_KEY_HANDLE_LOCATION: "$AUTOKEY_GCS_KEY_HANDLE_LOCATION"
echo AUTOKEY_GCS_KEY_HANDLE_NAME: "$AUTOKEY_GCS_KEY_HANDLE_NAME"
43 changes: 43 additions & 0 deletions scripts/import_autokey_state.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
#!/bin/bash

# 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.

echo ----------------------------------------------
echo Starting terraform init process
echo ----------------------------------------------

terraform init

echo ----------------------------------------------
echo terraform init process completed
echo ----------------------------------------------

echo ----------------------------------------------
echo Starting terraform import process
echo ----------------------------------------------

if [ -n "$AUTOKEY_BQ_KEY_HANDLE_NAME" ]; then
terraform import google_kms_key_handle.primary\[\"bq_dataset\"\] projects/"$AUTOKEY_BQ_KEY_HANDLE_PROJECT"/locations/"$AUTOKEY_BQ_KEY_HANDLE_LOCATION"/keyHandles/"$AUTOKEY_BQ_KEY_HANDLE_NAME"
fi
if [ -n "$AUTOKEY_DISK_KEY_HANDLE_NAME" ]; then
terraform import google_kms_key_handle.primary\[\"compute_disk\"\] projects/"$AUTOKEY_DISK_KEY_HANDLE_PROJECT"/locations/"$AUTOKEY_DISK_KEY_HANDLE_LOCATION"/keyHandles/"$AUTOKEY_DISK_KEY_HANDLE_NAME"
fi
if [ -n "$AUTOKEY_DISK_KEY_HANDLE_NAME" ]; then
terraform import google_kms_key_handle.primary\[\"gcs_bucket\"\] projects/"$AUTOKEY_GCS_KEY_HANDLE_PROJECT"/locations/"$AUTOKEY_GCS_KEY_HANDLE_LOCATION"/keyHandles/"$AUTOKEY_GCS_KEY_HANDLE_NAME"
fi

echo ----------------------------------------------
echo terraform import completed
echo ----------------------------------------------
31 changes: 31 additions & 0 deletions scripts/unset_autokey_env_vars.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#!/bin/bash

romanini-ciandt marked this conversation as resolved.
Show resolved Hide resolved
# 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.

unset AUTOKEY_FOLDER_NUMBER
unset AUTOKEY_KMS_PROJECT_ID
unset AUTOKEY_BQ_KEY_HANDLE_PROJECT
unset AUTOKEY_BQ_KEY_HANDLE_LOCATION
unset AUTOKEY_BQ_KEY_HANDLE_NAME
unset AUTOKEY_DISK_KEY_HANDLE_PROJECT
unset AUTOKEY_DISK_KEY_HANDLE_LOCATION
unset AUTOKEY_DISK_KEY_HANDLE_NAME
unset AUTOKEY_GCS_KEY_HANDLE_PROJECT
unset AUTOKEY_GCS_KEY_HANDLE_LOCATION
unset AUTOKEY_GCS_KEY_HANDLE_NAME

echo ----------------------------------------------
echo unset env vars process completed
echo ----------------------------------------------