Skip to content

Commit

Permalink
feat: Add sharing data with partner automation (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
romanini-ciandt authored Apr 3, 2024
1 parent 6fc55b6 commit ecc1592
Show file tree
Hide file tree
Showing 26 changed files with 936 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@ crash.log
# version control.
**/*.tfvars

# Add an exception for *.example.tfvars (These should be included in git)
!*.example.tfvars

credentials.json

# tf lock file
Expand Down
12 changes: 12 additions & 0 deletions build/int.cloudbuild.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,18 @@ steps:
- 'TF_VAR_org_id=$_ORG_ID'
- 'TF_VAR_folder_id=$_FOLDER_ID'
- 'TF_VAR_billing_account=$_BILLING_ACCOUNT'
- id: create
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run all --stage init --verbose']
- id: converge
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run all --stage apply --verbose']
- id: verify
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run all --stage verify --verbose']
- id: destroy
name: 'gcr.io/cloud-foundation-cicd/$_DOCKER_IMAGE_DEVELOPER_TOOLS:$_DOCKER_TAG_VERSION_DEVELOPER_TOOLS'
args: ['/bin/bash', '-c', 'cft test run all --stage teardown --verbose']
tags:
- 'ci'
- 'integration'
Expand Down
25 changes: 25 additions & 0 deletions examples/share_encrypted_data_with_partners_bootstrap/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* 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.
*/

module "bootstrap" {
source = "../../share-encrypted-data-with-partners/consumer/0-bootstrap"

project_id = var.project_id
keyring = "simple-example-keyring"
key = "simple-example-key"
import_job_public_key_path = "./wrapping-key.pem"
prevent_destroy = false
}
20 changes: 20 additions & 0 deletions examples/share_encrypted_data_with_partners_bootstrap/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 = "GCP project ID to use for the creation of resources."
type = string
}
21 changes: 21 additions & 0 deletions share-encrypted-data-with-partners/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Raw Encryption: Building infrastructure for sharing encrypted data with partners

## Overview

This guide provides patterns that can be used to continuously share sensitive data in encrypted form from external sources (on-prem or other clouds) with partners using the raw encryption feature in Cloud KMS with Terraform.

## Context

This automation is based in two personas: **producer** and **consumer**.

**Producer** is the entity that will generate the DEK (Data Encryption Key) and wants to send the encrypted data, while the **consumer** is the entity that will create the required GCP resources in order to receive the wrapped DEK together with the data to be decrypted.

## Expected workflow

1. Consumer [0-bootstrap terraform module](./consumer/0-bootstrap/README.md) execution;
1. Consumer sends the Import Job public key generated to Producer;
1. Producer [terraform module](./producer/README.md) execution;
1. Producer [encrypt process](./examples/python/README.md) execution;
1. Producer sends the wrapped DEK and the encrypted data to Consumer;
1. Consumer [1-key-import terraform module](./consumer/0-bootstrap/README.md) execution;
1. Consumer [decrypt process](./examples/python/README.md) execution;
63 changes: 63 additions & 0 deletions share-encrypted-data-with-partners/consumer/0-bootstrap/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
# [Consumer 0-bootstrap module] Raw Encryption: Building infrastructure for sharing encrypted data with partners

## Overview

This module provides the Terraform bootstrap infrastructure creation (keyring, key and import job) needed to exchange encrypted data with partners through Cloud KMS raw encryption.

## Prerequisites

- [Terraform](https://developer.hashicorp.com/terraform/downloads);
- [Google Cloud CLI (`gcloud`)](https://cloud.google.com/sdk/docs/install-sdk);
- You must be authenticated in your GCP account. If you're not you should run `gcloud auth login`;
- An existing [GCP project](https://cloud.google.com/resource-manager/docs/creating-managing-projects#creating_a_project);
- Enable GCP services in the project created above:
- cloudkms.googleapis.com

**Note:** You can enable these services using `gcloud services enable <SERVICE>` command or terraform automation would auto-enable them for you.

## Deploy infrastructure

1. Rename `terraform.example.tfvars` to `terraform.tfvars`:
```sh
mv terraform.example.tfvars terraform.tfvars
```

1. Update `terraform.tfvars` file with the required values.

1. Create the infrastructure.

```sh
terraform init
terraform plan
terraform apply
```
**Note:** Copy all the outputs provided by `terraform apply`. They will be required during the encrypt/decrypt process.

1. All the bootstrap infrastructure required to receive encrypted data (wrapped DEK and ciphertext) from the sender using raw encryption is deployed. You can now send the Import Job public key file (stored in `import_job_public_key_path`) to the sender so that they can go through the DEK (Data Encryption Key) wrapping process.

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

| Name | Description | Type | Default | Required |
|------|-------------|------|---------|:--------:|
| crypto\_key\_algorithm\_template | Algorithm to use when creating a key template. See more: https://cloud.google.com/kms/docs/reference/rest/v1/CryptoKeyVersionAlgorithm. | `string` | `"AES_256_GCM"` | no |
| import\_job\_method | Wrapping method to be used for incoming key material. See more: https://cloud.google.com/kms/docs/key-wrapping. | `string` | `"rsa-oaep-4096-sha256"` | no |
| import\_job\_public\_key\_path | Path to import job public key that will be auto-generated. The DEK is encrypted (also known as wrapped) by a key encryption key (KEK) provided by import job. | `string` | n/a | yes |
| key | Name of the key to be created. | `string` | n/a | yes |
| keyring | Name of the keyring to be created. | `string` | n/a | yes |
| location | Location for the keyring. For available KMS locations see: https://cloud.google.com/kms/docs/locations. | `string` | `"us-central1"` | no |
| prevent\_destroy | Set the prevent\_destroy lifecycle attribute on keys. | `bool` | `true` | no |
| project\_id | GCP project ID to use for the creation of resources. | `string` | n/a | yes |
| suffix | A suffix to be used as an identifier for resources. (e.g., suffix for KMS Key, Keyring, SAs, etc.). If not provided, a 4 character random one will be generated. | `string` | `""` | no |

## Outputs

| Name | Description |
|------|-------------|
| import\_job\_id | ID of the Import Job created. |
| key | Name of the key created. |
| keyring | Name of the keyring. |
| location | Location of the keyring created. |
| project\_id | ID of the GCP project being used. |

<!-- END OF PRE-COMMIT-TERRAFORM DOCS HOOK -->
93 changes: 93 additions & 0 deletions share-encrypted-data-with-partners/consumer/0-bootstrap/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/**
* 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.
*/

locals {
default_suffix = var.suffix != "" ? var.suffix : random_string.suffix.result
apis_to_enable = [
"cloudkms.googleapis.com",
"cloudresourcemanager.googleapis.com"
]
}

resource "google_project_service" "apis_to_enable" {
for_each = toset(local.apis_to_enable)

project = var.project_id
service = each.key
disable_on_destroy = false
}

resource "time_sleep" "enable_projects_apis_sleep" {
create_duration = "30s"

depends_on = [google_project_service.apis_to_enable]
}

resource "random_string" "suffix" {
length = 4
special = false
upper = false
}

resource "google_kms_key_ring" "keyring" {
name = "${var.keyring}-${local.default_suffix}"
location = var.location
project = var.project_id

depends_on = [time_sleep.enable_projects_apis_sleep]
}

resource "google_kms_crypto_key" "dek-prevent-destroy-true" {
count = var.prevent_destroy ? 1 : 0

name = "${var.key}-${local.default_suffix}"
key_ring = google_kms_key_ring.keyring.id
purpose = "RAW_ENCRYPT_DECRYPT"
import_only = true
skip_initial_version_creation = true

version_template {
algorithm = var.crypto_key_algorithm_template
protection_level = "HSM"
}

lifecycle {
prevent_destroy = true
}

depends_on = [time_sleep.enable_projects_apis_sleep]
}

resource "google_kms_crypto_key" "dek-prevent-destroy-false" {
count = var.prevent_destroy ? 0 : 1

name = "${var.key}-${local.default_suffix}"
key_ring = google_kms_key_ring.keyring.id
purpose = "RAW_ENCRYPT_DECRYPT"
import_only = true
skip_initial_version_creation = true

version_template {
algorithm = var.crypto_key_algorithm_template
protection_level = "HSM"
}

lifecycle {
prevent_destroy = false
}

depends_on = [time_sleep.enable_projects_apis_sleep]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* 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.
*/

locals {
import_job_id = "import-job-${local.default_suffix}"
}

// Create the import job into cloud KMS
resource "null_resource" "gcloud-import-job-creation" {

provisioner "local-exec" {
command = "gcloud kms import-jobs create ${local.import_job_id} --location ${var.location} --keyring ${google_kms_key_ring.keyring.name} --import-method ${var.import_job_method} --protection-level hsm --project ${var.project_id}"
}

depends_on = [google_kms_key_ring.keyring]
}

// Retrieve the wrapping (public) key of the import job from cloud KMS
resource "null_resource" "extract-pem-from-import-job" {

provisioner "local-exec" {
command = "gcloud kms import-jobs describe ${local.import_job_id} --project=${var.project_id} --location=${var.location} --keyring=${google_kms_key_ring.keyring.name} --format=\"value(publicKey.pem)\" > ${var.import_job_public_key_path}"
}

depends_on = [null_resource.gcloud-import-job-creation]
}
40 changes: 40 additions & 0 deletions share-encrypted-data-with-partners/consumer/0-bootstrap/outputs.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* 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 = "Name of the keyring."
value = google_kms_key_ring.keyring.name
}

output "location" {
description = "Location of the keyring created."
value = google_kms_key_ring.keyring.location
}

output "key" {
description = "Name of the key created."
value = "${var.key}-${local.default_suffix}"
}

output "project_id" {
description = "ID of the GCP project being used."
value = google_kms_key_ring.keyring.project
}

output "import_job_id" {
description = "ID of the Import Job created."
value = local.import_job_id
}
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.
*/

project_id = "REPLACE-WITH-YOUR-PROJECT-ID"
keyring = "example-keyring-terraform"
key = "example-key-terraform"
import_job_public_key_path = "./wrapping-key.pem"
Loading

0 comments on commit ecc1592

Please sign in to comment.