From f1924914afb00bafcaeccb6a88299e534517dab7 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 11 May 2020 16:54:32 +0200 Subject: [PATCH 001/129] Use flat source insted of submodule in envoy cos module (#72) * use fabric format for in/out table in cos-generic-metadata module's README * switch to flat modulespace in envoy cos module --- .../cos-generic-metadata/README.md | 40 +++++++++---------- .../envoy-traffic-director/README.md | 18 +++++---- .../envoy-traffic-director/main.tf | 6 +-- .../modules/cos-generic-metadata | 1 - 4 files changed, 32 insertions(+), 33 deletions(-) delete mode 120000 modules/cloud-config-container/envoy-traffic-director/modules/cos-generic-metadata diff --git a/modules/cloud-config-container/cos-generic-metadata/README.md b/modules/cloud-config-container/cos-generic-metadata/README.md index 8e85e421..1194728f 100644 --- a/modules/cloud-config-container/cos-generic-metadata/README.md +++ b/modules/cloud-config-container/cos-generic-metadata/README.md @@ -21,9 +21,7 @@ module "cos-envoy" { container_args = "-c /etc/envoy/envoy.yaml --log-level info --allow-unknown-static-fields" container_volumes = [ - { host = "/etc/envoy/envoy.yaml", - container = "/etc/envoy/envoy.yaml" - } + { host = "/etc/envoy/envoy.yaml", container = "/etc/envoy/envoy.yaml" } ] docker_args = "--network host --pid host" @@ -63,25 +61,25 @@ module "cos-envoy" { ## Variables -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| container\_image | Container image. | `string` | n/a | yes | -| boot\_commands | List of cloud-init `bootcmd`s | `list(string)` | `[]` | no | -| cloud\_config | Cloud config template path. If provided, takes precedence over all other arguments. | `string` | `null` | no | -| config\_variables | Additional variables used to render the template passed via `cloud_config` | `map(any)` | `{}` | no | -| container\_args | Arguments for container | `string` | `""` | no | -| container\_name | Name of the container to be run | `string` | `"container"` | no | -| container\_volumes | List of volumes |
list(object({
host = string,
container = string
}))
| `[]` | no | -| docker\_args | Extra arguments to be passed for docker | `string` | `null` | no | -| file\_defaults | Default owner and permissions for files. |
object({
owner = string
permissions = string
})
|
{
"owner": "root",
"permissions": "0644"
}
| no | -| files | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. |
map(object({
content = string
owner = string
permissions = string
}))
| `{}` | no | -| gcp\_logging | Should container logs be sent to Google Cloud Logging | `bool` | `true` | no | -| run\_commands | List of cloud-init `runcmd`s | `list(string)` | `[]` | no | -| users | List of usernames to be created. If provided, first user will be used to run the container. |
list(object({
username = string,
uid = number,
}))
| `[]` | no | +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| container_image | Container image. | string | ✓ | | +| *boot_commands* | List of cloud-init `bootcmd`s | list(string) | | [] | +| *cloud_config* | Cloud config template path. If provided, takes precedence over all other arguments. | string | | null | +| *config_variables* | Additional variables used to render the template passed via `cloud_config` | map(any) | | {} | +| *container_args* | Arguments for container | string | | | +| *container_name* | Name of the container to be run | string | | container | +| *container_volumes* | List of volumes | list(object({...})) | | [] | +| *docker_args* | Extra arguments to be passed for docker | string | | null | +| *file_defaults* | Default owner and permissions for files. | object({...}) | | ... | +| *files* | Map of extra files to create on the instance, path as key. Owner and permissions will use defaults if null. | map(object({...})) | | {} | +| *gcp_logging* | Should container logs be sent to Google Cloud Logging | bool | | true | +| *run_commands* | List of cloud-init `runcmd`s | list(string) | | [] | +| *users* | List of usernames to be created. If provided, first user will be used to run the container. | list(object({...})) | | ... | ## Outputs -| Name | Description | -|------|-------------| -| cloud\_config | Rendered cloud-config file to be passed as user-data instance metadata. | +| name | description | sensitive | +|---|---|:---:| +| cloud_config | Rendered cloud-config file to be passed as user-data instance metadata. | | diff --git a/modules/cloud-config-container/envoy-traffic-director/README.md b/modules/cloud-config-container/envoy-traffic-director/README.md index 8cb39563..6e2dae0d 100644 --- a/modules/cloud-config-container/envoy-traffic-director/README.md +++ b/modules/cloud-config-container/envoy-traffic-director/README.md @@ -2,6 +2,10 @@ This module manages a `cloud-config` configuration that starts a containerized Envoy Proxy on Container Optimized OS connected to Traffic Director. The default configuration creates a reverse proxy exposed on the node's port 80. Traffic routing policies and management should be managed by other means via Traffic Director. +The generated cloud config is rendered in the `cloud_config` output, and is meant to be used in instances or instance templates via the `user-data` metadata. + +This module depends on the [`cos-generic-metadata` module](../cos-generic-metadata) being the parent folder. If you change its location be sure to adjust the `source` attribute in `main.tf`. + ## Examples ### Default configuration @@ -46,14 +50,14 @@ module "vm-cos" { ## Variables -| Name | Description | Type | Default | Required | -|------|-------------|------|---------|:--------:| -| envoy\_image | Envoy Proxy container image to use. | `string` | `"envoyproxy/envoy:v1.14.1"` | no | -| gcp\_logging | Should container logs be sent to Google Cloud Logging | `bool` | `true` | no | +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| *envoy_image* | Envoy Proxy container image to use. | string | | envoyproxy/envoy:v1.14.1 | +| *gcp_logging* | Should container logs be sent to Google Cloud Logging | bool | | true | ## Outputs -| Name | Description | -|------|-------------| -| cloud\_config | Rendered cloud-config file to be passed as user-data instance metadata. | +| name | description | sensitive | +|---|---|:---:| +| cloud_config | Rendered cloud-config file to be passed as user-data instance metadata. | | diff --git a/modules/cloud-config-container/envoy-traffic-director/main.tf b/modules/cloud-config-container/envoy-traffic-director/main.tf index 768ed5af..0b390d8c 100644 --- a/modules/cloud-config-container/envoy-traffic-director/main.tf +++ b/modules/cloud-config-container/envoy-traffic-director/main.tf @@ -15,7 +15,7 @@ */ module "cos-envoy-td" { - source = "./modules/cos-generic-metadata" + source = "../cos-generic-metadata" boot_commands = [ "systemctl start node-problem-detector", @@ -26,9 +26,7 @@ module "cos-envoy-td" { container_args = "-c /etc/envoy/envoy.yaml --log-level info --allow-unknown-static-fields" container_volumes = [ - { host = "/etc/envoy/envoy.yaml", - container = "/etc/envoy/envoy.yaml" - } + { host = "/etc/envoy/envoy.yaml", container = "/etc/envoy/envoy.yaml" } ] docker_args = "--network host --pid host" diff --git a/modules/cloud-config-container/envoy-traffic-director/modules/cos-generic-metadata b/modules/cloud-config-container/envoy-traffic-director/modules/cos-generic-metadata deleted file mode 120000 index 66c564ef..00000000 --- a/modules/cloud-config-container/envoy-traffic-director/modules/cos-generic-metadata +++ /dev/null @@ -1 +0,0 @@ -../../cos-generic-metadata \ No newline at end of file From bd73e1ade9879ce02334ceb26180276b26516eb3 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 11 May 2020 17:51:00 +0200 Subject: [PATCH 002/129] New pubsub module (#73) * pubsub module, untested * fixed a few errors --- modules/bigquery-dataset/README.md | 3 - modules/pubsub/README.md | 120 +++++++++++++++++++++++++++++ modules/pubsub/main.tf | 113 +++++++++++++++++++++++++++ modules/pubsub/outputs.tf | 46 +++++++++++ modules/pubsub/variables.tf | 120 +++++++++++++++++++++++++++++ modules/pubsub/versions.tf | 19 +++++ 6 files changed, 418 insertions(+), 3 deletions(-) create mode 100644 modules/pubsub/README.md create mode 100644 modules/pubsub/main.tf create mode 100644 modules/pubsub/outputs.tf create mode 100644 modules/pubsub/variables.tf create mode 100644 modules/pubsub/versions.tf diff --git a/modules/bigquery-dataset/README.md b/modules/bigquery-dataset/README.md index ecbbe8f1..427d89a8 100644 --- a/modules/bigquery-dataset/README.md +++ b/modules/bigquery-dataset/README.md @@ -158,6 +158,3 @@ module "bigquery-dataset" { | views | View resources. | | -## TODO - -- [ ] add support for tables diff --git a/modules/pubsub/README.md b/modules/pubsub/README.md new file mode 100644 index 00000000..5a1b05e9 --- /dev/null +++ b/modules/pubsub/README.md @@ -0,0 +1,120 @@ +# Google Cloud Pub/Sub Module + +This module allows managing a single Pub/Sub topic, including multiple subscriptions and IAM bindings at the topic and subscriptions levels. + + +## Examples + +### Simple topic with IAM + +```hcl +module "pubsub" { + source = "./modules/pubsub" + project_id = "my-project + name = "my-topic" + iam_roles = [ + "roles/pubsub.viewer", + "roles/pubsub.subscriber" + ] + iam_members = { + "roles/pubsub.viewer" = ["group:foo@example.com"] + "roles/pubsub.subscriber" = ["user:user1@example.com"] + } +``` + +### Subscriptions + +Subscriptions are defined with the `subscriptions` variable, allowing optional configuration of per-subscription defaults. Push subscriptions need extra configuration, shown in the following example. + +```hcl +module "pubsub" { + source = "./modules/pubsub" + project_id = "my-project + name = "my-topic" + subscriptions = { + test-pull = null + test-pull-override = { + labels = { test = "override" } + options = { + ack_deadline_seconds = null + message_retention_duration = null + retain_acked_messages = true + expiration_policy_ttl = null + } + } + } +} +``` + +### Push subscriptions + +Push subscriptions need extra configuration in the `push_configs` variable. + +```hcl +module "pubsub" { + source = "./modules/pubsub" + project_id = "my-project + name = "my-topic" + subscriptions = { + test-push = null + } + push_configs = { + test-push = { + endpoint = "https://example.com/foo" + attributes = null + oidc_token = null + } + } +} +``` + +### Subscriptions with IAM + +```hcl +module "pubsub" { + source = "./modules/pubsub" + project_id = "my-project + name = "my-topic" + subscriptions = { + test-1 = null + test-1 = null + } + subscription_iam_roles = { + test-1 = ["roles/pubsub.subscriber"] + } + subscription_iam_members = { + test-1 = { + "roles/pubsub.subscriber" = ["user:user1@ludomagno.net"] + } + } +} +``` + + +## Variables + +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| name | PubSub topic name. | string | ✓ | | +| project_id | Project used for resources. | string | ✓ | | +| *dead_letter_configs* | Per-subscription dead letter policy configuration. | map(object({...})) | | {} | +| *defaults* | Subscription defaults for options. | object({...}) | | ... | +| *iam_members* | IAM members for each topic role. | map(list(string)) | | {} | +| *iam_roles* | IAM roles for topic. | list(string) | | [] | +| *kms_key* | KMS customer managed encryption key. | string | | null | +| *labels* | Labels. | map(string) | | {} | +| *push_configs* | Push subscription configurations. | map(object({...})) | | {} | +| *regions* | List of regions used to set persistence policy. | list(string) | | [] | +| *subscription_iam_members* | IAM members for each subscription and role. | map(map(list(string))) | | {} | +| *subscription_iam_roles* | IAM roles for each subscription. | map(list(string)) | | {} | +| *subscriptions* | Topic subscriptions. Also define push configs for push subscriptions. If options is set to null subscription defaults will be used. Labels default to topic labels if set to null. | map(object({...})) | | {} | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| id | Topic id. | | +| subscription_id | Subscription ids. | | +| subscriptions | Subscription resources. | | +| topic | Topic resource. | | + diff --git a/modules/pubsub/main.tf b/modules/pubsub/main.tf new file mode 100644 index 00000000..50876070 --- /dev/null +++ b/modules/pubsub/main.tf @@ -0,0 +1,113 @@ +/** + * Copyright 2020 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 { + iam_pairs = var.subscription_iam_roles == null ? [] : flatten([ + for name, roles in var.subscription_iam_roles : + [for role in roles : { name = name, role = role }] + ]) + iam_keypairs = { + for pair in local.iam_pairs : + "${pair.name}-${pair.role}" => pair + } + iam_members = ( + var.subscription_iam_members == null ? {} : var.subscription_iam_members + ) + oidc_config = { + for k, v in var.push_configs : k => v.oidc_token + } + subscriptions = { + for k, v in var.subscriptions : k => { + labels = try(v.labels, v, null) == null ? var.labels : v.labels + options = try(v.options, v, null) == null ? var.defaults : v.options + } + } +} + +resource "google_pubsub_topic" "default" { + project = var.project_id + name = var.name + kms_key_name = var.kms_key + labels = var.labels + + dynamic message_storage_policy { + for_each = length(var.regions) > 0 ? [var.regions] : [] + content { + allowed_persistence_regions = var.regions + } + } +} + +resource "google_pubsub_topic_iam_binding" "default" { + for_each = toset(var.iam_roles) + project = var.project_id + topic = google_pubsub_topic.default.name + role = each.value + members = lookup(var.iam_members, each.value, []) +} + +resource "google_pubsub_subscription" "default" { + for_each = local.subscriptions + project = var.project_id + name = each.key + topic = google_pubsub_topic.default.name + labels = each.value.labels + ack_deadline_seconds = each.value.options.ack_deadline_seconds + message_retention_duration = each.value.options.message_retention_duration + retain_acked_messages = each.value.options.retain_acked_messages + + dynamic expiration_policy { + for_each = each.value.options.expiration_policy_ttl == null ? [] : [""] + content { + ttl = each.value.options.expiration_policy_ttl + } + } + + dynamic dead_letter_policy { + for_each = try(var.dead_letter_configs[each.key], null) == null ? [] : [""] + content { + dead_letter_topic = var.dead_letter_configs[each.key].topic + max_delivery_attempts = var.dead_letter_configs[each.key].max_delivery_attempts + } + } + + dynamic push_config { + for_each = try(var.push_configs[each.key], null) == null ? [] : [""] + content { + push_endpoint = var.push_configs[each.key].endpoint + attributes = var.push_configs[each.key].attributes + dynamic oidc_token { + for_each = ( + local.oidc_config[each.key] == null ? [] : [""] + ) + content { + service_account_email = local.oidc_config[each.key].service_account_email + audience = local.oidc_config[each.key].audience + } + } + } + } +} + +resource "google_pubsub_subscription_iam_binding" "default" { + for_each = local.iam_keypairs + project = var.project_id + subscription = google_pubsub_subscription.default[each.value.name].name + role = each.value.role + members = lookup( + lookup(local.iam_members, each.value.name, {}), each.value.role, [] + ) +} diff --git a/modules/pubsub/outputs.tf b/modules/pubsub/outputs.tf new file mode 100644 index 00000000..950f60b2 --- /dev/null +++ b/modules/pubsub/outputs.tf @@ -0,0 +1,46 @@ +/** + * Copyright 2020 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 "id" { + description = "Topic id." + value = google_pubsub_topic.default.id +} + +output "subscriptions" { + description = "Subscription resources." + value = google_pubsub_subscription.default + depends_on = [ + google_pubsub_subscription_iam_binding.default + ] +} + +output "subscription_id" { + description = "Subscription ids." + value = { + for k, v in google_pubsub_subscription.default : k => v.id + } + depends_on = [ + google_pubsub_subscription_iam_binding.default + ] +} + +output "topic" { + description = "Topic resource." + value = google_pubsub_topic.default + depends_on = [ + google_pubsub_topic_iam_binding.default + ] +} diff --git a/modules/pubsub/variables.tf b/modules/pubsub/variables.tf new file mode 100644 index 00000000..d642c7a6 --- /dev/null +++ b/modules/pubsub/variables.tf @@ -0,0 +1,120 @@ +/** + * Copyright 2020 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 "dead_letter_configs" { + description = "Per-subscription dead letter policy configuration." + type = map(object({ + topic = string + max_delivery_attemps = number + })) + default = {} +} + +variable "defaults" { + description = "Subscription defaults for options." + type = object({ + ack_deadline_seconds = number + message_retention_duration = number + retain_acked_messages = bool + expiration_policy_ttl = string + }) + default = { + ack_deadline_seconds = null + message_retention_duration = null + retain_acked_messages = null + expiration_policy_ttl = null + } +} + +variable "iam_members" { + description = "IAM members for each topic role." + type = map(list(string)) + default = {} +} + +variable "iam_roles" { + description = "IAM roles for topic." + type = list(string) + default = [] +} + +variable "kms_key" { + description = "KMS customer managed encryption key." + type = string + default = null +} + +variable "labels" { + description = "Labels." + type = map(string) + default = {} +} + +variable "name" { + description = "PubSub topic name." + type = string +} + +variable "regions" { + description = "List of regions used to set persistence policy." + type = list(string) + default = [] +} + +variable "project_id" { + description = "Project used for resources." + type = string +} + + +variable "push_configs" { + description = "Push subscription configurations." + type = map(object({ + attributes = map(string) + endpoint = string + oidc_token = object({ + audience = string + service_account_email = string + }) + })) + default = {} +} + +variable "subscriptions" { + description = "Topic subscriptions. Also define push configs for push subscriptions. If options is set to null subscription defaults will be used. Labels default to topic labels if set to null." + type = map(object({ + labels = map(string) + options = object({ + ack_deadline_seconds = number + message_retention_duration = number + retain_acked_messages = bool + expiration_policy_ttl = string + }) + })) + default = {} +} + +variable "subscription_iam_members" { + description = "IAM members for each subscription and role." + type = map(map(list(string))) + default = {} +} + +variable "subscription_iam_roles" { + description = "IAM roles for each subscription." + type = map(list(string)) + default = {} +} diff --git a/modules/pubsub/versions.tf b/modules/pubsub/versions.tf new file mode 100644 index 00000000..ce6918e0 --- /dev/null +++ b/modules/pubsub/versions.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2019 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_version = ">= 0.12.6" +} From fdea316893a7f93f376eed815bbafdf644cab95f Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 11 May 2020 17:52:06 +0200 Subject: [PATCH 003/129] Update CHANGELOG.md --- CHANGELOG.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32c99c53..41c90f35 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [1.5.0] - 2020-05-11 + - **incompatible change** the `bigquery` module has been removed and replaced by the new `bigquery-dataset` module - **incompatible change** subnets in the `net-vpc` modules are now passed as a list instead of map, and all related variables for IAM and flow logs use `region/name` instead of `name` keys; it's now possible to have the same subnet name in different regions - replace all references to the removed `resourceviews.googleapis.com` API with `container.googleapis.com` @@ -11,7 +13,7 @@ All notable changes to this project will be documented in this file. - fix health checks in `compute-mig` and `net-ilb` modules - new `cos-generic-metadata` module in the `cloud-config-container` suite - new `envoy-traffic-director` module in the `cloud-config-container` suite -- new `pubsub` module (untested) +- new `pubsub` module ## [1.4.1] - 2020-05-02 @@ -55,7 +57,8 @@ All notable changes to this project will be documented in this file. - merge development branch with suite of new modules and end-to-end examples -[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.4.1...HEAD +[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.5.0...HEAD +[1.5.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.4.1...v1.5.0 [1.4.1]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.4.0...v1.4.1 [1.4.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.3.0...v1.4.0 [1.3.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.2...v1.3.0 From da97405e31c48e470c5f30633f78cc6e052924c8 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Tue, 12 May 2020 13:35:13 +0200 Subject: [PATCH 004/129] add support for service directory zones to dns module --- modules/dns/README.md | 9 ++++++--- modules/dns/main.tf | 27 +++++++++++++++++---------- modules/dns/variables.tf | 13 ++++++++----- 3 files changed, 31 insertions(+), 18 deletions(-) diff --git a/modules/dns/README.md b/modules/dns/README.md index 6993e569..207572c9 100644 --- a/modules/dns/README.md +++ b/modules/dns/README.md @@ -1,6 +1,8 @@ # Google Cloud DNS Module -This module allows simple management of Google Cloud DNS zones and records. It supports creating public, private, forwarding, and peering zones. For DNSSEC configuration, refer to the [`dns_managed_zone` documentation](https://www.terraform.io/docs/providers/google/r/dns_managed_zone.html#dnssec_config). +This module allows simple management of Google Cloud DNS zones and records. It supports creating public, private, forwarding, peering and service directory based zones. + +For DNSSEC configuration, refer to the [`dns_managed_zone` documentation](https://www.terraform.io/docs/providers/google/r/dns_managed_zone.html#dnssec_config). ## Example @@ -32,9 +34,10 @@ module "private-dns" { | *description* | Domain description. | string | | Terraform managed. | | *dnssec_config* | DNSSEC configuration: kind, non_existence, state. | any | | {} | | *forwarders* | List of target name servers, only valid for 'forwarding' zone types. | list(string) | | [] | -| *peer_network* | Peering network self link, only valid for 'peering' zone types. | string | | | +| *peer_network* | Peering network self link, only valid for 'peering' zone types. | string | | null | | *recordsets* | List of DNS record objects to manage. | list(object({...})) | | [] | -| *type* | Type of zone to create, valid values are 'public', 'private', 'forwarding', 'peering'. | string | | private | +| *service_directory_namespace* | Service directory namespace id (URL), only valid for 'service-directory' zone types. | string | | null | +| *type* | Type of zone to create, valid values are 'public', 'private', 'forwarding', 'peering', 'service-directory'. | string | | private | ## Outputs diff --git a/modules/dns/main.tf b/modules/dns/main.tf index 6e098b8d..abb0beb2 100644 --- a/modules/dns/main.tf +++ b/modules/dns/main.tf @@ -38,14 +38,11 @@ resource "google_dns_managed_zone" "non-public" { dynamic forwarding_config { for_each = ( - var.type == "forwarding" && var.forwarders != null - ? { config = var.forwarders } - : {} + var.type == "forwarding" && var.forwarders != null ? [""] : [] ) - iterator = config content { dynamic "target_name_servers" { - for_each = config.value + for_each = var.forwarders iterator = address content { ipv4_address = address.value @@ -56,14 +53,11 @@ resource "google_dns_managed_zone" "non-public" { dynamic peering_config { for_each = ( - var.type == "peering" && var.peer_network != null - ? { config = var.peer_network } - : {} + var.type == "peering" && var.peer_network != null ? [""] : [] ) - iterator = config content { target_network { - network_url = config.value + network_url = var.peer_network } } } @@ -78,6 +72,19 @@ resource "google_dns_managed_zone" "non-public" { } } + dynamic service_directory_config { + for_each = ( + var.type == "service-directory" && var.service_directory_namespace != null + ? [""] + : [] + ) + content { + namespace { + namespace_url = var.service_directory_namespace + } + } + } + } resource "google_dns_managed_zone" "public" { diff --git a/modules/dns/variables.tf b/modules/dns/variables.tf index 0991038c..f38fb36a 100644 --- a/modules/dns/variables.tf +++ b/modules/dns/variables.tf @@ -30,9 +30,6 @@ variable "description" { default = "Terraform managed." } -# TODO(ludoo): add link to DNSSEC documentation in README -# https://www.terraform.io/docs/providers/google/r/dns_managed_zone.html#dnssec_config - variable "default_key_specs_key" { description = "DNSSEC default key signing specifications: algorithm, key_length, key_type, kind." type = any @@ -71,7 +68,7 @@ variable "name" { variable "peer_network" { description = "Peering network self link, only valid for 'peering' zone types." type = string - default = "" + default = null } variable "project_id" { @@ -90,8 +87,14 @@ variable "recordsets" { default = [] } +variable "service_directory_namespace" { + description = "Service directory namespace id (URL), only valid for 'service-directory' zone types." + type = string + default = null +} + variable "type" { - description = "Type of zone to create, valid values are 'public', 'private', 'forwarding', 'peering'." + description = "Type of zone to create, valid values are 'public', 'private', 'forwarding', 'peering', 'service-directory'." type = string default = "private" } From 324890073ba8d753f9e28e4822cf8182b4bf0f71 Mon Sep 17 00:00:00 2001 From: Roberto Jung Drebes Date: Tue, 12 May 2020 18:13:06 +0200 Subject: [PATCH 005/129] adds project_id to external gateway (#74) --- modules/net-vpn-ha/main.tf | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/net-vpn-ha/main.tf b/modules/net-vpn-ha/main.tf index 751081ee..141bffc7 100644 --- a/modules/net-vpn-ha/main.tf +++ b/modules/net-vpn-ha/main.tf @@ -42,6 +42,7 @@ resource "google_compute_external_vpn_gateway" "external_gateway" { provider = google-beta count = var.peer_external_gateway != null ? 1 : 0 name = "external-${var.name}" + project = var.project_id redundancy_type = var.peer_external_gateway.redundancy_type description = "Terraform managed external VPN gateway" dynamic "interface" { From de9825310c11ec5d1bc3cc6e9736253e8ced1021 Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Tue, 12 May 2020 18:46:50 +0200 Subject: [PATCH 006/129] Fix another gke-cluster dynamic block typo --- modules/gke-cluster/main.tf | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/modules/gke-cluster/main.tf b/modules/gke-cluster/main.tf index 31ef293a..d08ea0d8 100644 --- a/modules/gke-cluster/main.tf +++ b/modules/gke-cluster/main.tf @@ -147,14 +147,15 @@ resource "google_container_cluster" "cluster" { enabled = true resource_limits { resource_type = "cpu" - minimum = config.cpu_min - maximum = config.cpu_max + minimum = config.value.cpu_min + maximum = config.value.cpu_max } resource_limits { resource_type = "memory" - minimum = config.memory_min - maximum = config.memory_max + minimum = config.value.memory_min + maximum = config.value.memory_max } + // TODO: support GPUs too } } From 88b124ddc83066ddb71b255e291b92d765198e2e Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Tue, 12 May 2020 18:52:03 +0200 Subject: [PATCH 007/129] first service-directory module implementation --- modules/service-directory/README.md | 99 ++++++++++++++++++++++++++ modules/service-directory/main.tf | 81 +++++++++++++++++++++ modules/service-directory/outputs.tf | 66 +++++++++++++++++ modules/service-directory/variables.tf | 80 +++++++++++++++++++++ modules/service-directory/versions.tf | 19 +++++ 5 files changed, 345 insertions(+) create mode 100644 modules/service-directory/README.md create mode 100644 modules/service-directory/main.tf create mode 100644 modules/service-directory/outputs.tf create mode 100644 modules/service-directory/variables.tf create mode 100644 modules/service-directory/versions.tf diff --git a/modules/service-directory/README.md b/modules/service-directory/README.md new file mode 100644 index 00000000..ed94ef9a --- /dev/null +++ b/modules/service-directory/README.md @@ -0,0 +1,99 @@ +# Google Cloud Service Directory Module + +This module allows managing a single [Service Directory](https://cloud.google.com/service-directory) namespace, including multiple services, endpoints and IAM bindings at the namespace and service levels. + +It can be used in conjunction with the [DNS](../dns) module to create service-directory based DNS zones, offloading IAM control of `A` and `SRV` records at the namespace or service level to Service Directory. The last examples shows how to wire the two modules together. + + +## Examples + +### Namespace with IAM + +```hcl +module "service-directory" { + source = "./modules/service-directory" + project_id = "my-project + location = "europe-west1" + name = "sd-1" + iam_members = { + "roles/servicedirectory.editor" = [ + "serviceAccount:namespace-editor@example.com" + ] + } + iam_roles = [ + "roles/servicedirectory.editor" + ] +``` + +### Services with IAM and endpoints + +```hcl +module "service-directory" { + source = "./modules/service-directory" + project_id = "my-project + location = "europe-west1" + name = "sd-1" + services = { + one = { + endpoints = ["first", "second"] + metadata = null + } + } + service_iam_members = { + one = { + "roles/servicedirectory.editor" = [ + "serviceAccount:service-editor.example.com" + ] + } + } + service_iam_roles = { + one = ["roles/servicedirectory.editor"] + } + endpoint_config = { + "one/first" = { address = "127.0.0.1", port = 80, metadata = {} } + "one/second" = { address = "127.0.0.2", port = 80, metadata = {} } + } +} +``` + +### DNS based zone + +TODO + +```hcl +module "service-directory" { + source = "./modules/service-directory" + project_id = "my-project + location = "europe-west1" + name = "sd-1" +} +``` + + +## Variables + +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| location | Namespace location. | string | ✓ | | +| name | Namespace name. | string | ✓ | | +| project_id | Project used for resources. | string | ✓ | | +| *endpoint_config* | Map of endpoint attributes, keys are in service/endpoint format. | map(object({...})) | | {} | +| *iam_members* | IAM members for each namespace role. | map(list(string)) | | {} | +| *iam_roles* | IAM roles for the namespace. | list(string) | | [] | +| *labels* | Labels. | map(string) | | {} | +| *service_iam_members* | IAM members for each service and role. | map(map(list(string))) | | {} | +| *service_iam_roles* | IAM roles for each service. | map(list(string)) | | {} | +| *services* | Service configuration, using service names as keys. | map(object({...})) | | {} | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| endpoints | Endpoint resources. | | +| id | Namespace id (short name). | | +| name | Namespace name (long name). | | +| namespace | Namespace resource. | | +| service_id | Service ids (short names). | | +| service_names | Service ids (long names). | | +| services | Service resources. | | + diff --git a/modules/service-directory/main.tf b/modules/service-directory/main.tf new file mode 100644 index 00000000..8348de44 --- /dev/null +++ b/modules/service-directory/main.tf @@ -0,0 +1,81 @@ +/** + * Copyright 2020 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 { + endpoint_list = flatten([ + for name, attrs in var.services : [ + for endpoint in attrs.endpoints : { service : name, endpoint : endpoint } + ] + ]) + endpoints = { + for ep in local.endpoint_list : "${ep.service}/${ep.endpoint}" => ep + } + iam_pairs = var.service_iam_roles == null ? [] : flatten([ + for name, roles in var.service_iam_roles : + [for role in roles : { name = name, role = role }] + ]) + iam_keypairs = { + for pair in local.iam_pairs : + "${pair.name}-${pair.role}" => pair + } + iam_members = ( + var.service_iam_members == null ? {} : var.service_iam_members + ) +} + +resource "google_service_directory_namespace" "default" { + provider = google-beta + project = var.project_id + namespace_id = var.name + location = var.location + labels = var.labels +} + +resource "google_service_directory_namespace_iam_binding" "default" { + provider = google-beta + for_each = toset(var.iam_roles) + name = google_service_directory_namespace.default.name + role = each.value + members = lookup(var.iam_members, each.value, []) +} + +resource "google_service_directory_service" "default" { + provider = google-beta + for_each = var.services + namespace = google_service_directory_namespace.default.id + service_id = each.key + metadata = each.value.metadata +} + +resource "google_service_directory_service_iam_binding" "default" { + provider = google-beta + for_each = local.iam_keypairs + name = google_service_directory_service.default[each.value.name].name + role = each.value.role + members = lookup( + lookup(local.iam_members, each.value.name, {}), each.value.role, [] + ) +} + +resource "google_service_directory_endpoint" "default" { + provider = google-beta + for_each = local.endpoints + endpoint_id = each.value.endpoint + service = google_service_directory_service.default[each.value.service].id + metadata = try(var.endpoint_config[each.key].metadata, null) + address = try(var.endpoint_config[each.key].address, null) + port = try(var.endpoint_config[each.key].port, null) +} diff --git a/modules/service-directory/outputs.tf b/modules/service-directory/outputs.tf new file mode 100644 index 00000000..0fab3996 --- /dev/null +++ b/modules/service-directory/outputs.tf @@ -0,0 +1,66 @@ +/** + * Copyright 2020 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 "endpoints" { + description = "Endpoint resources." + value = google_service_directory_endpoint.default +} + +output "id" { + description = "Namespace id (short name)." + value = google_service_directory_namespace.default.id +} + +output "name" { + description = "Namespace name (long name)." + value = google_service_directory_namespace.default.name +} + +output "namespace" { + description = "Namespace resource." + value = google_service_directory_namespace.default + depends_on = [ + google_service_directory_namespace_iam_binding.default + ] +} + +output "services" { + description = "Service resources." + value = google_service_directory_service.default + depends_on = [ + google_service_directory_service_iam_binding.default + ] +} + +output "service_id" { + description = "Service ids (short names)." + value = { + for k, v in google_service_directory_service.default : k => v.id + } + depends_on = [ + google_service_directory_service_iam_binding.default + ] +} + +output "service_names" { + description = "Service ids (long names)." + value = { + for k, v in google_service_directory_service.default : k => v.name + } + depends_on = [ + google_service_directory_service_iam_binding.default + ] +} diff --git a/modules/service-directory/variables.tf b/modules/service-directory/variables.tf new file mode 100644 index 00000000..8b921d56 --- /dev/null +++ b/modules/service-directory/variables.tf @@ -0,0 +1,80 @@ +/** + * Copyright 2020 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. + */ + +# we need a separate variable as address will be dynamic in most cases +variable "endpoint_config" { + description = "Map of endpoint attributes, keys are in service/endpoint format." + type = map(object({ + address = string + port = number + metadata = map(string) + })) + default = {} +} + +variable "iam_members" { + description = "IAM members for each namespace role." + type = map(list(string)) + default = {} +} + +variable "iam_roles" { + description = "IAM roles for the namespace." + type = list(string) + default = [] +} + +variable "labels" { + description = "Labels." + type = map(string) + default = {} +} + +variable "location" { + description = "Namespace location." + type = string +} + +variable "name" { + description = "Namespace name." + type = string +} + +variable "project_id" { + description = "Project used for resources." + type = string +} + +variable "service_iam_members" { + description = "IAM members for each service and role." + type = map(map(list(string))) + default = {} +} + +variable "service_iam_roles" { + description = "IAM roles for each service." + type = map(list(string)) + default = {} +} + +variable "services" { + description = "Service configuration, using service names as keys." + type = map(object({ + endpoints = list(string) + metadata = map(string) + })) + default = {} +} diff --git a/modules/service-directory/versions.tf b/modules/service-directory/versions.tf new file mode 100644 index 00000000..ce6918e0 --- /dev/null +++ b/modules/service-directory/versions.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2019 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_version = ">= 0.12.6" +} From 63f1f3e066daea0c2e73f0c4f3d21ed8e871145c Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Tue, 12 May 2020 19:17:46 +0200 Subject: [PATCH 008/129] Add cluster CA certificate as output for gke-cluster --- modules/gke-cluster/README.md | 1 + modules/gke-cluster/outputs.tf | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/modules/gke-cluster/README.md b/modules/gke-cluster/README.md index fcbae58f..e081bf70 100644 --- a/modules/gke-cluster/README.md +++ b/modules/gke-cluster/README.md @@ -70,6 +70,7 @@ module "cluster-1" { | name | description | sensitive | |---|---|:---:| +| ca_certificate | Public certificate of the cluster (base64-encoded). | ✓ | | cluster | Cluster resource. | ✓ | | endpoint | Cluster endpoint. | | | location | Cluster location. | | diff --git a/modules/gke-cluster/outputs.tf b/modules/gke-cluster/outputs.tf index 6937ee96..cb19e92d 100644 --- a/modules/gke-cluster/outputs.tf +++ b/modules/gke-cluster/outputs.tf @@ -39,3 +39,9 @@ output "name" { description = "Cluster name." value = google_container_cluster.cluster.name } + +output "ca_certificate" { + description = "Public certificate of the cluster (base64-encoded)." + value = google_container_cluster.cluster.master_auth.0.cluster_ca_certificate + sensitive = true +} From 2dcd86df82046890a6ee27313973a6ecbaeaad7e Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Tue, 12 May 2020 19:26:52 +0200 Subject: [PATCH 009/129] Mention gke-cluster changes in CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41c90f35..8b2de888 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- Add output to `gke-cluster` exposing the cluster's CA certificate +- Fix `gke-cluster` autoscaling options ## [1.5.0] - 2020-05-11 From e85173e4402fb5bf24624f5d919b3686699e4133 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Tue, 12 May 2020 20:26:34 +0200 Subject: [PATCH 010/129] add DNS example to service directory --- modules/service-directory/README.md | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) diff --git a/modules/service-directory/README.md b/modules/service-directory/README.md index ed94ef9a..8f58c0b4 100644 --- a/modules/service-directory/README.md +++ b/modules/service-directory/README.md @@ -12,7 +12,7 @@ It can be used in conjunction with the [DNS](../dns) module to create service-di ```hcl module "service-directory" { source = "./modules/service-directory" - project_id = "my-project + project_id = "my-project" location = "europe-west1" name = "sd-1" iam_members = { @@ -23,6 +23,7 @@ module "service-directory" { iam_roles = [ "roles/servicedirectory.editor" ] +} ``` ### Services with IAM and endpoints @@ -30,7 +31,7 @@ module "service-directory" { ```hcl module "service-directory" { source = "./modules/service-directory" - project_id = "my-project + project_id = "my-project" location = "europe-west1" name = "sd-1" services = { @@ -58,15 +59,32 @@ module "service-directory" { ### DNS based zone -TODO +Wiring a service directory namespace to a private DNS zone allows querying the namespace, and delegating control of DNS records at the namespace or service level. This effectively allows fine grained ACL control of Cloud DNS zones. ```hcl module "service-directory" { source = "./modules/service-directory" - project_id = "my-project + project_id = "my-project" location = "europe-west1" - name = "sd-1" + name = "apps" + services = { + app1 = { endpoints = ["one"], metadata = null } + } + endpoint_config = { + "app1/one" = { address = "127.0.0.1", port = 80, metadata = {} } + } } + +module "dns-sd" { + source = "./modules/dns" + project_id = "my-project" + type = "service-directory" + name = "apps" + domain = "apps.example.org." + client_networks = [local.vpc_self_link] + service_directory_namespace = module.service-directory.id +} + ``` From 835915c4e34b37642e120f1e24530075342cd5a9 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 13 May 2020 07:54:03 +0200 Subject: [PATCH 011/129] Update README.md --- modules/service-directory/README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/modules/service-directory/README.md b/modules/service-directory/README.md index 8f58c0b4..861e67d6 100644 --- a/modules/service-directory/README.md +++ b/modules/service-directory/README.md @@ -67,6 +67,14 @@ module "service-directory" { project_id = "my-project" location = "europe-west1" name = "apps" + iam_members = { + "roles/servicedirectory.editor" = [ + "serviceAccount:namespace-editor@example.com" + ] + } + iam_roles = [ + "roles/servicedirectory.editor" + ] services = { app1 = { endpoints = ["one"], metadata = null } } From cd3730393fe5966773e9b31761dc833d825ed89e Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 13 May 2020 07:54:46 +0200 Subject: [PATCH 012/129] Update README.md --- modules/service-directory/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/service-directory/README.md b/modules/service-directory/README.md index 861e67d6..c57bd9f8 100644 --- a/modules/service-directory/README.md +++ b/modules/service-directory/README.md @@ -2,7 +2,7 @@ This module allows managing a single [Service Directory](https://cloud.google.com/service-directory) namespace, including multiple services, endpoints and IAM bindings at the namespace and service levels. -It can be used in conjunction with the [DNS](../dns) module to create service-directory based DNS zones, offloading IAM control of `A` and `SRV` records at the namespace or service level to Service Directory. The last examples shows how to wire the two modules together. +It can be used in conjunction with the [DNS](../dns) module to create [service-directory based DNS zones](https://cloud.google.com/service-directory/docs/configuring-service-directory-zone, offloading IAM control of `A` and `SRV` records at the namespace or service level to Service Directory. The last examples shows how to wire the two modules together. ## Examples From 55f787d8098d546a6c4b06e67ba285bfe74d5111 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 13 May 2020 10:53:09 +0200 Subject: [PATCH 013/129] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 30c51719..95a20dbd 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Currently available modules: - **foundational** - [folders](./modules/folders), [log sinks](./modules/logging-sinks), [organization](./modules/organization), [project](./modules/project), [service accounts](./modules/iam-service-accounts) - **networking** - [VPC](./modules/net-vpc), [VPC firewall](./modules/net-vpc-firewall), [VPC peering](./modules/net-vpc-peering), [VPN static](./modules/net-vpn-static), [VPN dynamic](./modules/net-vpn-dynamic), [VPN HA](./modules/net-vpn-ha), [NAT](./modules/net-cloudnat), [address reservation](./modules/net-address), [DNS](./modules/dns), [L4 ILB](./modules/net-ilb) - **compute** - [VM/VM group](./modules/compute-vm), [MIG](./modules/compute-mig), [GKE cluster](./modules/gke-cluster), [GKE nodepool](./modules/gke-nodepool), [COS container](./modules/cos-container) (coredns, mysql, onprem, squid) -- **data** - [GCS](./modules/gcs), [BigQuery dataset](./modules/bigquery-dataset) +- **data** - [GCS](./modules/gcs), [BigQuery dataset](./modules/bigquery-dataset), [Pub/Sub](./modules/pubsub) - **security** - [KMS](./modules/kms), [SecretManager](./modules/secret-manager) For more information and usage examples see each module's README file. From 411795ecf33b8891b6c47f2a867ec114dd5261cd Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 13 May 2020 10:53:43 +0200 Subject: [PATCH 014/129] Update README.md --- modules/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/README.md b/modules/README.md index 418ed65e..37a7bedb 100644 --- a/modules/README.md +++ b/modules/README.md @@ -42,6 +42,7 @@ Specific modules also offer support for non-authoritative bindings (e.g. `google - [BigQuery dataset](./bigquery-dataset) - [GCS](./gcs) +- [Pub/Sub](./modules/pubsub) ## Security From 4cf87d993afc190d7d3d300941fa9998fdda319d Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 13 May 2020 10:54:22 +0200 Subject: [PATCH 015/129] Update README.md --- modules/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/README.md b/modules/README.md index 37a7bedb..f0e57ebb 100644 --- a/modules/README.md +++ b/modules/README.md @@ -27,7 +27,7 @@ Specific modules also offer support for non-authoritative bindings (e.g. `google - [VPC peering](./net-vpc-peering) - [VPN static](./net-vpn-static) - [VPN dynamic](./net-vpn-dynamic) -- [VPN HA](./net-vpn-ha)) +- [VPN HA](./net-vpn-ha) - [ ] TODO: xLB modules ## Compute/Container From 008d0a9aabddfb2694daaae82c94bc920ca17e08 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 13 May 2020 15:54:06 +0200 Subject: [PATCH 016/129] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b2de888..eefec9cd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - Add output to `gke-cluster` exposing the cluster's CA certificate - Fix `gke-cluster` autoscaling options +- new `service-directory` module ## [1.5.0] - 2020-05-11 From a27695ae4d4ca0e7242f83da143987928886720a Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 13 May 2020 15:54:49 +0200 Subject: [PATCH 017/129] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 95a20dbd..b9770bd5 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ The current list of modules supports most of the core foundational and networkin Currently available modules: - **foundational** - [folders](./modules/folders), [log sinks](./modules/logging-sinks), [organization](./modules/organization), [project](./modules/project), [service accounts](./modules/iam-service-accounts) -- **networking** - [VPC](./modules/net-vpc), [VPC firewall](./modules/net-vpc-firewall), [VPC peering](./modules/net-vpc-peering), [VPN static](./modules/net-vpn-static), [VPN dynamic](./modules/net-vpn-dynamic), [VPN HA](./modules/net-vpn-ha), [NAT](./modules/net-cloudnat), [address reservation](./modules/net-address), [DNS](./modules/dns), [L4 ILB](./modules/net-ilb) +- **networking** - [VPC](./modules/net-vpc), [VPC firewall](./modules/net-vpc-firewall), [VPC peering](./modules/net-vpc-peering), [VPN static](./modules/net-vpn-static), [VPN dynamic](./modules/net-vpn-dynamic), [VPN HA](./modules/net-vpn-ha), [NAT](./modules/net-cloudnat), [address reservation](./modules/net-address), [DNS](./modules/dns), [L4 ILB](./modules/net-ilb), [Service Directory](./modules/service-directory) - **compute** - [VM/VM group](./modules/compute-vm), [MIG](./modules/compute-mig), [GKE cluster](./modules/gke-cluster), [GKE nodepool](./modules/gke-nodepool), [COS container](./modules/cos-container) (coredns, mysql, onprem, squid) - **data** - [GCS](./modules/gcs), [BigQuery dataset](./modules/bigquery-dataset), [Pub/Sub](./modules/pubsub) - **security** - [KMS](./modules/kms), [SecretManager](./modules/secret-manager) From b3cdca67de77b68e618a88f57f5136bbd0548875 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 13 May 2020 15:55:26 +0200 Subject: [PATCH 018/129] Update README.md --- modules/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/README.md b/modules/README.md index f0e57ebb..c6a31272 100644 --- a/modules/README.md +++ b/modules/README.md @@ -22,6 +22,7 @@ Specific modules also offer support for non-authoritative bindings (e.g. `google - [Cloud DNS](./dns) - [Cloud NAT](./net-cloudnat) - [L4 Internal Load Balancer](./net-ilb) +- [Service Directory](./service-directory) - [VPC](./net-vpc) - [VPC firewall](./net-vpc-firewall) - [VPC peering](./net-vpc-peering) From e7f92be88cac9a882ea2c9c4cbf78cef168a74a1 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 13 May 2020 15:56:15 +0200 Subject: [PATCH 019/129] Update CHANGELOG.md --- CHANGELOG.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index eefec9cd..2888ef6d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] -- Add output to `gke-cluster` exposing the cluster's CA certificate -- Fix `gke-cluster` autoscaling options +- add output to `gke-cluster` exposing the cluster's CA certificate +- xix `gke-cluster` autoscaling options +- add support for Service Directory bound zones to the `dns` module - new `service-directory` module ## [1.5.0] - 2020-05-11 From 65d6b7f1c33e70d99684e115f2dea17425c3a3bc Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 13 May 2020 15:56:26 +0200 Subject: [PATCH 020/129] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2888ef6d..a08ed592 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - add output to `gke-cluster` exposing the cluster's CA certificate -- xix `gke-cluster` autoscaling options +- fix `gke-cluster` autoscaling options - add support for Service Directory bound zones to the `dns` module - new `service-directory` module From dd365f6bb0e6ae228be2039b79a1669078daa1e6 Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Thu, 14 May 2020 19:05:55 +0200 Subject: [PATCH 021/129] Fix comment in shared VPC + GKE example --- infrastructure/shared-vpc-gke/main.tf | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/infrastructure/shared-vpc-gke/main.tf b/infrastructure/shared-vpc-gke/main.tf index 1c8d01bd..c958d36c 100644 --- a/infrastructure/shared-vpc-gke/main.tf +++ b/infrastructure/shared-vpc-gke/main.tf @@ -17,6 +17,7 @@ ############################################################################### # the container.hostServiceAgentUser role is needed for GKE on shared VPC +# see: https://cloud.google.com/kubernetes-engine/docs/how-to/cluster-shared-vpc#grant_host_service_agent_role module "project-host" { source = "../../modules/project" @@ -81,12 +82,6 @@ module "project-svc-gke" { # Networking # ################################################################################ -# the service project GKE robot needs the `hostServiceAgent` role throughout -# the entire life of its clusters; the `iam_project_id` project output is used -# here to set the project id so that the VPC depends on that binding, and any -# cluster using it then also depends on it indirectly; you can of course use -# the `project_id` output instead if you don't care about destroying - # subnet IAM bindings control which identities can use the individual subnets module "vpc-shared" { From 2946d2872744854698d366f330ad1ce5cc3cb628 Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Thu, 14 May 2020 20:48:29 +0200 Subject: [PATCH 022/129] Source repository module (#76) * Source repository module * Fix typos --- modules/source-repository/README.md | 38 ++++++++++++++++++++++++++ modules/source-repository/main.tf | 32 ++++++++++++++++++++++ modules/source-repository/outputs.tf | 25 +++++++++++++++++ modules/source-repository/variables.tf | 37 +++++++++++++++++++++++++ modules/source-repository/versions.tf | 19 +++++++++++++ 5 files changed, 151 insertions(+) create mode 100644 modules/source-repository/README.md create mode 100644 modules/source-repository/main.tf create mode 100644 modules/source-repository/outputs.tf create mode 100644 modules/source-repository/variables.tf create mode 100644 modules/source-repository/versions.tf diff --git a/modules/source-repository/README.md b/modules/source-repository/README.md new file mode 100644 index 00000000..c5a2eb85 --- /dev/null +++ b/modules/source-repository/README.md @@ -0,0 +1,38 @@ +# Google Cloud Source Repository Module + +This module allows managing a single Cloud Source Repository, including IAM bindings. + + +## Examples + +### Simple repository with IAM + +```hcl +module "repo" { + source e = "./modules/source-repository" + project_id = "my-project" + name = "my-repo" + iam_roles = ["roles/source.reader"] + iam_members = { + "roles/source.reader" = ["user:foo@example.com"] + } +} +``` + + +## Variables + +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| name | Repository topic name. | string | ✓ | | +| project_id | Project used for resources. | string | ✓ | | +| *iam_members* | IAM members for each topic role. | map(list(string)) | | {} | +| *iam_roles* | IAM roles for topic. | list(string) | | [] | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| id | Repository id. | | +| url | Repository URL. | | + diff --git a/modules/source-repository/main.tf b/modules/source-repository/main.tf new file mode 100644 index 00000000..810b4482 --- /dev/null +++ b/modules/source-repository/main.tf @@ -0,0 +1,32 @@ +/** + * Copyright 2020 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 "google_sourcerepo_repository" "default" { + project = var.project_id + name = var.name +} + +resource "google_sourcerepo_repository_iam_binding" "default" { + for_each = toset(var.iam_roles) + project = var.project_id + repository = google_sourcerepo_repository.default.name + role = each.value + members = lookup(var.iam_members, each.value, []) + + depends_on = [ + google_sourcerepo_repository.default + ] +} diff --git a/modules/source-repository/outputs.tf b/modules/source-repository/outputs.tf new file mode 100644 index 00000000..023c2672 --- /dev/null +++ b/modules/source-repository/outputs.tf @@ -0,0 +1,25 @@ +/** + * Copyright 2020 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 "id" { + description = "Repository id." + value = google_sourcerepo_repository.default.id +} + +output "url" { + description = "Repository URL." + value = google_sourcerepo_repository.default.url +} diff --git a/modules/source-repository/variables.tf b/modules/source-repository/variables.tf new file mode 100644 index 00000000..1725d4b4 --- /dev/null +++ b/modules/source-repository/variables.tf @@ -0,0 +1,37 @@ +/** + * Copyright 2020 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 = "Project used for resources." + type = string +} + +variable "iam_members" { + description = "IAM members for each topic role." + type = map(list(string)) + default = {} +} + +variable "iam_roles" { + description = "IAM roles for topic." + type = list(string) + default = [] +} + +variable "name" { + description = "Repository topic name." + type = string +} diff --git a/modules/source-repository/versions.tf b/modules/source-repository/versions.tf new file mode 100644 index 00000000..ce6918e0 --- /dev/null +++ b/modules/source-repository/versions.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2019 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_version = ">= 0.12.6" +} From 959d600271424fdc01a6bbb4cc41c965bf51e7b8 Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Thu, 14 May 2020 21:40:24 +0200 Subject: [PATCH 023/129] Add source-repositories to README.me --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index b9770bd5..d452917b 100644 --- a/README.md +++ b/README.md @@ -37,5 +37,6 @@ Currently available modules: - **compute** - [VM/VM group](./modules/compute-vm), [MIG](./modules/compute-mig), [GKE cluster](./modules/gke-cluster), [GKE nodepool](./modules/gke-nodepool), [COS container](./modules/cos-container) (coredns, mysql, onprem, squid) - **data** - [GCS](./modules/gcs), [BigQuery dataset](./modules/bigquery-dataset), [Pub/Sub](./modules/pubsub) - **security** - [KMS](./modules/kms), [SecretManager](./modules/secret-manager) +- **development** - [Cloud Source Repository](./modules/source-repository) For more information and usage examples see each module's README file. From 5c23418bb4c81434bfc69e46556752e297655517 Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Thu, 14 May 2020 21:41:20 +0200 Subject: [PATCH 024/129] Mention source-repository in CHANGELOG --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a08ed592..db4bba7d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. - fix `gke-cluster` autoscaling options - add support for Service Directory bound zones to the `dns` module - new `service-directory` module +- new `source-repository` module ## [1.5.0] - 2020-05-11 From 453f4e52b06a52bd1507657d14a7bf4c97ab6132 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 20 May 2020 16:21:41 +0200 Subject: [PATCH 025/129] Update CHANGELOG.md --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index db4bba7d..ddde6fba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file. ## [Unreleased] + +## [1.6.0] - 2020-05-20 + - add output to `gke-cluster` exposing the cluster's CA certificate - fix `gke-cluster` autoscaling options - add support for Service Directory bound zones to the `dns` module @@ -62,7 +65,8 @@ All notable changes to this project will be documented in this file. - merge development branch with suite of new modules and end-to-end examples -[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.5.0...HEAD +[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.6.0...HEAD +[1.6.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.5.0...v1.6.0 [1.5.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.4.1...v1.5.0 [1.4.1]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.4.0...v1.4.1 [1.4.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.3.0...v1.4.0 From 461662ad1db9719ccb987c3eaec171ee67ae97c4 Mon Sep 17 00:00:00 2001 From: lcaggio Date: Fri, 22 May 2020 12:30:24 +0200 Subject: [PATCH 026/129] First commit for Data Fusion module (#77) * First commit for Data Fusion module * Fix comments and improve ip_allocation logic. * Add example * generate variables and outputs table, fix example headings * update year in boilerplates * rename firewall variable, remove region from resource names Co-authored-by: Ludovico Magnocavallo --- modules/datafusion/README.md | 63 +++++++++++++++++++++ modules/datafusion/main.tf | 79 ++++++++++++++++++++++++++ modules/datafusion/outputs.tf | 45 +++++++++++++++ modules/datafusion/variables.tf | 99 +++++++++++++++++++++++++++++++++ modules/datafusion/versions.tf | 19 +++++++ 5 files changed, 305 insertions(+) create mode 100644 modules/datafusion/README.md create mode 100644 modules/datafusion/main.tf create mode 100644 modules/datafusion/outputs.tf create mode 100644 modules/datafusion/variables.tf create mode 100644 modules/datafusion/versions.tf diff --git a/modules/datafusion/README.md b/modules/datafusion/README.md new file mode 100644 index 00000000..75fddc65 --- /dev/null +++ b/modules/datafusion/README.md @@ -0,0 +1,63 @@ +# Google Cloud Data Fusion Module + +This module allows simple management of ['Google Data Fusion'](https://cloud.google.com/data-fusion) instances. It supports creating Basic or Enterprise, public or private instances. + +## Examples + +## Auto-managed IP allocation + +```hcl +module "datafusion" { + source = "./modules/datafusion" + name = "my-datafusion" + region = "europe-west1" + project_id = "my-project" + network = "my-network-name" +} +``` + +### Externally managed IP allocation + +```hcl +module "datafusion" { + source = "./modules/datafusion" + name = "my-datafusion" + region = "europe-west1" + project_id = "my-project" + network = "my-network-name" + ip_allocation_create = false + ip_allocation = "10.0.0.0/22" +} +``` + + +## Variables + +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| name | Name of the DataFusion instance. | string | ✓ | | +| network | Name of the network in the project with which the tenant project will be peered for executing pipelines in the form of projects/{project-id}/global/networks/{network} | string | ✓ | | +| project_id | Project ID. | string | ✓ | | +| region | DataFusion region. | string | ✓ | | +| *description* | DataFuzion instance description. | string | | Terraform managed. | +| *enable_stackdriver_logging* | Option to enable Stackdriver Logging. | bool | | false | +| *enable_stackdriver_monitoring* | Option to enable Stackdriver Monitorig. | bool | | false | +| *firewall_create* | Create Network firewall rules to enable SSH. | bool | | true | +| *ip_allocation* | Ip allocated for datafusion instance when not using the auto created one and created outside of the module. | string | | null | +| *ip_allocation_create* | Create Ip range for datafusion instance. | bool | | true | +| *labels* | The resource labels for instance to use to annotate any related underlying resources, such as Compute Engine VMs. | map(string) | | {} | +| *network_peering* | Create Network peering between project and DataFusion tenant project. | bool | | true | +| *private_instance* | Create private instance. | bool | | true | +| *type* | Datafusion Instance type. It can be BASIC or ENTERPRISE (default value). | string | | ENTERPRISE | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| id | DataFusion instance ID. | | +| ip_allocation | IP range reserved for Data Fusion instance in case of a private instance. | | +| resource | DataFusion resource. | | +| service_account | DataFusion Service Account. | | +| service_endpoint | DataFusion Service Endpoint. | | +| version | DataFusion version. | | + diff --git a/modules/datafusion/main.tf b/modules/datafusion/main.tf new file mode 100644 index 00000000..9161c013 --- /dev/null +++ b/modules/datafusion/main.tf @@ -0,0 +1,79 @@ +/** + * Copyright 2020 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 { + prefix_length = 22 + ip_allocation = ( + var.ip_allocation_create + ? "${google_compute_global_address.default[0].address}/${local.prefix_length}" + : var.ip_allocation + ) + tenant_project = regex( + "cloud-datafusion-management-sa@([\\w-]+).iam.gserviceaccount.com", + google_data_fusion_instance.default.service_account + )[0] +} + +resource "google_compute_global_address" "default" { + count = var.ip_allocation_create ? 1 : 0 + project = var.project_id + name = "cdf-${var.name}" + address_type = "INTERNAL" + purpose = "VPC_PEERING" + prefix_length = local.prefix_length + network = var.network +} + +resource "google_compute_network_peering" "default" { + count = var.network_peering == true ? 1 : 0 + name = "cdf-${var.name}" + network = "projects/${var.project_id}/global/networks/${var.network}" + peer_network = "projects/${local.tenant_project}/global/networks/${var.region}-${google_data_fusion_instance.default.name}" + export_custom_routes = true + import_custom_routes = true +} + +resource "google_compute_firewall" "default" { + count = var.firewall_create == true ? 1 : 0 + name = "${var.name}-allow-ssh" + project = var.project_id + network = var.network + source_ranges = [local.ip_allocation] + target_tags = ["${var.name}-allow-ssh"] + + allow { + protocol = "tcp" + ports = ["22"] + } +} + +resource "google_data_fusion_instance" "default" { + provider = google-beta + project = var.project_id + name = var.name + type = var.type + description = var.description + labels = var.labels + region = var.region + private_instance = var.private_instance + enable_stackdriver_logging = var.enable_stackdriver_logging + enable_stackdriver_monitoring = var.enable_stackdriver_monitoring + network_config { + network = var.network + ip_allocation = local.ip_allocation + } +} + diff --git a/modules/datafusion/outputs.tf b/modules/datafusion/outputs.tf new file mode 100644 index 00000000..92adf5e4 --- /dev/null +++ b/modules/datafusion/outputs.tf @@ -0,0 +1,45 @@ +/** + * Copyright 2020 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 "id" { + description = "DataFusion instance ID." + value = google_data_fusion_instance.default.id +} + +output "ip_allocation" { + description = "IP range reserved for Data Fusion instance in case of a private instance." + value = "${local.ip_allocation}" +} + +output "resource" { + description = "DataFusion resource." + value = google_data_fusion_instance.default +} + +output "service_account" { + description = "DataFusion Service Account." + value = google_data_fusion_instance.default.service_account +} + +output "service_endpoint" { + description = "DataFusion Service Endpoint." + value = google_data_fusion_instance.default.service_endpoint +} + +output "version" { + description = "DataFusion version." + value = google_data_fusion_instance.default.version +} diff --git a/modules/datafusion/variables.tf b/modules/datafusion/variables.tf new file mode 100644 index 00000000..f10a6e3f --- /dev/null +++ b/modules/datafusion/variables.tf @@ -0,0 +1,99 @@ +/** + * Copyright 2020 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. + */ + +############################################################################### +# DtaFusion variables # +############################################################################### + +variable "description" { + description = "DataFuzion instance description." + type = string + default = "Terraform managed." +} + +variable "enable_stackdriver_logging" { + description = "Option to enable Stackdriver Logging." + type = bool + default = false +} + +variable "enable_stackdriver_monitoring" { + description = "Option to enable Stackdriver Monitorig." + type = bool + default = false +} + +variable "labels" { + description = "The resource labels for instance to use to annotate any related underlying resources, such as Compute Engine VMs." + type = map(string) + default = {} +} + +variable "name" { + description = "Name of the DataFusion instance." + type = string +} + +variable "network" { + description = "Name of the network in the project with which the tenant project will be peered for executing pipelines in the form of projects/{project-id}/global/networks/{network}" + type = string +} + +variable "firewall_create" { + description = "Create Network firewall rules to enable SSH." + type = bool + default = true +} + +variable "network_peering" { + description = "Create Network peering between project and DataFusion tenant project." + type = bool + default = true +} + +variable "private_instance" { + description = "Create private instance." + type = bool + default = true +} + +variable "project_id" { + description = "Project ID." + type = string +} + +variable "region" { + description = "DataFusion region." + type = string +} + +variable "ip_allocation_create" { + description = "Create Ip range for datafusion instance." + type = bool + default = true +} + +variable "ip_allocation" { + description = "Ip allocated for datafusion instance when not using the auto created one and created outside of the module." + type = string + default = null +} + +variable "type" { + description = "Datafusion Instance type. It can be BASIC or ENTERPRISE (default value)." + type = string + default = "ENTERPRISE" +} diff --git a/modules/datafusion/versions.tf b/modules/datafusion/versions.tf new file mode 100644 index 00000000..bc4c2a9d --- /dev/null +++ b/modules/datafusion/versions.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2020 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_version = ">= 0.12.6" +} From a486827671d466352aa6ed05c567e454cd0abbd5 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Fri, 22 May 2020 12:31:12 +0200 Subject: [PATCH 027/129] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ddde6fba..8cec43b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ All notable changes to this project will be documented in this file. - add support for Service Directory bound zones to the `dns` module - new `service-directory` module - new `source-repository` module +- new `datafusion` module ## [1.5.0] - 2020-05-11 From 8934d6de255e8c8b656e9e9c96403554752ee90e Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Fri, 22 May 2020 12:31:29 +0200 Subject: [PATCH 028/129] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8cec43b2..4a38f235 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- new `datafusion` module + ## [1.6.0] - 2020-05-20 - add output to `gke-cluster` exposing the cluster's CA certificate @@ -11,7 +13,6 @@ All notable changes to this project will be documented in this file. - add support for Service Directory bound zones to the `dns` module - new `service-directory` module - new `source-repository` module -- new `datafusion` module ## [1.5.0] - 2020-05-11 From b75e6becf0bb11e5e46001673c88a8298bb96116 Mon Sep 17 00:00:00 2001 From: Chris Taylor Date: Fri, 22 May 2020 13:47:50 -0400 Subject: [PATCH 029/129] Correct the name used to reference the folders module (#78) --- modules/folders/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/folders/README.md b/modules/folders/README.md index b1568711..12375fdd 100644 --- a/modules/folders/README.md +++ b/modules/folders/README.md @@ -8,7 +8,7 @@ This module allow creation and management of sets of folders sharing a common pa ```hcl module "folder" { - source = "./modules/folder" + source = "./modules/folders" parent = "organizations/1234567890" names = ["Folder one", "Folder two] iam_members = { @@ -26,7 +26,7 @@ module "folder" { ```hcl module "folder" { - source = "./modules/folder" + source = "./modules/folders" parent = "organizations/1234567890" names = ["Folder one", "Folder two] policy_boolean = { From 4bf3a8146364055d5f26b0dbfa22878e35ecc81d Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Mon, 25 May 2020 11:35:18 +0200 Subject: [PATCH 030/129] Fix typo in folder README --- modules/folders/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/folders/README.md b/modules/folders/README.md index 12375fdd..456bd40a 100644 --- a/modules/folders/README.md +++ b/modules/folders/README.md @@ -10,7 +10,7 @@ This module allow creation and management of sets of folders sharing a common pa module "folder" { source = "./modules/folders" parent = "organizations/1234567890" - names = ["Folder one", "Folder two] + names = ["Folder one", "Folder two"] iam_members = { "Folder one" = { "roles/owner" => ["group:users@example.com"] From 0f291fbde33e97e27dc180495c1a054652470420 Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Tue, 26 May 2020 07:18:33 +0200 Subject: [PATCH 031/129] Add Container Registry module (#80) --- CHANGELOG.md | 1 + README.md | 2 +- modules/container-registry/README.md | 34 ++++++++++++++++++++++ modules/container-registry/main.tf | 27 ++++++++++++++++++ modules/container-registry/outputs.tf | 20 +++++++++++++ modules/container-registry/variables.tf | 38 +++++++++++++++++++++++++ modules/container-registry/versions.tf | 19 +++++++++++++ 7 files changed, 140 insertions(+), 1 deletion(-) create mode 100644 modules/container-registry/README.md create mode 100644 modules/container-registry/main.tf create mode 100644 modules/container-registry/outputs.tf create mode 100644 modules/container-registry/variables.tf create mode 100644 modules/container-registry/versions.tf diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a38f235..2f20cb2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - new `datafusion` module +- new `container-registry` module ## [1.6.0] - 2020-05-20 diff --git a/README.md b/README.md index d452917b..827e84f0 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,6 @@ Currently available modules: - **compute** - [VM/VM group](./modules/compute-vm), [MIG](./modules/compute-mig), [GKE cluster](./modules/gke-cluster), [GKE nodepool](./modules/gke-nodepool), [COS container](./modules/cos-container) (coredns, mysql, onprem, squid) - **data** - [GCS](./modules/gcs), [BigQuery dataset](./modules/bigquery-dataset), [Pub/Sub](./modules/pubsub) - **security** - [KMS](./modules/kms), [SecretManager](./modules/secret-manager) -- **development** - [Cloud Source Repository](./modules/source-repository) +- **development** - [Cloud Source Repository](./modules/source-repository), [Container Registry](./modules/container-registry) For more information and usage examples see each module's README file. diff --git a/modules/container-registry/README.md b/modules/container-registry/README.md new file mode 100644 index 00000000..aac0f02c --- /dev/null +++ b/modules/container-registry/README.md @@ -0,0 +1,34 @@ +# Google Cloud Container Registry Module + +This module simplifies the creation of GCS buckets used by Google Container Registry. + +## Example + +```hcl +module "container_registry" { + source = "../../modules/container-registry" + project_id = "myproject" + location = "EU" + iam_roles = ["roles/storage.admin"] + iam_members = { + "roles/storage.admin" = ["group:cicd@example.com"] + } +} +``` + + +## Variables + +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| project_id | Registry project id. | string | ✓ | | +| *iam_members* | Map of member lists used to set authoritative bindings, keyed by role. | map(list(string)) | | null | +| *iam_roles* | List of roles used to set authoritative bindings. | list(string) | | null | +| *location* | Bucket location. Can be US, EU, ASIA or empty | string | | | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| bucket_id | ID of the GCS bucket created | | + diff --git a/modules/container-registry/main.tf b/modules/container-registry/main.tf new file mode 100644 index 00000000..073e2995 --- /dev/null +++ b/modules/container-registry/main.tf @@ -0,0 +1,27 @@ +/** + * Copyright 2020 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 "google_container_registry" "registry" { + project = var.project_id + location = var.location +} + +resource "google_storage_bucket_iam_binding" "bindings" { + for_each = toset(var.iam_roles) + bucket = google_container_registry.registry.id + role = each.value + members = lookup(var.iam_members, each.value, []) +} diff --git a/modules/container-registry/outputs.tf b/modules/container-registry/outputs.tf new file mode 100644 index 00000000..cbd09710 --- /dev/null +++ b/modules/container-registry/outputs.tf @@ -0,0 +1,20 @@ +/** + * Copyright 2020 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 "bucket_id" { + description = "ID of the GCS bucket created" + value = google_container_registry.registry.id +} diff --git a/modules/container-registry/variables.tf b/modules/container-registry/variables.tf new file mode 100644 index 00000000..15074aca --- /dev/null +++ b/modules/container-registry/variables.tf @@ -0,0 +1,38 @@ +/** + * Copyright 2020 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 "iam_members" { + description = "Map of member lists used to set authoritative bindings, keyed by role." + type = map(list(string)) + default = null +} + +variable "iam_roles" { + description = "List of roles used to set authoritative bindings." + type = list(string) + default = null +} + +variable "location" { + description = "Registry location. Can be US, EU, ASIA or empty" + type = string + default = "" +} + +variable "project_id" { + description = "Registry project id." + type = string +} diff --git a/modules/container-registry/versions.tf b/modules/container-registry/versions.tf new file mode 100644 index 00000000..bc4c2a9d --- /dev/null +++ b/modules/container-registry/versions.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2020 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_version = ">= 0.12.6" +} From c3893d436effbc9199a839ad1fbe2766e18fac28 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Tue, 26 May 2020 07:19:24 +0200 Subject: [PATCH 032/129] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 827e84f0..e8b10d66 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Currently available modules: - **foundational** - [folders](./modules/folders), [log sinks](./modules/logging-sinks), [organization](./modules/organization), [project](./modules/project), [service accounts](./modules/iam-service-accounts) - **networking** - [VPC](./modules/net-vpc), [VPC firewall](./modules/net-vpc-firewall), [VPC peering](./modules/net-vpc-peering), [VPN static](./modules/net-vpn-static), [VPN dynamic](./modules/net-vpn-dynamic), [VPN HA](./modules/net-vpn-ha), [NAT](./modules/net-cloudnat), [address reservation](./modules/net-address), [DNS](./modules/dns), [L4 ILB](./modules/net-ilb), [Service Directory](./modules/service-directory) - **compute** - [VM/VM group](./modules/compute-vm), [MIG](./modules/compute-mig), [GKE cluster](./modules/gke-cluster), [GKE nodepool](./modules/gke-nodepool), [COS container](./modules/cos-container) (coredns, mysql, onprem, squid) -- **data** - [GCS](./modules/gcs), [BigQuery dataset](./modules/bigquery-dataset), [Pub/Sub](./modules/pubsub) +- **data** - [GCS](./modules/gcs), [BigQuery dataset](./modules/bigquery-dataset), [Pub/Sub](./modules/pubsub), [Datafusion](./modules/datafusion) - **security** - [KMS](./modules/kms), [SecretManager](./modules/secret-manager) - **development** - [Cloud Source Repository](./modules/source-repository), [Container Registry](./modules/container-registry) From de6b4515c2f31612099a5942070247b77286db6b Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Tue, 26 May 2020 07:21:52 +0200 Subject: [PATCH 033/129] Update README.md --- modules/README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/modules/README.md b/modules/README.md index c6a31272..9150f09a 100644 --- a/modules/README.md +++ b/modules/README.md @@ -42,8 +42,14 @@ Specific modules also offer support for non-authoritative bindings (e.g. `google ## Data - [BigQuery dataset](./bigquery-dataset) +- [Datafusion](./datafusion) - [GCS](./gcs) -- [Pub/Sub](./modules/pubsub) +- [Pub/Sub](./pubsub) + +## Development + +- [Container Registry](./container-registry) +- [Source Repository](./source-repository) ## Security From e1ad77c6d906f4b95389691c303004fb13a1a375 Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Tue, 26 May 2020 12:03:15 +0200 Subject: [PATCH 034/129] Add Artifact Registry module (#81) --- CHANGELOG.md | 1 + README.md | 2 +- modules/artifact-registry/README.md | 43 ++++++++++++++++++ modules/artifact-registry/main.tf | 35 +++++++++++++++ modules/artifact-registry/outputs.tf | 25 +++++++++++ modules/artifact-registry/variables.tf | 61 ++++++++++++++++++++++++++ modules/artifact-registry/versions.tf | 19 ++++++++ 7 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 modules/artifact-registry/README.md create mode 100644 modules/artifact-registry/main.tf create mode 100644 modules/artifact-registry/outputs.tf create mode 100644 modules/artifact-registry/variables.tf create mode 100644 modules/artifact-registry/versions.tf diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f20cb2a..16d91567 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. - new `datafusion` module - new `container-registry` module +- new `artifact-registry` module ## [1.6.0] - 2020-05-20 diff --git a/README.md b/README.md index e8b10d66..53aef3c6 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,6 @@ Currently available modules: - **compute** - [VM/VM group](./modules/compute-vm), [MIG](./modules/compute-mig), [GKE cluster](./modules/gke-cluster), [GKE nodepool](./modules/gke-nodepool), [COS container](./modules/cos-container) (coredns, mysql, onprem, squid) - **data** - [GCS](./modules/gcs), [BigQuery dataset](./modules/bigquery-dataset), [Pub/Sub](./modules/pubsub), [Datafusion](./modules/datafusion) - **security** - [KMS](./modules/kms), [SecretManager](./modules/secret-manager) -- **development** - [Cloud Source Repository](./modules/source-repository), [Container Registry](./modules/container-registry) +- **development** - [Cloud Source Repository](./modules/source-repository), [Container Registry](./modules/container-registry), [Artifact Registry](./modules/artifact-registry) For more information and usage examples see each module's README file. diff --git a/modules/artifact-registry/README.md b/modules/artifact-registry/README.md new file mode 100644 index 00000000..480ea23a --- /dev/null +++ b/modules/artifact-registry/README.md @@ -0,0 +1,43 @@ +# Google Cloud Artifact Registry Module + +This module simplifies the creation of repositories using Google Cloud Artifact Registry. + +Note: Artifact Registry is still in beta, hence this module currently uses the beta provider. + +## Example + +```hcl +module "docker_artifact_registry" { + source = "./modules/artifact-registry" + project_id = "myproject" + location = "europe-west1" + format = "DOCKER" + id = "myregistry" + iam_roles = ["roles/artifactregistry.admin"] + iam_members = { + "roles/artifactregistry.admin" = ["group:cicd@example.com"] + } +} +``` + + +## Variables + +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| id | Repository id | string | ✓ | | +| project_id | Registry project id. | string | ✓ | | +| *description* | An optional description for the repository | string | | Terraform-managed registry | +| *format* | Repository format. One of DOCKER or UNSPECIFIED | string | | DOCKER | +| *iam_members* | Map of member lists used to set authoritative bindings, keyed by role. | map(list(string)) | | {} | +| *iam_roles* | List of roles used to set authoritative bindings. | list(string) | | [] | +| *labels* | Labels to be attached to the registry. | map(string) | | {} | +| *location* | Registry location. Use `gcloud beta artifacts locations list' to get valid values | string | | | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| id | Repository id | | +| name | Repository name | | + diff --git a/modules/artifact-registry/main.tf b/modules/artifact-registry/main.tf new file mode 100644 index 00000000..81c366f4 --- /dev/null +++ b/modules/artifact-registry/main.tf @@ -0,0 +1,35 @@ +/** + * Copyright 2020 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 "google_artifact_registry_repository" "registry" { + provider = google-beta + project = var.project_id + location = var.location + description = var.description + format = var.format + labels = var.labels + repository_id = var.id +} + +resource "google_artifact_registry_repository_iam_binding" "bindings" { + provider = google-beta + for_each = toset(var.iam_roles) + project = var.project_id + location = google_artifact_registry_repository.registry.location + repository = google_artifact_registry_repository.registry.name + role = each.value + members = lookup(var.iam_members, each.value, []) +} diff --git a/modules/artifact-registry/outputs.tf b/modules/artifact-registry/outputs.tf new file mode 100644 index 00000000..5800cb3f --- /dev/null +++ b/modules/artifact-registry/outputs.tf @@ -0,0 +1,25 @@ +/** + * Copyright 2020 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 "id" { + description = "Repository id" + value = google_artifact_registry_repository.registry.id +} + +output "name" { + description = "Repository name" + value = google_artifact_registry_repository.registry.name +} diff --git a/modules/artifact-registry/variables.tf b/modules/artifact-registry/variables.tf new file mode 100644 index 00000000..7aa8fdca --- /dev/null +++ b/modules/artifact-registry/variables.tf @@ -0,0 +1,61 @@ +/** + * Copyright 2020 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 "iam_members" { + description = "Map of member lists used to set authoritative bindings, keyed by role." + type = map(list(string)) + default = {} +} + +variable "iam_roles" { + description = "List of roles used to set authoritative bindings." + type = list(string) + default = [] +} + +variable "location" { + description = "Registry location. Use `gcloud beta artifacts locations list' to get valid values" + type = string + default = "" +} + +variable "project_id" { + description = "Registry project id." + type = string +} + +variable "labels" { + description = "Labels to be attached to the registry." + type = map(string) + default = {} +} + +variable "format" { + description = "Repository format. One of DOCKER or UNSPECIFIED" + type = string + default = "DOCKER" +} + +variable "description" { + description = "An optional description for the repository" + type = string + default = "Terraform-managed registry" +} + +variable "id" { + description = "Repository id" + type = string +} diff --git a/modules/artifact-registry/versions.tf b/modules/artifact-registry/versions.tf new file mode 100644 index 00000000..bc4c2a9d --- /dev/null +++ b/modules/artifact-registry/versions.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2020 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_version = ">= 0.12.6" +} From f8cbfe9fbfe3d3f48f20f5cd3cd480b7807dcb5f Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Tue, 26 May 2020 12:10:02 +0200 Subject: [PATCH 035/129] Update README.md --- modules/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/README.md b/modules/README.md index 9150f09a..b95c87d4 100644 --- a/modules/README.md +++ b/modules/README.md @@ -48,6 +48,7 @@ Specific modules also offer support for non-authoritative bindings (e.g. `google ## Development +- [Artifact Registry](./artifact-registry) - [Container Registry](./container-registry) - [Source Repository](./source-repository) From 840607d837859e244283248785e1066b3eeda2dd Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Tue, 26 May 2020 12:11:27 +0200 Subject: [PATCH 036/129] Fix another typo in GCS README --- modules/folders/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/folders/README.md b/modules/folders/README.md index 456bd40a..24117707 100644 --- a/modules/folders/README.md +++ b/modules/folders/README.md @@ -28,7 +28,7 @@ module "folder" { module "folder" { source = "./modules/folders" parent = "organizations/1234567890" - names = ["Folder one", "Folder two] + names = ["Folder one", "Folder two"] policy_boolean = { "constraints/compute.disableGuestAttributesAccess" = true "constraints/compute.skipDefaultNetworkCreation" = true From e2004d0c0d30e342cdf076fd76aff7f2dbe2baab Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Fri, 29 May 2020 08:07:08 +0200 Subject: [PATCH 037/129] Update README.md --- modules/pubsub/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/pubsub/README.md b/modules/pubsub/README.md index 5a1b05e9..30a6e0e0 100644 --- a/modules/pubsub/README.md +++ b/modules/pubsub/README.md @@ -20,6 +20,7 @@ module "pubsub" { "roles/pubsub.viewer" = ["group:foo@example.com"] "roles/pubsub.subscriber" = ["user:user1@example.com"] } +} ``` ### Subscriptions From 133623dee927c2ed0fbfd8a3fe7dbe82a415ba45 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Fri, 29 May 2020 08:08:09 +0200 Subject: [PATCH 038/129] Update README.md --- modules/pubsub/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/pubsub/README.md b/modules/pubsub/README.md index 30a6e0e0..4b672760 100644 --- a/modules/pubsub/README.md +++ b/modules/pubsub/README.md @@ -10,7 +10,7 @@ This module allows managing a single Pub/Sub topic, including multiple subscript ```hcl module "pubsub" { source = "./modules/pubsub" - project_id = "my-project + project_id = "my-project" name = "my-topic" iam_roles = [ "roles/pubsub.viewer", From 476c41d33343346f50357ca89412abcd4e086bdb Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Fri, 29 May 2020 08:25:51 +0200 Subject: [PATCH 039/129] Update README.md --- modules/bigquery-dataset/README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/modules/bigquery-dataset/README.md b/modules/bigquery-dataset/README.md index 427d89a8..20f946c0 100644 --- a/modules/bigquery-dataset/README.md +++ b/modules/bigquery-dataset/README.md @@ -20,7 +20,7 @@ The access variables are split into `access_roles` and `access_identities` varia ```hcl module "bigquery-dataset" { source = "./modules/bigquery-dataset" - project_id = "my-project + project_id = "my-project" id = "my-dataset" access_roles = { reader-group = { role = "READER", type = "group_by_email" } @@ -40,7 +40,7 @@ Dataset options are set via the `options` variable. all options must be specifie ```hcl module "bigquery-dataset" { source = "./modules/bigquery-dataset" - project_id = "my-project + project_id = "my-project" id = "my-dataset" options = { default_table_expiration_ms = 3600000 @@ -57,7 +57,7 @@ Tables are created via the `tables` variable, or the `view` variable for views. ```hcl module "bigquery-dataset" { source = "./modules/bigquery-dataset" - project_id = "my-project + project_id = "my-project" id = "my-dataset" tables = { table_a = { @@ -76,7 +76,7 @@ If partitioning is needed, populate the `partitioning` variable using either the ```hcl module "bigquery-dataset" { source = "./modules/bigquery-dataset" - project_id = "my-project + project_id = "my-project" id = "my-dataset" tables = { table_a = { @@ -99,7 +99,7 @@ To create views use the `view` variable. If you're querying a table created by t ```hcl module "bigquery-dataset" { source = "./modules/bigquery-dataset" - project_id = "my-project + project_id = "my-project" id = "my-dataset" tables = { table_a = { From 7f40aba4cd90786af2d3515a4839a873995ba28d Mon Sep 17 00:00:00 2001 From: lcaggio Date: Sat, 30 May 2020 08:57:21 +0200 Subject: [PATCH 040/129] Support Cloud KMS on Compute-VM module + Fixes (#79) * * Add support to KMS disk encryption (boot and attached) * Fix Instance Group Example * Fix * * Fix image boot disk * Add example with disk encryption * Fix Title * Improve logic * Fix Readme Fix viariable description * Update README.md * update README variables/outputs table * add change to CHANGELOG Co-authored-by: Ludovico Magnocavallo --- CHANGELOG.md | 1 + modules/compute-vm/README.md | 51 +++++++++++++++++++++++++++++++-- modules/compute-vm/main.tf | 10 +++++++ modules/compute-vm/variables.tf | 10 +++++++ 4 files changed, 69 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16d91567..3b3d0bb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- add support for disk encryption to the `compute-vm` module - new `datafusion` module - new `container-registry` module - new `artifact-registry` module diff --git a/modules/compute-vm/README.md b/modules/compute-vm/README.md index 14fb10dc..4e37dc7e 100644 --- a/modules/compute-vm/README.md +++ b/modules/compute-vm/README.md @@ -31,12 +31,57 @@ module "simple-vm-example" { } ``` +### Disk encryption with Cloud KMS + +This example shows how to control disk encryption via the the `encryption` variable, in this case the self link to a KMS CryptoKey that will be used to encrypt boot and attached disk. Managing the key with the `../kms` module is of course possible, but is not shown here. + +```hcl +module "kms-vm-example" { + source = "../modules/compute-vm" + project_id = local.project_id + region = local.region + zone = local.zone + name = "kms-test" + network_interfaces = [{ + network = local.network_self_link, + subnetwork = local.subnet_self_link, + nat = false, + addresses = null + }] + attached_disks = [ + { + name = "attached-disk" + size = 10 + image = null + options = { + auto_delete = true + mode = null + source = null + type = null + } + } + ] + service_account_create = true + instance_count = 1 + boot_disk = { + image = "projects/debian-cloud/global/images/family/debian-10" + type = "pd-ssd" + size = 10 + } + encryption = { + encrypt_boot = true + disk_encryption_key_raw = null + kms_key_self_link = local.kms_key.self_link + } +} +``` + ### Instance template This example shows how to use the module to manage an instance template that defines an additional attached disk for each instance, and overrides defaults for the boot disk image and service account. ```hcl -module "debian-test" { +module "cos-test" { source = "../modules/compute-vm" project_id = "my-project" region = "europe-west1" @@ -86,11 +131,10 @@ module "instance-group" { } service_account = local.service_account_email service_account_scopes = ["https://www.googleapis.com/auth/cloud-platform"] - use_instance_template = true metadata = { user-data = local.cloud_config } - group = {} + group = { named_ports = {} } } ``` @@ -108,6 +152,7 @@ module "instance-group" { | *attached_disk_defaults* | Defaults for attached disks options. | object({...}) | | ... | | *attached_disks* | Additional disks, if options is null defaults will be used in its place. | list(object({...})) | | [] | | *boot_disk* | Boot disk properties. | object({...}) | | ... | +| *encryption* | Encryption options. Only one of kms_key_self_link and disk_encryption_key_raw may be set. If needed, you can specify to encrypt or not the boot disk. | object({...}) | | null | | *group* | Define this variable to create an instance group for instances. Disabled for template use. | object({...}) | | null | | *hostname* | Instance FQDN name. | string | | null | | *instance_count* | Number of instances to create (only for non-template usage). | number | | 1 | diff --git a/modules/compute-vm/main.tf b/modules/compute-vm/main.tf index e97d576c..7542e114 100644 --- a/modules/compute-vm/main.tf +++ b/modules/compute-vm/main.tf @@ -66,6 +66,14 @@ resource "google_compute_disk" "disks" { disk_type = local.attached_disks[each.value.disk_name].options.type image = local.attached_disks[each.value.disk_name].image }) + dynamic disk_encryption_key { + for_each = var.encryption != null ? [""] : [] + + content { + raw_key = var.encryption.disk_encryption_key_raw + kms_key_self_link = var.encryption.kms_key_self_link + } + } } resource "google_compute_instance" "default" { @@ -103,6 +111,8 @@ resource "google_compute_instance" "default" { image = var.boot_disk.image size = var.boot_disk.size } + disk_encryption_key_raw = var.encryption != null ? var.encryption.disk_encryption_key_raw : null + kms_key_self_link = var.encryption != null ? var.encryption.kms_key_self_link : null } dynamic network_interface { diff --git a/modules/compute-vm/variables.tf b/modules/compute-vm/variables.tf index 3593fef2..0470290d 100644 --- a/modules/compute-vm/variables.tf +++ b/modules/compute-vm/variables.tf @@ -60,6 +60,16 @@ variable "boot_disk" { } } +variable "encryption" { + description = "Encryption options. Only one of kms_key_self_link and disk_encryption_key_raw may be set. If needed, you can specify to encrypt or not the boot disk." + type = object({ + encrypt_boot = bool + disk_encryption_key_raw = string + kms_key_self_link = string + }) + default = null +} + variable "group" { description = "Define this variable to create an instance group for instances. Disabled for template use." type = object({ From 037c14ef0985fad285b04c715a1894afc01f2d55 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Sat, 30 May 2020 08:59:08 +0200 Subject: [PATCH 041/129] Update CHANGELOG.md --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3b3d0bb5..bbc49afd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [1.7.0] - 2020-05-30 + - add support for disk encryption to the `compute-vm` module - new `datafusion` module - new `container-registry` module @@ -70,7 +72,8 @@ All notable changes to this project will be documented in this file. - merge development branch with suite of new modules and end-to-end examples -[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.6.0...HEAD +[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.7.0...HEAD +[1.7.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.6.0...v1.7.0 [1.6.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.5.0...v1.6.0 [1.5.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.4.1...v1.5.0 [1.4.1]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.4.0...v1.4.1 From aaa80bb49b3cc73dead0c9a0e06a11dd04a43d8b Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Sun, 31 May 2020 09:39:03 +0200 Subject: [PATCH 042/129] refactor service account module outputs --- modules/iam-service-accounts/main.tf | 27 ++------ modules/iam-service-accounts/outputs.tf | 23 +++++-- modules/iam-service-accounts/variables.tf | 34 +++++----- .../modules/iam_service_accounts/__init__.py | 13 ++++ .../iam_service_accounts/fixture/main.tf | 30 +++++++++ .../iam_service_accounts/fixture/variables.tf | 65 +++++++++++++++++++ .../modules/iam_service_accounts/test_plan.py | 51 +++++++++++++++ 7 files changed, 196 insertions(+), 47 deletions(-) create mode 100644 tests/modules/iam_service_accounts/__init__.py create mode 100644 tests/modules/iam_service_accounts/fixture/main.tf create mode 100644 tests/modules/iam_service_accounts/fixture/variables.tf create mode 100644 tests/modules/iam_service_accounts/test_plan.py diff --git a/modules/iam-service-accounts/main.tf b/modules/iam-service-accounts/main.tf index 21524fa3..12f6e128 100644 --- a/modules/iam-service-accounts/main.tf +++ b/modules/iam-service-accounts/main.tf @@ -54,32 +54,13 @@ locals { ] ] ]) - keys = ( - var.generate_keys - ? { - for name in var.names : - name => lookup(google_service_account_key.keys, name, null) - } - : {} - ) - prefix = ( - var.prefix != "" - ? "${var.prefix}-" - : "" - ) - resource = ( - length(var.names) > 0 - ? lookup(local.resources, var.names[0], null) - : null - ) + keys = var.generate_keys ? google_service_account_key.keys : {} + prefix = var.prefix != null ? "${var.prefix}-" : "" + resource = try(google_service_account.service_accounts[var.names[0]], null) resource_iam_emails = { - for name, resource in local.resources : + for name, resource in google_service_account.service_accounts : name => "serviceAccount:${resource.email}" } - resources = { - for name in var.names : - name => lookup(google_service_account.service_accounts, name, null) - } } resource "google_service_account" "service_accounts" { diff --git a/modules/iam-service-accounts/outputs.tf b/modules/iam-service-accounts/outputs.tf index 9901675e..530ccd1c 100644 --- a/modules/iam-service-accounts/outputs.tf +++ b/modules/iam-service-accounts/outputs.tf @@ -21,27 +21,30 @@ output "service_account" { output "service_accounts" { description = "Service account resources." - value = local.resources + value = google_service_account.service_accounts } output "email" { description = "Service account email (for single use)." - value = local.resource == null ? null : local.resource.email + value = try(local.resource.email, null) } output "iam_email" { description = "IAM-format service account email (for single use)." - value = local.resource == null ? null : "serviceAccount:${local.resource.email}" + value = try("serviceAccount:${local.resource.email}", null) } output "key" { description = "Service account key (for single use)." - value = lookup(local.keys, var.names[0], null) + value = try(local.keys[var.names[0]], null) } output "emails" { description = "Service account emails." - value = { for name, resource in local.resources : name => resource.email } + value = { + for name, resource in google_service_account.service_accounts : + name => resource.email + } } output "iam_emails" { @@ -51,12 +54,18 @@ output "iam_emails" { output "emails_list" { description = "Service account emails." - value = [for name, resource in local.resources : resource.email] + value = [ + for name, resource in google_service_account.service_accounts : + resource.email + ] } output "iam_emails_list" { description = "IAM-format service account emails." - value = [for name, resource in local.resources : "serviceAccount:${resource.email}"] + value = [ + for name, resource in google_service_account.service_accounts : + "serviceAccount:${resource.email}" + ] } output "keys" { diff --git a/modules/iam-service-accounts/variables.tf b/modules/iam-service-accounts/variables.tf index 60e0ed5f..adcdc671 100644 --- a/modules/iam-service-accounts/variables.tf +++ b/modules/iam-service-accounts/variables.tf @@ -20,23 +20,6 @@ variable "generate_keys" { default = false } -variable "names" { - description = "Names of the service accounts to create." - type = list(string) - default = [] -} - -variable "prefix" { - description = "Prefix applied to service account names." - type = string - default = "" -} - -variable "project_id" { - description = "Project id where service account will be created." - type = string -} - variable "iam_members" { description = "Map of member lists which are granted authoritative roles on the service accounts, keyed by role." type = map(list(string)) @@ -78,3 +61,20 @@ variable "iam_storage_roles" { type = map(list(string)) default = {} } + +variable "names" { + description = "Names of the service accounts to create." + type = list(string) + default = [] +} + +variable "prefix" { + description = "Prefix applied to service account names." + type = string + default = null +} + +variable "project_id" { + description = "Project id where service account will be created." + type = string +} diff --git a/tests/modules/iam_service_accounts/__init__.py b/tests/modules/iam_service_accounts/__init__.py new file mode 100644 index 00000000..6913f02e --- /dev/null +++ b/tests/modules/iam_service_accounts/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2020 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. diff --git a/tests/modules/iam_service_accounts/fixture/main.tf b/tests/modules/iam_service_accounts/fixture/main.tf new file mode 100644 index 00000000..69188086 --- /dev/null +++ b/tests/modules/iam_service_accounts/fixture/main.tf @@ -0,0 +1,30 @@ +/** + * Copyright 2020 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 "test" { + source = "../../../../modules/iam-service-accounts" + project_id = var.project_id + names = ["sa-one", "sa-two", "sa-three"] + prefix = var.prefix + generate_keys = var.generate_keys + iam_members = var.iam_members + iam_roles = var.iam_roles + iam_billing_roles = var.iam_billing_roles + iam_folder_roles = var.iam_folder_roles + iam_organization_roles = var.iam_organization_roles + iam_project_roles = var.iam_project_roles + iam_storage_roles = var.iam_storage_roles +} diff --git a/tests/modules/iam_service_accounts/fixture/variables.tf b/tests/modules/iam_service_accounts/fixture/variables.tf new file mode 100644 index 00000000..0a784a94 --- /dev/null +++ b/tests/modules/iam_service_accounts/fixture/variables.tf @@ -0,0 +1,65 @@ +/** + * Copyright 2020 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 "generate_keys" { + type = bool + default = false +} + +variable "iam_members" { + type = map(list(string)) + default = {} +} + +variable "iam_roles" { + type = list(string) + default = [] +} + +variable "iam_billing_roles" { + type = map(list(string)) + default = {} +} + +variable "iam_folder_roles" { + type = map(list(string)) + default = {} +} + +variable "iam_organization_roles" { + type = map(list(string)) + default = {} +} + +variable "iam_project_roles" { + type = map(list(string)) + default = {} +} + +variable "iam_storage_roles" { + type = map(list(string)) + default = {} +} + +variable "prefix" { + type = string + default = null +} + +variable "project_id" { + type = string + default = "my-project" +} diff --git a/tests/modules/iam_service_accounts/test_plan.py b/tests/modules/iam_service_accounts/test_plan.py new file mode 100644 index 00000000..dbcb2bef --- /dev/null +++ b/tests/modules/iam_service_accounts/test_plan.py @@ -0,0 +1,51 @@ +# Copyright 2020 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. + + +import os +import pytest + + +FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture') + + +def test_resources(plan_runner): + "Test service account resource." + _, resources = plan_runner(FIXTURES_DIR) + assert len(resources) == 3 + assert set(r['type'] for r in resources) == set(['google_service_account']) + assert set(r['values']['account_id'] for r in resources) == set([ + 'sa-one', 'sa-two', 'sa-three' + ]) + _, resources = plan_runner(FIXTURES_DIR, prefix='foo') + assert set(r['values']['account_id'] for r in resources) == set([ + 'foo-sa-one', 'foo-sa-two', 'foo-sa-three' + ]) + + +def test_iam_roles(plan_runner): + "Test iam roles with no memmbers." + _, resources = plan_runner(FIXTURES_DIR, + iam_roles='["roles/iam.serviceAccountUser"]') + assert len(resources) == 6 + iam_resources = [r for r in resources if r['type'] + != 'google_service_account'] + assert len(iam_resources) == 3 + assert set(r['type'] for r in iam_resources) == set( + ['google_service_account_iam_binding']) + assert [r['index'] for r in iam_resources] == [ + 'sa-one-roles/iam.serviceAccountUser', + 'sa-three-roles/iam.serviceAccountUser', + 'sa-two-roles/iam.serviceAccountUser', + ] From 6b0b147e7ecc068ef9408849c13cb8c01594fe7a Mon Sep 17 00:00:00 2001 From: "T.V.VIGNESH" Date: Mon, 1 Jun 2020 11:27:14 +0530 Subject: [PATCH 043/129] Added PD CSI Driver Addon support (#84) * Added PD CSI Driver Addon support Google supports CSI Driver for PD (https://cloud.google.com/kubernetes-engine/docs/how-to/gce-pd-csi-driver) which is also supported by TF Google Beta Provider (https://www.terraform.io/docs/providers/google/r/container_cluster.html#gce_persistent_disk_csi_driver_config). Added the same support to this module. * Added PD CSI Config to variables The PD CSI config has been added to variables to support PD CSI Driver (https://www.terraform.io/docs/providers/google/r/container_cluster.html#gce_persistent_disk_csi_driver_config) --- modules/gke-cluster/main.tf | 3 +++ modules/gke-cluster/variables.tf | 2 ++ 2 files changed, 5 insertions(+) diff --git a/modules/gke-cluster/main.tf b/modules/gke-cluster/main.tf index d08ea0d8..86fe095a 100644 --- a/modules/gke-cluster/main.tf +++ b/modules/gke-cluster/main.tf @@ -75,6 +75,9 @@ resource "google_container_cluster" "cluster" { disabled = ! var.addons.istio_config.enabled auth = var.addons.istio_config.tls ? "AUTH_MUTUAL_TLS" : "AUTH_NONE" } + gce_persistent_disk_csi_driver_config { + enabled = var.addons.gce_persistent_disk_csi_driver_config + } } # TODO(ludomagno): support setting address ranges instead of range names diff --git a/modules/gke-cluster/variables.tf b/modules/gke-cluster/variables.tf index 270a20f2..62b3709c 100644 --- a/modules/gke-cluster/variables.tf +++ b/modules/gke-cluster/variables.tf @@ -26,6 +26,7 @@ variable "addons" { tls = bool }) network_policy_config = bool + gce_persistent_disk_csi_driver_config = bool }) default = { cloudrun_config = false @@ -37,6 +38,7 @@ variable "addons" { tls = false } network_policy_config = false + gce_persistent_disk_csi_driver_config = false } } From 1a6bb8dad3aa4c22515343b82094230b52f4673b Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 1 Jun 2020 07:58:24 +0200 Subject: [PATCH 044/129] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index bbc49afd..f96293c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- add support for PD CSI driver in GKE module + ## [1.7.0] - 2020-05-30 - add support for disk encryption to the `compute-vm` module From 778362cf955dcb98856ce1ab8d4f0adf5e40b5b7 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 1 Jun 2020 09:32:47 +0200 Subject: [PATCH 045/129] Better service account outputs in project module (#82) * rationalize project module product service accounts output * fix typos in shared vpc example service accounts * add extra robot service accounts * update CHANGELOG --- CHANGELOG.md | 1 + infrastructure/shared-vpc-gke/main.tf | 10 +++---- modules/project/README.md | 5 +--- modules/project/main.tf | 4 --- modules/project/outputs.tf | 30 ++++++--------------- modules/project/service_accounts.tf | 39 +++++++++++++++++++++++++++ 6 files changed, 54 insertions(+), 35 deletions(-) create mode 100644 modules/project/service_accounts.tf diff --git a/CHANGELOG.md b/CHANGELOG.md index f96293c4..f4fef4a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- **incompatible change** robot and default service accounts outputs in the `project` module have been refactored and are now exposed via a single `service_account` output (cf [#82]) - add support for PD CSI driver in GKE module ## [1.7.0] - 2020-05-30 diff --git a/infrastructure/shared-vpc-gke/main.tf b/infrastructure/shared-vpc-gke/main.tf index c958d36c..6d8ff1e2 100644 --- a/infrastructure/shared-vpc-gke/main.tf +++ b/infrastructure/shared-vpc-gke/main.tf @@ -31,7 +31,7 @@ module "project-host" { ] iam_members = { "roles/container.hostServiceAgentUser" = [ - "serviceAccount:${module.project-svc-gke.gke_service_account}" + "serviceAccount:${module.project-svc-gke.service_accounts.robots.container-engine}" ] "roles/owner" = var.owners_host } @@ -117,16 +117,16 @@ module "vpc-shared" { iam_members = { "${var.region}/gce" = { "roles/compute.networkUser" = concat(var.owners_gce, [ - "serviceAccount:${module.project-svc-gce.cloudsvc_service_account}", + "serviceAccount:${module.project-svc-gce.service_accounts.cloud_services}", ]) } "${var.region}/gke" = { "roles/compute.networkUser" = concat(var.owners_gke, [ - "serviceAccount:${module.project-svc-gke.cloudsvc_service_account}", - "serviceAccount:${module.project-svc-gke.gke_service_account}", + "serviceAccount:${module.project-svc-gke.service_accounts.cloud_services}", + "serviceAccount:${module.project-svc-gke.service_accounts.robots.container-engine}", ]) "roles/compute.securityAdmin" = [ - "serviceAccount:${module.project-svc-gke.gke_service_account}", + "serviceAccount:${module.project-svc-gke.service_accounts.robots.container-engine}", ] } } diff --git a/modules/project/README.md b/modules/project/README.md index 582b7b29..9ab49796 100644 --- a/modules/project/README.md +++ b/modules/project/README.md @@ -80,12 +80,9 @@ module "project" { | name | description | sensitive | |---|---|:---:| -| cloudsvc_service_account | Cloud services service account. | | | custom_roles | Ids of the created custom roles. | | -| gce_service_account | Default GCE service account. | | -| gcr_service_account | Default GCR service account. | | -| gke_service_account | Default GKE service account. | | | name | Project ame. | | | number | Project number. | | | project_id | Project id. | | +| service_accounts | Product robot service accounts in project. | | diff --git a/modules/project/main.tf b/modules/project/main.tf index 7e4aaeb0..5ccee12e 100644 --- a/modules/project/main.tf +++ b/modules/project/main.tf @@ -15,10 +15,6 @@ */ locals { - cloudsvc_service_account = "${google_project.project.number}@cloudservices.gserviceaccount.com" - gce_service_account = "${google_project.project.number}-compute@developer.gserviceaccount.com" - gcr_service_account = "service-${google_project.project.number}@containerregistry.iam.gserviceaccount.com" - gke_service_account = "service-${google_project.project.number}@container-engine-robot.iam.gserviceaccount.com" iam_additive_pairs = flatten([ for role in var.iam_additive_roles : [ for member in lookup(var.iam_additive_members, role, []) : diff --git a/modules/project/outputs.tf b/modules/project/outputs.tf index c0751677..67c9af68 100644 --- a/modules/project/outputs.tf +++ b/modules/project/outputs.tf @@ -44,28 +44,14 @@ output "number" { ] } -output "cloudsvc_service_account" { - description = "Cloud services service account." - value = "${local.cloudsvc_service_account}" - depends_on = [google_project_service.project_services] -} - -output "gce_service_account" { - description = "Default GCE service account." - value = local.gce_service_account - depends_on = [google_project_service.project_services] -} - -output "gcr_service_account" { - description = "Default GCR service account." - value = local.gcr_service_account - depends_on = [google_project_service.project_services] -} - -output "gke_service_account" { - description = "Default GKE service account." - value = local.gke_service_account - depends_on = [google_project_service.project_services] +output "service_accounts" { + description = "Product robot service accounts in project." + value = { + cloud_services = local.service_account_cloud_services + default = local.service_accounts_default + robots = local.service_accounts_robots + } + depends_on = [google_project_service.project_services] } output "custom_roles" { diff --git a/modules/project/service_accounts.tf b/modules/project/service_accounts.tf new file mode 100644 index 00000000..d0ccee65 --- /dev/null +++ b/modules/project/service_accounts.tf @@ -0,0 +1,39 @@ +/** + * Copyright 2020 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 { + service_account_cloud_services = "${google_project.project.number}@cloudservices.gserviceaccount.com" + service_accounts_default = { + compute = "${google_project.project.number}-compute@developer.gserviceaccount.com" + gae = "${google_project.project.project_id}@appspot.gserviceaccount.com" + } + service_accounts_robot_services = { + cloudasset = "gcp-sa-cloudasset" + cloudbuild = "gcp-sa-cloudbuild" + compute = "compute-system" + container-engine = "container-engine-robot" + containerregistry = "containerregistry" + dataproc = "dataproc-accounts" + gae-flex = "gae-api-prod" + gcf = "gcf-admin-robot" + pubsub = "gcp-sa-pubsub" + storage = "gs-project-accounts" + } + service_accounts_robots = { + for service, name in local.service_accounts_robot_services : + service => "service-${google_project.project.number}@${name}.iam.gserviceaccount.com" + } +} From 09964147733b6d23e1a882473804437af3637eef Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 1 Jun 2020 09:36:07 +0200 Subject: [PATCH 046/129] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4fef4a0..29af43c2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] -- **incompatible change** robot and default service accounts outputs in the `project` module have been refactored and are now exposed via a single `service_account` output (cf [#82]) +- **incompatible change** robot and default service accounts outputs in the `project` module have been refactored and are now exposed via a single `service_account` output (see PR #82) - add support for PD CSI driver in GKE module ## [1.7.0] - 2020-05-30 From 682764a9113506b492c1aa5ce876b8500dbf9be3 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 1 Jun 2020 09:37:07 +0200 Subject: [PATCH 047/129] Update CHANGELOG.md --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29af43c2..ba987548 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] -- **incompatible change** robot and default service accounts outputs in the `project` module have been refactored and are now exposed via a single `service_account` output (see PR #82) +- **incompatible change** robot and default service accounts outputs in the `project` module have been refactored and are now exposed via a single `service_account` output (cf [#82]) - add support for PD CSI driver in GKE module ## [1.7.0] - 2020-05-30 @@ -85,3 +85,4 @@ All notable changes to this project will be documented in this file. [1.2.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.1...v1.2 [1.1.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.0...v1.1 [1.0.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v0.1...v1.0 +[#82]: https://github.com/terraform-google-modules/cloud-foundation-fabric/pull/82 From 947cdc0aaa856607318b4296fa20c0c44efa8f1b Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 1 Jun 2020 11:43:43 +0200 Subject: [PATCH 048/129] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ba987548..ff208fed 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. - **incompatible change** robot and default service accounts outputs in the `project` module have been refactored and are now exposed via a single `service_account` output (cf [#82]) - add support for PD CSI driver in GKE module +- refactor [iam-service-accounts] module outputs to be more resilient ## [1.7.0] - 2020-05-30 From cd70dcc23892fb00585c164a23b8b1d01ec67697 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 1 Jun 2020 12:14:02 +0200 Subject: [PATCH 049/129] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff208fed..3987a9f0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ All notable changes to this project will be documented in this file. - **incompatible change** robot and default service accounts outputs in the `project` module have been refactored and are now exposed via a single `service_account` output (cf [#82]) - add support for PD CSI driver in GKE module -- refactor [iam-service-accounts] module outputs to be more resilient +- refactor `iam-service-accounts` module outputs to be more resilient ## [1.7.0] - 2020-05-30 From af95bb3110afc2451d479c151c8d4b3eb14e500f Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Tue, 2 Jun 2020 10:14:03 +0200 Subject: [PATCH 050/129] Update cloud-config.yaml --- modules/cloud-config-container/nginx/cloud-config.yaml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/cloud-config-container/nginx/cloud-config.yaml b/modules/cloud-config-container/nginx/cloud-config.yaml index 83ceab81..18d8051e 100644 --- a/modules/cloud-config-container/nginx/cloud-config.yaml +++ b/modules/cloud-config-container/nginx/cloud-config.yaml @@ -74,5 +74,4 @@ bootcmd: runcmd: - iptables -I INPUT 1 -p tcp -m tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT - systemctl daemon-reload - - systemctl restart systemd-resolved.service - - systemctl start nginx \ No newline at end of file + - systemctl start nginx From 4dd927d8d7006645e6c9a0a6ea83c0f2facb2821 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 3 Jun 2020 08:43:10 +0200 Subject: [PATCH 051/129] KMS module refactoring (#85) * first rewrite, untested * validation fixes * fix errors, rename variables, improve README, tested * minimal kms module test * README tweaks --- modules/kms/README.md | 105 +++++++++++++---------- modules/kms/main.tf | 89 +++++++++++-------- modules/kms/outputs.tf | 37 ++++++-- modules/kms/variables.tf | 74 ++++++++++------ tests/modules/kms/__init__.py | 13 +++ tests/modules/kms/fixture/main.tf | 29 +++++++ tests/modules/kms/fixture/outputs.tf | 19 +++++ tests/modules/kms/fixture/variables.tf | 113 +++++++++++++++++++++++++ tests/modules/kms/test_plan.py | 33 ++++++++ 9 files changed, 398 insertions(+), 114 deletions(-) create mode 100644 tests/modules/kms/__init__.py create mode 100644 tests/modules/kms/fixture/main.tf create mode 100644 tests/modules/kms/fixture/outputs.tf create mode 100644 tests/modules/kms/fixture/variables.tf create mode 100644 tests/modules/kms/test_plan.py diff --git a/modules/kms/README.md b/modules/kms/README.md index 55a0e944..69ceb882 100644 --- a/modules/kms/README.md +++ b/modules/kms/README.md @@ -1,40 +1,71 @@ # Google KMS Module -Simple Cloud KMS module that allows managing a keyring, zero or more keys in the keyring, and IAM role bindings on individual keys. +This module allows creating and managing KMS crypto keys and IAM bindings at both the keyring and crypto key level. An existing keyring can be used, or a new one can be created and managed by the module if needed. -The `protected` flag in the `key_attributes` variable sets the `prevent_destroy` lifecycle argument on an a per-key basis. +When using an existing keyring be mindful about applying IAM bindings, as all bindings used by this module are authoritative, and you might inadvertently override bindings managed by the keyring creator. + +## Protecting against destroy + +In this module **no lifecycle blocks are set on resources to prevent destroy**, in order to allow for experimentation and testing where rapid `apply`/`destroy` cycles are needed. If you plan on using this module to manage non-development resources, **clone it and uncomment the lifecycle blocks** found in `main.tf`. ## Examples -### Minimal example +### Using an existing keyring ```hcl module "kms" { - source = "../modules/kms" - project_id = "my-project" - keyring = "test" - location = "europe" - keys = ["key-a", "key-b"] + source = "../modules/kms" + project_id = "my-project" + iam_roles = ["roles/owner"] + iam_members = { + "roles/owner" = ["user:user1@example.com"] + } + keyring = { location = "europe-west1", name = "test" } + keyring_create = false + keys = { key-a = null, key-b = null, key-c = null } } ``` -### Granting access to keys via IAM +### Keyring creation and crypto key rotation and IAM roles ```hcl module "kms" { - source = "../modules/kms" - project_id = "my-project" - keyring = "test" - location = "europe" - keys = ["key-a", "key-b"] - iam_roles = { - key-a = ["roles/cloudkms.cryptoKeyDecrypter"] + source = "../modules/kms" + project_id = "my-project" + key_iam_roles = { + key-a = ["roles/owner"] } - iam_members = { + key_iam_members = { key-a = { - "roles/cloudkms.cryptoKeyDecrypter" = ["user:me@example.org"] + "roles/owner" = ["user:user1@example.com"] } } + keyring = { location = "europe-west1", name = "test" } + keys = { + key-a = null + key-b = { rotation_period = "604800s", labels = null } + key-c = { rotation_period = null, labels = { env = "test" } } + } +} +``` + +### Crypto key purpose + +```hcl +module "kms" { + source = "../modules/kms" + project_id = "my-project" + key_purpose = { + key-c = { + purpose = "ASYMMETRIC_SIGN" + version_template = { + algorithm = "EC_SIGN_P384_SHA384" + protection_level = null + } + } + } + keyring = { location = "europe-west1", name = "test" } + keys = { key-a = null, key-b = null, key-c = null } } ``` @@ -43,14 +74,16 @@ module "kms" { | name | description | type | required | default | |---|---|:---: |:---:|:---:| -| keyring | Keyring name. | string | ✓ | | -| location | Location for the keyring. | string | ✓ | | +| keyring | Keyring attributes. | object({...}) | ✓ | | | project_id | Project id where the keyring will be created. | string | ✓ | | -| *iam_members* | IAM members keyed by key name and role. | map(map(list(string))) | | {} | -| *iam_roles* | IAM roles keyed by key name. | map(list(string)) | | {} | -| *key_attributes* | Optional key attributes per key. | map(object({...})) | | {} | -| *key_defaults* | Key attribute defaults. | object({...}) | | ... | -| *keys* | Key names. | list(string) | | [] | +| *iam_members* | Keyring IAM members. | map(list(string)) | | {} | +| *iam_roles* | Keyring IAM roles. | list(string) | | [] | +| *key_iam_members* | IAM members keyed by key name and role. | map(map(list(string))) | | {} | +| *key_iam_roles* | IAM roles keyed by key name. | map(list(string)) | | {} | +| *key_purpose* | Per-key purpose, if not set defaults will be used. If purpose is not `ENCRYPT_DECRYPT` (the default), `version_template.algorithm` is required. | map(object({...})) | | {} | +| *key_purpose_defaults* | Defaults used for key purpose when not defined at the key level. If purpose is not `ENCRYPT_DECRYPT` (the default), `version_template.algorithm` is required. | object({...}) | | ... | +| *keyring_create* | Set to false to manage keys and IAM bindings in an existing keyring. | bool | | true | +| *keys* | Key names and base attributes. Set attributes to null if not needed. | map(object({...})) | | {} | ## Outputs @@ -59,25 +92,7 @@ module "kms" { | key_self_links | Key self links. | | | keyring | Keyring resource. | | | keys | Key resources. | | -| location | Keyring self link. | | -| name | Keyring self link. | | +| location | Keyring location. | | +| name | Keyring name. | | | self_link | Keyring self link. | | - -## Requirements - -These sections describe requirements for using this module. - -### IAM - -The following roles must be used to provision the resources of this module: - -- Cloud KMS Admin: `roles/cloudkms.admin` or -- Owner: `roles/owner` - -### APIs - -A project with the following APIs enabled must be used to host the -resources of this module: - -- Google Cloud Key Management Service: `cloudkms.googleapis.com` diff --git a/modules/kms/main.tf b/modules/kms/main.tf index 18c14eff..b488ac71 100644 --- a/modules/kms/main.tf +++ b/modules/kms/main.tf @@ -15,59 +15,74 @@ */ locals { - # distinct is needed to make the expanding function argument work - iam_pairs = flatten([ - for name, roles in var.iam_roles : + key_iam_pairs = flatten([ + for name, roles in var.key_iam_roles : [for role in roles : { name = name, role = role }] ]) - iam_keypairs = { - for pair in local.iam_pairs : + key_iam_keypairs = { + for pair in local.key_iam_pairs : "${pair.name}-${pair.role}" => pair } - key_attributes = { - for name in var.keys : - name => lookup(var.key_attributes, name, var.key_defaults) + key_purpose = { + for key, attrs in var.keys : key => try( + var.key_purpose[key], var.key_purpose_defaults + ) } - keys = merge( - { for name, resource in google_kms_crypto_key.keys : name => resource }, - { for name, resource in google_kms_crypto_key.keys-ephemeral : name => resource } + keyring = ( + var.keyring_create + ? google_kms_key_ring.default.0 + : data.google_kms_key_ring.default.0 ) } -resource "google_kms_key_ring" "key_ring" { - name = var.keyring +data "google_kms_key_ring" "default" { + count = var.keyring_create ? 0 : 1 project = var.project_id - location = var.location + name = var.keyring.name + location = var.keyring.location } -resource "google_kms_crypto_key" "keys" { - for_each = { - for name, attrs in local.key_attributes : - name => attrs if attrs.protected - } +resource "google_kms_key_ring" "default" { + count = var.keyring_create ? 1 : 0 + project = var.project_id + name = var.keyring.name + location = var.keyring.location + # lifecycle { + # prevent_destroy = true + # } +} + +resource "google_kms_key_ring_iam_binding" "default" { + for_each = toset(var.iam_roles) + key_ring_id = local.keyring.self_link + role = each.value + members = lookup(var.iam_members, each.value, []) +} + +resource "google_kms_crypto_key" "default" { + for_each = var.keys + key_ring = local.keyring.self_link name = each.key - key_ring = google_kms_key_ring.key_ring.self_link - rotation_period = each.value.rotation_period - lifecycle { - prevent_destroy = true + rotation_period = try(each.value.rotation_period, null) + labels = try(each.value.labels, null) + purpose = try(local.key_purpose[each.key].purpose, null) + dynamic version_template { + for_each = local.key_purpose[each.key].version_template == null ? [] : [""] + content { + algorithm = local.key_purpose[each.key].version_template.algorithm + protection_level = local.key_purpose[each.key].version_template.protection_level + } } + # lifecycle { + # prevent_destroy = true + # } } -resource "google_kms_crypto_key" "keys-ephemeral" { - for_each = { - for name, attrs in local.key_attributes : - name => attrs if ! attrs.protected - } - name = each.key - key_ring = google_kms_key_ring.key_ring.self_link - rotation_period = each.value.rotation_period -} - -resource "google_kms_crypto_key_iam_binding" "bindings" { - for_each = local.iam_keypairs +resource "google_kms_crypto_key_iam_binding" "default" { + for_each = local.key_iam_keypairs role = each.value.role - crypto_key_id = local.keys[each.value.name].self_link + crypto_key_id = google_kms_crypto_key.default[each.value.name].self_link members = lookup( - lookup(var.iam_members, each.value.name, {}), each.value.role, [] + lookup(var.key_iam_members, each.value.name, {}), each.value.role, [] ) } diff --git a/modules/kms/outputs.tf b/modules/kms/outputs.tf index de30ea17..d92190a5 100644 --- a/modules/kms/outputs.tf +++ b/modules/kms/outputs.tf @@ -16,30 +16,51 @@ output "keyring" { description = "Keyring resource." - value = google_kms_key_ring.key_ring + value = local.keyring + depends_on = [ + google_kms_key_ring_iam_binding.default + ] } output "location" { - description = "Keyring self link." - value = google_kms_key_ring.key_ring.location + description = "Keyring location." + value = local.keyring.location + depends_on = [ + google_kms_key_ring_iam_binding.default + ] } output "name" { - description = "Keyring self link." - value = google_kms_key_ring.key_ring.name + description = "Keyring name." + value = local.keyring.name + depends_on = [ + google_kms_key_ring_iam_binding.default + ] } output "self_link" { description = "Keyring self link." - value = google_kms_key_ring.key_ring.self_link + value = local.keyring.self_link + depends_on = [ + google_kms_key_ring_iam_binding.default + ] } output "keys" { description = "Key resources." - value = local.keys + value = google_kms_crypto_key.default + depends_on = [ + google_kms_crypto_key_iam_binding.default + ] } output "key_self_links" { description = "Key self links." - value = { for name, resource in local.keys : name => resource.self_link } + value = { + for name, resource in google_kms_crypto_key.default : + name => resource.self_link + } + depends_on = [ + google_kms_crypto_key_iam_binding.default + ] } diff --git a/modules/kms/variables.tf b/modules/kms/variables.tf index e976b72b..42ec689b 100644 --- a/modules/kms/variables.tf +++ b/modules/kms/variables.tf @@ -15,53 +15,79 @@ */ variable "iam_members" { + description = "Keyring IAM members." + type = map(list(string)) + default = {} +} + +variable "iam_roles" { + description = "Keyring IAM roles." + type = list(string) + default = [] +} + +variable "key_iam_members" { description = "IAM members keyed by key name and role." type = map(map(list(string))) default = {} } -variable "iam_roles" { +variable "key_iam_roles" { description = "IAM roles keyed by key name." type = map(list(string)) default = {} } -variable "keyring" { - description = "Keyring name." - type = string -} - -variable "key_attributes" { - description = "Optional key attributes per key." +variable "key_purpose" { + description = "Per-key purpose, if not set defaults will be used. If purpose is not `ENCRYPT_DECRYPT` (the default), `version_template.algorithm` is required." type = map(object({ - protected = bool - rotation_period = string + purpose = string + version_template = object({ + algorithm = string + protection_level = string + }) })) default = {} } -variable "key_defaults" { - description = "Key attribute defaults." +variable "key_purpose_defaults" { + description = "Defaults used for key purpose when not defined at the key level. If purpose is not `ENCRYPT_DECRYPT` (the default), `version_template.algorithm` is required." type = object({ - protected = bool - rotation_period = string + purpose = string + version_template = object({ + algorithm = string + protection_level = string + }) }) default = { - protected = true - rotation_period = "100000s" + purpose = null + version_template = null } } -variable "keys" { - description = "Key names." - type = list(string) - default = [] +# cf https://cloud.google.com/kms/docs/locations + +variable "keyring" { + description = "Keyring attributes." + type = object({ + location = string + name = string + }) } -# cf https://cloud.google.com/kms/docs/locations -variable "location" { - description = "Location for the keyring." - type = string +variable "keyring_create" { + description = "Set to false to manage keys and IAM bindings in an existing keyring." + type = bool + default = true +} + +variable "keys" { + description = "Key names and base attributes. Set attributes to null if not needed." + type = map(object({ + rotation_period = string + labels = map(string) + })) + default = {} } variable "project_id" { diff --git a/tests/modules/kms/__init__.py b/tests/modules/kms/__init__.py new file mode 100644 index 00000000..6913f02e --- /dev/null +++ b/tests/modules/kms/__init__.py @@ -0,0 +1,13 @@ +# Copyright 2020 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. diff --git a/tests/modules/kms/fixture/main.tf b/tests/modules/kms/fixture/main.tf new file mode 100644 index 00000000..f027f978 --- /dev/null +++ b/tests/modules/kms/fixture/main.tf @@ -0,0 +1,29 @@ +/** + * Copyright 2020 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 "test" { + source = "../../../../modules/kms" + iam_members = var.iam_members + iam_roles = var.iam_roles + key_iam_members = var.key_iam_members + key_iam_roles = var.key_iam_roles + key_purpose = var.key_purpose + key_purpose_defaults = var.key_purpose_defaults + keyring = var.keyring + keyring_create = var.keyring_create + keys = var.keys + project_id = var.project_id +} diff --git a/tests/modules/kms/fixture/outputs.tf b/tests/modules/kms/fixture/outputs.tf new file mode 100644 index 00000000..77b8211f --- /dev/null +++ b/tests/modules/kms/fixture/outputs.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2020 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 "module" { + value = module.test +} diff --git a/tests/modules/kms/fixture/variables.tf b/tests/modules/kms/fixture/variables.tf new file mode 100644 index 00000000..10f3f318 --- /dev/null +++ b/tests/modules/kms/fixture/variables.tf @@ -0,0 +1,113 @@ +/** + * Copyright 2020 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 "iam_members" { + type = map(list(string)) + default = { + "roles/owner" = ["user:ludo@ludomagno.net"] + } +} + +variable "iam_roles" { + type = list(string) + default = ["roles/owner"] +} + +variable "key_iam_members" { + type = map(map(list(string))) + default = { + key-a = { + "roles/owner" = ["user:ludo@ludomagno.net"] + } + } +} + +variable "key_iam_roles" { + type = map(list(string)) + default = { + key-a = ["roles/owner"] + } +} + +variable "key_purpose" { + type = map(object({ + purpose = string + version_template = object({ + algorithm = string + protection_level = string + }) + })) + default = { + key-b = { + purpose = "ENCRYPT_DECRYPT" + version_template = null + } + key-c = { + purpose = "ASYMMETRIC_SIGN" + version_template = { + algorithm = "EC_SIGN_P384_SHA384" + protection_level = null + } + } + } +} + +variable "key_purpose_defaults" { + type = object({ + purpose = string + version_template = object({ + algorithm = string + protection_level = string + }) + }) + default = { + purpose = null + version_template = null + } +} + +variable "keyring" { + type = object({ + location = string + name = string + }) + default = { + location = "europe-west1" + name = "test-module" + } +} + +variable "keyring_create" { + type = bool + default = true +} + +variable "keys" { + type = map(object({ + rotation_period = string + labels = map(string) + })) + default = { + key-a = null + key-b = { rotation_period = "604800s", labels = null } + key-c = { rotation_period = null, labels = { env = "test" } } + } +} + +variable "project_id" { + type = string + default = "my-project" +} diff --git a/tests/modules/kms/test_plan.py b/tests/modules/kms/test_plan.py new file mode 100644 index 00000000..cd9d6c7c --- /dev/null +++ b/tests/modules/kms/test_plan.py @@ -0,0 +1,33 @@ +# Copyright 2020 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. + + +import os +import pytest + + +FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture') + + +def test_resources(plan_runner): + "Test module resources." + _, resources = plan_runner(FIXTURES_DIR) + assert sorted(r['type'] for r in resources) == [ + 'google_kms_crypto_key', + 'google_kms_crypto_key', + 'google_kms_crypto_key', + 'google_kms_crypto_key_iam_binding', + 'google_kms_key_ring', + 'google_kms_key_ring_iam_binding' + ] From 66bb75ff7750b3c9ba65192c195e9ad8f4aaf231 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 3 Jun 2020 08:44:38 +0200 Subject: [PATCH 052/129] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3987a9f0..00ef25a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- **incompatible change** the `kms` module has been refactored and will be incompatible with previous state - **incompatible change** robot and default service accounts outputs in the `project` module have been refactored and are now exposed via a single `service_account` output (cf [#82]) - add support for PD CSI driver in GKE module - refactor `iam-service-accounts` module outputs to be more resilient From 99642be58af40bd24493fbef0e82a1b37ead92a9 Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Wed, 3 Jun 2020 09:27:10 +0200 Subject: [PATCH 053/129] Add option to use private GCR to cos-generic-metadata (#86) --- .../cloud-config-container/cos-generic-metadata/README.md | 1 + .../cos-generic-metadata/cloud-config.yaml | 4 ++++ modules/cloud-config-container/cos-generic-metadata/main.tf | 1 + .../cos-generic-metadata/variables.tf | 6 ++++++ 4 files changed, 12 insertions(+) diff --git a/modules/cloud-config-container/cos-generic-metadata/README.md b/modules/cloud-config-container/cos-generic-metadata/README.md index 1194728f..ad5ada41 100644 --- a/modules/cloud-config-container/cos-generic-metadata/README.md +++ b/modules/cloud-config-container/cos-generic-metadata/README.md @@ -64,6 +64,7 @@ module "cos-envoy" { | name | description | type | required | default | |---|---|:---: |:---:|:---:| | container_image | Container image. | string | ✓ | | +| *authenticate_gcr* | Setup docker to pull images from private GCR. Requires at least one user since the token is stored in the home of the first user defined. | bool | | false | | *boot_commands* | List of cloud-init `bootcmd`s | list(string) | | [] | | *cloud_config* | Cloud config template path. If provided, takes precedence over all other arguments. | string | | null | | *config_variables* | Additional variables used to render the template passed via `cloud_config` | map(any) | | {} | diff --git a/modules/cloud-config-container/cos-generic-metadata/cloud-config.yaml b/modules/cloud-config-container/cos-generic-metadata/cloud-config.yaml index 9f8e38fa..2341415c 100644 --- a/modules/cloud-config-container/cos-generic-metadata/cloud-config.yaml +++ b/modules/cloud-config-container/cos-generic-metadata/cloud-config.yaml @@ -44,6 +44,10 @@ write_files: After=gcr-online.target docker.socket Wants=gcr-online.target docker.socket docker-events-collector.service [Service] +%{ if authenticate_gcr && length(users) > 0 ~} + Environment="HOME=/home/${users[0].username}" + ExecStartPre=/usr/bin/docker-credential-gcr configure-docker +%{ endif ~} ExecStart=/usr/bin/docker run --rm --name=${container_name} \ %{ if length(users) > 0 ~} --user=${users[0].uid} \ diff --git a/modules/cloud-config-container/cos-generic-metadata/main.tf b/modules/cloud-config-container/cos-generic-metadata/main.tf index ee4c2ae0..85043b19 100644 --- a/modules/cloud-config-container/cos-generic-metadata/main.tf +++ b/modules/cloud-config-container/cos-generic-metadata/main.tf @@ -26,6 +26,7 @@ locals { gcp_logging = var.gcp_logging run_commands = var.run_commands users = var.users + authenticate_gcr = var.authenticate_gcr })) files = { for path, attrs in var.files : path => { diff --git a/modules/cloud-config-container/cos-generic-metadata/variables.tf b/modules/cloud-config-container/cos-generic-metadata/variables.tf index 1d54de00..4040fa44 100644 --- a/modules/cloud-config-container/cos-generic-metadata/variables.tf +++ b/modules/cloud-config-container/cos-generic-metadata/variables.tf @@ -108,3 +108,9 @@ variable "users" { default = [ ] } + +variable "authenticate_gcr" { + description = "Setup docker to pull images from private GCR. Requires at least one user since the token is stored in the home of the first user defined." + type = bool + default = false +} From 24118c0f5be288699cd165e13dde939434e64c1d Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 3 Jun 2020 09:42:24 +0200 Subject: [PATCH 054/129] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 00ef25a6..33bb17cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. - **incompatible change** robot and default service accounts outputs in the `project` module have been refactored and are now exposed via a single `service_account` output (cf [#82]) - add support for PD CSI driver in GKE module - refactor `iam-service-accounts` module outputs to be more resilient +- add option to use private GCR to `cos-generic-metadata` module ## [1.7.0] - 2020-05-30 From 268132efe43ce7c704bda6eab4d6ab4dd3b9f8ee Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 3 Jun 2020 09:43:30 +0200 Subject: [PATCH 055/129] Update CHANGELOG.md --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33bb17cc..063d8bac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [1.8.0] - 2020-06-03 + - **incompatible change** the `kms` module has been refactored and will be incompatible with previous state - **incompatible change** robot and default service accounts outputs in the `project` module have been refactored and are now exposed via a single `service_account` output (cf [#82]) - add support for PD CSI driver in GKE module @@ -79,6 +81,7 @@ All notable changes to this project will be documented in this file. - merge development branch with suite of new modules and end-to-end examples [Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.7.0...HEAD +[1.8.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.7.0...v1.8.0 [1.7.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.6.0...v1.7.0 [1.6.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.5.0...v1.6.0 [1.5.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.4.1...v1.5.0 From eb4c1d5d98969aaab2a6310f2a68e3924d5b18f9 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Fri, 5 Jun 2020 09:41:58 +0200 Subject: [PATCH 056/129] Update README.md --- modules/net-ilb/README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/modules/net-ilb/README.md b/modules/net-ilb/README.md index 3669c54b..23957e28 100644 --- a/modules/net-ilb/README.md +++ b/modules/net-ilb/README.md @@ -2,6 +2,11 @@ This module allows managing a GCE Internal Load Balancer and integrates the forwarding rule, regional backend, and optional health check resources. It's designed to be a simple match for the [`compute-vm`](../compute-vm) module, which can be used to manage instance templates and instance groups. +## TODO + +- [ ] do not create health check resource if `var.health_check` is not `null` (workaround is to set `var.health_check_config` to `null` +- [ ] add a variable for setting address purpose to `SHARED_LOADBALANCER_VIP` and an output for the address + ## Issues TODO(ludoo): check if this is still the case after splitting out MIG from compute-vm From 4a40497ce68087a9244d30b0bc52a94e74569bc8 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Fri, 5 Jun 2020 09:51:36 +0200 Subject: [PATCH 057/129] Update README.md --- modules/net-ilb/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/net-ilb/README.md b/modules/net-ilb/README.md index 23957e28..759ad80f 100644 --- a/modules/net-ilb/README.md +++ b/modules/net-ilb/README.md @@ -5,7 +5,7 @@ This module allows managing a GCE Internal Load Balancer and integrates the forw ## TODO - [ ] do not create health check resource if `var.health_check` is not `null` (workaround is to set `var.health_check_config` to `null` -- [ ] add a variable for setting address purpose to `SHARED_LOADBALANCER_VIP` and an output for the address +- [ ] add a variable for setting address purpose to `SHARED_LOADBALANCER_VIP` and an output for the address once the [provider support has been implemented](https://github.com/terraform-providers/terraform-provider-google/issues/6499) ## Issues From 474fd7364f0f4cec646b791e435326420863bf38 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Fri, 5 Jun 2020 21:24:28 +0200 Subject: [PATCH 058/129] use "all" for admin firewall rule in net-vpc-firewall module --- modules/net-vpc-firewall/main.tf | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/modules/net-vpc-firewall/main.tf b/modules/net-vpc-firewall/main.tf index 7252e3a8..49affdd7 100644 --- a/modules/net-vpc-firewall/main.tf +++ b/modules/net-vpc-firewall/main.tf @@ -34,9 +34,7 @@ resource "google_compute_firewall" "allow-admins" { network = var.network project = var.project_id source_ranges = var.admin_ranges - allow { protocol = "icmp" } - allow { protocol = "tcp" } - allow { protocol = "udp" } + allow { protocol = "all" } } ############################################################################### From 24e9e0c28097599f2ad74d81f21a693cfe9a65ae Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Fri, 5 Jun 2020 21:25:18 +0200 Subject: [PATCH 059/129] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 063d8bac..d2961f3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- use `all` instead of specifying protocols in the admin firewall rule of the `net-vpc-firewall` module + ## [1.8.0] - 2020-06-03 - **incompatible change** the `kms` module has been refactored and will be incompatible with previous state From 1b450fe44490b27cb55bbd490a1645d7cadd5956 Mon Sep 17 00:00:00 2001 From: lcaggio Date: Fri, 5 Jun 2020 21:59:34 +0200 Subject: [PATCH 060/129] Add Cloud KMS support to GCS module (#87) * Add support to Cloud KMS * Fixes * Fix tests * Fix tests * - change variable name to be consistent with BQ module - remove output, not needed - change string default value to null * use locals to pre-populate kms key variable for all names * rename kms variable, fix prefix check in locals Co-authored-by: Ludovico Magnocavallo --- modules/gcs/README.md | 32 +++++++++++++++++++++++--- modules/gcs/main.tf | 15 +++++++++++- modules/gcs/variables.tf | 12 +++++++--- tests/modules/gcs/fixture/variables.tf | 2 +- 4 files changed, 53 insertions(+), 8 deletions(-) diff --git a/modules/gcs/README.md b/modules/gcs/README.md index 98545db8..839faadd 100644 --- a/modules/gcs/README.md +++ b/modules/gcs/README.md @@ -26,6 +26,31 @@ module "buckets" { } ``` +### Example with Cloud KMS + +```hcl +module "buckets" { + source = "./modules/gcs" + project_id = "myproject" + prefix = "test" + names = ["bucket-one", "bucket-two"] + bucket_policy_only = { + bucket-one = false + } + iam_members = { + bucket-two = { + "roles/storage.admin" = ["group:storage@example.com"] + } + } + iam_roles = { + bucket-two = ["roles/storage.admin"] + } + kms_keys = { + bucket-two = local.kms_key.self_link, + } +} +``` + ## Variables @@ -34,12 +59,13 @@ module "buckets" { | names | Bucket name suffixes. | list(string) | ✓ | | | project_id | Bucket project id. | string | ✓ | | | *bucket_policy_only* | Optional map to disable object ACLS keyed by name, defaults to true. | map(bool) | | {} | +| *encryption_keys* | Per-bucket KMS keys that will be used for encryption. | map(string) | | {} | | *force_destroy* | Optional map to set force destroy keyed by name, defaults to false. | map(bool) | | {} | -| *iam_members* | IAM members keyed by bucket name and role. | map(map(list(string))) | | null | -| *iam_roles* | IAM roles keyed by bucket name. | map(list(string)) | | null | +| *iam_members* | IAM members keyed by bucket name and role. | map(map(list(string))) | | {} | +| *iam_roles* | IAM roles keyed by bucket name. | map(list(string)) | | {} | | *labels* | Labels to be attached to all buckets. | map(string) | | {} | | *location* | Bucket location. | string | | EU | -| *prefix* | Prefix used to generate the bucket name. | string | | | +| *prefix* | Prefix used to generate the bucket name. | string | | null | | *storage_class* | Bucket storage class. | string | | MULTI_REGIONAL | | *versioning* | Optional map to set versioning keyed by name, defaults to false. | map(bool) | | {} | diff --git a/modules/gcs/main.tf b/modules/gcs/main.tf index baff11d9..f345ed3b 100644 --- a/modules/gcs/main.tf +++ b/modules/gcs/main.tf @@ -31,7 +31,12 @@ locals { "${pair.name}-${pair.role}" => pair } iam_members = var.iam_members == null ? {} : var.iam_members - prefix = var.prefix == "" ? "" : join("-", [var.prefix, lower(var.location), ""]) + prefix = ( + var.prefix == null || var.prefix == "" # keep "" for backward compatibility + ? "" + : join("-", [var.prefix, lower(var.location), ""]) + ) + kms_keys = { for name in var.names : name => lookup(var.encryption_keys, name, null) } } resource "google_storage_bucket" "buckets" { @@ -50,6 +55,14 @@ resource "google_storage_bucket" "buckets" { name = lower(each.key) storage_class = lower(var.storage_class) }) + + dynamic encryption { + for_each = local.kms_keys[each.key] == null ? [] : [""] + + content { + default_kms_key_name = local.kms_keys[each.key] + } + } } resource "google_storage_bucket_iam_binding" "bindings" { diff --git a/modules/gcs/variables.tf b/modules/gcs/variables.tf index 6cc712eb..cdc63ecc 100644 --- a/modules/gcs/variables.tf +++ b/modules/gcs/variables.tf @@ -29,13 +29,19 @@ variable "force_destroy" { variable "iam_members" { description = "IAM members keyed by bucket name and role." type = map(map(list(string))) - default = null + default = {} } variable "iam_roles" { description = "IAM roles keyed by bucket name." type = map(list(string)) - default = null + default = {} +} + +variable "encryption_keys" { + description = "Per-bucket KMS keys that will be used for encryption." + type = map(string) + default = {} } variable "labels" { @@ -58,7 +64,7 @@ variable "names" { variable "prefix" { description = "Prefix used to generate the bucket name." type = string - default = "" + default = null } variable "project_id" { diff --git a/tests/modules/gcs/fixture/variables.tf b/tests/modules/gcs/fixture/variables.tf index 7caec8c7..08e95396 100644 --- a/tests/modules/gcs/fixture/variables.tf +++ b/tests/modules/gcs/fixture/variables.tf @@ -41,7 +41,7 @@ variable "labels" { variable "prefix" { type = string - default = "" + default = null } variable "storage_class" { From 7f49615c1d635820490388ab2ab86cd878494cf4 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Fri, 5 Jun 2020 22:00:19 +0200 Subject: [PATCH 061/129] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index d2961f3e..5cc453cc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - use `all` instead of specifying protocols in the admin firewall rule of the `net-vpc-firewall` module +- add support for encryption keys in `gcs` module ## [1.8.0] - 2020-06-03 From cf79c65d3bc678e7b7e1f9ce7a0d72caf25ee6d9 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Sun, 7 Jun 2020 18:06:15 +0200 Subject: [PATCH 062/129] Set instance zone in net vpc route to avoid recreation (#90) --- modules/net-vpc/README.md | 19 ++++++++++--------- modules/net-vpc/main.tf | 4 +++- modules/net-vpc/variables.tf | 8 ++++---- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/modules/net-vpc/README.md b/modules/net-vpc/README.md index 2a3a17b6..334c7fbb 100644 --- a/modules/net-vpc/README.md +++ b/modules/net-vpc/README.md @@ -112,20 +112,21 @@ module "vpc-host" { | name | The name of the network being created | string | ✓ | | | project_id | The ID of the project where this VPC will be created | string | ✓ | | | *auto_create_subnetworks* | Set to true to create an auto mode subnet, defaults to custom mode. | bool | | false | +| *delete_default_routes_on_create* | Set to true to delete the default routes at creation time. | bool | | false | | *description* | An optional description of this resource (triggers recreation on change). | string | | Terraform-managed. | -| *iam_members* | List of IAM members keyed by subnet 'region/name' and role. | map(map(list(string))) | | null | -| *iam_roles* | List of IAM roles keyed by subnet 'region/name'. | map(list(string)) | | null | +| *iam_members* | List of IAM members keyed by subnet 'region/name' and role. | map(map(list(string))) | | {} | +| *iam_roles* | List of IAM roles keyed by subnet 'region/name'. | map(list(string)) | | {} | | *log_config_defaults* | Default configuration for flow logs when enabled. | object({...}) | | ... | -| *log_configs* | Map keyed by subnet 'region/name' of optional configurations for flow logs when enabled. | map(map(string)) | | null | +| *log_configs* | Map keyed by subnet 'region/name' of optional configurations for flow logs when enabled. | map(map(string)) | | {} | | *peering_config* | VPC peering configuration. | object({...}) | | null | -| *routes* | Network routes, keyed by name. | map(object({...})) | | null | +| *routes* | Network routes, keyed by name. | map(object({...})) | | {} | | *routing_mode* | The network routing mode (default 'GLOBAL') | string | | GLOBAL | | *shared_vpc_host* | Enable shared VPC for this project. | bool | | false | | *shared_vpc_service_projects* | Shared VPC service projects to register with this host | list(string) | | [] | | *subnet_descriptions* | Optional map of subnet descriptions, keyed by subnet 'region/name'. | map(string) | | {} | | *subnet_flow_logs* | Optional map of boolean to control flow logs (default is disabled), keyed by subnet 'region/name'. | map(bool) | | {} | | *subnet_private_access* | Optional map of boolean to control private Google access (default is enabled), keyed by subnet 'region/name'. | map(bool) | | {} | -| *subnets* | The list of subnets being created | map(object({...})) | | null | +| *subnets* | The list of subnets being created | list(object({...})) | | [] | ## Outputs @@ -136,10 +137,10 @@ module "vpc-host" { | network | Network resource. | | | project_id | Shared VPC host project id. | | | self_link | The URI of the VPC being created. | | -| subnet_ips | Map of subnet address ranges keyed by 'region/name'. | | -| subnet_regions | Map of subnet regions keyed by 'region/name'. | | -| subnet_secondary_ranges | Map of subnet secondary ranges keyed by 'region/name'. | | -| subnet_self_links | Map of subnet self links keyed by 'region/name'. | | +| subnet_ips | Map of subnet address ranges keyed by name. | | +| subnet_regions | Map of subnet regions keyed by name. | | +| subnet_secondary_ranges | Map of subnet secondary ranges keyed by name. | | +| subnet_self_links | Map of subnet self links keyed by name. | | | subnets | Subnet resources. | | diff --git a/modules/net-vpc/main.tf b/modules/net-vpc/main.tf index 333518df..87d68df3 100644 --- a/modules/net-vpc/main.tf +++ b/modules/net-vpc/main.tf @@ -64,7 +64,7 @@ locals { } subnets = { for subnet in var.subnets : - "${subnet.region}/${subnet.name}" => subnet + "${subnet.region}/${subnet.name}" => subnet } } @@ -184,6 +184,8 @@ resource "google_compute_route" "instance" { priority = each.value.priority tags = each.value.tags next_hop_instance = each.value.next_hop + # not setting the instance zone will trigger a refresh + next_hop_instance_zone = regex("zones/([^/]+)/", each.value.next_hop)[0] } resource "google_compute_route" "ip" { diff --git a/modules/net-vpc/variables.tf b/modules/net-vpc/variables.tf index 0632e8ac..d06eb401 100644 --- a/modules/net-vpc/variables.tf +++ b/modules/net-vpc/variables.tf @@ -35,19 +35,19 @@ variable "description" { variable "iam_roles" { description = "List of IAM roles keyed by subnet 'region/name'." type = map(list(string)) - default = null + default = {} } variable "iam_members" { description = "List of IAM members keyed by subnet 'region/name' and role." type = map(map(list(string))) - default = null + default = {} } variable "log_configs" { description = "Map keyed by subnet 'region/name' of optional configurations for flow logs when enabled." type = map(map(string)) - default = null + default = {} } variable "log_config_defaults" { @@ -93,7 +93,7 @@ variable "routes" { next_hop_type = string # gateway, instance, ip, vpn_tunnel, ilb next_hop = string })) - default = null + default = {} } variable "routing_mode" { From 62836cb7a496683336481f78de14c8f3cba2da6a Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Sun, 7 Jun 2020 18:08:00 +0200 Subject: [PATCH 063/129] Update CHANGELOG.md --- CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5cc453cc..ae000b79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,8 +4,11 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [1.8.1] - 2020-06-07 + - use `all` instead of specifying protocols in the admin firewall rule of the `net-vpc-firewall` module - add support for encryption keys in `gcs` module +- set `next_hop_instance_zone` in `net-vpc` for next hop instance routes to avoid triggering recreation ## [1.8.0] - 2020-06-03 @@ -83,7 +86,8 @@ All notable changes to this project will be documented in this file. - merge development branch with suite of new modules and end-to-end examples -[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.7.0...HEAD +[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.8.1...HEAD +[1.8.1]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.8.0...v1.8.1 [1.8.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.7.0...v1.8.0 [1.7.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.6.0...v1.7.0 [1.6.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.5.0...v1.6.0 From 2e597e2c58aca0584997569745a20c81d785ee7f Mon Sep 17 00:00:00 2001 From: Julio Castillo Date: Mon, 8 Jun 2020 13:43:13 +0200 Subject: [PATCH 064/129] Add Network Endpoint Group module (#91) * Add Network Endpoint Group module * Update CHANGELOG * Move neg to experimental * Revert "Update CHANGELOG" This reverts commit 9282932f88655089e642a9e9954504f19528621e. * Revert README changes --- modules/__experimental/net-neg/README.md | 46 +++++++++++++++++++ modules/__experimental/net-neg/main.tf | 33 ++++++++++++++ modules/__experimental/net-neg/outputs.tf | 30 +++++++++++++ modules/__experimental/net-neg/variables.tf | 49 +++++++++++++++++++++ modules/__experimental/net-neg/versions.tf | 19 ++++++++ 5 files changed, 177 insertions(+) create mode 100644 modules/__experimental/net-neg/README.md create mode 100644 modules/__experimental/net-neg/main.tf create mode 100644 modules/__experimental/net-neg/outputs.tf create mode 100644 modules/__experimental/net-neg/variables.tf create mode 100644 modules/__experimental/net-neg/versions.tf diff --git a/modules/__experimental/net-neg/README.md b/modules/__experimental/net-neg/README.md new file mode 100644 index 00000000..5a1e6a33 --- /dev/null +++ b/modules/__experimental/net-neg/README.md @@ -0,0 +1,46 @@ +# Network Endpoint Group Module + +This modules allows creating zonal network endpoint groups. + +Note: this module will integrated into a general-purpose load balancing module in the future. + +## Example +```hcl +module "neg" { + source = "./modules/net-neg" + project_id = "myproject" + name = "myneg" + network = module.vpc.self_link + subnetwork = module.vpc.subnet_self_links["europe-west1/default"] + zone = "europe-west1-b" + endpoints = [ + for instance in module.vm.instances : + { + instance = instance.name + port = 80 + ip_address = instance.network_interface[0].network_ip + } + ] +} +``` + + +## Variables + +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| endpoints | List of (instance, port, address) of the NEG | list(object({...})) | ✓ | | +| name | NEG name | string | ✓ | | +| network | Name or self link of the VPC used for the NEG. Use the self link for Shared VPC. | string | ✓ | | +| project_id | NEG project id. | string | ✓ | | +| subnetwork | VPC subnetwork name or self link. | string | ✓ | | +| zone | NEG zone | string | ✓ | | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| id | Network endpoint group ID | | +| self_lnk | Network endpoint group self link | | +| size | Size of the network endpoint group | | + diff --git a/modules/__experimental/net-neg/main.tf b/modules/__experimental/net-neg/main.tf new file mode 100644 index 00000000..ceaa6d8f --- /dev/null +++ b/modules/__experimental/net-neg/main.tf @@ -0,0 +1,33 @@ +/** + * Copyright 2020 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 "google_compute_network_endpoint_group" "group" { + project = var.project_id + name = var.name + network = var.network + subnetwork = var.subnetwork + zone = var.zone +} + +resource "google_compute_network_endpoint" "endpoint" { + for_each = { for endpoint in var.endpoints : endpoint.instance => endpoint } + project = var.project_id + network_endpoint_group = google_compute_network_endpoint_group.group.name + instance = each.value.instance + port = each.value.port + ip_address = each.value.ip_address + zone = var.zone +} diff --git a/modules/__experimental/net-neg/outputs.tf b/modules/__experimental/net-neg/outputs.tf new file mode 100644 index 00000000..c579256b --- /dev/null +++ b/modules/__experimental/net-neg/outputs.tf @@ -0,0 +1,30 @@ +/** + * Copyright 2020 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 "id" { + description = "Network endpoint group ID" + value = google_compute_network_endpoint_group.group.name +} + +output "size" { + description = "Size of the network endpoint group" + value = google_compute_network_endpoint_group.group.size +} + +output "self_lnk" { + description = "Network endpoint group self link" + value = google_compute_network_endpoint_group.group.self_link +} diff --git a/modules/__experimental/net-neg/variables.tf b/modules/__experimental/net-neg/variables.tf new file mode 100644 index 00000000..fdc8c19f --- /dev/null +++ b/modules/__experimental/net-neg/variables.tf @@ -0,0 +1,49 @@ +/** + * Copyright 2020 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 = "NEG project id." + type = string +} + +variable "name" { + description = "NEG name" + type = string +} + +variable "network" { + description = "Name or self link of the VPC used for the NEG. Use the self link for Shared VPC." + type = string +} + +variable "subnetwork" { + description = "VPC subnetwork name or self link." + type = string +} + +variable "zone" { + description = "NEG zone" + type = string +} + +variable "endpoints" { + description = "List of (instance, port, address) of the NEG" + type = list(object({ + instance = string + port = number + ip_address = string + })) +} diff --git a/modules/__experimental/net-neg/versions.tf b/modules/__experimental/net-neg/versions.tf new file mode 100644 index 00000000..bc4c2a9d --- /dev/null +++ b/modules/__experimental/net-neg/versions.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2020 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_version = ">= 0.12.6" +} From 08d244145fe94a5b8b3c6aeee9dafcc59c20bea5 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Mon, 8 Jun 2020 17:36:35 +0200 Subject: [PATCH 065/129] Add e2e example to use Cloud KMS with GCE and GCS. KMS deployed in a separate project to reflect common architecture pattern where companies have a centralized KMS and service projects using crypto keys. --- README.md | 3 +- data-solutions/README.md | 14 ++ data-solutions/cloud-kms/README.md | 65 +++++++++ data-solutions/cloud-kms/backend.tf.sample | 20 +++ data-solutions/cloud-kms/diagram.png | Bin 0 -> 146426 bytes data-solutions/cloud-kms/main.tf | 156 +++++++++++++++++++++ data-solutions/cloud-kms/outputs.tf | 37 +++++ data-solutions/cloud-kms/variables.tf | 72 ++++++++++ data-solutions/cloud-kms/versions.tf | 17 +++ 9 files changed, 383 insertions(+), 1 deletion(-) create mode 100644 data-solutions/README.md create mode 100644 data-solutions/cloud-kms/README.md create mode 100644 data-solutions/cloud-kms/backend.tf.sample create mode 100644 data-solutions/cloud-kms/diagram.png create mode 100644 data-solutions/cloud-kms/main.tf create mode 100644 data-solutions/cloud-kms/outputs.tf create mode 100644 data-solutions/cloud-kms/variables.tf create mode 100644 data-solutions/cloud-kms/versions.tf diff --git a/README.md b/README.md index 53aef3c6..c7ac2d48 100644 --- a/README.md +++ b/README.md @@ -19,8 +19,9 @@ Currently available examples: - **foundations** - [single level hierarchy](./foundations/environments/) (environments), [multiple level hierarchy](./foundations/business-units/) (business units + environments) - **infrastructure** - [hub and spoke via peering](./infrastructure/hub-and-spoke-peering/), [hub and spoke via VPN](./infrastructure/hub-and-spoke-vpn/), [DNS and Google Private Access for on-premises](./infrastructure/onprem-google-access-dns/), [Shared VPC with GKE support](./infrastructure/shared-vpc-gke/) +- **data solutions** - [Cloud KMS with Cloud Storage and Compute Engine](./data-solutions/cloud-kms/) -For more information see the README files in the [foundations](./foundations/) and [infrastructure](./infrastructure/) folders. +For more information see the README files in the [foundations](./foundations/), [infrastructure](./infrastructure/) and [data solutions](./data-solutions/) folders. ## Modules diff --git a/data-solutions/README.md b/data-solutions/README.md new file mode 100644 index 00000000..5e518bf4 --- /dev/null +++ b/data-solutions/README.md @@ -0,0 +1,14 @@ +# GCP Data Services examples + +The examples in this folder implement **typical data servicies topologies**, or **end-to-end scenarios** that allow testing specific features like Cloud KMS to encrypt your data or VPC-SC to mitigate data exfiltration. + +They are meant to be used as minimal but complete starting points to create actual infrastructure, and as playgrounds to experiment with specific Google Cloud features. + +## Examples + +### Cloud KMS with Cloud Storage and Compute Engine + + This [example](./cloud-kms/) implements a project to host a centralized Cloud KMS instance and a service project that will use Crypto keys to encrypt resources at rest. + +The sample highlights roles and permissions needed to implement the architecture described. +
\ No newline at end of file diff --git a/data-solutions/cloud-kms/README.md b/data-solutions/cloud-kms/README.md new file mode 100644 index 00000000..6fc28210 --- /dev/null +++ b/data-solutions/cloud-kms/README.md @@ -0,0 +1,65 @@ +# Cloud KMS with Cloud Storage and Compute Engine + +This sample creates a sample [Cloud KMS](https://cloud.google.com/kms?hl=it) configuration to be used with [Cloud Storage](https://cloud.google.com/storage/docs/encryption/using-customer-managed-keys) and [Copute Engine](https://cloud.google.com/compute/docs/disks/customer-managed-encryption). +Cloud KMS is deployed in a separate project to highlight the IAM binding needed and to mock a more real scenario where you usually have a project to manage keys across all your projects in one single place. + +The sample has been purposefully kept simple so that it can be used as a basis for different and more complex configuration. This is the high level diagram: + +![High-level diagram](diagram.png "High-level diagram") + +## Managed resources and services + +This sample creates several distinct groups of resources: + +- projects + - Cloud KMS project + - Service Project configured for GCE instances and GCS buckets +- networking + - VPC network + - One subnet + - Firewall rules for [SSH access via IAP](https://cloud.google.com/iap/docs/using-tcp-forwarding) and open communication within the VPC +- IAM + - One service account for the GGE instance +- KMS + - One key ring + - One crypto key (Procection level: softwere) for Cloud Engine + - One crypto key (Protection level: softwere) for Cloud Storage +- GCE + - One instance encrypted with a CMEK Cryptokey hosted in Cloud KMS +- GCS + - One bucket encrypted with a CMEK Cryptokey hosted in Cloud KMS + +## Accessing the bastion instance and GKE cluster + +The bastion VM has no public address so access is mediated via [IAP](https://cloud.google.com/iap/docs), which is supported transparently in the `gcloud compute ssh` command. Authentication is via OS Login set as a project default. + +Cluster access from the bastion can leverage the instance service account's `container.developer` role: the only configuration needed is to fetch cluster credentials via `gcloud container clusters get-credentials` passing the correct cluster name, location and project via command options. + +## Destroying + +There's a minor glitch that can surface running `terraform destroy`, where the service project attachments to the Shared VPC will not get destroyed even with the relevant API call succeeding. We are investigating the issue, in the meantime just manually remove the attachment in the Cloud console or via the `gcloud beta compute shared-vpc associated-projects remove` command when `terraform destroy` fails, and then relaunch the command. + + +## Variables + +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| billing_account | Billing account id used as default for new projects. | string | ✓ | | +| projects_parent | The resource name of the parent Folder or Organization. Must be of the form folders/folder_id or organizations/org_id. | string | ✓ | | +| *project_kms_name* | Name for the new KMS Project. | string | | my-project-kms-001 | +| *project_service_name* | Name for the new Service Project. | string | | my-project-service-001 | +| *resource_location* | The location where resources will be deployed. | string | | europe | +| *resource_region* | The region where resources will be deployed. | string | | europe-west1 | +| *resource_zone* | The zone where resources will be deployed. | string | | europe-west1-b | +| *vpc_ip_cidr_range* | Ip range used in the subnet deployef in the Service Project. | string | | 10.0.0.0/20 | +| *vpc_name* | Name of the VPC created in the Service Project. | string | | local | +| *vpc_subnet_name* | Name of the subnet created in the Service Project. | string | | subnet | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| buckets_keys | GCS Buckets Cloud KMS crypto keys. | | +| projects | Project ids. | | +| vms_keys | GCE VMs Cloud KMS crypto keys. | | + diff --git a/data-solutions/cloud-kms/backend.tf.sample b/data-solutions/cloud-kms/backend.tf.sample new file mode 100644 index 00000000..a540c7cd --- /dev/null +++ b/data-solutions/cloud-kms/backend.tf.sample @@ -0,0 +1,20 @@ +# Copyright 2020 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 +# +# https://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 { + backend "gcs" { + bucket = "" + } +} diff --git a/data-solutions/cloud-kms/diagram.png b/data-solutions/cloud-kms/diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..a2bac201bd8010f3e2716d83076bc0110e55c530 GIT binary patch literal 146426 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

>m?GXo+!d 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 Re7CIg+7;(ts%-rK`Cphz=M?|| literal 0 HcmV?d00001 diff --git a/data-solutions/cloud-kms/main.tf b/data-solutions/cloud-kms/main.tf new file mode 100644 index 00000000..d75e0c95 --- /dev/null +++ b/data-solutions/cloud-kms/main.tf @@ -0,0 +1,156 @@ +# Copyright 2020 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 +# +# https://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. + +############################################################################### +# Projects # +############################################################################### + +module "project-service" { + source = "../../modules/project" + name = var.project_service_name + parent = var.projects_parent + billing_account = var.billing_account + services = [ + "compute.googleapis.com", + "servicenetworking.googleapis.com", + "storage-component.googleapis.com" + ] + oslogin = true +} + +module "project-kms" { + source = "../../modules/project" + name = var.project_kms_name + parent = var.projects_parent + billing_account = var.billing_account + services = [ + "cloudkms.googleapis.com", + "servicenetworking.googleapis.com" + ] + oslogin = true +} + +############################################################################### +# Networking # +############################################################################### + +module "vpc" { + source = "../../modules/net-vpc" + project_id = module.project-service.project_id + name = var.vpc_name + subnets = [ + { + ip_cidr_range = var.vpc_ip_cidr_range + name = var.vpc_subnet_name + region = var.resource_region + secondary_ip_range = {} + } + ] +} + +module "vpc-firewall" { + source = "../../modules/net-vpc-firewall" + project_id = module.project-service.project_id + network = module.vpc.name + admin_ranges_enabled = true + admin_ranges = [var.vpc_ip_cidr_range] + ssh_source_ranges = ["0.0.0.0/0"] +} + +############################################################################### +# KMS # +############################################################################### + +module "kms" { + source = "../../modules/kms" + project_id = module.project-kms.project_id + keyring = { + name = "my-keyring", + location = var.resource_location + } + keys = { key-gce = null, key-gcs = null } + key_iam_roles = { + key-gce = ["roles/cloudkms.cryptoKeyEncrypterDecrypter"] + } + key_iam_members = { + key-gce = { + "roles/cloudkms.cryptoKeyEncrypterDecrypter" = [ + "serviceAccount:${module.project-service.service_accounts.robots.compute}", + ] + }, + key-gcs = { + "roles/cloudkms.cryptoKeyEncrypterDecrypter" = [ + "serviceAccount:${module.project-service.service_accounts.robots.storage}", + ] + } + } +} + +############################################################################### +# GCE # +############################################################################### + +module "kms_vm_example" { + source = "../../modules/compute-vm" + project_id = module.project-service.project_id + region = var.resource_region + zone = var.resource_zone + name = "kms-vm" + network_interfaces = [{ + network = module.vpc.self_link, + subnetwork = module.vpc.subnet_self_links["${var.resource_region}/subnet"], + nat = false, + addresses = null + }] + attached_disks = [ + { + name = "attacheddisk" + size = 10 + image = null + options = { + auto_delete = true + mode = null + source = null + type = null + } + } + ] + instance_count = 1 + boot_disk = { + image = "projects/debian-cloud/global/images/family/debian-10" + type = "pd-ssd" + size = 10 + encrypt_disk = true + } + tags = ["ssh"] + encryption = { + encrypt_boot = true + disk_encryption_key_raw = null + kms_key_self_link = module.kms.key_self_links.key-gce + } +} + +############################################################################### +# GCS # +############################################################################### + +module "kms-gcs" { + source = "../../modules/gcs" + project_id = module.project-service.project_id + prefix = "my-bucket-001" + names = ["kms-gcs"] + encryption_key = { + kms-gcs = module.kms.keys.key-gce.self_link, + } +} diff --git a/data-solutions/cloud-kms/outputs.tf b/data-solutions/cloud-kms/outputs.tf new file mode 100644 index 00000000..0da4c1d2 --- /dev/null +++ b/data-solutions/cloud-kms/outputs.tf @@ -0,0 +1,37 @@ +# Copyright 2020 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 +# +# https://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 "projects" { + description = "Project ids." + value = { + service-project = module.project-service.project_id + kms-project = module.project-kms.project_id + } +} + +output "vms_keys" { + description = "GCE VMs Cloud KMS crypto keys." + value = { + for instance in module.kms_vm_example.instances : + instance.name => instance.boot_disk.0.kms_key_self_link + } +} + +output "buckets_keys" { + description = "GCS Buckets Cloud KMS crypto keys." + value = { + for bucket in module.kms-gcs.buckets : + bucket.name => bucket.encryption + } +} diff --git a/data-solutions/cloud-kms/variables.tf b/data-solutions/cloud-kms/variables.tf new file mode 100644 index 00000000..34f2ea58 --- /dev/null +++ b/data-solutions/cloud-kms/variables.tf @@ -0,0 +1,72 @@ +# Copyright 2020 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 +# +# https://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 "billing_account" { + description = "Billing account id used as default for new projects." + type = string +} + +variable "project_service_name" { + description = "Name for the new Service Project." + type = string + default = "my-project-service-001" +} + +variable "project_kms_name" { + description = "Name for the new KMS Project." + type = string + default = "my-project-kms-001" +} + +variable "projects_parent" { + description = "The resource name of the parent Folder or Organization. Must be of the form folders/folder_id or organizations/org_id." + type = string +} + +variable "resource_location" { + description = "The location where resources will be deployed." + type = string + default = "europe" +} + +variable "resource_region" { + description = "The region where resources will be deployed." + type = string + default = "europe-west1" +} + +variable "resource_zone" { + description = "The zone where resources will be deployed." + type = string + default = "europe-west1-b" +} + +variable "vpc_name" { + description = "Name of the VPC created in the Service Project." + type = string + default = "local" +} + +variable "vpc_subnet_name" { + description = "Name of the subnet created in the Service Project." + type = string + default = "subnet" +} + +variable "vpc_ip_cidr_range" { + description = "Ip range used in the subnet deployef in the Service Project." + type = string + default = "10.0.0.0/20" +} diff --git a/data-solutions/cloud-kms/versions.tf b/data-solutions/cloud-kms/versions.tf new file mode 100644 index 00000000..de5425c2 --- /dev/null +++ b/data-solutions/cloud-kms/versions.tf @@ -0,0 +1,17 @@ +# Copyright 2020 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 +# +# https://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_version = ">= 0.12" +} From 644522d4953d18a4797e227caae69f58dfb40718 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Mon, 8 Jun 2020 17:51:02 +0200 Subject: [PATCH 066/129] Fix readme --- data-solutions/cloud-kms/README.md | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/data-solutions/cloud-kms/README.md b/data-solutions/cloud-kms/README.md index 6fc28210..058a6aca 100644 --- a/data-solutions/cloud-kms/README.md +++ b/data-solutions/cloud-kms/README.md @@ -29,16 +29,6 @@ This sample creates several distinct groups of resources: - GCS - One bucket encrypted with a CMEK Cryptokey hosted in Cloud KMS -## Accessing the bastion instance and GKE cluster - -The bastion VM has no public address so access is mediated via [IAP](https://cloud.google.com/iap/docs), which is supported transparently in the `gcloud compute ssh` command. Authentication is via OS Login set as a project default. - -Cluster access from the bastion can leverage the instance service account's `container.developer` role: the only configuration needed is to fetch cluster credentials via `gcloud container clusters get-credentials` passing the correct cluster name, location and project via command options. - -## Destroying - -There's a minor glitch that can surface running `terraform destroy`, where the service project attachments to the Shared VPC will not get destroyed even with the relevant API call succeeding. We are investigating the issue, in the meantime just manually remove the attachment in the Cloud console or via the `gcloud beta compute shared-vpc associated-projects remove` command when `terraform destroy` fails, and then relaunch the command. - ## Variables From 9706d2c386be8106e761e5de13a209e48ce76616 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Tue, 9 Jun 2020 02:40:26 +0200 Subject: [PATCH 067/129] Add BigTable module --- modules/bigtable-instance/README.md | 59 ++++++++++++++ modules/bigtable-instance/main.tf | 68 ++++++++++++++++ modules/bigtable-instance/outputs.tf | 46 +++++++++++ modules/bigtable-instance/variables.tf | 105 +++++++++++++++++++++++++ modules/bigtable-instance/versions.tf | 19 +++++ 5 files changed, 297 insertions(+) create mode 100644 modules/bigtable-instance/README.md create mode 100644 modules/bigtable-instance/main.tf create mode 100644 modules/bigtable-instance/outputs.tf create mode 100644 modules/bigtable-instance/variables.tf create mode 100644 modules/bigtable-instance/versions.tf diff --git a/modules/bigtable-instance/README.md b/modules/bigtable-instance/README.md new file mode 100644 index 00000000..d34e6bbc --- /dev/null +++ b/modules/bigtable-instance/README.md @@ -0,0 +1,59 @@ +# Google Cloud BigTable Module + +This module allows managing a single BigTable instance, including access configuration and tables. + +## TODO + +- [ ] support bigtable_gc_policy +- [ ] support bigtable_app_profile + +## Examples + +### Simple instance with access configuration + +```hcl + +module "big-table-instance" { + source = "./modules/bigtable-instance" + project_id = "my-project" + name = "instance" + cluster_id = "instance" + instance_type = "PRODUCTION" + tables = ["table1","table2"] + access_roles = ["viewer"] + access_roles_binding = { + viewer = ["user:viewer@testdomain.com"] + } +} +``` + + +## Variables + +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| name | he name of the Cloud Bigtable instance. | string | ✓ | | +| project_id | Id of the project where datasets will be created. | string | ✓ | | +| *access_roles* | Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. | list(string) | | [] | +| *access_roles_binding* | Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. Other roles within the IAM policy for the instance are preserved. | map(list(string)) | | {} | +| *cluster_id* | The ID of the Cloud Bigtable cluster. | string | | europe-west1 | +| *deletion_protection* | Whether or not to allow Terraform to destroy the instance. Unless this field is set to false in Terraform state, a terraform destroy or terraform apply that would delete the instance will fail. | | | true | +| *display_name* | The human-readable display name of the Bigtable instance. | | | null | +| *instance_type* | None | string | | DEVELOPMENT | +| *num_nodes* | The number of nodes in your Cloud Bigtable cluster. | number | | 1 | +| *storage_type* | The storage type to use. | string | | SSD | +| *table_options_default* | Default option of tables created in the BigTable instnace. | object({...}) | | ... | +| *tables* | Tables to be created in the BigTable instnace. | list(string) | | [] | +| *tables_options* | Tables to be created in the BigTable instnace. | map(object({...})) | | {} | +| *zone* | The zone to create the Cloud Bigtable cluster in. | string | | europe-west1-b | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| id | An identifier for the resource with format projects/{{project}}/instances/{{name}}. | | +| instance | BigTable intance. | | +| table_ids | Map of fully qualified table ids keyed by table name. | | +| tables | Table resources. | | + + diff --git a/modules/bigtable-instance/main.tf b/modules/bigtable-instance/main.tf new file mode 100644 index 00000000..e8beacf8 --- /dev/null +++ b/modules/bigtable-instance/main.tf @@ -0,0 +1,68 @@ +/** + * Copyright 2020 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 { + tables = { + for k in var.tables : k => lookup(var.tables_options, k, var.table_options_default) + } + + access_roles_bindings = { + for k in var.access_roles : k => lookup(var.access_roles_binding, k, []) + } +} + +resource "google_bigtable_instance" "default" { + project = var.project_id + name = var.name + cluster { + cluster_id = var.cluster_id + zone = var.zone + storage_type = var.storage_type + } + instance_type = var.instance_type + + display_name = var.display_name == null ? var.display_name : var.name + deletion_protection = var.deletion_protection +} + +resource "google_bigtable_instance_iam_binding" "default" { + for_each = local.access_roles_bindings + + project = var.project_id + instance = google_bigtable_instance.default.name + role = "roles/bigtable.${each.key}" + members = each.value +} + +resource "google_bigtable_table" "default" { + for_each = local.tables + project = var.project_id + instance_name = google_bigtable_instance.default.name + name = each.key + split_keys = each.value.split_keys + + dynamic column_family { + for_each = each.value.column_family != null ? [""] : [] + + content { + family = each.value.column_family + } + } + + # lifecycle { + # prevent_destroy = true + # } +} diff --git a/modules/bigtable-instance/outputs.tf b/modules/bigtable-instance/outputs.tf new file mode 100644 index 00000000..2012b5c6 --- /dev/null +++ b/modules/bigtable-instance/outputs.tf @@ -0,0 +1,46 @@ +/** + * Copyright 2020 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 "id" { + description = "An identifier for the resource with format projects/{{project}}/instances/{{name}}." + value = google_bigtable_instance.default.id + depends_on = [ + google_bigtable_instance_iam_binding, + google_bigtable_table + ] +} + +output "instance" { + description = "BigTable intance." + value = google_bigtable_instance.default + depends_on = [ + google_bigtable_instance_iam_binding, + google_bigtable_table + ] +} + +output "tables" { + description = "Table resources." + value = google_bigtable_table.default +} + +output "table_ids" { + description = "Map of fully qualified table ids keyed by table name." + value = { for k, v in google_bigtable_table.default : v.name => v.id } +} + + + diff --git a/modules/bigtable-instance/variables.tf b/modules/bigtable-instance/variables.tf new file mode 100644 index 00000000..16066b13 --- /dev/null +++ b/modules/bigtable-instance/variables.tf @@ -0,0 +1,105 @@ +/** + * Copyright 2019 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 "access_roles" { + description = "Authoritative for a given role. Updates the IAM policy to grant a role to a list of members." + type = list(string) + default = [] +} + +variable "access_roles_binding" { + description = "Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. Other roles within the IAM policy for the instance are preserved." + type = map(list(string)) + default = {} +} + +variable "cluster_id" { + description = "The ID of the Cloud Bigtable cluster." + type = string + default = "europe-west1" +} + +variable "deletion_protection" { + description = "Whether or not to allow Terraform to destroy the instance. Unless this field is set to false in Terraform state, a terraform destroy or terraform apply that would delete the instance will fail." + default = true +} + +variable "display_name" { + description = "The human-readable display name of the Bigtable instance." + default = null +} + +variable "instance_type" { + description = "The instance type to create. One of \"DEVELOPMENT\" or \"PRODUCTION\". Defaults to \"DEVELOPMENT\"" + type = string + default = "DEVELOPMENT" +} + +variable "name" { + description = "he name of the Cloud Bigtable instance." + type = string +} + +variable "num_nodes" { + description = "The number of nodes in your Cloud Bigtable cluster." + type = number + default = 1 +} + +variable "project_id" { + description = "Id of the project where datasets will be created." + type = string +} + +variable "storage_type" { + description = "The storage type to use." + type = string + default = "SSD" +} + +variable "tables" { + description = "Tables to be created in the BigTable instnace." + type = list(string) + default = [] +} + +variable "tables_options" { + description = "Tables to be created in the BigTable instnace." + type = map(object({ + split_keys = list(string) + column_family = string + }) + ) + default = {} +} + +variable "table_options_default" { + description = "Default option of tables created in the BigTable instnace." + type = object({ + split_keys = list(string) + column_family = string + }) + default = { + split_keys = [] + column_family = null + } +} + +variable "zone" { + description = "The zone to create the Cloud Bigtable cluster in." + type = string + default = "europe-west1-b" +} diff --git a/modules/bigtable-instance/versions.tf b/modules/bigtable-instance/versions.tf new file mode 100644 index 00000000..ce6918e0 --- /dev/null +++ b/modules/bigtable-instance/versions.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2019 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_version = ">= 0.12.6" +} From 8d75a278a62c88eabc19c1f3cbb4c99b08511bef Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Tue, 9 Jun 2020 15:55:22 +0200 Subject: [PATCH 068/129] Fixes --- modules/bigtable-instance/main.tf | 8 ++++---- modules/bigtable-instance/variables.tf | 26 ++++++++++---------------- 2 files changed, 14 insertions(+), 20 deletions(-) diff --git a/modules/bigtable-instance/main.tf b/modules/bigtable-instance/main.tf index e8beacf8..0e7129ff 100644 --- a/modules/bigtable-instance/main.tf +++ b/modules/bigtable-instance/main.tf @@ -16,11 +16,11 @@ locals { tables = { - for k in var.tables : k => lookup(var.tables_options, k, var.table_options_default) + for k, v in var.tables : k => v.table_options != null ? v.table_options : var.table_options_defaults } - access_roles_bindings = { - for k in var.access_roles : k => lookup(var.access_roles_binding, k, []) + iam_roles_bindings = { + for k in var.iam_roles : k => lookup(var.iam_members, k, []) } } @@ -39,7 +39,7 @@ resource "google_bigtable_instance" "default" { } resource "google_bigtable_instance_iam_binding" "default" { - for_each = local.access_roles_bindings + for_each = local.iam_roles_bindings project = var.project_id instance = google_bigtable_instance.default.name diff --git a/modules/bigtable-instance/variables.tf b/modules/bigtable-instance/variables.tf index 16066b13..982bfb8a 100644 --- a/modules/bigtable-instance/variables.tf +++ b/modules/bigtable-instance/variables.tf @@ -14,13 +14,13 @@ * limitations under the License. */ -variable "access_roles" { +variable "iam_roles" { description = "Authoritative for a given role. Updates the IAM policy to grant a role to a list of members." type = list(string) default = [] } -variable "access_roles_binding" { +variable "iam_members" { description = "Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. Other roles within the IAM policy for the instance are preserved." type = map(list(string)) default = {} @@ -49,7 +49,7 @@ variable "instance_type" { } variable "name" { - description = "he name of the Cloud Bigtable instance." + description = "The name of the Cloud Bigtable instance." type = string } @@ -71,23 +71,18 @@ variable "storage_type" { } variable "tables" { - description = "Tables to be created in the BigTable instnace." - type = list(string) - default = [] -} - -variable "tables_options" { - description = "Tables to be created in the BigTable instnace." + description = "Tables to be created in the BigTable instance." type = map(object({ - split_keys = list(string) - column_family = string + table_options = object({ + split_keys = list(string) + column_family = string }) - ) + })) default = {} } -variable "table_options_default" { - description = "Default option of tables created in the BigTable instnace." +variable "table_options_defaults" { + description = "Default option of tables created in the BigTable instance." type = object({ split_keys = list(string) column_family = string @@ -101,5 +96,4 @@ variable "table_options_default" { variable "zone" { description = "The zone to create the Cloud Bigtable cluster in." type = string - default = "europe-west1-b" } From 2f97d246f60bd3f5f1a91add3ff4c80778175da9 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Tue, 9 Jun 2020 16:03:10 +0200 Subject: [PATCH 069/129] Fix README --- modules/bigtable-instance/README.md | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/modules/bigtable-instance/README.md b/modules/bigtable-instance/README.md index d34e6bbc..f63e1cf0 100644 --- a/modules/bigtable-instance/README.md +++ b/modules/bigtable-instance/README.md @@ -19,9 +19,16 @@ module "big-table-instance" { name = "instance" cluster_id = "instance" instance_type = "PRODUCTION" - tables = ["table1","table2"] - access_roles = ["viewer"] - access_roles_binding = { + tables = { + test1 = { table_options = null }, + test2 = { table_options = { + split_keys = ["a", "b", "c"] + column_family = null + } + } + } + iam_roles = ["viewer"] + iam_members = { viewer = ["user:viewer@testdomain.com"] } } @@ -32,20 +39,19 @@ module "big-table-instance" { | name | description | type | required | default | |---|---|:---: |:---:|:---:| -| name | he name of the Cloud Bigtable instance. | string | ✓ | | +| name | The name of the Cloud Bigtable instance. | string | ✓ | | | project_id | Id of the project where datasets will be created. | string | ✓ | | -| *access_roles* | Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. | list(string) | | [] | -| *access_roles_binding* | Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. Other roles within the IAM policy for the instance are preserved. | map(list(string)) | | {} | +| zone | The zone to create the Cloud Bigtable cluster in. | string | ✓ | | | *cluster_id* | The ID of the Cloud Bigtable cluster. | string | | europe-west1 | | *deletion_protection* | Whether or not to allow Terraform to destroy the instance. Unless this field is set to false in Terraform state, a terraform destroy or terraform apply that would delete the instance will fail. | | | true | | *display_name* | The human-readable display name of the Bigtable instance. | | | null | +| *iam_members* | Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. Other roles within the IAM policy for the instance are preserved. | map(list(string)) | | {} | +| *iam_roles* | Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. | list(string) | | [] | | *instance_type* | None | string | | DEVELOPMENT | | *num_nodes* | The number of nodes in your Cloud Bigtable cluster. | number | | 1 | | *storage_type* | The storage type to use. | string | | SSD | -| *table_options_default* | Default option of tables created in the BigTable instnace. | object({...}) | | ... | -| *tables* | Tables to be created in the BigTable instnace. | list(string) | | [] | -| *tables_options* | Tables to be created in the BigTable instnace. | map(object({...})) | | {} | -| *zone* | The zone to create the Cloud Bigtable cluster in. | string | | europe-west1-b | +| *table_options_defaults* | Default option of tables created in the BigTable instance. | object({...}) | | ... | +| *tables* | Tables to be created in the BigTable instance. | map(object({...})) | | {} | ## Outputs From 14841180496cde41adcd84e95845deab953c008c Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Tue, 9 Jun 2020 16:25:05 +0200 Subject: [PATCH 070/129] update top-level README update modules/README update CHANGELOG --- CHANGELOG.md | 1 + README.md | 2 +- modules/README.md | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ae000b79..806597ea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- new `bigtable-instance` module ## [1.8.1] - 2020-06-07 diff --git a/README.md b/README.md index 53aef3c6..71d5f86f 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Currently available modules: - **foundational** - [folders](./modules/folders), [log sinks](./modules/logging-sinks), [organization](./modules/organization), [project](./modules/project), [service accounts](./modules/iam-service-accounts) - **networking** - [VPC](./modules/net-vpc), [VPC firewall](./modules/net-vpc-firewall), [VPC peering](./modules/net-vpc-peering), [VPN static](./modules/net-vpn-static), [VPN dynamic](./modules/net-vpn-dynamic), [VPN HA](./modules/net-vpn-ha), [NAT](./modules/net-cloudnat), [address reservation](./modules/net-address), [DNS](./modules/dns), [L4 ILB](./modules/net-ilb), [Service Directory](./modules/service-directory) - **compute** - [VM/VM group](./modules/compute-vm), [MIG](./modules/compute-mig), [GKE cluster](./modules/gke-cluster), [GKE nodepool](./modules/gke-nodepool), [COS container](./modules/cos-container) (coredns, mysql, onprem, squid) -- **data** - [GCS](./modules/gcs), [BigQuery dataset](./modules/bigquery-dataset), [Pub/Sub](./modules/pubsub), [Datafusion](./modules/datafusion) +- **data** - [GCS](./modules/gcs), [BigQuery dataset](./modules/bigquery-dataset), [Pub/Sub](./modules/pubsub), [Datafusion](./modules/datafusion), [Bigtable instance](./modules/bigtable-instance) - **security** - [KMS](./modules/kms), [SecretManager](./modules/secret-manager) - **development** - [Cloud Source Repository](./modules/source-repository), [Container Registry](./modules/container-registry), [Artifact Registry](./modules/artifact-registry) diff --git a/modules/README.md b/modules/README.md index b95c87d4..a831c734 100644 --- a/modules/README.md +++ b/modules/README.md @@ -45,6 +45,7 @@ Specific modules also offer support for non-authoritative bindings (e.g. `google - [Datafusion](./datafusion) - [GCS](./gcs) - [Pub/Sub](./pubsub) +- [Bigtable instance](./bigtable-instance) ## Development From 61bf03d143bdf337c89a4f9b7b62b722a99d70f1 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Tue, 9 Jun 2020 17:21:07 +0200 Subject: [PATCH 071/129] Update README.md --- modules/folders/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/folders/README.md b/modules/folders/README.md index 24117707..7efb4b68 100644 --- a/modules/folders/README.md +++ b/modules/folders/README.md @@ -13,7 +13,7 @@ module "folder" { names = ["Folder one", "Folder two"] iam_members = { "Folder one" = { - "roles/owner" => ["group:users@example.com"] + "roles/owner" = ["group:users@example.com"] } } iam_roles = { From 25d3b2ebdd2cb68ccfa89d33013e32bf00d357bb Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 10 Jun 2020 07:55:18 +0200 Subject: [PATCH 072/129] add iam support to compute-vm module (#95) --- modules/compute-vm/README.md | 2 + modules/compute-vm/main.tf | 13 +++++++ modules/compute-vm/variables.tf | 12 ++++++ tests/modules/compute_vm/fixture/main.tf | 2 + tests/modules/compute_vm/fixture/variables.tf | 10 +++++ tests/modules/compute_vm/test_plan.py | 37 +++++++++++++++---- 6 files changed, 69 insertions(+), 7 deletions(-) diff --git a/modules/compute-vm/README.md b/modules/compute-vm/README.md index 4e37dc7e..91b35abb 100644 --- a/modules/compute-vm/README.md +++ b/modules/compute-vm/README.md @@ -155,6 +155,8 @@ module "instance-group" { | *encryption* | Encryption options. Only one of kms_key_self_link and disk_encryption_key_raw may be set. If needed, you can specify to encrypt or not the boot disk. | object({...}) | | null | | *group* | Define this variable to create an instance group for instances. Disabled for template use. | object({...}) | | null | | *hostname* | Instance FQDN name. | string | | null | +| *iam_members* | Map of member lists used to set authoritative bindings, keyed by role. Ignored for template use. | map(list(string)) | | {} | +| *iam_roles* | List of roles used to set authoritative bindings. Ignored for template use. | list(string) | | [] | | *instance_count* | Number of instances to create (only for non-template usage). | number | | 1 | | *instance_type* | Instance type. | string | | f1-micro | | *labels* | Instance labels. | map(string) | | {} | diff --git a/modules/compute-vm/main.tf b/modules/compute-vm/main.tf index 7542e114..08981b71 100644 --- a/modules/compute-vm/main.tf +++ b/modules/compute-vm/main.tf @@ -25,6 +25,10 @@ locals { for pair in setproduct(keys(local.names), keys(local.attached_disks)) : "${pair[0]}-${pair[1]}" => { name = pair[0], disk_name = pair[1] } } + iam_roles = var.use_instance_template ? {} : { + for pair in setproduct(var.iam_roles, keys(local.names)) : + "${pair.0}/${pair.1}" => { role = pair.0, name = pair.1 } + } names = ( var.use_instance_template ? { "${var.name}" = 0 } @@ -164,6 +168,15 @@ resource "google_compute_instance" "default" { } +resource "google_compute_instance_iam_binding" "default" { + for_each = local.iam_roles + project = var.project_id + zone = var.zone + instance_name = each.value.name + role = each.value.role + members = lookup(var.iam_members, each.value.role, []) +} + resource "google_compute_instance_template" "default" { count = var.use_instance_template ? 1 : 0 project = var.project_id diff --git a/modules/compute-vm/variables.tf b/modules/compute-vm/variables.tf index 0470290d..2102d2fb 100644 --- a/modules/compute-vm/variables.tf +++ b/modules/compute-vm/variables.tf @@ -84,6 +84,18 @@ variable "hostname" { default = null } +variable "iam_members" { + description = "Map of member lists used to set authoritative bindings, keyed by role. Ignored for template use." + type = map(list(string)) + default = {} +} + +variable "iam_roles" { + description = "List of roles used to set authoritative bindings. Ignored for template use." + type = list(string) + default = [] +} + variable "instance_count" { description = "Number of instances to create (only for non-template usage)." type = number diff --git a/tests/modules/compute_vm/fixture/main.tf b/tests/modules/compute_vm/fixture/main.tf index a1348834..41999d08 100644 --- a/tests/modules/compute_vm/fixture/main.tf +++ b/tests/modules/compute_vm/fixture/main.tf @@ -30,4 +30,6 @@ module "test" { instance_count = var.instance_count use_instance_template = var.use_instance_template group = var.group + iam_roles = var.iam_roles + iam_members = var.iam_members } diff --git a/tests/modules/compute_vm/fixture/variables.tf b/tests/modules/compute_vm/fixture/variables.tf index 7191d315..118383fb 100644 --- a/tests/modules/compute_vm/fixture/variables.tf +++ b/tests/modules/compute_vm/fixture/variables.tf @@ -19,6 +19,16 @@ variable "group" { default = null } +variable "iam_members" { + type = map(list(string)) + default = {} +} + +variable "iam_roles" { + type = list(string) + default = [] +} + variable "instance_count" { type = number default = 1 diff --git a/tests/modules/compute_vm/test_plan.py b/tests/modules/compute_vm/test_plan.py index 733ee1ee..a37b55ac 100644 --- a/tests/modules/compute_vm/test_plan.py +++ b/tests/modules/compute_vm/test_plan.py @@ -21,35 +21,58 @@ FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture') def test_single_instance(plan_runner): - plan, resources = plan_runner(FIXTURES_DIR) + _, resources = plan_runner(FIXTURES_DIR) assert len(resources) == 1 assert resources[0]['type'] == 'google_compute_instance' def test_multiple_instances(plan_runner): - plan, resources = plan_runner(FIXTURES_DIR, instance_count=2) + _, resources = plan_runner(FIXTURES_DIR, instance_count=2) assert len(resources) == 2 assert set(r['type'] for r in resources) == set(['google_compute_instance']) def test_service_account(plan_runner): - plan, resources = plan_runner(FIXTURES_DIR, instance_count=2, - service_account_create='true') + _, resources = plan_runner(FIXTURES_DIR, instance_count=2, + service_account_create='true') assert len(resources) == 3 assert 'google_service_account' in [r['type'] for r in resources] def test_template(plan_runner): - plan, resources = plan_runner(FIXTURES_DIR, use_instance_template='true') + _, resources = plan_runner(FIXTURES_DIR, use_instance_template='true') assert len(resources) == 1 assert resources[0]['type'] == 'google_compute_instance_template' assert resources[0]['values']['name_prefix'] == 'test-' def test_group(plan_runner): - plan, resources = plan_runner(FIXTURES_DIR, instance_count=2, - group='{named_ports={}}') + _, resources = plan_runner(FIXTURES_DIR, instance_count=2, + group='{named_ports={}}') assert len(resources) == 3 assert set(r['type'] for r in resources) == set([ 'google_compute_instance_group', 'google_compute_instance' ]) + + +def test_iam(plan_runner): + iam_roles = '["roles/compute.instanceAdmin", "roles/iam.serviceAccountUser"]' + iam_members = ( + '{"roles/compute.instanceAdmin" = ["user:a@a.com", "user:b@a.com"],' + '"roles/iam.serviceAccountUser" = ["user:a@a.com"]}' + ) + _, resources = plan_runner( + FIXTURES_DIR, instance_count=2, iam_roles=iam_roles, iam_members=iam_members) + assert len(resources) == 6 + assert set(r['type'] for r in resources) == set([ + 'google_compute_instance', 'google_compute_instance_iam_binding']) + iam_bindings = dict( + (r['index'], r['values']['members']) for r in resources if r['type'] + == 'google_compute_instance_iam_binding' + ) + assert iam_bindings == { + 'roles/compute.instanceAdmin/test-1': ['user:a@a.com', 'user:b@a.com'], + 'roles/compute.instanceAdmin/test-2': ['user:a@a.com', 'user:b@a.com'], + 'roles/iam.serviceAccountUser/test-1': ['user:a@a.com'], + 'roles/iam.serviceAccountUser/test-2': ['user:a@a.com'], + } From 0a742b50fef3c3c1ebb8f5373c2987384e987fdc Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 10 Jun 2020 07:56:41 +0200 Subject: [PATCH 073/129] Update CHANGELOG.md --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 806597ea..523305e8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,11 @@ All notable changes to this project will be documented in this file. ## [Unreleased] + +## [1.9.0] - 2020-06-10 + - new `bigtable-instance` module +- add support for IAM bindings to `compute-vm` module ## [1.8.1] - 2020-06-07 @@ -87,7 +91,8 @@ All notable changes to this project will be documented in this file. - merge development branch with suite of new modules and end-to-end examples -[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.8.1...HEAD +[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.9.0...HEAD +[1.9.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.8.1...v1.9.0 [1.8.1]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.8.0...v1.8.1 [1.8.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.7.0...v1.8.0 [1.7.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.6.0...v1.7.0 From 45bbae29e77d932cab534f379792beec493b1631 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 10 Jun 2020 13:29:44 +0200 Subject: [PATCH 074/129] Update README.md --- data-solutions/README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/data-solutions/README.md b/data-solutions/README.md index 5e518bf4..f9e7e87a 100644 --- a/data-solutions/README.md +++ b/data-solutions/README.md @@ -1,6 +1,6 @@ # GCP Data Services examples -The examples in this folder implement **typical data servicies topologies**, or **end-to-end scenarios** that allow testing specific features like Cloud KMS to encrypt your data or VPC-SC to mitigate data exfiltration. +The examples in this folder implement **typical data service topologies** and **end-to-end scenarios**, that allow testing specific features like Cloud KMS to encrypt your data, or VPC-SC to mitigate data exfiltration. They are meant to be used as minimal but complete starting points to create actual infrastructure, and as playgrounds to experiment with specific Google Cloud features. @@ -8,7 +8,4 @@ They are meant to be used as minimal but complete starting points to create actu ### Cloud KMS with Cloud Storage and Compute Engine - This [example](./cloud-kms/) implements a project to host a centralized Cloud KMS instance and a service project that will use Crypto keys to encrypt resources at rest. - -The sample highlights roles and permissions needed to implement the architecture described. -
\ No newline at end of file + This [example](./cloud-kms/) implements a project that hosts a centralized Cloud KMS instance, and a second project where KMS keys will be used to encrypt resources at rest (CMEK). The roles and permissions needed to use the services are part of the example. From 1f7963a0679362beb0640bb4110f3a6aa313c6fe Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 10 Jun 2020 13:34:49 +0200 Subject: [PATCH 075/129] Update README.md --- data-solutions/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data-solutions/README.md b/data-solutions/README.md index f9e7e87a..4a6889be 100644 --- a/data-solutions/README.md +++ b/data-solutions/README.md @@ -6,6 +6,6 @@ They are meant to be used as minimal but complete starting points to create actu ## Examples -### Cloud KMS with Cloud Storage and Compute Engine +### CMEK for Cloud Storage and Compute Engine via centralized KMS - This [example](./cloud-kms/) implements a project that hosts a centralized Cloud KMS instance, and a second project where KMS keys will be used to encrypt resources at rest (CMEK). The roles and permissions needed to use the services are part of the example. + This [example](./cloud-kms/) implements [CMEK](https://cloud.google.com/kms/docs/cmek) for GCS and GCE, via keys hosted in KMS running in a centralized project. The example shows the basic resources and permissions for the typical use case of application projects implementing encryption at rest via a centrally managed KMS service. From ec35a485c259f0b604dff293d2c78bde1b71f4c0 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 10 Jun 2020 13:36:35 +0200 Subject: [PATCH 076/129] crop diagram --- data-solutions/cloud-kms/diagram.png | Bin 146426 -> 148348 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data-solutions/cloud-kms/diagram.png b/data-solutions/cloud-kms/diagram.png index a2bac201bd8010f3e2716d83076bc0110e55c530..18fe1adf508c24cfbdb8ccf676087d822d9272de 100644 GIT binary patch literal 148348 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

>m?GXo+!d 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 Re7CIg+7;(ts%-rK`Cphz=M?|| From d029ee8e3a91b6128e53ebb3ea17c0c17100a7de Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Wed, 10 Jun 2020 15:22:43 +0200 Subject: [PATCH 077/129] - Rename example to `cmek-via-centralized-kms` - updated CHANGELOG and READMEs --- CHANGELOG.md | 2 ++ README.md | 2 +- data-solutions/README.md | 2 +- .../README.md | 2 +- .../backend.tf.sample | 0 .../diagram.png | Bin .../{cloud-kms => cmek-via-centralized-kms}/main.tf | 0 .../outputs.tf | 0 .../variables.tf | 0 .../versions.tf | 0 10 files changed, 5 insertions(+), 3 deletions(-) rename data-solutions/{cloud-kms => cmek-via-centralized-kms}/README.md (97%) rename data-solutions/{cloud-kms => cmek-via-centralized-kms}/backend.tf.sample (100%) rename data-solutions/{cloud-kms => cmek-via-centralized-kms}/diagram.png (100%) rename data-solutions/{cloud-kms => cmek-via-centralized-kms}/main.tf (100%) rename data-solutions/{cloud-kms => cmek-via-centralized-kms}/outputs.tf (100%) rename data-solutions/{cloud-kms => cmek-via-centralized-kms}/variables.tf (100%) rename data-solutions/{cloud-kms => cmek-via-centralized-kms}/versions.tf (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 523305e8..4c15a8bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- new `data-solutions` section +- new `cmek-via-centralized-kms` e2e example ## [1.9.0] - 2020-06-10 diff --git a/README.md b/README.md index 4940430c..28be754d 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Currently available examples: - **foundations** - [single level hierarchy](./foundations/environments/) (environments), [multiple level hierarchy](./foundations/business-units/) (business units + environments) - **infrastructure** - [hub and spoke via peering](./infrastructure/hub-and-spoke-peering/), [hub and spoke via VPN](./infrastructure/hub-and-spoke-vpn/), [DNS and Google Private Access for on-premises](./infrastructure/onprem-google-access-dns/), [Shared VPC with GKE support](./infrastructure/shared-vpc-gke/) -- **data solutions** - [Cloud KMS with Cloud Storage and Compute Engine](./data-solutions/cloud-kms/) +- **data solutions** - [CMEK on Cloud Storage and Compute Engine via centralized Cloud KMS](./data-solutions/cmek-via-centralized-kms/) For more information see the README files in the [foundations](./foundations/), [infrastructure](./infrastructure/) and [data solutions](./data-solutions/) folders. diff --git a/data-solutions/README.md b/data-solutions/README.md index 4a6889be..f8f70d75 100644 --- a/data-solutions/README.md +++ b/data-solutions/README.md @@ -8,4 +8,4 @@ They are meant to be used as minimal but complete starting points to create actu ### CMEK for Cloud Storage and Compute Engine via centralized KMS - This [example](./cloud-kms/) implements [CMEK](https://cloud.google.com/kms/docs/cmek) for GCS and GCE, via keys hosted in KMS running in a centralized project. The example shows the basic resources and permissions for the typical use case of application projects implementing encryption at rest via a centrally managed KMS service. + This [example](./cmek-via-centralized-kms/) implements [CMEK](https://cloud.google.com/kms/docs/cmek) for GCS and GCE, via keys hosted in KMS running in a centralized project. The example shows the basic resources and permissions for the typical use case of application projects implementing encryption at rest via a centrally managed KMS service. diff --git a/data-solutions/cloud-kms/README.md b/data-solutions/cmek-via-centralized-kms/README.md similarity index 97% rename from data-solutions/cloud-kms/README.md rename to data-solutions/cmek-via-centralized-kms/README.md index 058a6aca..d1ea3bef 100644 --- a/data-solutions/cloud-kms/README.md +++ b/data-solutions/cmek-via-centralized-kms/README.md @@ -1,4 +1,4 @@ -# Cloud KMS with Cloud Storage and Compute Engine +# CMEK on Cloud Storage and Compute Engine via centralized Cloud KMS This sample creates a sample [Cloud KMS](https://cloud.google.com/kms?hl=it) configuration to be used with [Cloud Storage](https://cloud.google.com/storage/docs/encryption/using-customer-managed-keys) and [Copute Engine](https://cloud.google.com/compute/docs/disks/customer-managed-encryption). Cloud KMS is deployed in a separate project to highlight the IAM binding needed and to mock a more real scenario where you usually have a project to manage keys across all your projects in one single place. diff --git a/data-solutions/cloud-kms/backend.tf.sample b/data-solutions/cmek-via-centralized-kms/backend.tf.sample similarity index 100% rename from data-solutions/cloud-kms/backend.tf.sample rename to data-solutions/cmek-via-centralized-kms/backend.tf.sample diff --git a/data-solutions/cloud-kms/diagram.png b/data-solutions/cmek-via-centralized-kms/diagram.png similarity index 100% rename from data-solutions/cloud-kms/diagram.png rename to data-solutions/cmek-via-centralized-kms/diagram.png diff --git a/data-solutions/cloud-kms/main.tf b/data-solutions/cmek-via-centralized-kms/main.tf similarity index 100% rename from data-solutions/cloud-kms/main.tf rename to data-solutions/cmek-via-centralized-kms/main.tf diff --git a/data-solutions/cloud-kms/outputs.tf b/data-solutions/cmek-via-centralized-kms/outputs.tf similarity index 100% rename from data-solutions/cloud-kms/outputs.tf rename to data-solutions/cmek-via-centralized-kms/outputs.tf diff --git a/data-solutions/cloud-kms/variables.tf b/data-solutions/cmek-via-centralized-kms/variables.tf similarity index 100% rename from data-solutions/cloud-kms/variables.tf rename to data-solutions/cmek-via-centralized-kms/variables.tf diff --git a/data-solutions/cloud-kms/versions.tf b/data-solutions/cmek-via-centralized-kms/versions.tf similarity index 100% rename from data-solutions/cloud-kms/versions.tf rename to data-solutions/cmek-via-centralized-kms/versions.tf From 718a851af4e42ba32743c01565a506c85a55ad49 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Wed, 10 Jun 2020 16:31:42 +0200 Subject: [PATCH 078/129] Fix encryption_keys variable name --- data-solutions/cmek-via-centralized-kms/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data-solutions/cmek-via-centralized-kms/main.tf b/data-solutions/cmek-via-centralized-kms/main.tf index d75e0c95..ab0175bb 100644 --- a/data-solutions/cmek-via-centralized-kms/main.tf +++ b/data-solutions/cmek-via-centralized-kms/main.tf @@ -150,7 +150,7 @@ module "kms-gcs" { project_id = module.project-service.project_id prefix = "my-bucket-001" names = ["kms-gcs"] - encryption_key = { + encryption_keys = { kms-gcs = module.kms.keys.key-gce.self_link, } } From 82751466e4b729138aea779184d396dbf58caa3d Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 10 Jun 2020 18:40:50 +0200 Subject: [PATCH 079/129] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 28be754d..789c9842 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Currently available examples: - **foundations** - [single level hierarchy](./foundations/environments/) (environments), [multiple level hierarchy](./foundations/business-units/) (business units + environments) - **infrastructure** - [hub and spoke via peering](./infrastructure/hub-and-spoke-peering/), [hub and spoke via VPN](./infrastructure/hub-and-spoke-vpn/), [DNS and Google Private Access for on-premises](./infrastructure/onprem-google-access-dns/), [Shared VPC with GKE support](./infrastructure/shared-vpc-gke/) -- **data solutions** - [CMEK on Cloud Storage and Compute Engine via centralized Cloud KMS](./data-solutions/cmek-via-centralized-kms/) +- **data solutions** - [GCE/GCS CMEK via centralized Cloud KMS](./data-solutions/cmek-via-centralized-kms/) For more information see the README files in the [foundations](./foundations/), [infrastructure](./infrastructure/) and [data solutions](./data-solutions/) folders. From 14463dc93fa9a6e18486b2baa52add2c844a5c35 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 10 Jun 2020 18:41:55 +0200 Subject: [PATCH 080/129] Update README.md --- data-solutions/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data-solutions/README.md b/data-solutions/README.md index f8f70d75..bff07f7a 100644 --- a/data-solutions/README.md +++ b/data-solutions/README.md @@ -6,6 +6,6 @@ They are meant to be used as minimal but complete starting points to create actu ## Examples -### CMEK for Cloud Storage and Compute Engine via centralized KMS +### GCE and GCS CMEK via centralized Cloud KMS This [example](./cmek-via-centralized-kms/) implements [CMEK](https://cloud.google.com/kms/docs/cmek) for GCS and GCE, via keys hosted in KMS running in a centralized project. The example shows the basic resources and permissions for the typical use case of application projects implementing encryption at rest via a centrally managed KMS service. From 9b33ece7034ef309a7a2061dff750d28e1a388a9 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 10 Jun 2020 18:45:43 +0200 Subject: [PATCH 081/129] Update README.md --- data-solutions/cmek-via-centralized-kms/README.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/data-solutions/cmek-via-centralized-kms/README.md b/data-solutions/cmek-via-centralized-kms/README.md index d1ea3bef..79991bf5 100644 --- a/data-solutions/cmek-via-centralized-kms/README.md +++ b/data-solutions/cmek-via-centralized-kms/README.md @@ -1,9 +1,10 @@ -# CMEK on Cloud Storage and Compute Engine via centralized Cloud KMS +# GCE and GCS CMEK via centralized Cloud KMS -This sample creates a sample [Cloud KMS](https://cloud.google.com/kms?hl=it) configuration to be used with [Cloud Storage](https://cloud.google.com/storage/docs/encryption/using-customer-managed-keys) and [Copute Engine](https://cloud.google.com/compute/docs/disks/customer-managed-encryption). -Cloud KMS is deployed in a separate project to highlight the IAM binding needed and to mock a more real scenario where you usually have a project to manage keys across all your projects in one single place. +This example creates a sample centralized [Cloud KMS](https://cloud.google.com/kms?hl=it) configuration, and uses it to implement CMEK for [Cloud Storage](https://cloud.google.com/storage/docs/encryption/using-customer-managed-keys) and [Compute Engine](https://cloud.google.com/compute/docs/disks/customer-managed-encryption) in a separate project. -The sample has been purposefully kept simple so that it can be used as a basis for different and more complex configuration. This is the high level diagram: +The example is designed to match real-world use cases with a minimum amount of resources, and be used as a starting point for scenarios where application projects implement CMEK using keys managed by a central team. It also includes the IAM wiring needd to make such scenarios work. + +This is the hgh level diagram: ![High-level diagram](diagram.png "High-level diagram") From 9b910790ce60a293ff23c4d1564d0c61fbaf978a Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 10 Jun 2020 18:45:57 +0200 Subject: [PATCH 082/129] Update README.md --- data-solutions/cmek-via-centralized-kms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data-solutions/cmek-via-centralized-kms/README.md b/data-solutions/cmek-via-centralized-kms/README.md index 79991bf5..1faaf6dd 100644 --- a/data-solutions/cmek-via-centralized-kms/README.md +++ b/data-solutions/cmek-via-centralized-kms/README.md @@ -4,7 +4,7 @@ This example creates a sample centralized [Cloud KMS](https://cloud.google.com/k The example is designed to match real-world use cases with a minimum amount of resources, and be used as a starting point for scenarios where application projects implement CMEK using keys managed by a central team. It also includes the IAM wiring needd to make such scenarios work. -This is the hgh level diagram: +This is the high level diagram: ![High-level diagram](diagram.png "High-level diagram") From 9def09fdcb8bde0ac057d4208da8cea1577f428a Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 10 Jun 2020 18:46:16 +0200 Subject: [PATCH 083/129] Update README.md --- data-solutions/cmek-via-centralized-kms/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data-solutions/cmek-via-centralized-kms/README.md b/data-solutions/cmek-via-centralized-kms/README.md index 1faaf6dd..c37f8012 100644 --- a/data-solutions/cmek-via-centralized-kms/README.md +++ b/data-solutions/cmek-via-centralized-kms/README.md @@ -2,7 +2,7 @@ This example creates a sample centralized [Cloud KMS](https://cloud.google.com/kms?hl=it) configuration, and uses it to implement CMEK for [Cloud Storage](https://cloud.google.com/storage/docs/encryption/using-customer-managed-keys) and [Compute Engine](https://cloud.google.com/compute/docs/disks/customer-managed-encryption) in a separate project. -The example is designed to match real-world use cases with a minimum amount of resources, and be used as a starting point for scenarios where application projects implement CMEK using keys managed by a central team. It also includes the IAM wiring needd to make such scenarios work. +The example is designed to match real-world use cases with a minimum amount of resources, and be used as a starting point for scenarios where application projects implement CMEK using keys managed by a central team. It also includes the IAM wiring needed to make such scenarios work. This is the high level diagram: From 7b57e5642aa25396fc6c74f1826869985c4b0563 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Thu, 11 Jun 2020 09:53:04 +0200 Subject: [PATCH 084/129] Fixes based on comments on the PR --- .../cmek-via-centralized-kms/README.md | 14 ++++---- .../cmek-via-centralized-kms/main.tf | 15 ++++---- .../cmek-via-centralized-kms/outputs.tf | 36 +++++++++++++------ .../cmek-via-centralized-kms/variables.tf | 30 ++++++++-------- .../cmek-via-centralized-kms/versions.tf | 2 +- 5 files changed, 57 insertions(+), 40 deletions(-) diff --git a/data-solutions/cmek-via-centralized-kms/README.md b/data-solutions/cmek-via-centralized-kms/README.md index d1ea3bef..a8b6dd89 100644 --- a/data-solutions/cmek-via-centralized-kms/README.md +++ b/data-solutions/cmek-via-centralized-kms/README.md @@ -35,21 +35,23 @@ This sample creates several distinct groups of resources: | name | description | type | required | default | |---|---|:---: |:---:|:---:| | billing_account | Billing account id used as default for new projects. | string | ✓ | | -| projects_parent | The resource name of the parent Folder or Organization. Must be of the form folders/folder_id or organizations/org_id. | string | ✓ | | +| root_node | The resource name of the parent Folder or Organization. Must be of the form folders/folder_id or organizations/org_id. | string | ✓ | | +| *location* | The location where resources will be deployed. | string | | europe | | *project_kms_name* | Name for the new KMS Project. | string | | my-project-kms-001 | | *project_service_name* | Name for the new Service Project. | string | | my-project-service-001 | -| *resource_location* | The location where resources will be deployed. | string | | europe | -| *resource_region* | The region where resources will be deployed. | string | | europe-west1 | -| *resource_zone* | The zone where resources will be deployed. | string | | europe-west1-b | +| *region* | The region where resources will be deployed. | string | | europe-west1 | | *vpc_ip_cidr_range* | Ip range used in the subnet deployef in the Service Project. | string | | 10.0.0.0/20 | | *vpc_name* | Name of the VPC created in the Service Project. | string | | local | | *vpc_subnet_name* | Name of the subnet created in the Service Project. | string | | subnet | +| *zone* | The zone where resources will be deployed. | string | | europe-west1-b | ## Outputs | name | description | sensitive | |---|---|:---:| -| buckets_keys | GCS Buckets Cloud KMS crypto keys. | | +| bucket | GCS Bucket Cloud KMS crypto keys. | | +| bucket_keys | GCS Bucket Cloud KMS crypto keys. | | | projects | Project ids. | | -| vms_keys | GCE VMs Cloud KMS crypto keys. | | +| vm | GCE VMs. | | +| vm_keys | GCE VM Cloud KMS crypto keys. | | diff --git a/data-solutions/cmek-via-centralized-kms/main.tf b/data-solutions/cmek-via-centralized-kms/main.tf index ab0175bb..464f208f 100644 --- a/data-solutions/cmek-via-centralized-kms/main.tf +++ b/data-solutions/cmek-via-centralized-kms/main.tf @@ -19,7 +19,7 @@ module "project-service" { source = "../../modules/project" name = var.project_service_name - parent = var.projects_parent + parent = var.root_node billing_account = var.billing_account services = [ "compute.googleapis.com", @@ -32,7 +32,7 @@ module "project-service" { module "project-kms" { source = "../../modules/project" name = var.project_kms_name - parent = var.projects_parent + parent = var.root_node billing_account = var.billing_account services = [ "cloudkms.googleapis.com", @@ -53,7 +53,7 @@ module "vpc" { { ip_cidr_range = var.vpc_ip_cidr_range name = var.vpc_subnet_name - region = var.resource_region + region = var.region secondary_ip_range = {} } ] @@ -65,7 +65,6 @@ module "vpc-firewall" { network = module.vpc.name admin_ranges_enabled = true admin_ranges = [var.vpc_ip_cidr_range] - ssh_source_ranges = ["0.0.0.0/0"] } ############################################################################### @@ -77,7 +76,7 @@ module "kms" { project_id = module.project-kms.project_id keyring = { name = "my-keyring", - location = var.resource_location + location = var.location } keys = { key-gce = null, key-gcs = null } key_iam_roles = { @@ -104,12 +103,12 @@ module "kms" { module "kms_vm_example" { source = "../../modules/compute-vm" project_id = module.project-service.project_id - region = var.resource_region - zone = var.resource_zone + region = var.region + zone = var.zone name = "kms-vm" network_interfaces = [{ network = module.vpc.self_link, - subnetwork = module.vpc.subnet_self_links["${var.resource_region}/subnet"], + subnetwork = module.vpc.subnet_self_links["${var.region}/subnet"], nat = false, addresses = null }] diff --git a/data-solutions/cmek-via-centralized-kms/outputs.tf b/data-solutions/cmek-via-centralized-kms/outputs.tf index 0da4c1d2..b8874ffb 100644 --- a/data-solutions/cmek-via-centralized-kms/outputs.tf +++ b/data-solutions/cmek-via-centralized-kms/outputs.tf @@ -12,6 +12,22 @@ # See the License for the specific language governing permissions and # limitations under the License. +output "bucket" { + description = "GCS Bucket Cloud KMS crypto keys." + value = { + for bucket in module.kms-gcs.buckets : + bucket.name => bucket.url + } +} + +output "bucket_keys" { + description = "GCS Bucket Cloud KMS crypto keys." + value = { + for bucket in module.kms-gcs.buckets : + bucket.name => bucket.encryption + } +} + output "projects" { description = "Project ids." value = { @@ -20,18 +36,18 @@ output "projects" { } } -output "vms_keys" { - description = "GCE VMs Cloud KMS crypto keys." +output "vm" { + description = "GCE VMs." + value = { + for instance in concat(module.kms_vm_example.instances) : + instance.name => instance.network_interface.0.network_ip + } +} + +output "vm_keys" { + description = "GCE VM Cloud KMS crypto keys." value = { for instance in module.kms_vm_example.instances : instance.name => instance.boot_disk.0.kms_key_self_link } } - -output "buckets_keys" { - description = "GCS Buckets Cloud KMS crypto keys." - value = { - for bucket in module.kms-gcs.buckets : - bucket.name => bucket.encryption - } -} diff --git a/data-solutions/cmek-via-centralized-kms/variables.tf b/data-solutions/cmek-via-centralized-kms/variables.tf index 34f2ea58..fdc0ac94 100644 --- a/data-solutions/cmek-via-centralized-kms/variables.tf +++ b/data-solutions/cmek-via-centralized-kms/variables.tf @@ -18,6 +18,12 @@ variable "billing_account" { type = string } +variable "location" { + description = "The location where resources will be deployed." + type = string + default = "europe" +} + variable "project_service_name" { description = "Name for the new Service Project." type = string @@ -30,27 +36,15 @@ variable "project_kms_name" { default = "my-project-kms-001" } -variable "projects_parent" { - description = "The resource name of the parent Folder or Organization. Must be of the form folders/folder_id or organizations/org_id." - type = string -} - -variable "resource_location" { - description = "The location where resources will be deployed." - type = string - default = "europe" -} - -variable "resource_region" { +variable "region" { description = "The region where resources will be deployed." type = string default = "europe-west1" } -variable "resource_zone" { - description = "The zone where resources will be deployed." +variable "root_node" { + description = "The resource name of the parent Folder or Organization. Must be of the form folders/folder_id or organizations/org_id." type = string - default = "europe-west1-b" } variable "vpc_name" { @@ -70,3 +64,9 @@ variable "vpc_ip_cidr_range" { type = string default = "10.0.0.0/20" } + +variable "zone" { + description = "The zone where resources will be deployed." + type = string + default = "europe-west1-b" +} diff --git a/data-solutions/cmek-via-centralized-kms/versions.tf b/data-solutions/cmek-via-centralized-kms/versions.tf index de5425c2..057095c0 100644 --- a/data-solutions/cmek-via-centralized-kms/versions.tf +++ b/data-solutions/cmek-via-centralized-kms/versions.tf @@ -13,5 +13,5 @@ # limitations under the License. terraform { - required_version = ">= 0.12" + required_version = ">= 0.12.6" } From 46aaff9a71ebe206bfe1e928db0f92d19620e4c6 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Thu, 11 Jun 2020 10:08:48 +0200 Subject: [PATCH 085/129] Fix VM output --- data-solutions/cmek-via-centralized-kms/outputs.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data-solutions/cmek-via-centralized-kms/outputs.tf b/data-solutions/cmek-via-centralized-kms/outputs.tf index b8874ffb..99d26e15 100644 --- a/data-solutions/cmek-via-centralized-kms/outputs.tf +++ b/data-solutions/cmek-via-centralized-kms/outputs.tf @@ -39,7 +39,7 @@ output "projects" { output "vm" { description = "GCE VMs." value = { - for instance in concat(module.kms_vm_example.instances) : + for instance in module.kms_vm_example.instances : instance.name => instance.network_interface.0.network_ip } } From c1c96cac7fd57520929c6d34d3e1a0e15d18f64a Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Thu, 11 Jun 2020 15:51:25 +0200 Subject: [PATCH 086/129] interpolate gateway name in route name for static vpn --- modules/net-vpn-static/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/net-vpn-static/main.tf b/modules/net-vpn-static/main.tf index 559d8d95..91a5c23f 100644 --- a/modules/net-vpn-static/main.tf +++ b/modules/net-vpn-static/main.tf @@ -67,7 +67,7 @@ resource "google_compute_forwarding_rule" "udp-4500" { resource "google_compute_route" "route" { for_each = local.route_pairs - name = "vpn-${each.key}" + name = "vpn-${var.name}-${each.key}" project = var.project_id network = var.network dest_range = each.value.range From 9d7f5570e0b8c9b5d1ffdec548426db1b0f6e787 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Thu, 11 Jun 2020 15:58:44 +0200 Subject: [PATCH 087/129] Update CHANGELOG.md --- CHANGELOG.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4c15a8bc..35908468 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,11 @@ All notable changes to this project will be documented in this file. ## [Unreleased] -- new `data-solutions` section -- new `cmek-via-centralized-kms` e2e example + +## [2.0.0] - 2020-06-11 + +- new `data-solutions` section and `cmek-via-centralized-kms` example +- **incompatible change** static VPN routes now interpolate the VPN gateway name to enforce uniqueness, upgrading from a previous version will drop and recreate routes ## [1.9.0] - 2020-06-10 @@ -93,7 +96,8 @@ All notable changes to this project will be documented in this file. - merge development branch with suite of new modules and end-to-end examples -[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.9.0...HEAD +[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.0.0...HEAD +[2.0.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.9.0...v2.0.0 [1.9.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.8.1...v1.9.0 [1.8.1]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.8.0...v1.8.1 [1.8.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.7.0...v1.8.0 From ae2e4dc3ad12d995c60dac8947b3c7e5f5c96d04 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Fri, 12 Jun 2020 12:07:28 +0200 Subject: [PATCH 088/129] interpolate vpc name in routes --- .gitignore | 1 + CHANGELOG.md | 2 ++ modules/net-vpc/main.tf | 10 +++++----- tests/modules/net_vpc/test_plan.py | 2 +- 4 files changed, 9 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 24b82fc3..150023ac 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ backend.tf backend-config.hcl credentials.json key.json +terraform-ls.tf diff --git a/CHANGELOG.md b/CHANGELOG.md index 35908468..14b37623 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- **incompatible change** routes in the `net-vpc` module now interpolate the VPC name to ensure uniqueness, upgrading from a previous version will drop and recreate routes + ## [2.0.0] - 2020-06-11 - new `data-solutions` section and `cmek-via-centralized-kms` example diff --git a/modules/net-vpc/main.tf b/modules/net-vpc/main.tf index 87d68df3..3c21f467 100644 --- a/modules/net-vpc/main.tf +++ b/modules/net-vpc/main.tf @@ -154,7 +154,7 @@ resource "google_compute_route" "gateway" { for_each = local.routes_gateway project = var.project_id network = google_compute_network.network.name - name = each.key + name = "${var.name}-${each.key}" description = "Terraform-managed." dest_range = each.value.dest_range priority = each.value.priority @@ -166,7 +166,7 @@ resource "google_compute_route" "ilb" { for_each = local.routes_ilb project = var.project_id network = google_compute_network.network.name - name = each.key + name = "${var.name}-${each.key}" description = "Terraform-managed." dest_range = each.value.dest_range priority = each.value.priority @@ -178,7 +178,7 @@ resource "google_compute_route" "instance" { for_each = local.routes_instance project = var.project_id network = google_compute_network.network.name - name = each.key + name = "${var.name}-${each.key}" description = "Terraform-managed." dest_range = each.value.dest_range priority = each.value.priority @@ -192,7 +192,7 @@ resource "google_compute_route" "ip" { for_each = local.routes_ip project = var.project_id network = google_compute_network.network.name - name = each.key + name = "${var.name}-${each.key}" description = "Terraform-managed." dest_range = each.value.dest_range priority = each.value.priority @@ -204,7 +204,7 @@ resource "google_compute_route" "vpn_tunnel" { for_each = local.routes_vpn_tunnel project = var.project_id network = google_compute_network.network.name - name = each.key + name = "${var.name}-${each.key}" description = "Terraform-managed." dest_range = each.value.dest_range priority = each.value.priority diff --git a/tests/modules/net_vpc/test_plan.py b/tests/modules/net_vpc/test_plan.py index fc2852ca..23607ca7 100644 --- a/tests/modules/net_vpc/test_plan.py +++ b/tests/modules/net_vpc/test_plan.py @@ -86,5 +86,5 @@ def test_vpc_routes(plan_runner): _, resources = plan_runner(FIXTURES_DIR, routes=_var_routes) assert len(resources) == 3 resource = [r for r in resources if r['values'] - ['name'] == 'next-hop-test'][0] + ['name'] == 'my-vpc-next-hop-test'][0] assert resource['values']['next_hop_%s' % next_hop_type] From 7a100d08d46b030f46c73a3c261940dfa94616bb Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Wed, 17 Jun 2020 05:41:13 +0200 Subject: [PATCH 089/129] Move top-level docker images folder to the onprem module (#96) * move docker folder to the onprme module * update CHANGELOG --- CHANGELOG.md | 3 ++- modules/cloud-config-container/onprem/README.md | 4 ++-- .../onprem/docker-images/README.md | 3 +++ .../onprem/docker-images}/strongswan/Dockerfile | 0 .../onprem/docker-images}/strongswan/README.md | 14 +++++++------- .../docker-images}/strongswan/cloudbuild.yaml | 0 .../onprem/docker-images}/strongswan/entrypoint.sh | 0 .../onprem/docker-images}/strongswan/ipsec-vti.sh | 0 .../onprem/docker-images}/toolbox/Dockerfile | 0 .../onprem/docker-images}/toolbox/README.md | 2 +- .../onprem/docker-images}/toolbox/cloudbuild.yaml | 0 .../onprem/docker-images}/toolbox/entrypoint.sh | 0 12 files changed, 15 insertions(+), 11 deletions(-) create mode 100644 modules/cloud-config-container/onprem/docker-images/README.md rename {docker-images => modules/cloud-config-container/onprem/docker-images}/strongswan/Dockerfile (100%) rename {docker-images => modules/cloud-config-container/onprem/docker-images}/strongswan/README.md (88%) rename {docker-images => modules/cloud-config-container/onprem/docker-images}/strongswan/cloudbuild.yaml (100%) rename {docker-images => modules/cloud-config-container/onprem/docker-images}/strongswan/entrypoint.sh (100%) rename {docker-images => modules/cloud-config-container/onprem/docker-images}/strongswan/ipsec-vti.sh (100%) rename {docker-images => modules/cloud-config-container/onprem/docker-images}/toolbox/Dockerfile (100%) rename {docker-images => modules/cloud-config-container/onprem/docker-images}/toolbox/README.md (97%) rename {docker-images => modules/cloud-config-container/onprem/docker-images}/toolbox/cloudbuild.yaml (100%) rename {docker-images => modules/cloud-config-container/onprem/docker-images}/toolbox/entrypoint.sh (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 14b37623..ebaed3de 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,11 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - **incompatible change** routes in the `net-vpc` module now interpolate the VPC name to ensure uniqueness, upgrading from a previous version will drop and recreate routes +- the top-level `docker-images` folder has been moved inside `modules/cloud-config-container/onprem` ## [2.0.0] - 2020-06-11 -- new `data-solutions` section and `cmek-via-centralized-kms` example +- new `data-solutions` section and `cmek-via-centralized-kms` example - **incompatible change** static VPN routes now interpolate the VPN gateway name to enforce uniqueness, upgrading from a previous version will drop and recreate routes ## [1.9.0] - 2020-06-10 diff --git a/modules/cloud-config-container/onprem/README.md b/modules/cloud-config-container/onprem/README.md index 260aad1b..a4a6c9ab 100644 --- a/modules/cloud-config-container/onprem/README.md +++ b/modules/cloud-config-container/onprem/README.md @@ -4,11 +4,11 @@ This module manages a `cloud-config` configuration that starts an emulated on-pr The emulated on-premises infrastructure is composed of: -- a Strongswan container managing the VPN tunnel to GCP +- a [Strongswan container](./docker-images/strongswan) managing the VPN tunnel to GCP - an optional Bird container managing the BGP session - a CoreDNS container servng local DNS and forwarding to GCP - an Nginx container serving a simple static web page -- a generic Linux container used as a jump host inside the on-premises network +- a [generic Linux container](./docker-images/toolbox) used as a jump host inside the on-premises network A [complete scenario using this module](../../../infrastructure/onprem-google-access-dns) is available in the infrastructure examples. diff --git a/modules/cloud-config-container/onprem/docker-images/README.md b/modules/cloud-config-container/onprem/docker-images/README.md new file mode 100644 index 00000000..e9342f7e --- /dev/null +++ b/modules/cloud-config-container/onprem/docker-images/README.md @@ -0,0 +1,3 @@ +# Supporting container images + +The images in this folder are used by the [`onprem` module](../). \ No newline at end of file diff --git a/docker-images/strongswan/Dockerfile b/modules/cloud-config-container/onprem/docker-images/strongswan/Dockerfile similarity index 100% rename from docker-images/strongswan/Dockerfile rename to modules/cloud-config-container/onprem/docker-images/strongswan/Dockerfile diff --git a/docker-images/strongswan/README.md b/modules/cloud-config-container/onprem/docker-images/strongswan/README.md similarity index 88% rename from docker-images/strongswan/README.md rename to modules/cloud-config-container/onprem/docker-images/strongswan/README.md index 42225416..cc6eca12 100644 --- a/docker-images/strongswan/README.md +++ b/modules/cloud-config-container/onprem/docker-images/strongswan/README.md @@ -1,9 +1,14 @@ # StrongSwan docker container -### [strongSwan](https://www.strongswan.org/) is an OpenSource IPsec-based VPN Solution +## Build + +```bash +gcloud builds submit . --config=cloudbuild.yaml +``` + +## Docker compose example -### Docker compose example ```yaml version: "3" services: @@ -37,8 +42,3 @@ services: - "/var/lib/docker-compose/onprem/bird/bird.conf:/etc/bird/bird.conf:ro" ``` - -### Build -```bash -gcloud builds submit . --config=cloudbuild.yaml -``` diff --git a/docker-images/strongswan/cloudbuild.yaml b/modules/cloud-config-container/onprem/docker-images/strongswan/cloudbuild.yaml similarity index 100% rename from docker-images/strongswan/cloudbuild.yaml rename to modules/cloud-config-container/onprem/docker-images/strongswan/cloudbuild.yaml diff --git a/docker-images/strongswan/entrypoint.sh b/modules/cloud-config-container/onprem/docker-images/strongswan/entrypoint.sh similarity index 100% rename from docker-images/strongswan/entrypoint.sh rename to modules/cloud-config-container/onprem/docker-images/strongswan/entrypoint.sh diff --git a/docker-images/strongswan/ipsec-vti.sh b/modules/cloud-config-container/onprem/docker-images/strongswan/ipsec-vti.sh similarity index 100% rename from docker-images/strongswan/ipsec-vti.sh rename to modules/cloud-config-container/onprem/docker-images/strongswan/ipsec-vti.sh diff --git a/docker-images/toolbox/Dockerfile b/modules/cloud-config-container/onprem/docker-images/toolbox/Dockerfile similarity index 100% rename from docker-images/toolbox/Dockerfile rename to modules/cloud-config-container/onprem/docker-images/toolbox/Dockerfile diff --git a/docker-images/toolbox/README.md b/modules/cloud-config-container/onprem/docker-images/toolbox/README.md similarity index 97% rename from docker-images/toolbox/README.md rename to modules/cloud-config-container/onprem/docker-images/toolbox/README.md index 6e2f70c2..6daada8f 100644 --- a/docker-images/toolbox/README.md +++ b/modules/cloud-config-container/onprem/docker-images/toolbox/README.md @@ -3,7 +3,7 @@ Lightweight container with some basic console tools used for testing and probing. -## Building +## Build ```bash gcloud builds submit . --config=cloudbuild.yaml diff --git a/docker-images/toolbox/cloudbuild.yaml b/modules/cloud-config-container/onprem/docker-images/toolbox/cloudbuild.yaml similarity index 100% rename from docker-images/toolbox/cloudbuild.yaml rename to modules/cloud-config-container/onprem/docker-images/toolbox/cloudbuild.yaml diff --git a/docker-images/toolbox/entrypoint.sh b/modules/cloud-config-container/onprem/docker-images/toolbox/entrypoint.sh similarity index 100% rename from docker-images/toolbox/entrypoint.sh rename to modules/cloud-config-container/onprem/docker-images/toolbox/entrypoint.sh From ddc2f9c20dc0ec3da58e75d24277b56b20a470c7 Mon Sep 17 00:00:00 2001 From: Aleksandr Averbukh Date: Wed, 17 Jun 2020 11:43:46 +0200 Subject: [PATCH 090/129] dns_keys output added to the dns module (#97) * dns_keys output added to the dns module, so DNSSEC attributes like DS entry will be outputed if DNSSEC configuration is provided * Fix confition for dns_keys data source --- CHANGELOG.md | 1 + modules/dns/README.md | 1 + modules/dns/main.tf | 9 ++++++++- modules/dns/outputs.tf | 5 +++++ modules/dns/versions.tf | 6 +++++- 5 files changed, 20 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ebaed3de..abe1bfd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ All notable changes to this project will be documented in this file. - **incompatible change** routes in the `net-vpc` module now interpolate the VPC name to ensure uniqueness, upgrading from a previous version will drop and recreate routes - the top-level `docker-images` folder has been moved inside `modules/cloud-config-container/onprem` +- `dns_keys` output added to the `dns` module ## [2.0.0] - 2020-06-11 diff --git a/modules/dns/README.md b/modules/dns/README.md index 207572c9..d391c4cf 100644 --- a/modules/dns/README.md +++ b/modules/dns/README.md @@ -43,6 +43,7 @@ module "private-dns" { | name | description | sensitive | |---|---|:---:| +| dns_keys | DNSKEY and DS records of DNSSEC-signed managed zones. | | | domain | The DNS zone domain. | | | name | The DNS zone name. | | | name_servers | The DNS zone name servers. | | diff --git a/modules/dns/main.tf b/modules/dns/main.tf index abb0beb2..f29d2768 100644 --- a/modules/dns/main.tf +++ b/modules/dns/main.tf @@ -15,7 +15,6 @@ */ locals { - is_static_zone = var.type == "public" || var.type == "private" recordsets = var.recordsets == null ? {} : { for record in var.recordsets : join("/", [record.name, record.type]) => record @@ -25,6 +24,9 @@ locals { google_dns_managed_zone.public.0, null ) ) + dns_keys = try( + data.google_dns_keys.dns_keys.0, null + ) } resource "google_dns_managed_zone" "non-public" { @@ -120,6 +122,11 @@ resource "google_dns_managed_zone" "public" { } +data "google_dns_keys" "dns_keys" { + count = var.dnssec_config == {} || var.type != "public" ? 0 : 1 + managed_zone = google_dns_managed_zone.public.0.id +} + resource "google_dns_record_set" "cloud-static-records" { for_each = ( var.type == "public" || var.type == "private" diff --git a/modules/dns/outputs.tf b/modules/dns/outputs.tf index 87add740..ebb5f766 100644 --- a/modules/dns/outputs.tf +++ b/modules/dns/outputs.tf @@ -38,3 +38,8 @@ output "name_servers" { description = "The DNS zone name servers." value = try(local.zone.name_servers, null) } + +output "dns_keys" { + description = "DNSKEY and DS records of DNSSEC-signed managed zones." + value = local.dns_keys +} diff --git a/modules/dns/versions.tf b/modules/dns/versions.tf index ce6918e0..09324d5d 100644 --- a/modules/dns/versions.tf +++ b/modules/dns/versions.tf @@ -15,5 +15,9 @@ */ terraform { - required_version = ">= 0.12.6" + required_version = ">= 0.12.20" + required_providers { + google = "~> 3.10" + google-beta = "~> 3.10" + } } From 65245637479473df5ee2955393e3a24dc40f4e33 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Fri, 19 Jun 2020 09:49:37 +0200 Subject: [PATCH 091/129] Add optional unmanaged instance groups to net-ilb (#98) * add optional unmanaged instance groups to net-ilb * depend health check creation on the health_check variable * add example for self-managed group * update changelog --- CHANGELOG.md | 1 + modules/net-ilb/README.md | 41 +++++++++++++++++++++++++++--- modules/net-ilb/main.tf | 48 ++++++++++++++++++++++++++++-------- modules/net-ilb/outputs.tf | 12 +++++++++ modules/net-ilb/variables.tf | 10 ++++++++ 5 files changed, 99 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index abe1bfd6..6340c2e9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. - **incompatible change** routes in the `net-vpc` module now interpolate the VPC name to ensure uniqueness, upgrading from a previous version will drop and recreate routes - the top-level `docker-images` folder has been moved inside `modules/cloud-config-container/onprem` - `dns_keys` output added to the `dns` module +- add `group-config` variable, `groups` and `group_self_links` outputs to `net-ilb` module to allow creating ILBs for externally managed instances ## [2.0.0] - 2020-06-11 diff --git a/modules/net-ilb/README.md b/modules/net-ilb/README.md index 759ad80f..197f2a1e 100644 --- a/modules/net-ilb/README.md +++ b/modules/net-ilb/README.md @@ -15,7 +15,40 @@ There are some corner cases (eg when switching the instance template from intern One other issue is a `Provider produced inconsistent final plan` error which is sometimes raised when switching template version. This seems to be related to this [open provider issue](https://github.com/terraform-providers/terraform-provider-google/issues/3937), but it's relatively harmless since the resource is updated, and subsequent applies raise no errors. -## Example +## Examples + +### Externally managed instances + +This examples shows how to create an ILB by combining externally managed instances (in a custom module or even outside of the current root module) in an unmanaged group. + +```hcl +module "ilb" { + source = "./modules/net-ilb" + project_id = "my-project" + region = "europe-west1" + name = "ilb-test" + service_label = "ilb-test" + network = local.network_self_link + subnetwork = local.subnetwork_self_link + group_configs = { + my-group = { + zone = europe-west1-b, named_ports = null, instances = [ + local.instance1_self_link, local.instance2_self_link + ] + } + } + backends = [{ + failover = false + group = module.ilb.groups.my-group.self_link + balancing_mode = "CONNECTION" + }] + health_check_config = { + type = "http", check = { port = 80 }, config = {}, logging = true + } +} +``` + +### End to end example This example spins up a simple HTTP server and combines four modules: @@ -81,6 +114,7 @@ module "ilb" { | name | description | type | required | default | |---|---|:---: |:---:|:---:| | backends | Load balancer backends, balancing mode is one of 'CONNECTION' or 'UTILIZATION'. | list(object({...})) | ✓ | | +| group_configs | Optional unmanaged groups to create. Can be referenced in backends via outputs. | map(object({...})) | ✓ | | | name | Name used for all resources. | string | ✓ | | | network | Network used for resources. | string | ✓ | | | project_id | Project id where resources will be created. | string | ✓ | | @@ -91,9 +125,8 @@ module "ilb" { | *failover_config* | Optional failover configuration. | object({...}) | | null | | *global_access* | Global access, defaults to false if not set. | bool | | null | | *health_check* | Name of existing health check to use, disables auto-created health check. | string | | null | -| *health_check_config* | Configuration of the auto-created helth check. | object({...}) | | ... | +| *health_check_config* | Configuration of the auto-created helth check. | object({...}) | | ... | | *labels* | Labels set on resources. | map(string) | | {} | -| *log_sample_rate* | Set a value between 0 and 1 to enable logging for resources, and set the sampling rate for backend logging. | number | | null | | *ports* | Comma-separated ports, leave null to use all ports. | list(string) | | null | | *protocol* | IP protocol used, defaults to TCP. | string | | TCP | | *service_label* | Optional prefix of the fully qualified forwarding rule name. | string | | null | @@ -109,6 +142,8 @@ module "ilb" { | forwarding_rule_address | Forwarding rule address. | | | forwarding_rule_id | Forwarding rule id. | | | forwarding_rule_self_link | Forwarding rule self link. | | +| group_self_links | Optional unmanaged instance group self links. | | +| groups | Optional unmanaged instance group resources. | | | health_check | Auto-created health-check resource. | | | health_check_self_id | Auto-created health-check self id. | | | health_check_self_link | Auto-created health-check self link. | | diff --git a/modules/net-ilb/main.tf b/modules/net-ilb/main.tf index eb6ee475..75440d2f 100644 --- a/modules/net-ilb/main.tf +++ b/modules/net-ilb/main.tf @@ -29,6 +29,7 @@ locals { google_compute_health_check.http2.0, {} ) + health_check_type = try(var.health_check_config.type, null) } resource "google_compute_forwarding_rule" "default" { @@ -89,9 +90,28 @@ resource "google_compute_region_backend_service" "default" { } +resource "google_compute_instance_group" "unmanaged" { + for_each = var.group_configs + project = var.project_id + zone = each.value.zone + name = each.key + description = "Terraform-managed." + instances = each.value.instances + dynamic named_port { + for_each = each.value.named_ports != null ? each.value.named_ports : {} + iterator = config + content { + name = config.key + port = config.value + } + } +} + resource "google_compute_health_check" "http" { - provider = google-beta - count = try(var.health_check_config.type, null) == "http" ? 1 : 0 + provider = google-beta + count = ( + var.health_check == null && local.health_check_type == "http" ? 1 : 0 + ) project = var.project_id name = var.name description = "Terraform managed." @@ -120,8 +140,10 @@ resource "google_compute_health_check" "http" { } resource "google_compute_health_check" "https" { - provider = google-beta - count = try(var.health_check_config.type, null) == "https" ? 1 : 0 + provider = google-beta + count = ( + var.health_check == null && local.health_check_type == "https" ? 1 : 0 + ) project = var.project_id name = var.name description = "Terraform managed." @@ -150,8 +172,10 @@ resource "google_compute_health_check" "https" { } resource "google_compute_health_check" "tcp" { - provider = google-beta - count = try(var.health_check_config.type, null) == "tcp" ? 1 : 0 + provider = google-beta + count = ( + var.health_check == null && local.health_check_type == "tcp" ? 1 : 0 + ) project = var.project_id name = var.name description = "Terraform managed." @@ -179,8 +203,10 @@ resource "google_compute_health_check" "tcp" { } resource "google_compute_health_check" "ssl" { - provider = google-beta - count = try(var.health_check_config.type, null) == "ssl" ? 1 : 0 + provider = google-beta + count = ( + var.health_check == null && local.health_check_type == "ssl" ? 1 : 0 + ) project = var.project_id name = var.name description = "Terraform managed." @@ -208,8 +234,10 @@ resource "google_compute_health_check" "ssl" { } resource "google_compute_health_check" "http2" { - provider = google-beta - count = try(var.health_check_config.type, null) == "http2" ? 1 : 0 + provider = google-beta + count = ( + var.health_check == null && local.health_check_type == "http2" ? 1 : 0 + ) project = var.project_id name = var.name description = "Terraform managed." diff --git a/modules/net-ilb/outputs.tf b/modules/net-ilb/outputs.tf index 8418e40a..6f8ddd60 100644 --- a/modules/net-ilb/outputs.tf +++ b/modules/net-ilb/outputs.tf @@ -49,6 +49,18 @@ output "forwarding_rule_self_link" { value = google_compute_forwarding_rule.default.self_link } +output "groups" { + description = "Optional unmanaged instance group resources." + value = google_compute_instance_group.unmanaged +} + +output "group_self_links" { + description = "Optional unmanaged instance group self links." + value = { + for k, v in google_compute_instance_group.unmanaged : k => v.self_link + } +} + output "health_check" { description = "Auto-created health-check resource." value = local.health_check_resource diff --git a/modules/net-ilb/variables.tf b/modules/net-ilb/variables.tf index df7e7ee8..f4f0036a 100644 --- a/modules/net-ilb/variables.tf +++ b/modules/net-ilb/variables.tf @@ -55,6 +55,16 @@ variable "global_access" { default = null } +variable "group_configs" { + description = "Optional unmanaged groups to create. Can be referenced in backends via outputs." + type = map(object({ + instances = list(string) + named_ports = map(number) + zone = string + })) + default = {} +} + variable "health_check" { description = "Name of existing health check to use, disables auto-created health check." type = string From e2a9e3d415a715f1d012768ccb9fa061a814031d Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Fri, 19 Jun 2020 11:16:22 +0200 Subject: [PATCH 092/129] Update README.md --- modules/net-ilb/README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/modules/net-ilb/README.md b/modules/net-ilb/README.md index 197f2a1e..a368b8ea 100644 --- a/modules/net-ilb/README.md +++ b/modules/net-ilb/README.md @@ -4,7 +4,6 @@ This module allows managing a GCE Internal Load Balancer and integrates the forw ## TODO -- [ ] do not create health check resource if `var.health_check` is not `null` (workaround is to set `var.health_check_config` to `null` - [ ] add a variable for setting address purpose to `SHARED_LOADBALANCER_VIP` and an output for the address once the [provider support has been implemented](https://github.com/terraform-providers/terraform-provider-google/issues/6499) ## Issues @@ -19,7 +18,7 @@ One other issue is a `Provider produced inconsistent final plan` error which is ### Externally managed instances -This examples shows how to create an ILB by combining externally managed instances (in a custom module or even outside of the current root module) in an unmanaged group. +This examples shows how to create an ILB by combining externally managed instances (in a custom module or even outside of the current root module) in an unmanaged group. When using internally managed groups, remember to run `terraform apply` each time group instances change. ```hcl module "ilb" { From 9f3500bff3df0bb1651f29c20f9ec1da0b6d88e3 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 22 Jun 2020 16:16:19 +0200 Subject: [PATCH 093/129] IAM bindings in compute-vm need to depend on the instance resource --- CHANGELOG.md | 1 + modules/compute-vm/main.tf | 1 + 2 files changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6340c2e9..b8dafed7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file. - the top-level `docker-images` folder has been moved inside `modules/cloud-config-container/onprem` - `dns_keys` output added to the `dns` module - add `group-config` variable, `groups` and `group_self_links` outputs to `net-ilb` module to allow creating ILBs for externally managed instances +- make the IAM bindings depend on the compute instance in the `compute-vm` module ## [2.0.0] - 2020-06-11 diff --git a/modules/compute-vm/main.tf b/modules/compute-vm/main.tf index 08981b71..83121fbd 100644 --- a/modules/compute-vm/main.tf +++ b/modules/compute-vm/main.tf @@ -175,6 +175,7 @@ resource "google_compute_instance_iam_binding" "default" { instance_name = each.value.name role = each.value.role members = lookup(var.iam_members, each.value.role, []) + depends_on = [google_compute_instance.default] } resource "google_compute_instance_template" "default" { From 3c60af506feca5c1bc5d869502e627f93447c31f Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 22 Jun 2020 17:18:01 +0200 Subject: [PATCH 094/129] Update CHANGELOG.md --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b8dafed7..0b9e9b3a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [2.1.0] - 2020-06-22 + - **incompatible change** routes in the `net-vpc` module now interpolate the VPC name to ensure uniqueness, upgrading from a previous version will drop and recreate routes - the top-level `docker-images` folder has been moved inside `modules/cloud-config-container/onprem` - `dns_keys` output added to the `dns` module @@ -102,7 +104,8 @@ All notable changes to this project will be documented in this file. - merge development branch with suite of new modules and end-to-end examples -[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.0.0...HEAD +[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.1.0...HEAD +[2.1.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.0.0...v2.1.0 [2.0.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.9.0...v2.0.0 [1.9.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.8.1...v1.9.0 [1.8.1]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.8.0...v1.8.1 From 908371ab917b018faef616aaad257a340ddae472 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Tue, 23 Jun 2020 18:12:10 +0200 Subject: [PATCH 095/129] Module to handle Cloud Endpoints --- modules/endpoint/README.md | 42 ++++++++++++++++++++++++++ modules/endpoint/main.tf | 46 ++++++++++++++++++++++++++++ modules/endpoint/outputs.tf | 30 +++++++++++++++++++ modules/endpoint/variables.tf | 56 +++++++++++++++++++++++++++++++++++ modules/endpoint/versions.tf | 19 ++++++++++++ 5 files changed, 193 insertions(+) create mode 100644 modules/endpoint/README.md create mode 100644 modules/endpoint/main.tf create mode 100644 modules/endpoint/outputs.tf create mode 100644 modules/endpoint/variables.tf create mode 100644 modules/endpoint/versions.tf diff --git a/modules/endpoint/README.md b/modules/endpoint/README.md new file mode 100644 index 00000000..0d7bcfed --- /dev/null +++ b/modules/endpoint/README.md @@ -0,0 +1,42 @@ +# Google Cloud Data Fusion Module + +This module allows simple management of ['Google Cloud Endpoints'](https://cloud.google.com/endpoints/) services. It supports creating ['OpenAPI'](https://cloud.google.com/endpoints/docs/openapi) or ['gRPC'](https://cloud.google.com/endpoints/docs/grpc/about-grpc). + +## Examples + +### OpenAPI + +```hcl +module "endpoint" { + source = "../../modules/endpoint" + project_id = local.project_id + service_name = local.service_name + openapi_config = local.openapi_config + iam_roles = ["servicemanagement.serviceController"] + iam_members = { + "servicemanagement.serviceController" = ["serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com"] + } +} +``` + + +## Variables + +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| service_name | The name of the service. Usually of the form '$apiname.endpoints.$projectid.cloud.goog'. | string | ✓ | | +| *grpc_config* | The path to the full text of the Service Config YAML file. | string | | null | +| *iam_members* | Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. Other roles within the IAM policy for the instance are preserved. | map(list(string)) | | {} | +| *iam_roles* | Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. | list(string) | | [] | +| *openapi_config* | The path to the full text of the OpenAPI YAML configuration. Either this, or both of grpc_config and protoc_output_base64 must be specified. | string | | null | +| *project_id* | The project ID that the service belongs to. | string | | null | +| *protoc_output_base64* | The path to the full contents of the Service Descriptor File generated by protoc. | string | | null | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| endpoint_service | The Endpoint service resource. | | +| endpoints | A list of Endpoint objects. | | +| service_name | The name of the service.. | | + diff --git a/modules/endpoint/main.tf b/modules/endpoint/main.tf new file mode 100644 index 00000000..dbe26a07 --- /dev/null +++ b/modules/endpoint/main.tf @@ -0,0 +1,46 @@ +/** + * Copyright 2020 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 { + iam_roles_bindings = { + for k in var.iam_roles : k => lookup(var.iam_members, k, []) + } +} + +resource "google_endpoints_service" "default" { + project = var.project_id + service_name = var.service_name + + openapi_config = var.openapi_config != null ? file(var.openapi_config) : null + grpc_config = var.grpc_config != null ? file(var.grpc_config) : null + + protoc_output_base64 = var.protoc_output_base64 != null ? base64encode(file(var.protoc_output_base64)) : null +} + +resource "google_project_service" "default" { + project = var.project_id + service = google_endpoints_service.default.service_name + disable_on_destroy = true + disable_dependent_services = true +} + +resource "google_endpoints_service_iam_binding" "default" { + for_each = local.iam_roles_bindings + + service_name = google_endpoints_service.default.service_name + role = "roles/${each.key}" + members = each.value +} \ No newline at end of file diff --git a/modules/endpoint/outputs.tf b/modules/endpoint/outputs.tf new file mode 100644 index 00000000..4c7df9e5 --- /dev/null +++ b/modules/endpoint/outputs.tf @@ -0,0 +1,30 @@ +/** + * Copyright 2020 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 "service_name" { + description = "The name of the service.." + value = google_endpoints_service.default.service_name +} + +output "endpoint_service" { + description = "The Endpoint service resource." + value = google_endpoints_service.default +} + +output "endpoints" { + description = "A list of Endpoint objects." + value = google_endpoints_service.default.endpoints +} \ No newline at end of file diff --git a/modules/endpoint/variables.tf b/modules/endpoint/variables.tf new file mode 100644 index 00000000..20d3fa53 --- /dev/null +++ b/modules/endpoint/variables.tf @@ -0,0 +1,56 @@ +/** + * Copyright 2020 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 "grpc_config" { + description = "The path to the full text of the Service Config YAML file." + type = string + default = null +} + +variable "iam_roles" { + description = "Authoritative for a given role. Updates the IAM policy to grant a role to a list of members." + type = list(string) + default = [] +} + +variable "iam_members" { + description = "Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. Other roles within the IAM policy for the instance are preserved." + type = map(list(string)) + default = {} +} + +variable "openapi_config" { + description = "The path to the full text of the OpenAPI YAML configuration. Either this, or both of grpc_config and protoc_output_base64 must be specified." + type = string + default = null +} + +variable "project_id" { + description = "The project ID that the service belongs to." + type = string + default = null +} + +variable "protoc_output_base64" { + description = "The path to the full contents of the Service Descriptor File generated by protoc." + type = string + default = null +} + +variable "service_name" { + description = "The name of the service. Usually of the form '$apiname.endpoints.$projectid.cloud.goog'." + type = string +} \ No newline at end of file diff --git a/modules/endpoint/versions.tf b/modules/endpoint/versions.tf new file mode 100644 index 00000000..bc4c2a9d --- /dev/null +++ b/modules/endpoint/versions.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2020 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_version = ">= 0.12.6" +} From c4bbba4fbf18a7651ba2ea6fca5f00f47f3ce89b Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Tue, 23 Jun 2020 18:22:54 +0200 Subject: [PATCH 096/129] Fixes --- modules/endpoint/README.md | 10 ++++++---- modules/endpoint/main.tf | 2 +- modules/endpoint/outputs.tf | 4 ++-- modules/endpoint/variables.tf | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/modules/endpoint/README.md b/modules/endpoint/README.md index 0d7bcfed..ce0a2711 100644 --- a/modules/endpoint/README.md +++ b/modules/endpoint/README.md @@ -1,4 +1,4 @@ -# Google Cloud Data Fusion Module +# Google Cloud Endpoints This module allows simple management of ['Google Cloud Endpoints'](https://cloud.google.com/endpoints/) services. It supports creating ['OpenAPI'](https://cloud.google.com/endpoints/docs/openapi) or ['gRPC'](https://cloud.google.com/endpoints/docs/grpc/about-grpc). @@ -9,9 +9,9 @@ This module allows simple management of ['Google Cloud Endpoints'](https://cloud ```hcl module "endpoint" { source = "../../modules/endpoint" - project_id = local.project_id - service_name = local.service_name - openapi_config = local.openapi_config + project_id = "my-project" + service_name = "my-project" + openapi_config = "echo-api.endpoints.YOUR-PROJECT-ID.cloud.goog" iam_roles = ["servicemanagement.serviceController"] iam_members = { "servicemanagement.serviceController" = ["serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com"] @@ -19,6 +19,8 @@ module "endpoint" { } ``` +[Here](https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/endpoints/getting-started/openapi.yaml) you can find an example of a openapi.yaml file. + ## Variables diff --git a/modules/endpoint/main.tf b/modules/endpoint/main.tf index dbe26a07..6bb96670 100644 --- a/modules/endpoint/main.tf +++ b/modules/endpoint/main.tf @@ -43,4 +43,4 @@ resource "google_endpoints_service_iam_binding" "default" { service_name = google_endpoints_service.default.service_name role = "roles/${each.key}" members = each.value -} \ No newline at end of file +} diff --git a/modules/endpoint/outputs.tf b/modules/endpoint/outputs.tf index 4c7df9e5..e4da1de6 100644 --- a/modules/endpoint/outputs.tf +++ b/modules/endpoint/outputs.tf @@ -19,7 +19,7 @@ output "service_name" { value = google_endpoints_service.default.service_name } -output "endpoint_service" { +output "endpoints_service" { description = "The Endpoint service resource." value = google_endpoints_service.default } @@ -27,4 +27,4 @@ output "endpoint_service" { output "endpoints" { description = "A list of Endpoint objects." value = google_endpoints_service.default.endpoints -} \ No newline at end of file +} diff --git a/modules/endpoint/variables.tf b/modules/endpoint/variables.tf index 20d3fa53..93a534ba 100644 --- a/modules/endpoint/variables.tf +++ b/modules/endpoint/variables.tf @@ -53,4 +53,4 @@ variable "protoc_output_base64" { variable "service_name" { description = "The name of the service. Usually of the form '$apiname.endpoints.$projectid.cloud.goog'." type = string -} \ No newline at end of file +} From 30da293c0a520fd0c0f71fdb4c0433c72921bdb1 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Wed, 24 Jun 2020 10:31:10 +0200 Subject: [PATCH 097/129] Fix Readme --- modules/endpoint/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/endpoint/README.md b/modules/endpoint/README.md index ce0a2711..c61b00a5 100644 --- a/modules/endpoint/README.md +++ b/modules/endpoint/README.md @@ -1,6 +1,6 @@ # Google Cloud Endpoints -This module allows simple management of ['Google Cloud Endpoints'](https://cloud.google.com/endpoints/) services. It supports creating ['OpenAPI'](https://cloud.google.com/endpoints/docs/openapi) or ['gRPC'](https://cloud.google.com/endpoints/docs/grpc/about-grpc). +This module allows simple management of ['Google Cloud Endpoints'](https://cloud.google.com/endpoints/) services. It supports creating ['OpenAPI'](https://cloud.google.com/endpoints/docs/openapi) or ['gRPC'](https://cloud.google.com/endpoints/docs/grpc/about-grpc) endpoints. ## Examples @@ -19,7 +19,7 @@ module "endpoint" { } ``` -[Here](https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/endpoints/getting-started/openapi.yaml) you can find an example of a openapi.yaml file. +[Here](https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/endpoints/getting-started/openapi.yaml) you can find an example of an openapi.yaml file. ## Variables From 6356ce628c7d1a4016ace335f6091473e12d8d74 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Wed, 24 Jun 2020 15:52:30 +0200 Subject: [PATCH 098/129] Fixes based on comments on the PR --- modules/endpoint/README.md | 9 ++++----- modules/endpoint/main.tf | 16 +++------------- modules/endpoint/variables.tf | 21 +++++++++------------ 3 files changed, 16 insertions(+), 30 deletions(-) diff --git a/modules/endpoint/README.md b/modules/endpoint/README.md index c61b00a5..5ae3195d 100644 --- a/modules/endpoint/README.md +++ b/modules/endpoint/README.md @@ -19,26 +19,25 @@ module "endpoint" { } ``` -[Here](https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/endpoints/getting-started/openapi.yaml) you can find an example of an openapi.yaml file. +[Here](https://github.com/GoogleCloudPlatform/python-docs-samples/blob/master/endpoints/getting-started/openapi.yaml) you can find an example of an openapi.yaml file. Once created the endpoint, remember to activate the service at project level. ## Variables | name | description | type | required | default | |---|---|:---: |:---:|:---:| +| grpc_config | The configuration for a gRPC enpoint. Either this, openapi_config must be specified. | object({...}) | ✓ | | +| openapi_config | The configuration for an OpenAPI endopoint. Either this, grpc_config must be specified. | object({...}) | ✓ | | | service_name | The name of the service. Usually of the form '$apiname.endpoints.$projectid.cloud.goog'. | string | ✓ | | -| *grpc_config* | The path to the full text of the Service Config YAML file. | string | | null | | *iam_members* | Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. Other roles within the IAM policy for the instance are preserved. | map(list(string)) | | {} | | *iam_roles* | Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. | list(string) | | [] | -| *openapi_config* | The path to the full text of the OpenAPI YAML configuration. Either this, or both of grpc_config and protoc_output_base64 must be specified. | string | | null | | *project_id* | The project ID that the service belongs to. | string | | null | -| *protoc_output_base64* | The path to the full contents of the Service Descriptor File generated by protoc. | string | | null | ## Outputs | name | description | sensitive | |---|---|:---:| -| endpoint_service | The Endpoint service resource. | | | endpoints | A list of Endpoint objects. | | +| endpoints_service | The Endpoint service resource. | | | service_name | The name of the service.. | | diff --git a/modules/endpoint/main.tf b/modules/endpoint/main.tf index 6bb96670..1b9cedbe 100644 --- a/modules/endpoint/main.tf +++ b/modules/endpoint/main.tf @@ -23,23 +23,13 @@ locals { resource "google_endpoints_service" "default" { project = var.project_id service_name = var.service_name - - openapi_config = var.openapi_config != null ? file(var.openapi_config) : null - grpc_config = var.grpc_config != null ? file(var.grpc_config) : null - - protoc_output_base64 = var.protoc_output_base64 != null ? base64encode(file(var.protoc_output_base64)) : null -} - -resource "google_project_service" "default" { - project = var.project_id - service = google_endpoints_service.default.service_name - disable_on_destroy = true - disable_dependent_services = true + openapi_config = var.openapi_config != null ? file(var.openapi_config.yaml_path) : null + grpc_config = var.grpc_config != null ? file(var.grpc_config.yaml_path) : null + protoc_output_base64 = var.grpc_config != null ? base64encode(file(var.grpc_config.protoc_output_path)) : null } resource "google_endpoints_service_iam_binding" "default" { for_each = local.iam_roles_bindings - service_name = google_endpoints_service.default.service_name role = "roles/${each.key}" members = each.value diff --git a/modules/endpoint/variables.tf b/modules/endpoint/variables.tf index 93a534ba..8ece3e76 100644 --- a/modules/endpoint/variables.tf +++ b/modules/endpoint/variables.tf @@ -15,9 +15,11 @@ */ variable "grpc_config" { - description = "The path to the full text of the Service Config YAML file." - type = string - default = null + description = "The configuration for a gRPC enpoint. Either this, openapi_config must be specified." + type = object({ + yaml_path = string + protoc_output_path = string + }) } variable "iam_roles" { @@ -33,9 +35,10 @@ variable "iam_members" { } variable "openapi_config" { - description = "The path to the full text of the OpenAPI YAML configuration. Either this, or both of grpc_config and protoc_output_base64 must be specified." - type = string - default = null + description = "The configuration for an OpenAPI endopoint. Either this, grpc_config must be specified." + type = object({ + yaml_path = string + }) } variable "project_id" { @@ -44,12 +47,6 @@ variable "project_id" { default = null } -variable "protoc_output_base64" { - description = "The path to the full contents of the Service Descriptor File generated by protoc." - type = string - default = null -} - variable "service_name" { description = "The name of the service. Usually of the form '$apiname.endpoints.$projectid.cloud.goog'." type = string From 825a159990d1e286980bfbe988e2f5d79ec3756c Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Wed, 24 Jun 2020 17:59:57 +0200 Subject: [PATCH 099/129] Correct typos Rename module to be consistent with the real name of the GCP service Add link to the module on READMEs --- CHANGELOG.md | 1 + README.md | 2 +- modules/README.md | 1 + modules/{endpoint => endpoints}/README.md | 0 modules/endpoints/main.tf | 36 +++++++++++++++ modules/endpoints/outputs.tf | 30 +++++++++++++ modules/endpoints/variables.tf | 53 +++++++++++++++++++++++ modules/endpoints/versions.tf | 19 ++++++++ 8 files changed, 141 insertions(+), 1 deletion(-) rename modules/{endpoint => endpoints}/README.md (100%) create mode 100644 modules/endpoints/main.tf create mode 100644 modules/endpoints/outputs.tf create mode 100644 modules/endpoints/variables.tf create mode 100644 modules/endpoints/versions.tf diff --git a/CHANGELOG.md b/CHANGELOG.md index abe1bfd6..9878678f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ All notable changes to this project will be documented in this file. - **incompatible change** routes in the `net-vpc` module now interpolate the VPC name to ensure uniqueness, upgrading from a previous version will drop and recreate routes - the top-level `docker-images` folder has been moved inside `modules/cloud-config-container/onprem` - `dns_keys` output added to the `dns` module +- new 'Cloud Endpoints' module ## [2.0.0] - 2020-06-11 diff --git a/README.md b/README.md index 789c9842..db02b66e 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ The current list of modules supports most of the core foundational and networkin Currently available modules: - **foundational** - [folders](./modules/folders), [log sinks](./modules/logging-sinks), [organization](./modules/organization), [project](./modules/project), [service accounts](./modules/iam-service-accounts) -- **networking** - [VPC](./modules/net-vpc), [VPC firewall](./modules/net-vpc-firewall), [VPC peering](./modules/net-vpc-peering), [VPN static](./modules/net-vpn-static), [VPN dynamic](./modules/net-vpn-dynamic), [VPN HA](./modules/net-vpn-ha), [NAT](./modules/net-cloudnat), [address reservation](./modules/net-address), [DNS](./modules/dns), [L4 ILB](./modules/net-ilb), [Service Directory](./modules/service-directory) +- **networking** - [VPC](./modules/net-vpc), [VPC firewall](./modules/net-vpc-firewall), [VPC peering](./modules/net-vpc-peering), [VPN static](./modules/net-vpn-static), [VPN dynamic](./modules/net-vpn-dynamic), [VPN HA](./modules/net-vpn-ha), [NAT](./modules/net-cloudnat), [address reservation](./modules/net-address), [DNS](./modules/dns), [L4 ILB](./modules/net-ilb), [Service Directory](./modules/service-directory), [Cloud Endpoints](./modules/cloudenpoints) - **compute** - [VM/VM group](./modules/compute-vm), [MIG](./modules/compute-mig), [GKE cluster](./modules/gke-cluster), [GKE nodepool](./modules/gke-nodepool), [COS container](./modules/cos-container) (coredns, mysql, onprem, squid) - **data** - [GCS](./modules/gcs), [BigQuery dataset](./modules/bigquery-dataset), [Pub/Sub](./modules/pubsub), [Datafusion](./modules/datafusion), [Bigtable instance](./modules/bigtable-instance) - **security** - [KMS](./modules/kms), [SecretManager](./modules/secret-manager) diff --git a/modules/README.md b/modules/README.md index a831c734..d94f6dc0 100644 --- a/modules/README.md +++ b/modules/README.md @@ -21,6 +21,7 @@ Specific modules also offer support for non-authoritative bindings (e.g. `google - [address reservation](./net-address) - [Cloud DNS](./dns) - [Cloud NAT](./net-cloudnat) +- [Cloud Endpoints](./endpoints) - [L4 Internal Load Balancer](./net-ilb) - [Service Directory](./service-directory) - [VPC](./net-vpc) diff --git a/modules/endpoint/README.md b/modules/endpoints/README.md similarity index 100% rename from modules/endpoint/README.md rename to modules/endpoints/README.md diff --git a/modules/endpoints/main.tf b/modules/endpoints/main.tf new file mode 100644 index 00000000..1b9cedbe --- /dev/null +++ b/modules/endpoints/main.tf @@ -0,0 +1,36 @@ +/** + * Copyright 2020 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 { + iam_roles_bindings = { + for k in var.iam_roles : k => lookup(var.iam_members, k, []) + } +} + +resource "google_endpoints_service" "default" { + project = var.project_id + service_name = var.service_name + openapi_config = var.openapi_config != null ? file(var.openapi_config.yaml_path) : null + grpc_config = var.grpc_config != null ? file(var.grpc_config.yaml_path) : null + protoc_output_base64 = var.grpc_config != null ? base64encode(file(var.grpc_config.protoc_output_path)) : null +} + +resource "google_endpoints_service_iam_binding" "default" { + for_each = local.iam_roles_bindings + service_name = google_endpoints_service.default.service_name + role = "roles/${each.key}" + members = each.value +} diff --git a/modules/endpoints/outputs.tf b/modules/endpoints/outputs.tf new file mode 100644 index 00000000..e4da1de6 --- /dev/null +++ b/modules/endpoints/outputs.tf @@ -0,0 +1,30 @@ +/** + * Copyright 2020 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 "service_name" { + description = "The name of the service.." + value = google_endpoints_service.default.service_name +} + +output "endpoints_service" { + description = "The Endpoint service resource." + value = google_endpoints_service.default +} + +output "endpoints" { + description = "A list of Endpoint objects." + value = google_endpoints_service.default.endpoints +} diff --git a/modules/endpoints/variables.tf b/modules/endpoints/variables.tf new file mode 100644 index 00000000..8ece3e76 --- /dev/null +++ b/modules/endpoints/variables.tf @@ -0,0 +1,53 @@ +/** + * Copyright 2020 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 "grpc_config" { + description = "The configuration for a gRPC enpoint. Either this, openapi_config must be specified." + type = object({ + yaml_path = string + protoc_output_path = string + }) +} + +variable "iam_roles" { + description = "Authoritative for a given role. Updates the IAM policy to grant a role to a list of members." + type = list(string) + default = [] +} + +variable "iam_members" { + description = "Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. Other roles within the IAM policy for the instance are preserved." + type = map(list(string)) + default = {} +} + +variable "openapi_config" { + description = "The configuration for an OpenAPI endopoint. Either this, grpc_config must be specified." + type = object({ + yaml_path = string + }) +} + +variable "project_id" { + description = "The project ID that the service belongs to." + type = string + default = null +} + +variable "service_name" { + description = "The name of the service. Usually of the form '$apiname.endpoints.$projectid.cloud.goog'." + type = string +} diff --git a/modules/endpoints/versions.tf b/modules/endpoints/versions.tf new file mode 100644 index 00000000..bc4c2a9d --- /dev/null +++ b/modules/endpoints/versions.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2020 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_version = ">= 0.12.6" +} From 9c85f9e647734e1672381c652a3d02857a77aebf Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Wed, 24 Jun 2020 18:08:09 +0200 Subject: [PATCH 100/129] Delete old folder --- modules/endpoint/main.tf | 36 ------------------------ modules/endpoint/outputs.tf | 30 -------------------- modules/endpoint/variables.tf | 53 ----------------------------------- modules/endpoint/versions.tf | 19 ------------- 4 files changed, 138 deletions(-) delete mode 100644 modules/endpoint/main.tf delete mode 100644 modules/endpoint/outputs.tf delete mode 100644 modules/endpoint/variables.tf delete mode 100644 modules/endpoint/versions.tf diff --git a/modules/endpoint/main.tf b/modules/endpoint/main.tf deleted file mode 100644 index 1b9cedbe..00000000 --- a/modules/endpoint/main.tf +++ /dev/null @@ -1,36 +0,0 @@ -/** - * Copyright 2020 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 { - iam_roles_bindings = { - for k in var.iam_roles : k => lookup(var.iam_members, k, []) - } -} - -resource "google_endpoints_service" "default" { - project = var.project_id - service_name = var.service_name - openapi_config = var.openapi_config != null ? file(var.openapi_config.yaml_path) : null - grpc_config = var.grpc_config != null ? file(var.grpc_config.yaml_path) : null - protoc_output_base64 = var.grpc_config != null ? base64encode(file(var.grpc_config.protoc_output_path)) : null -} - -resource "google_endpoints_service_iam_binding" "default" { - for_each = local.iam_roles_bindings - service_name = google_endpoints_service.default.service_name - role = "roles/${each.key}" - members = each.value -} diff --git a/modules/endpoint/outputs.tf b/modules/endpoint/outputs.tf deleted file mode 100644 index e4da1de6..00000000 --- a/modules/endpoint/outputs.tf +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright 2020 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 "service_name" { - description = "The name of the service.." - value = google_endpoints_service.default.service_name -} - -output "endpoints_service" { - description = "The Endpoint service resource." - value = google_endpoints_service.default -} - -output "endpoints" { - description = "A list of Endpoint objects." - value = google_endpoints_service.default.endpoints -} diff --git a/modules/endpoint/variables.tf b/modules/endpoint/variables.tf deleted file mode 100644 index 8ece3e76..00000000 --- a/modules/endpoint/variables.tf +++ /dev/null @@ -1,53 +0,0 @@ -/** - * Copyright 2020 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 "grpc_config" { - description = "The configuration for a gRPC enpoint. Either this, openapi_config must be specified." - type = object({ - yaml_path = string - protoc_output_path = string - }) -} - -variable "iam_roles" { - description = "Authoritative for a given role. Updates the IAM policy to grant a role to a list of members." - type = list(string) - default = [] -} - -variable "iam_members" { - description = "Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. Other roles within the IAM policy for the instance are preserved." - type = map(list(string)) - default = {} -} - -variable "openapi_config" { - description = "The configuration for an OpenAPI endopoint. Either this, grpc_config must be specified." - type = object({ - yaml_path = string - }) -} - -variable "project_id" { - description = "The project ID that the service belongs to." - type = string - default = null -} - -variable "service_name" { - description = "The name of the service. Usually of the form '$apiname.endpoints.$projectid.cloud.goog'." - type = string -} diff --git a/modules/endpoint/versions.tf b/modules/endpoint/versions.tf deleted file mode 100644 index bc4c2a9d..00000000 --- a/modules/endpoint/versions.tf +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Copyright 2020 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_version = ">= 0.12.6" -} From c1eb78c7467d732ea6f81511e0ec317233b11ebc Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Wed, 24 Jun 2020 18:12:10 +0200 Subject: [PATCH 101/129] Fix Example --- modules/endpoints/README.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/endpoints/README.md b/modules/endpoints/README.md index 5ae3195d..2bd24d59 100644 --- a/modules/endpoints/README.md +++ b/modules/endpoints/README.md @@ -10,8 +10,9 @@ This module allows simple management of ['Google Cloud Endpoints'](https://cloud module "endpoint" { source = "../../modules/endpoint" project_id = "my-project" - service_name = "my-project" - openapi_config = "echo-api.endpoints.YOUR-PROJECT-ID.cloud.goog" + service_name = "YOUR-API.endpoints.YOUR-PROJECT-ID.cloud.goog" + openapi_config = { "yaml_path" = "openapi.yaml" } + grpc_config = null iam_roles = ["servicemanagement.serviceController"] iam_members = { "servicemanagement.serviceController" = ["serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com"] From 72c2b9a54a47a6c20964aa727f3130fd9bb502e6 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Wed, 24 Jun 2020 18:13:45 +0200 Subject: [PATCH 102/129] Fix Variable description --- modules/endpoints/README.md | 4 ++-- modules/endpoints/variables.tf | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/endpoints/README.md b/modules/endpoints/README.md index 2bd24d59..f57952e4 100644 --- a/modules/endpoints/README.md +++ b/modules/endpoints/README.md @@ -27,8 +27,8 @@ module "endpoint" { | name | description | type | required | default | |---|---|:---: |:---:|:---:| -| grpc_config | The configuration for a gRPC enpoint. Either this, openapi_config must be specified. | object({...}) | ✓ | | -| openapi_config | The configuration for an OpenAPI endopoint. Either this, grpc_config must be specified. | object({...}) | ✓ | | +| grpc_config | The configuration for a gRPC enpoint. Either this or openapi_config must be specified. | object({...}) | ✓ | | +| openapi_config | The configuration for an OpenAPI endopoint. Either this or grpc_config must be specified. | object({...}) | ✓ | | | service_name | The name of the service. Usually of the form '$apiname.endpoints.$projectid.cloud.goog'. | string | ✓ | | | *iam_members* | Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. Other roles within the IAM policy for the instance are preserved. | map(list(string)) | | {} | | *iam_roles* | Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. | list(string) | | [] | diff --git a/modules/endpoints/variables.tf b/modules/endpoints/variables.tf index 8ece3e76..76fb8b8b 100644 --- a/modules/endpoints/variables.tf +++ b/modules/endpoints/variables.tf @@ -15,7 +15,7 @@ */ variable "grpc_config" { - description = "The configuration for a gRPC enpoint. Either this, openapi_config must be specified." + description = "The configuration for a gRPC enpoint. Either this or openapi_config must be specified." type = object({ yaml_path = string protoc_output_path = string @@ -35,7 +35,7 @@ variable "iam_members" { } variable "openapi_config" { - description = "The configuration for an OpenAPI endopoint. Either this, grpc_config must be specified." + description = "The configuration for an OpenAPI endopoint. Either this or grpc_config must be specified." type = object({ yaml_path = string }) From ec765857cbc0f8631b001bedaa1d0a7ee0b05f34 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Thu, 25 Jun 2020 10:04:57 +0200 Subject: [PATCH 103/129] Make project creation optional in project module (#99) * make project creation optional in project module * add variable to optionally configure project activation * add explicit dependency on custom roles to additive bindings * make parent variable optional * add test for null parent * fix custom roles output --- modules/project/README.md | 8 ++-- modules/project/main.tf | 45 ++++++++++++++-------- modules/project/outputs.tf | 13 ++++--- modules/project/service_accounts.tf | 8 ++-- modules/project/variables.tf | 23 ++++++++++- tests/modules/project/fixture/variables.tf | 2 +- tests/modules/project/test_plan.py | 10 ++++- 7 files changed, 77 insertions(+), 32 deletions(-) diff --git a/modules/project/README.md b/modules/project/README.md index 9ab49796..cd640673 100644 --- a/modules/project/README.md +++ b/modules/project/README.md @@ -58,9 +58,8 @@ module "project" { | name | description | type | required | default | |---|---|:---: |:---:|:---:| | name | Project name and id suffix. | string | ✓ | | -| parent | The resource name of the parent Folder or Organization. Must be of the form folders/folder_id or organizations/org_id. | string | ✓ | | | *auto_create_network* | Whether to create the default network for the project | bool | | false | -| *billing_account* | Billing account id. | string | | | +| *billing_account* | Billing account id. | string | | null | | *custom_roles* | Map of role name => list of permissions to create in this project. | map(list(string)) | | {} | | *iam_additive_members* | Map of member lists used to set non authoritative bindings, keyed by role. | map(list(string)) | | {} | | *iam_additive_roles* | List of roles used to set non authoritative bindings. | list(string) | | [] | @@ -71,9 +70,12 @@ module "project" { | *oslogin* | Enable OS Login. | bool | | false | | *oslogin_admins* | List of IAM-style identities that will be granted roles necessary for OS Login administrators. | list(string) | | [] | | *oslogin_users* | List of IAM-style identities that will be granted roles necessary for OS Login users. | list(string) | | [] | +| *parent* | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | string | | null | | *policy_boolean* | Map of boolean org policies and enforcement value, set value to null for policy restore. | map(bool) | | {} | | *policy_list* | Map of list org policies, status is true for allow, false for deny, null for restore. Values can only be used for allow or deny. | map(object({...})) | | {} | | *prefix* | Prefix used to generate project id and name. | string | | null | +| *project_create* | Create project. When set to false, uses a data source to reference existing project. | bool | | true | +| *service_config* | Configure service API activation. | object({...}) | | ... | | *services* | Service APIs to enable. | list(string) | | [] | ## Outputs @@ -81,7 +83,7 @@ module "project" { | name | description | sensitive | |---|---|:---:| | custom_roles | Ids of the created custom roles. | | -| name | Project ame. | | +| name | Project name. | | | number | Project number. | | | project_id | Project id. | | | service_accounts | Product robot service accounts in project. | | diff --git a/modules/project/main.tf b/modules/project/main.tf index 5ccee12e..637aa8de 100644 --- a/modules/project/main.tf +++ b/modules/project/main.tf @@ -25,12 +25,21 @@ locals { for pair in local.iam_additive_pairs : "${pair.role}-${pair.member}" => pair } - parent_type = split("/", var.parent)[0] - parent_id = split("/", var.parent)[1] + parent_type = var.parent == null ? null : split("/", var.parent)[0] + parent_id = var.parent == null ? null : split("/", var.parent)[1] prefix = var.prefix == null ? "" : "${var.prefix}-" + project = ( + var.project_create ? google_project.project.0 : data.google_project.project.0 + ) +} + +data "google_project" "project" { + count = var.project_create ? 0 : 1 + project_id = "${local.prefix}${var.name}" } resource "google_project" "project" { + count = var.project_create ? 1 : 0 org_id = local.parent_type == "organizations" ? local.parent_id : null folder_id = local.parent_type == "folders" ? local.parent_id : null project_id = "${local.prefix}${var.name}" @@ -42,7 +51,7 @@ resource "google_project" "project" { resource "google_project_iam_custom_role" "roles" { for_each = var.custom_roles - project = google_project.project.project_id + project = local.project.project_id role_id = each.key title = "Custom role ${each.key}" description = "Terraform-managed" @@ -51,7 +60,7 @@ resource "google_project_iam_custom_role" "roles" { resource "google_compute_project_metadata_item" "oslogin_meta" { count = var.oslogin ? 1 : 0 - project = google_project.project.project_id + project = local.project.project_id key = "enable-oslogin" value = "TRUE" # depend on services or it will fail on destroy @@ -60,7 +69,7 @@ resource "google_compute_project_metadata_item" "oslogin_meta" { resource "google_resource_manager_lien" "lien" { count = var.lien_reason != "" ? 1 : 0 - parent = "projects/${google_project.project.number}" + parent = "projects/${local.project.number}" restrictions = ["resourcemanager.projects.delete"] origin = "created-by-terraform" reason = var.lien_reason @@ -68,10 +77,10 @@ resource "google_resource_manager_lien" "lien" { resource "google_project_service" "project_services" { for_each = toset(var.services) - project = google_project.project.project_id + project = local.project.project_id service = each.value - disable_on_destroy = true - disable_dependent_services = true + disable_on_destroy = var.service_config.disable_on_destroy + disable_dependent_services = var.service_config.disable_dependent_services } # IAM notes: @@ -81,7 +90,7 @@ resource "google_project_service" "project_services" { resource "google_project_iam_binding" "authoritative" { for_each = toset(var.iam_roles) - project = google_project.project.project_id + project = local.project.project_id role = each.value members = lookup(var.iam_members, each.value, []) depends_on = [ @@ -92,42 +101,46 @@ resource "google_project_iam_binding" "authoritative" { resource "google_project_iam_member" "additive" { for_each = length(var.iam_additive_roles) > 0 ? local.iam_additive : {} - project = google_project.project.project_id + project = local.project.project_id role = each.value.role member = each.value.member + depends_on = [ + google_project_service.project_services, + google_project_iam_custom_role.roles + ] } resource "google_project_iam_member" "oslogin_iam_serviceaccountuser" { for_each = var.oslogin ? toset(distinct(concat(var.oslogin_admins, var.oslogin_users))) : toset([]) - project = google_project.project.project_id + project = local.project.project_id role = "roles/iam.serviceAccountUser" member = each.value } resource "google_project_iam_member" "oslogin_compute_viewer" { for_each = var.oslogin ? toset(distinct(concat(var.oslogin_admins, var.oslogin_users))) : toset([]) - project = google_project.project.project_id + project = local.project.project_id role = "roles/compute.viewer" member = each.value } resource "google_project_iam_member" "oslogin_admins" { for_each = var.oslogin ? toset(var.oslogin_admins) : toset([]) - project = google_project.project.project_id + project = local.project.project_id role = "roles/compute.osAdminLogin" member = each.value } resource "google_project_iam_member" "oslogin_users" { for_each = var.oslogin ? toset(var.oslogin_users) : toset([]) - project = google_project.project.project_id + project = local.project.project_id role = "roles/compute.osLogin" member = each.value } resource "google_project_organization_policy" "boolean" { for_each = var.policy_boolean - project = google_project.project.project_id + project = local.project.project_id constraint = each.key dynamic boolean_policy { @@ -148,7 +161,7 @@ resource "google_project_organization_policy" "boolean" { resource "google_project_organization_policy" "list" { for_each = var.policy_list - project = google_project.project.project_id + project = local.project.project_id constraint = each.key dynamic list_policy { diff --git a/modules/project/outputs.tf b/modules/project/outputs.tf index 67c9af68..1250f846 100644 --- a/modules/project/outputs.tf +++ b/modules/project/outputs.tf @@ -16,7 +16,7 @@ output "project_id" { description = "Project id." - value = google_project.project.project_id + value = local.project.project_id depends_on = [ google_project_organization_policy.boolean, google_project_organization_policy.list, @@ -25,8 +25,8 @@ output "project_id" { } output "name" { - description = "Project ame." - value = google_project.project.name + description = "Project name." + value = local.project.name depends_on = [ google_project_organization_policy.boolean, google_project_organization_policy.list, @@ -36,7 +36,7 @@ output "name" { output "number" { description = "Project number." - value = google_project.project.number + value = local.project.number depends_on = [ google_project_organization_policy.boolean, google_project_organization_policy.list, @@ -56,5 +56,8 @@ output "service_accounts" { output "custom_roles" { description = "Ids of the created custom roles." - value = [for role in google_project_iam_custom_role.roles : role.role_id] + value = { + for name, role in google_project_iam_custom_role.roles : + name => role.id + } } diff --git a/modules/project/service_accounts.tf b/modules/project/service_accounts.tf index d0ccee65..56e34496 100644 --- a/modules/project/service_accounts.tf +++ b/modules/project/service_accounts.tf @@ -15,10 +15,10 @@ */ locals { - service_account_cloud_services = "${google_project.project.number}@cloudservices.gserviceaccount.com" + service_account_cloud_services = "${local.project.number}@cloudservices.gserviceaccount.com" service_accounts_default = { - compute = "${google_project.project.number}-compute@developer.gserviceaccount.com" - gae = "${google_project.project.project_id}@appspot.gserviceaccount.com" + compute = "${local.project.number}-compute@developer.gserviceaccount.com" + gae = "${local.project.project_id}@appspot.gserviceaccount.com" } service_accounts_robot_services = { cloudasset = "gcp-sa-cloudasset" @@ -34,6 +34,6 @@ locals { } service_accounts_robots = { for service, name in local.service_accounts_robot_services : - service => "service-${google_project.project.number}@${name}.iam.gserviceaccount.com" + service => "service-${local.project.number}@${name}.iam.gserviceaccount.com" } } diff --git a/modules/project/variables.tf b/modules/project/variables.tf index fc6e12ab..6676b76a 100644 --- a/modules/project/variables.tf +++ b/modules/project/variables.tf @@ -23,7 +23,7 @@ variable "auto_create_network" { variable "billing_account" { description = "Billing account id." type = string - default = "" + default = null } variable "custom_roles" { @@ -92,8 +92,9 @@ variable "oslogin_users" { } variable "parent" { - description = "The resource name of the parent Folder or Organization. Must be of the form folders/folder_id or organizations/org_id." + description = "Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format." type = string + default = null } variable "policy_boolean" { @@ -119,8 +120,26 @@ variable "prefix" { default = null } +variable "project_create" { + description = "Create project. When set to false, uses a data source to reference existing project." + type = bool + default = true +} + variable "services" { description = "Service APIs to enable." type = list(string) default = [] } + +variable "service_config" { + description = "Configure service API activation." + type = object({ + disable_on_destroy = bool + disable_dependent_services = bool + }) + default = { + disable_on_destroy = true + disable_dependent_services = true + } +} diff --git a/tests/modules/project/fixture/variables.tf b/tests/modules/project/fixture/variables.tf index 3c467da1..4b859c92 100644 --- a/tests/modules/project/fixture/variables.tf +++ b/tests/modules/project/fixture/variables.tf @@ -71,7 +71,7 @@ variable "oslogin_users" { variable "parent" { type = string - default = "folders/12345678" + default = null } variable "policy_boolean" { diff --git a/tests/modules/project/test_plan.py b/tests/modules/project/test_plan.py index 4c5aba82..a526c1a5 100644 --- a/tests/modules/project/test_plan.py +++ b/tests/modules/project/test_plan.py @@ -32,7 +32,7 @@ def test_prefix(plan_runner): def test_parent(plan_runner): "Test project parent." - _, resources = plan_runner(FIXTURES_DIR) + _, resources = plan_runner(FIXTURES_DIR, parent='folders/12345678') assert len(resources) == 1 assert resources[0]['values']['folder_id'] == '12345678' assert resources[0]['values'].get('org_id') == None @@ -40,3 +40,11 @@ def test_parent(plan_runner): assert len(resources) == 1 assert resources[0]['values']['org_id'] == '12345678' assert resources[0]['values'].get('folder_id') == None + + +def test_no_parent(plan_runner): + "Test null project parent." + _, resources = plan_runner(FIXTURES_DIR) + assert len(resources) == 1 + assert resources[0]['values'].get('folder_id') == None + assert resources[0]['values'].get('org_id') == None From 0a5e3b7f17d736a4ae506177b916fefd70133ebe Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Thu, 25 Jun 2020 10:05:35 +0200 Subject: [PATCH 104/129] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 797b0085..f0de265f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] - new 'Cloud Endpoints' module +- make project creation optional in `project` module to allow managing a pre-existing project ## [2.1.0] - 2020-06-22 From 9a4ec24093084864459c03f53d59d29b465216f9 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Fri, 26 Jun 2020 21:45:41 +0200 Subject: [PATCH 105/129] First commit. TODO: - fix error on destroy - improve robot service account handling --- data-solutions/gcs-to-bq/README.md | 119 ++++++ data-solutions/gcs-to-bq/backend.tf.sample | 20 + data-solutions/gcs-to-bq/diagram.png | Bin 0 -> 201386 bytes data-solutions/gcs-to-bq/main.tf | 341 ++++++++++++++++++ data-solutions/gcs-to-bq/outputs.tf | 42 +++ .../gcs-to-bq/schema_bq_import.json | 14 + .../gcs-to-bq/schema_df_import.json | 18 + .../scripts/data_ingestion/README.md | 81 +++++ .../scripts/data_ingestion/REQUIREMENTS.txt | 2 + .../scripts/data_ingestion/data_ingestion.py | 133 +++++++ .../scripts/data_ingestion/diagram.png | Bin 0 -> 90257 bytes .../person_details_generator/README.md | 17 + .../person_details_generator/REQUIREMENTS.txt | 1 + .../person_details_generator.py | 43 +++ data-solutions/gcs-to-bq/variables.tf | 76 ++++ data-solutions/gcs-to-bq/versions.tf | 17 + modules/project/service_accounts.tf | 3 + 17 files changed, 927 insertions(+) create mode 100644 data-solutions/gcs-to-bq/README.md create mode 100644 data-solutions/gcs-to-bq/backend.tf.sample create mode 100644 data-solutions/gcs-to-bq/diagram.png create mode 100644 data-solutions/gcs-to-bq/main.tf create mode 100644 data-solutions/gcs-to-bq/outputs.tf create mode 100644 data-solutions/gcs-to-bq/schema_bq_import.json create mode 100644 data-solutions/gcs-to-bq/schema_df_import.json create mode 100644 data-solutions/gcs-to-bq/scripts/data_ingestion/README.md create mode 100644 data-solutions/gcs-to-bq/scripts/data_ingestion/REQUIREMENTS.txt create mode 100644 data-solutions/gcs-to-bq/scripts/data_ingestion/data_ingestion.py create mode 100644 data-solutions/gcs-to-bq/scripts/data_ingestion/diagram.png create mode 100644 data-solutions/gcs-to-bq/scripts/person_details_generator/README.md create mode 100644 data-solutions/gcs-to-bq/scripts/person_details_generator/REQUIREMENTS.txt create mode 100644 data-solutions/gcs-to-bq/scripts/person_details_generator/person_details_generator.py create mode 100644 data-solutions/gcs-to-bq/variables.tf create mode 100644 data-solutions/gcs-to-bq/versions.tf diff --git a/data-solutions/gcs-to-bq/README.md b/data-solutions/gcs-to-bq/README.md new file mode 100644 index 00000000..f1a13578 --- /dev/null +++ b/data-solutions/gcs-to-bq/README.md @@ -0,0 +1,119 @@ +# GCE and GCS CMEK via centralized Cloud KMS + +This example creates the infrastructure needed to run a [Cloud Dataflow](https://cloud.google.com/dataflow) pipeline to import data from [GCS](https://cloud.google.com/storage) to [Bigquery](https://cloud.google.com/bigquery). + +The solution will use: + - internal IP for GCE and Dataflow instances + - CMEK encription for GCS bucket, GCE instances, DataFlow instances and BigQuery Tables + - Cloud NAT to let resource comunicate to internet to run updates and packages installation + +The example is designed to match real-world use cases with a minimum amount of resources. It can be used as a starting point for more complex scenarios. + +This is the high level diagram: + +![GCS to Biquery High-level diagram](diagram.png "GCS to Biquery High-level diagram") + +## Managed resources and services + +This sample creates several distinct groups of resources: + +- projects + - Cloud KMS project + - Service Project configured for GCE instances, GCS buckets, Dataflow instances and BigQuery tables +- networking + - VPC network + - One subnet + - Firewall rules for [SSH access via IAP](https://cloud.google.com/iap/docs/using-tcp-forwarding) and open communication within the VPC +- IAM + - One service account for GGE instances + - One service account for Dataflow instances + - One service account for Bigquery tables +- KMS + - One contintent key ring (example: 'Europe') + - One crypto key (Procection level: softwere) for Cloud Engine + - One crypto key (Protection level: softwere) for Cloud Storage + - One regional key ring ('example: 'europe-west1') + - One crypto key (Protection level: softwere) for Cloud Dataflow +- GCE + - One instance encrypted with a CMEK Cryptokey hosted in Cloud KMS +- GCS + - One bucket encrypted with a CMEK Cryptokey hosted in Cloud KMS +- BQ + - One dataset encrypted with a CMEK Cryptokey hosted in Cloud KMS + - Two tables encrypted with a CMEK Cryptokey hosted in Cloud KMS + + +## Variables + +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| billing_account | Billing account id used as default for new projects. | string | ✓ | | +| project_kms_name | Name for the new KMS Project. | string | ✓ | | +| project_service_name | Name for the new Service Project. | string | ✓ | | +| root_node | The resource name of the parent Folder or Organization. Must be of the form folders/folder_id or organizations/org_id. | string | ✓ | | +| *location* | The location where resources will be deployed. | string | | europe | +| *region* | The region where resources will be deployed. | string | | europe-west1 | +| *ssh_source_ranges* | IP CIDR ranges that will be allowed to connect via SSH to the onprem instance. | list(string) | | ["0.0.0.0/0"] | +| *vpc_ip_cidr_range* | Ip range used in the subnet deployef in the Service Project. | string | | 10.0.0.0/20 | +| *vpc_name* | Name of the VPC created in the Service Project. | string | | local | +| *vpc_subnet_name* | Name of the subnet created in the Service Project. | string | | subnet | +| *zone* | The zone where resources will be deployed. | string | | europe-west1-b | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| bq_tables | Bigquery Tables. | | +| buckets | GCS Bucket Cloud KMS crypto keys. | | +| projects | Project ids. | | +| vm | GCE VMs. | | + + +## Test your environment +You can now connect to the GCE instance with the following command: + +```hcl + gcloud compute ssh vm-example-1 +``` + +You can run now the simple pipeline you can find [here](./script/data_ingestion/). Once you have installed required packages and copied a file into the GCS bucket, you can trigger the pipeline using internal ips with a command simila to: + +```hcl +python data_ingestion.py \ +--runner=DataflowRunner \ +--max_num_workers=10 \ +--autoscaling_algorithm=THROUGHPUT_BASED \ +--region=### REGION ### \ +--staging_location=gs://### TEMP BUCKET NAME ###/ \ +--temp_location=gs://### TEMP BUCKET NAME ###/ \ +--project=### PROJECT ID ### \ +--input=gs://### DATA BUCKET NAME###/### FILE NAME ###.csv \ +--output=### DATASET NAME ###.### TABLE NAME ### \ +--service_account_email=### SERVICE ACCOUNT EMAIL ### \ +--network=### NETWORK NAME ### \ +--subnetwork=### SUBNET NAME ### \ +--dataflow_kms_key=### CRYPTOKEY ID ### \ +--no_use_public_ips +``` + +for example: + +```hcl +python data_ingestion.py \ +--runner=DataflowRunner \ +--max_num_workers=10 \ +--autoscaling_algorithm=THROUGHPUT_BASED \ +--region=europe-west1 \ +--staging_location=gs://lc-001-eu-df-tmplocation/ \ +--temp_location=gs://lc-001-eu-df-tmplocation/ \ +--project=lcaggio-demo-001 \ +--input=gs://lc-001-eu-data/person.csv \ +--output=bq_dataset.df_import \ +--service_account_email=df-test@lcaggio-aa-demo-001.iam.gserviceaccount.com \ +--network=local \ +--subnetwork=regions/europe-west1/subnetworks/subnet \ +--dataflow_kms_key=projects/lcaggio-demo-kms/locations/europe-west1/keyRings/my-keyring-regional/cryptoKeys/key-df \ +--no_use_public_ips +``` + +You can check data imported into Google BigQuery from the Google Cloud Console UI. \ No newline at end of file diff --git a/data-solutions/gcs-to-bq/backend.tf.sample b/data-solutions/gcs-to-bq/backend.tf.sample new file mode 100644 index 00000000..a540c7cd --- /dev/null +++ b/data-solutions/gcs-to-bq/backend.tf.sample @@ -0,0 +1,20 @@ +# Copyright 2020 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 +# +# https://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 { + backend "gcs" { + bucket = "" + } +} diff --git a/data-solutions/gcs-to-bq/diagram.png b/data-solutions/gcs-to-bq/diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..2b1cb1988ba08345967b7a3de38a505e50d994f2 GIT binary patch literal 201386 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 bucket.url + } +} + +output "projects" { + description = "Project ids." + value = { + service-project = module.project-service.project_id + kms-project = module.project-kms.project_id + } +} + +output "vm" { + description = "GCE VMs." + value = { + for instance in module.vm_example.instances : + instance.name => instance.network_interface.0.network_ip + } +} diff --git a/data-solutions/gcs-to-bq/schema_bq_import.json b/data-solutions/gcs-to-bq/schema_bq_import.json new file mode 100644 index 00000000..e26fa3d2 --- /dev/null +++ b/data-solutions/gcs-to-bq/schema_bq_import.json @@ -0,0 +1,14 @@ +[ + { + "name": "name", + "type": "STRING" + }, + { + "name": "surname", + "type": "STRING" + }, + { + "name": "age", + "type": "NUMERIC" + } +] \ No newline at end of file diff --git a/data-solutions/gcs-to-bq/schema_df_import.json b/data-solutions/gcs-to-bq/schema_df_import.json new file mode 100644 index 00000000..516df6fa --- /dev/null +++ b/data-solutions/gcs-to-bq/schema_df_import.json @@ -0,0 +1,18 @@ +[ + { + "name": "name", + "type": "STRING" + }, + { + "name": "surname", + "type": "STRING" + }, + { + "name": "age", + "type": "NUMERIC" + }, + { + "name": "_TIMESTAMP", + "type": "TIMESTAMP" + } +] \ No newline at end of file diff --git a/data-solutions/gcs-to-bq/scripts/data_ingestion/README.md b/data-solutions/gcs-to-bq/scripts/data_ingestion/README.md new file mode 100644 index 00000000..1f1bac71 --- /dev/null +++ b/data-solutions/gcs-to-bq/scripts/data_ingestion/README.md @@ -0,0 +1,81 @@ +# Ingest CSV files from GCS into Bigquery + +In this example we create a Python [Apache Beam](https://beam.apache.org/) pipeline running on [Google Cloud Dataflow](https://cloud.google.com/dataflow/) to import CSV files into BigQuery adding a timestamp to each row. Below the architecture used: + +![Apache Beam pipeline to import CSV from GCS into BQ](diagram.png) + +The architecture uses: +* [Google Cloud Storage]() to store CSV source files +* [Google Cloud Dataflow](https://cloud.google.com/dataflow/) to read files from Google Cloud Storage, Transform data base on the structure of the file and import the data into Google BigQuery +* [Google BigQuery](https://cloud.google.com/bigquery/) to store data in a Data Lake. + +You can use this script as a starting point to import your files into Google BigQuery. You'll probably need to adapt the script logic to your requirements. + +## 1. Prerequisites + - Up and running GCP project with enabled billing account + - gcloud installed and initiated to your project + - Google Cloud Dataflow API enabled + - Google Cloud Storage Bucket containing the file to import (CSV format) containings name, surnames and age. Example: `Mario,Rossi,30`. + - Google Cloud Storage Bucket for temp and staging Google Dataflow files + - Google BigQuery dataset + - [Python](https://www.python.org/) >= 3.7 and python-dev module + - gcc + - Google Cloud [Application Default Credentials](https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login) + +## 2. Create virtual environment +Create a new virtual environment (recommended) and install requirements: + +``` +virtualenv env +source ./env/bin/activate +pip install -r requirements.txt +``` + +## 4. Upload files into Google Cloud Storage +Upload files to be imported into Google Bigquery in a Google Cloud Storage Bucket. You can use `gsutil` using a command like: +``` +gsutil cp [LOCAL_OBJECT_LOCATION] gs://[DESTINATION_BUCKET_NAME]/ +``` + +Files need to be in CSV format,For example: +``` +Enrico,Bianchi,20 +Mario,Rossi,30 +``` + +You can use the [person_details_generator](../person_details_generator/) script if you want to create random person details. + +## 5. Run pipeline +You can check parameters accepted by the `data_ingestion.py` script with the following command: +``` +python pipelines/data_ingestion --help +``` + +You can run the pipeline locally with the following command: +``` +python data_ingestion.py \ +--runner=DirectRunner \ +--project=###PUT HERE PROJECT ID### \ +--input=###PUT HERE THE FILE TO IMPORT. EXAMPLE: gs://bucket_name/person.csv ### \ +--output=###PUT HERE BQ DATASET.TABLE### +``` + +or you can run the pipeline on Google Dataflow using the following command: + +``` +python pipelines/data_ingestion_configurable.py \ +--runner=DataflowRunner \ +--max_num_workers=100 \ +--autoscaling_algorithm=THROUGHPUT_BASED \ +--region=###PUT HERE REGION### \ +--staging_location=###PUT HERE GCS STAGING LOCATION### \ +--temp_location=###PUT HERE GCS TMP LOCATION###\ +--project=###PUT HERE PROJECT ID### \ +--input-bucket=###PUT HERE GCS BUCKET NAME### \ +--input-path=###PUT HERE INPUT FOLDER### \ +--input-files=###PUT HERE FILE NAMES### \ +--bq-dataset=###PUT HERE BQ DATASET NAME### +``` + +## 6. Check results +You can check data imported into Google BigQuery from the Google Cloud Console UI. \ No newline at end of file diff --git a/data-solutions/gcs-to-bq/scripts/data_ingestion/REQUIREMENTS.txt b/data-solutions/gcs-to-bq/scripts/data_ingestion/REQUIREMENTS.txt new file mode 100644 index 00000000..ce9b3d90 --- /dev/null +++ b/data-solutions/gcs-to-bq/scripts/data_ingestion/REQUIREMENTS.txt @@ -0,0 +1,2 @@ +wheel +apache-beam diff --git a/data-solutions/gcs-to-bq/scripts/data_ingestion/data_ingestion.py b/data-solutions/gcs-to-bq/scripts/data_ingestion/data_ingestion.py new file mode 100644 index 00000000..54c89cd4 --- /dev/null +++ b/data-solutions/gcs-to-bq/scripts/data_ingestion/data_ingestion.py @@ -0,0 +1,133 @@ +# Copyright 2020 Google Inc. +# +# 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. +"""`data_ingestion.py` is a Dataflow pipeline which reads a CSV file and +writes its contents to a BigQuery table adding a timestamp. +""" + +import argparse +import logging +import re + +import apache_beam as beam +from apache_beam.options.pipeline_options import PipelineOptions + + +class DataIngestion: + """A helper class which contains the logic to translate the file into + a format BigQuery will accept.""" + + def parse_method(self, string_input): + """Translate CSV row to dictionary. + Args: + string_input: A comma separated list of values in the form of + name,surname + Example string_input: lorenzo,caggioni + Returns: + A dict mapping BigQuery column names as keys + example output: + { + 'name': 'mario', + 'surname': 'rossi', + 'age': 30 + } + """ + # Strip out carriage return, newline and quote characters. + values = re.split(",", re.sub('\r\n', '', re.sub('"', '', + string_input))) + row = dict( + zip(('name', 'surname', 'age'), + values)) + return row + + +class InjectTimestamp(beam.DoFn): + """A class which add a timestamp for each row. + Args: + element: A dictionary mapping BigQuery column names + Example: + { + 'name': 'mario', + 'surname': 'rossi', + 'age': 30 + } + Returns: + The input dictionary with a timestamp value added + Example: + { + 'name': 'mario', + 'surname': 'rossi', + 'age': 30 + '_TIMESTAMP': 1545730073 + } + """ + + def process(self, element): + import time + element['_TIMESTAMP'] = int(time.mktime(time.gmtime())) + return [element] + + +def run(argv=None): + """The main function which creates the pipeline and runs it.""" + + parser = argparse.ArgumentParser() + + parser.add_argument( + '--input', + dest='input', + required=False, + help='Input file to read. This can be a local file or ' + 'a file in a Google Storage Bucket.') + + parser.add_argument( + '--output', + dest='output', + required=False, + help='Output BQ table to write results to.') + + # Parse arguments from the command line. + known_args, pipeline_args = parser.parse_known_args(argv) + + # DataIngestion is a class we built in this script to hold the logic for + # transforming the file into a BigQuery table. + data_ingestion = DataIngestion() + + # Initiate the pipeline using the pipeline arguments + p = beam.Pipeline(options=PipelineOptions(pipeline_args)) + + (p + # Read the file. This is the source of the pipeline. + | 'Read from a File' >> beam.io.ReadFromText(known_args.input) + # Translates CSV row to a dictionary object consumable by BigQuery. + | 'String To BigQuery Row' >> + beam.Map(lambda s: data_ingestion.parse_method(s)) + # Add the timestamp on each row + | 'Inject Timestamp - ' >> beam.ParDo(InjectTimestamp()) + # Write data to Bigquery + | 'Write to BigQuery' >> beam.io.Write( + beam.io.BigQuerySink( + # BigQuery table name. + known_args.output, + # Bigquery table schema + schema='name:STRING,surname:STRING,age:NUMERIC,_TIMESTAMP:TIMESTAMP', + # Creates the table in BigQuery if it does not yet exist. + create_disposition=beam.io.BigQueryDisposition.CREATE_NEVER, + # Deletes all data in the BigQuery table before writing. + write_disposition=beam.io.BigQueryDisposition.WRITE_TRUNCATE))) + p.run().wait_until_finish() + + +if __name__ == '__main__': + logging.getLogger().setLevel(logging.INFO) + run() diff --git a/data-solutions/gcs-to-bq/scripts/data_ingestion/diagram.png b/data-solutions/gcs-to-bq/scripts/data_ingestion/diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..22e4518f7e5eefb38de434bc7ea7d36b31c29faa GIT binary patch literal 90257 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 literal 0 HcmV?d00001 diff --git a/data-solutions/gcs-to-bq/scripts/person_details_generator/README.md b/data-solutions/gcs-to-bq/scripts/person_details_generator/README.md new file mode 100644 index 00000000..43832cdf --- /dev/null +++ b/data-solutions/gcs-to-bq/scripts/person_details_generator/README.md @@ -0,0 +1,17 @@ +# Create random Person PII data + +In this example you can find a Python script to generate Person PII data in a CSV file format. + +To know how to use the script run: + +```hcl +python3 person_details_generator.py --help +``` + +## Example +To create a file 'person.csv' with 10000 of random person details data you can run: +```hcl +python3 person_details_generator.py \ +--count 10000 \ +--output person.csv +``` \ No newline at end of file diff --git a/data-solutions/gcs-to-bq/scripts/person_details_generator/REQUIREMENTS.txt b/data-solutions/gcs-to-bq/scripts/person_details_generator/REQUIREMENTS.txt new file mode 100644 index 00000000..b98f6609 --- /dev/null +++ b/data-solutions/gcs-to-bq/scripts/person_details_generator/REQUIREMENTS.txt @@ -0,0 +1 @@ +click \ No newline at end of file diff --git a/data-solutions/gcs-to-bq/scripts/person_details_generator/person_details_generator.py b/data-solutions/gcs-to-bq/scripts/person_details_generator/person_details_generator.py new file mode 100644 index 00000000..366954df --- /dev/null +++ b/data-solutions/gcs-to-bq/scripts/person_details_generator/person_details_generator.py @@ -0,0 +1,43 @@ +# Copyright 2020 Google Inc. +# +# 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. +"""`person_details_generator.py` is a Python script to generate random +Person PII (name, surname and age) having as input an array of +names and an array of surnames. +""" + +import click +import logging +import random + + +@click.command() +@click.option("--count", default=100, help="Number of generated names.") +@click.option("--output", default=False, help="Name of the output file. Content will be overwriten. If not defined, standard output will be used.") +@click.option("--first_names", default="Lorenzo,Giacomo,Chiara,Miriam", help="String of Names, comma separated. Default 'Lorenzo,Giacomo,Chiara,Miriam'") +@click.option("--last_names", default="Rossi, Bianchi,Brambilla,Caggioni", help="String of Names, comma separated. Default 'Rossi,Bianchi,Brambilla,Caggioni'") +def main(count, output, first_names, last_names): + generated_names = "".join(random.choice(first_names.split(',')) + "," + + random.choice(last_names.split(',')) + "," + + str(random.randint(1, 100)) + "\n" for _ in range(count))[:-1] + if output: + f = open(output, "w") + f.write(generated_names) + f.close() + else: + print(generated_names) + + +if __name__ == '__main__': + logging.getLogger().setLevel(logging.INFO) + main() diff --git a/data-solutions/gcs-to-bq/variables.tf b/data-solutions/gcs-to-bq/variables.tf new file mode 100644 index 00000000..fb53dd77 --- /dev/null +++ b/data-solutions/gcs-to-bq/variables.tf @@ -0,0 +1,76 @@ +# Copyright 2020 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 +# +# https://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 "billing_account" { + description = "Billing account id used as default for new projects." + type = string +} + +variable "location" { + description = "The location where resources will be deployed." + type = string + default = "europe" +} + +variable "project_service_name" { + description = "Name for the new Service Project." + type = string +} + +variable "project_kms_name" { + description = "Name for the new KMS Project." + type = string +} + +variable "region" { + description = "The region where resources will be deployed." + type = string + default = "europe-west1" +} + +variable "root_node" { + description = "The resource name of the parent Folder or Organization. Must be of the form folders/folder_id or organizations/org_id." + type = string +} + +variable "vpc_name" { + description = "Name of the VPC created in the Service Project." + type = string + default = "local" +} + +variable "vpc_subnet_name" { + description = "Name of the subnet created in the Service Project." + type = string + default = "subnet" +} + +variable "vpc_ip_cidr_range" { + description = "Ip range used in the subnet deployef in the Service Project." + type = string + default = "10.0.0.0/20" +} + +variable "zone" { + description = "The zone where resources will be deployed." + type = string + default = "europe-west1-b" +} + +variable "ssh_source_ranges" { + description = "IP CIDR ranges that will be allowed to connect via SSH to the onprem instance." + type = list(string) + default = ["0.0.0.0/0"] +} \ No newline at end of file diff --git a/data-solutions/gcs-to-bq/versions.tf b/data-solutions/gcs-to-bq/versions.tf new file mode 100644 index 00000000..057095c0 --- /dev/null +++ b/data-solutions/gcs-to-bq/versions.tf @@ -0,0 +1,17 @@ +# Copyright 2020 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 +# +# https://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_version = ">= 0.12.6" +} diff --git a/modules/project/service_accounts.tf b/modules/project/service_accounts.tf index d0ccee65..64d5566e 100644 --- a/modules/project/service_accounts.tf +++ b/modules/project/service_accounts.tf @@ -17,6 +17,8 @@ locals { service_account_cloud_services = "${google_project.project.number}@cloudservices.gserviceaccount.com" service_accounts_default = { + # TODO: Find a better place to store BQ service account + bq = "bq-${google_project.project.number}@bigquery-encryption.iam.gserviceaccount.com" compute = "${google_project.project.number}-compute@developer.gserviceaccount.com" gae = "${google_project.project.project_id}@appspot.gserviceaccount.com" } @@ -26,6 +28,7 @@ locals { compute = "compute-system" container-engine = "container-engine-robot" containerregistry = "containerregistry" + dataflow = "dataflow-service-producer-prod" dataproc = "dataproc-accounts" gae-flex = "gae-api-prod" gcf = "gcf-admin-robot" From 218a36c4139a47d20b493d5548595e88c055fa49 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Sun, 28 Jun 2020 11:01:13 +0200 Subject: [PATCH 106/129] remove spurious output from onprem example's README --- infrastructure/onprem-google-access-dns/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/infrastructure/onprem-google-access-dns/README.md b/infrastructure/onprem-google-access-dns/README.md index 2820c8f5..9f646104 100644 --- a/infrastructure/onprem-google-access-dns/README.md +++ b/infrastructure/onprem-google-access-dns/README.md @@ -153,16 +153,16 @@ The VPN used to connect to the on-premises environment does not account for HA, | project_id | Project id for all resources. | string | ✓ | | | *bgp_asn* | BGP ASNs. | map(number) | | ... | | *bgp_interface_ranges* | BGP interface IP CIDR ranges. | map(string) | | ... | +| *dns_forwarder_address* | Address of the DNS server used to forward queries from on-premises. | string | | 10.0.0.2 | +| *forwarder_address* | GCP DNS inbound policy forwarder address. | string | | 10.0.0.2 | | *ip_ranges* | IP CIDR ranges. | map(string) | | ... | | *region* | VPC region. | string | | europe-west1 | -| *resolver_address* | GCP DNS resolver address for the inbound policy. | string | | 10.0.0.2 | | *ssh_source_ranges* | IP CIDR ranges that will be allowed to connect via SSH to the onprem instance. | list(string) | | ["0.0.0.0/0"] | ## Outputs | name | description | sensitive | |---|---|:---:| -| foo | None | | | onprem-instance | Onprem instance details. | | | test-instance | Test instance details. | | From d3fe52ef3ae99fb31b5321b2ad3f9467753294d1 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Sun, 28 Jun 2020 11:19:15 +0200 Subject: [PATCH 107/129] fix minimum required version of google-beta provider in dns module --- modules/dns/versions.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/dns/versions.tf b/modules/dns/versions.tf index 09324d5d..50c4c4e5 100644 --- a/modules/dns/versions.tf +++ b/modules/dns/versions.tf @@ -18,6 +18,6 @@ terraform { required_version = ">= 0.12.20" required_providers { google = "~> 3.10" - google-beta = "~> 3.10" + google-beta = "~> 3.20" } } From 21758f399d36e107906546fa990ca4972ea73d4a Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Sun, 28 Jun 2020 12:11:54 +0200 Subject: [PATCH 108/129] Update README.md --- modules/cloud-config-container/coredns/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/modules/cloud-config-container/coredns/README.md b/modules/cloud-config-container/coredns/README.md index 5f8d5719..82ba51d8 100644 --- a/modules/cloud-config-container/coredns/README.md +++ b/modules/cloud-config-container/coredns/README.md @@ -24,7 +24,7 @@ This example will create a `cloud-config` that uses the module's defaults, creat ```hcl module "cos-coredns" { - source = "./modules/cos-container/coredns" + source = "./modules/cloud-config-container/coredns" } # use it as metadata in a compute instance or template @@ -40,8 +40,8 @@ This example will create a `cloud-config` using a custom CoreDNS configuration, ```hcl module "cos-coredns" { - source = "./modules/cos-container/coredns" - coredns_config = "./modules/cos-container/coredns/Corefile-hosts" + source = "./modules/cloud-config-container/coredns" + coredns_config = "./modules/cloud-config-container/coredns/Corefile-hosts" files = { "/etc/coredns/example.hosts" = { content = "127.0.0.2 foo.example.org foo" @@ -57,7 +57,7 @@ This example shows how to create the single instance optionally managed by the m ```hcl module "cos-coredns" { - source = "./modules/cos-container/coredns" + source = "./modules/cloud-config-container/coredns" test_instance = { project_id = "my-project" zone = "europe-west1-b" From ea334cd2c9643fc13aa8aec8e00c5374030bed42 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 29 Jun 2020 07:55:02 +0200 Subject: [PATCH 109/129] bum minimum required tf version --- infrastructure/onprem-google-access-dns/versions.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/infrastructure/onprem-google-access-dns/versions.tf b/infrastructure/onprem-google-access-dns/versions.tf index de5425c2..057095c0 100644 --- a/infrastructure/onprem-google-access-dns/versions.tf +++ b/infrastructure/onprem-google-access-dns/versions.tf @@ -13,5 +13,5 @@ # limitations under the License. terraform { - required_version = ">= 0.12" + required_version = ">= 0.12.6" } From c4850b83911437c291c847f9c7cc88aa1ca538bd Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 29 Jun 2020 08:05:44 +0200 Subject: [PATCH 110/129] Cloud functions module (#102) * wip * cloud function module * wip * cloud function module * update top-level READMEs and CHANGELOG * update top-level READMEs and CHANGELOG * remove duplicate boilerplate in variables * implement suggestions in PR review --- CHANGELOG.md | 4 +- README.md | 3 +- modules/README.md | 4 + modules/cloud-function/README.md | 162 ++++++++++++++++++++++++++++ modules/cloud-function/main.tf | 122 +++++++++++++++++++++ modules/cloud-function/outputs.tf | 55 ++++++++++ modules/cloud-function/variables.tf | 123 +++++++++++++++++++++ modules/cloud-function/versions.tf | 19 ++++ 8 files changed, 490 insertions(+), 2 deletions(-) create mode 100644 modules/cloud-function/README.md create mode 100644 modules/cloud-function/main.tf create mode 100644 modules/cloud-function/outputs.tf create mode 100644 modules/cloud-function/variables.tf create mode 100644 modules/cloud-function/versions.tf diff --git a/CHANGELOG.md b/CHANGELOG.md index f0de265f..9a10e827 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,10 @@ All notable changes to this project will be documented in this file. ## [Unreleased] -- new 'Cloud Endpoints' module + - make project creation optional in `project` module to allow managing a pre-existing project +- new `cloud-endpoints` module +- new `cloud-function` module ## [2.1.0] - 2020-06-22 diff --git a/README.md b/README.md index db02b66e..14aa6186 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,8 @@ Currently available modules: - **networking** - [VPC](./modules/net-vpc), [VPC firewall](./modules/net-vpc-firewall), [VPC peering](./modules/net-vpc-peering), [VPN static](./modules/net-vpn-static), [VPN dynamic](./modules/net-vpn-dynamic), [VPN HA](./modules/net-vpn-ha), [NAT](./modules/net-cloudnat), [address reservation](./modules/net-address), [DNS](./modules/dns), [L4 ILB](./modules/net-ilb), [Service Directory](./modules/service-directory), [Cloud Endpoints](./modules/cloudenpoints) - **compute** - [VM/VM group](./modules/compute-vm), [MIG](./modules/compute-mig), [GKE cluster](./modules/gke-cluster), [GKE nodepool](./modules/gke-nodepool), [COS container](./modules/cos-container) (coredns, mysql, onprem, squid) - **data** - [GCS](./modules/gcs), [BigQuery dataset](./modules/bigquery-dataset), [Pub/Sub](./modules/pubsub), [Datafusion](./modules/datafusion), [Bigtable instance](./modules/bigtable-instance) -- **security** - [KMS](./modules/kms), [SecretManager](./modules/secret-manager) - **development** - [Cloud Source Repository](./modules/source-repository), [Container Registry](./modules/container-registry), [Artifact Registry](./modules/artifact-registry) +- **security** - [KMS](./modules/kms), [SecretManager](./modules/secret-manager) +- **serverless** - [Cloud Functions](./cloud-functions) For more information and usage examples see each module's README file. diff --git a/modules/README.md b/modules/README.md index d94f6dc0..4c73872a 100644 --- a/modules/README.md +++ b/modules/README.md @@ -58,3 +58,7 @@ Specific modules also offer support for non-authoritative bindings (e.g. `google - [Cloud KMS](./kms) - [Secret Manager](./secret-manager) + +## Serverless + +- [Cloud Functions](./cloud-function) diff --git a/modules/cloud-function/README.md b/modules/cloud-function/README.md new file mode 100644 index 00000000..fb386a0c --- /dev/null +++ b/modules/cloud-function/README.md @@ -0,0 +1,162 @@ +# Cloud Function Module + +Cloud Function management, with support for IAM roles and optional bucket creation. + +The GCS object used for deployment uses a hash of the bundle zip contents in its name, which ensures change tracking and avoids recreating the function if the GCS object is deleted and needs recreating. + +## TODO + +- [ ] add support for `ingress_settings` +- [ ] add support for `vpc_connector` and `vpc_connector_egress_settings` +- [ ] add support for `source_repository` + +## Examples + +### HTTP trigger + +This deploys a Cloud Function with an HTTP endpoint, using a pre-existing GCS bucket for deployment, setting the service account to the Cloud Function default one, and delegating access control to the containing project. + +```hcl +module "cf-http" { + source = "../modules/net-cloudnat" + project_id = "my-project" + name = "test-cf-http" + bucket_name = "test-cf-bundles" + bundle_config = { + source_dir = "my-cf-source-folder + output_path = "bundle.zip" + } +} +``` + +### Non-HTTP triggers + +Other trigger types other than HTTP are configured via the `trigger_config` variable. This example shows a PubSub trigger. + +```hcl +module "cf-http" { + source = "../modules/net-cloudnat" + project_id = "my-project" + name = "test-cf-http" + bucket_name = "test-cf-bundles" + bundle_config = { + source_dir = "my-cf-source-folder + output_path = "bundle.zip" + } + trigger_config = { + event = "google.pubsub.topic.publish" + resource = local.my-topic + retry = null + } +} +``` + +### Controlling HTTP access + +To allow anonymous access to the function, grant the `roles/cloudfunctions.invoker` role to the special `allUsers` identifier. Use specific identities (service accounts, groups, etc.) instead of `allUsers` to only allow selective access. + +```hcl +module "cf-http" { + source = "../modules/net-cloudnat" + project_id = "my-project" + name = "test-cf-http" + bucket_name = "test-cf-bundles" + bundle_config = { + source_dir = "my-cf-source-folder + output_path = "bundle.zip" + } + iam_roles = ["roles/cloudfunctions.invoker"] + iam_members = { + "roles/cloudfunctions.invoker" = ["allUsers"] + } +} +``` + +### GCS bucket creation + +You can have the module auto-create the GCS bucket used for deployment via the `bucket_config` variable. Setting `bucket_config.location` to `null` will also use the function region for GCS. + +```hcl +module "cf-http" { + source = "../modules/net-cloudnat" + project_id = "my-project" + name = "test-cf-http" + bucket_name = "test-cf-bundles" + bucket_config = { + location = null + lifecycle_delete_age = 1 + } + bundle_config = { + source_dir = "my-cf-source-folder + output_path = "bundle.zip" + } +} +``` + +### Service account management + +To use a custom service account managed by the module, set `service_account_create` to `true` and leave `service_account` set to `null` value (default). + +```hcl +module "cf-http" { + source = "../modules/net-cloudnat" + project_id = "my-project" + name = "test-cf-http" + bucket_name = "test-cf-bundles" + bundle_config = { + source_dir = "my-cf-source-folder + output_path = "bundle.zip" + } + service_account_create = true +} +``` + +To use an externally managed service account, pass its email in `service_account` and leave `service_account_create` to `false` (the default). + +```hcl +module "cf-http" { + source = "../modules/net-cloudnat" + project_id = "my-project" + name = "test-cf-http" + bucket_name = "test-cf-bundles" + bundle_config = { + source_dir = "my-cf-source-folder + output_path = "bundle.zip" + } + service_account = local.service_account_email +} +``` + + +## Variables + +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| bucket_name | Name of the bucket that will be used for the function code. It will be created with prefix prepended if bucket_config is not null. | string | ✓ | | +| bundle_config | Cloud function source folder and generated zip bundle paths. Output path defaults to '/tmp/bundle.zip' if null. | object({...}) | ✓ | | +| name | Name used for cloud function and associated resources. | string | ✓ | | +| project_id | Project id used for all resources. | string | ✓ | | +| *bucket_config* | Enable and configure auto-created bucket. Set fields to null to use defaults. | object({...}) | | null | +| *environment_variables* | Cloud function environment variables. | map(string) | | {} | +| *function_config* | Cloud function configuration. | object({...}) | | ... | +| *iam_members* | Map of member lists used to set authoritative bindings, keyed by role. Ignored for template use. | map(list(string)) | | {} | +| *iam_roles* | List of roles used to set authoritative bindings. Ignored for template use. | list(string) | | [] | +| *labels* | Resource labels | map(string) | | {} | +| *prefix* | Optional prefix used for resource names. | string | | null | +| *region* | Region used for all resources. | string | | us-central1 | +| *service_account* | Service account email. Unused if service account is auto-created. | string | | null | +| *service_account_create* | Auto-create service account. | bool | | false | +| *trigger_config* | Function trigger configuration. Leave null for HTTP trigger. | object({...}) | | null | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| bucket | Bucket resource (only if auto-created). | | +| bucket_name | Bucket name. | | +| function | Cloud function resources. | | +| function_name | Cloud function name. | | +| service_account | Service account resource. | | +| service_account_email | Service account email. | | +| service_account_iam_email | Service account email. | | + diff --git a/modules/cloud-function/main.tf b/modules/cloud-function/main.tf new file mode 100644 index 00000000..a668a8bc --- /dev/null +++ b/modules/cloud-function/main.tf @@ -0,0 +1,122 @@ +/** + * Copyright 2020 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 { + bucket = ( + var.bucket_name != null + ? var.bucket_name + : ( + length(google_storage_bucket.bucket) > 0 + ? google_storage_bucket.bucket[0].name + : null + ) + ) + prefix = var.prefix == null ? "" : "${var.prefix}-" + service_account_email = ( + var.service_account_create + ? ( + length(google_service_account.service_account) > 0 + ? google_service_account.service_account[0].email + : null + ) + : var.service_account + ) +} + +resource "google_cloudfunctions_function" "function" { + project = var.project_id + region = var.region + name = "${local.prefix}${var.name}" + description = "Terraform managed." + runtime = var.function_config.runtime + available_memory_mb = var.function_config.memory + max_instances = var.function_config.instances + timeout = var.function_config.timeout + entry_point = var.function_config.entry_point + environment_variables = var.environment_variables + service_account_email = local.service_account_email + source_archive_bucket = local.bucket + source_archive_object = google_storage_bucket_object.bundle.name + labels = var.labels + trigger_http = var.trigger_config == null ? true : null + + dynamic event_trigger { + for_each = var.trigger_config == null ? [] : [""] + content { + event_type = var.trigger_config.event + resource = var.trigger_config.resource + dynamic failure_policy { + for_each = var.trigger_config.retry == null ? [] : [""] + content { + retry = var.trigger_config.retry + } + } + } + } + +} + +resource "google_cloudfunctions_function_iam_binding" "default" { + for_each = toset(var.iam_roles) + project = var.project_id + region = var.region + cloud_function = google_cloudfunctions_function.function.name + role = each.value + members = try(var.iam_members[each.value], {}) +} + +resource "google_storage_bucket" "bucket" { + count = var.bucket_config == null ? 0 : 1 + project = var.project_id + name = "${local.prefix}${var.bucket_name}" + location = ( + var.bucket_config.location == null + ? var.region + : var.bucket_config.location + ) + labels = var.labels + + dynamic lifecycle_rule { + for_each = var.bucket_config.lifecycle_delete_age == null ? [] : [""] + content { + action { type = "Delete" } + condition { age = var.bucket_config.lifecycle_delete_age } + } + } +} + +resource "google_storage_bucket_object" "bundle" { + name = "bundle-${data.archive_file.bundle.output_md5}.zip" + bucket = local.bucket + source = data.archive_file.bundle.output_path +} + +data "archive_file" "bundle" { + type = "zip" + source_dir = var.bundle_config.source_dir + output_path = ( + var.bundle_config.output_path == null + ? "/tmp/bundle.zip" + : var.bundle_config.output_path + ) +} + +resource "google_service_account" "service_account" { + count = var.service_account_create ? 1 : 0 + project = var.project_id + account_id = "tf-cf-${var.name}" + display_name = "Terraform Cloud Function ${var.name}." +} diff --git a/modules/cloud-function/outputs.tf b/modules/cloud-function/outputs.tf new file mode 100644 index 00000000..43e0eda7 --- /dev/null +++ b/modules/cloud-function/outputs.tf @@ -0,0 +1,55 @@ +/** + * Copyright 2020 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 "bucket" { + description = "Bucket resource (only if auto-created)." + value = var.bucket_config == null ? null : google_storage_bucket.bucket.0 +} + +output "bucket_name" { + description = "Bucket name." + value = local.bucket +} + +output "function" { + description = "Cloud function resources." + value = google_cloudfunctions_function.function +} + +output "function_name" { + description = "Cloud function name." + value = google_cloudfunctions_function.function.name +} + +output "service_account" { + description = "Service account resource." + value = ( + var.service_account_create ? google_service_account.service_account[0] : null + ) +} + +output "service_account_email" { + description = "Service account email." + value = local.service_account_email +} + +output "service_account_iam_email" { + description = "Service account email." + value = join("", [ + "serviceAccount:", + local.service_account_email == null ? "" : local.service_account_email + ]) +} diff --git a/modules/cloud-function/variables.tf b/modules/cloud-function/variables.tf new file mode 100644 index 00000000..83c8c048 --- /dev/null +++ b/modules/cloud-function/variables.tf @@ -0,0 +1,123 @@ +/** + * Copyright 2020 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 "bucket_config" { + description = "Enable and configure auto-created bucket. Set fields to null to use defaults." + type = object({ + location = string + lifecycle_delete_age = number + }) + default = null +} + +variable "bucket_name" { + description = "Name of the bucket that will be used for the function code. It will be created with prefix prepended if bucket_config is not null." + type = string +} + +variable "bundle_config" { + description = "Cloud function source folder and generated zip bundle paths. Output path defaults to '/tmp/bundle.zip' if null." + type = object({ + source_dir = string + output_path = string + }) +} + +variable "environment_variables" { + description = "Cloud function environment variables." + type = map(string) + default = {} +} + +variable "iam_members" { + description = "Map of member lists used to set authoritative bindings, keyed by role. Ignored for template use." + type = map(list(string)) + default = {} +} + +variable "iam_roles" { + description = "List of roles used to set authoritative bindings. Ignored for template use." + type = list(string) + default = [] +} + +variable "function_config" { + description = "Cloud function configuration." + type = object({ + entry_point = string + instances = number + memory = number + runtime = string + timeout = number + }) + default = { + entry_point = "main" + instances = 1 + memory = 256 + runtime = "python37" + timeout = 180 + } +} + +variable "labels" { + description = "Resource labels" + type = map(string) + default = {} +} + +variable "name" { + description = "Name used for cloud function and associated resources." + type = string +} + +variable "prefix" { + description = "Optional prefix used for resource names." + type = string + default = null +} + +variable "project_id" { + description = "Project id used for all resources." + type = string +} + +variable "region" { + description = "Region used for all resources." + type = string + default = "europe-west1" +} + +variable "service_account" { + description = "Service account email. Unused if service account is auto-created." + type = string + default = null +} + +variable "service_account_create" { + description = "Auto-create service account." + type = bool + default = false +} + +variable "trigger_config" { + description = "Function trigger configuration. Leave null for HTTP trigger." + type = object({ + event = string + resource = string + retry = bool + }) + default = null +} diff --git a/modules/cloud-function/versions.tf b/modules/cloud-function/versions.tf new file mode 100644 index 00000000..bc4c2a9d --- /dev/null +++ b/modules/cloud-function/versions.tf @@ -0,0 +1,19 @@ +/** + * Copyright 2020 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_version = ">= 0.12.6" +} From add7b7fa1a31201c297e13c86f9bc597c6e2ca6d Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Mon, 29 Jun 2020 08:06:41 +0200 Subject: [PATCH 111/129] Update CHANGELOG.md --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a10e827..3a943ae6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [2.2.0] - 2020-06-29 + - make project creation optional in `project` module to allow managing a pre-existing project - new `cloud-endpoints` module - new `cloud-function` module @@ -108,7 +110,8 @@ All notable changes to this project will be documented in this file. - merge development branch with suite of new modules and end-to-end examples -[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.1.0...HEAD +[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.2.0...HEAD +[2.2.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.1.0...v2.2.0 [2.1.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.0.0...v2.1.0 [2.0.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.9.0...v2.0.0 [1.9.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.8.1...v1.9.0 From 58e5dfa620600ef5564d6f33a2df6f58d4dbc9fb Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Tue, 30 Jun 2020 10:56:27 +0200 Subject: [PATCH 112/129] Fixes --- data-solutions/gcs-to-bq/README.md | 27 ++++++++++++++--- data-solutions/gcs-to-bq/main.tf | 5 ++-- data-solutions/gcs-to-bq/scripts/README.md | 4 +++ .../scripts/data_ingestion/README.md | 29 +++++++++++++++---- .../scripts/data_ingestion/REQUIREMENTS.txt | 5 ++-- 5 files changed, 56 insertions(+), 14 deletions(-) create mode 100644 data-solutions/gcs-to-bq/scripts/README.md diff --git a/data-solutions/gcs-to-bq/README.md b/data-solutions/gcs-to-bq/README.md index f1a13578..46c19467 100644 --- a/data-solutions/gcs-to-bq/README.md +++ b/data-solutions/gcs-to-bq/README.md @@ -69,7 +69,7 @@ This sample creates several distinct groups of resources: | vm | GCE VMs. | | -## Test your environment +## Test your environment with Cloud Dataflow You can now connect to the GCE instance with the following command: ```hcl @@ -106,14 +106,33 @@ python data_ingestion.py \ --region=europe-west1 \ --staging_location=gs://lc-001-eu-df-tmplocation/ \ --temp_location=gs://lc-001-eu-df-tmplocation/ \ ---project=lcaggio-demo-001 \ ---input=gs://lc-001-eu-data/person.csv \ +--project=lcaggio-demo \ +--input=gs://lc-eu-data/person.csv \ --output=bq_dataset.df_import \ ---service_account_email=df-test@lcaggio-aa-demo-001.iam.gserviceaccount.com \ +--service_account_email=df-test@lcaggio-demo.iam.gserviceaccount.com \ --network=local \ --subnetwork=regions/europe-west1/subnetworks/subnet \ --dataflow_kms_key=projects/lcaggio-demo-kms/locations/europe-west1/keyRings/my-keyring-regional/cryptoKeys/key-df \ --no_use_public_ips ``` +You can check data imported into Google BigQuery from the Google Cloud Console UI. + +## Test your environment with 'bq' CLI +You can now connect to the GCE instance with the following command: + +```hcl + gcloud compute ssh vm-example-1 +``` + +You can run now a simple 'bq load' command to import data into Bigquery. Below an example command: + +```hcl +bq load \ +--source_format=CSV \ +bq_dataset.bq_import \ +gs://my-bucket/person.csv \ +schema_bq_import.json +``` + You can check data imported into Google BigQuery from the Google Cloud Console UI. \ No newline at end of file diff --git a/data-solutions/gcs-to-bq/main.tf b/data-solutions/gcs-to-bq/main.tf index 2ffc352a..84521c03 100644 --- a/data-solutions/gcs-to-bq/main.tf +++ b/data-solutions/gcs-to-bq/main.tf @@ -15,7 +15,8 @@ locals { vm-startup-script = join("\n", [ "#! /bin/bash", - "apt-get update && apt-get install -y bash-completion git python3-venv gcc build-essential python-dev" + "apt-get update && apt-get install -y bash-completion git python3-venv gcc build-essential python-dev python3-dev", + "pip3 install --upgrade setuptools pip" ]) } @@ -230,7 +231,7 @@ module "vm_example" { } } ] - instance_count = 1 + instance_count = 2 boot_disk = { image = "projects/debian-cloud/global/images/family/debian-10" type = "pd-ssd" diff --git a/data-solutions/gcs-to-bq/scripts/README.md b/data-solutions/gcs-to-bq/scripts/README.md new file mode 100644 index 00000000..2ab41357 --- /dev/null +++ b/data-solutions/gcs-to-bq/scripts/README.md @@ -0,0 +1,4 @@ +# Sripts +In this section you can find two simple scripts to test your environment: + - [Data ingestion](./data_ingestion/): a simple Apache Beam Python pipeline to import data from Google Cloud Storage into Bigquery. + - [Person details generator](./person_details_generator/): a simple script to generate some random data to test your environment. \ No newline at end of file diff --git a/data-solutions/gcs-to-bq/scripts/data_ingestion/README.md b/data-solutions/gcs-to-bq/scripts/data_ingestion/README.md index 1f1bac71..f706021c 100644 --- a/data-solutions/gcs-to-bq/scripts/data_ingestion/README.md +++ b/data-solutions/gcs-to-bq/scripts/data_ingestion/README.md @@ -28,7 +28,7 @@ Create a new virtual environment (recommended) and install requirements: ``` virtualenv env source ./env/bin/activate -pip install -r requirements.txt +pip3 install -r requirements.txt ``` ## 4. Upload files into Google Cloud Storage @@ -63,7 +63,7 @@ python data_ingestion.py \ or you can run the pipeline on Google Dataflow using the following command: ``` -python pipelines/data_ingestion_configurable.py \ +python data_ingestion.py \ --runner=DataflowRunner \ --max_num_workers=100 \ --autoscaling_algorithm=THROUGHPUT_BASED \ @@ -71,10 +71,27 @@ python pipelines/data_ingestion_configurable.py \ --staging_location=###PUT HERE GCS STAGING LOCATION### \ --temp_location=###PUT HERE GCS TMP LOCATION###\ --project=###PUT HERE PROJECT ID### \ ---input-bucket=###PUT HERE GCS BUCKET NAME### \ ---input-path=###PUT HERE INPUT FOLDER### \ ---input-files=###PUT HERE FILE NAMES### \ ---bq-dataset=###PUT HERE BQ DATASET NAME### +--input=###PUT HERE GCS BUCKET NAME. EXAMPLE: gs://bucket_name/person.csv### \ +--output=###PUT HERE BQ DATASET NAME. EXAMPLE: bq_dataset.df_import### \ +``` + +Below an example to run the pipeline specifying Network and Subnetwork, using private IPs and using a KMS key to encrypt data at rest: + +``` +python data_ingestion.py \ +--runner=DataflowRunner \ +--max_num_workers=100 \ +--autoscaling_algorithm=THROUGHPUT_BASED \ +--region=###PUT HERE REGION### \ +--staging_location=###PUT HERE GCS STAGING LOCATION### \ +--temp_location=###PUT HERE GCS TMP LOCATION###\ +--project=###PUT HERE PROJECT ID### \ +--network=###PUT HERE YOUR NETWORK### \ +--subnetwork=###PUT HERE YOUR SUBNETWORK. EXAMPLE: regions/europe-west1/subnetworks/subnet### \ +--dataflowKmsKey=###PUT HERE KMES KEY. Example: projects/lcaggio-d-4-kms/locations/europe-west1/keyRings/my-keyring-regional/cryptoKeys/key-df### \ +--input=###PUT HERE GCS BUCKET NAME. EXAMPLE: gs://bucket_name/person.csv### \ +--output=###PUT HERE BQ DATASET NAME. EXAMPLE: bq_dataset.df_import### \ +--no_use_public_ips ``` ## 6. Check results diff --git a/data-solutions/gcs-to-bq/scripts/data_ingestion/REQUIREMENTS.txt b/data-solutions/gcs-to-bq/scripts/data_ingestion/REQUIREMENTS.txt index ce9b3d90..32bfbbd1 100644 --- a/data-solutions/gcs-to-bq/scripts/data_ingestion/REQUIREMENTS.txt +++ b/data-solutions/gcs-to-bq/scripts/data_ingestion/REQUIREMENTS.txt @@ -1,2 +1,3 @@ -wheel -apache-beam +apache-beam[gcp] +setuptools +wheel \ No newline at end of file From 42f0f5a454ba28b9c7d9f071765b7156740ddeed Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Tue, 30 Jun 2020 11:07:55 +0200 Subject: [PATCH 113/129] Fix --- data-solutions/gcs-to-bq/scripts/data_ingestion/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/data-solutions/gcs-to-bq/scripts/data_ingestion/README.md b/data-solutions/gcs-to-bq/scripts/data_ingestion/README.md index f706021c..badc4d1c 100644 --- a/data-solutions/gcs-to-bq/scripts/data_ingestion/README.md +++ b/data-solutions/gcs-to-bq/scripts/data_ingestion/README.md @@ -28,6 +28,7 @@ Create a new virtual environment (recommended) and install requirements: ``` virtualenv env source ./env/bin/activate +pip3 install --upgrade setuptools pip pip3 install -r requirements.txt ``` From abecaeef9c79c58ac59cca1f3a582853dbfcbe82 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Tue, 30 Jun 2020 16:34:56 +0200 Subject: [PATCH 114/129] Fix --- data-solutions/gcs-to-bq/schema_df_import.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/data-solutions/gcs-to-bq/schema_df_import.json b/data-solutions/gcs-to-bq/schema_df_import.json index 516df6fa..00e428d7 100644 --- a/data-solutions/gcs-to-bq/schema_df_import.json +++ b/data-solutions/gcs-to-bq/schema_df_import.json @@ -1,17 +1,21 @@ [ { + "mode": "NULLABLE", "name": "name", "type": "STRING" }, { + "mode": "NULLABLE", "name": "surname", "type": "STRING" }, { + "mode": "NULLABLE", "name": "age", "type": "NUMERIC" }, { + "mode": "NULLABLE", "name": "_TIMESTAMP", "type": "TIMESTAMP" } From 7c2d51f4de58c4a24b990d1649c018a1ff83b1e2 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Tue, 30 Jun 2020 16:46:47 +0200 Subject: [PATCH 115/129] Rename folder example. Add links on Readme Update Changelog --- CHANGELOG.md | 1 + README.md | 2 +- data-solutions/README.md | 3 +++ .../README.md | 2 +- .../backend.tf.sample | 0 .../diagram.png | Bin .../{gcs-to-bq => gcs-to-bq-with-dataflow}/main.tf | 0 .../outputs.tf | 0 .../schema_bq_import.json | 0 .../schema_df_import.json | 0 .../scripts/README.md | 0 .../scripts/data_ingestion/README.md | 0 .../scripts/data_ingestion/REQUIREMENTS.txt | 0 .../scripts/data_ingestion/data_ingestion.py | 0 .../scripts/data_ingestion/diagram.png | Bin .../scripts/person_details_generator/README.md | 0 .../person_details_generator/REQUIREMENTS.txt | 0 .../person_details_generator.py | 0 .../variables.tf | 0 .../versions.tf | 0 20 files changed, 6 insertions(+), 2 deletions(-) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/README.md (98%) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/backend.tf.sample (100%) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/diagram.png (100%) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/main.tf (100%) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/outputs.tf (100%) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/schema_bq_import.json (100%) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/schema_df_import.json (100%) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/scripts/README.md (100%) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/scripts/data_ingestion/README.md (100%) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/scripts/data_ingestion/REQUIREMENTS.txt (100%) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/scripts/data_ingestion/data_ingestion.py (100%) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/scripts/data_ingestion/diagram.png (100%) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/scripts/person_details_generator/README.md (100%) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/scripts/person_details_generator/REQUIREMENTS.txt (100%) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/scripts/person_details_generator/person_details_generator.py (100%) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/variables.tf (100%) rename data-solutions/{gcs-to-bq => gcs-to-bq-with-dataflow}/versions.tf (100%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 797b0085..7fceea9c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- new 'Cloud Storage to Bigquery with Cloud Dataflow' end to end data solution - new 'Cloud Endpoints' module ## [2.1.0] - 2020-06-22 diff --git a/README.md b/README.md index db02b66e..9a83c632 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ Currently available examples: - **foundations** - [single level hierarchy](./foundations/environments/) (environments), [multiple level hierarchy](./foundations/business-units/) (business units + environments) - **infrastructure** - [hub and spoke via peering](./infrastructure/hub-and-spoke-peering/), [hub and spoke via VPN](./infrastructure/hub-and-spoke-vpn/), [DNS and Google Private Access for on-premises](./infrastructure/onprem-google-access-dns/), [Shared VPC with GKE support](./infrastructure/shared-vpc-gke/) -- **data solutions** - [GCE/GCS CMEK via centralized Cloud KMS](./data-solutions/cmek-via-centralized-kms/) +- **data solutions** - [GCE/GCS CMEK via centralized Cloud KMS](./data-solutions/cmek-via-centralized-kms/), [Cloud Storage to Bigquery with Cloud Dataflow](./data-solutions/gcs-to-bq-with-dataflow/) For more information see the README files in the [foundations](./foundations/), [infrastructure](./infrastructure/) and [data solutions](./data-solutions/) folders. diff --git a/data-solutions/README.md b/data-solutions/README.md index bff07f7a..10845058 100644 --- a/data-solutions/README.md +++ b/data-solutions/README.md @@ -9,3 +9,6 @@ They are meant to be used as minimal but complete starting points to create actu ### GCE and GCS CMEK via centralized Cloud KMS This [example](./cmek-via-centralized-kms/) implements [CMEK](https://cloud.google.com/kms/docs/cmek) for GCS and GCE, via keys hosted in KMS running in a centralized project. The example shows the basic resources and permissions for the typical use case of application projects implementing encryption at rest via a centrally managed KMS service. + +### Cloud Storage to Bigquery with Cloud Dataflow + This [example](./gcs-to-bq-with-dataflow/) implements [Cloud Storage](https://cloud.google.com/kms/docs/cmek) to Bigquery data import using Cloud Dataflow.All resources use CMEK hosted in Cloud KMS running in a centralized project. The example shows the basic resources and permissions for the typical use case to read, transform and import data from Cloud Storage to Bigquery. diff --git a/data-solutions/gcs-to-bq/README.md b/data-solutions/gcs-to-bq-with-dataflow/README.md similarity index 98% rename from data-solutions/gcs-to-bq/README.md rename to data-solutions/gcs-to-bq-with-dataflow/README.md index 46c19467..b4b1a9de 100644 --- a/data-solutions/gcs-to-bq/README.md +++ b/data-solutions/gcs-to-bq-with-dataflow/README.md @@ -1,4 +1,4 @@ -# GCE and GCS CMEK via centralized Cloud KMS +# Cloud Storage to Bigquery with Cloud Dataflow This example creates the infrastructure needed to run a [Cloud Dataflow](https://cloud.google.com/dataflow) pipeline to import data from [GCS](https://cloud.google.com/storage) to [Bigquery](https://cloud.google.com/bigquery). diff --git a/data-solutions/gcs-to-bq/backend.tf.sample b/data-solutions/gcs-to-bq-with-dataflow/backend.tf.sample similarity index 100% rename from data-solutions/gcs-to-bq/backend.tf.sample rename to data-solutions/gcs-to-bq-with-dataflow/backend.tf.sample diff --git a/data-solutions/gcs-to-bq/diagram.png b/data-solutions/gcs-to-bq-with-dataflow/diagram.png similarity index 100% rename from data-solutions/gcs-to-bq/diagram.png rename to data-solutions/gcs-to-bq-with-dataflow/diagram.png diff --git a/data-solutions/gcs-to-bq/main.tf b/data-solutions/gcs-to-bq-with-dataflow/main.tf similarity index 100% rename from data-solutions/gcs-to-bq/main.tf rename to data-solutions/gcs-to-bq-with-dataflow/main.tf diff --git a/data-solutions/gcs-to-bq/outputs.tf b/data-solutions/gcs-to-bq-with-dataflow/outputs.tf similarity index 100% rename from data-solutions/gcs-to-bq/outputs.tf rename to data-solutions/gcs-to-bq-with-dataflow/outputs.tf diff --git a/data-solutions/gcs-to-bq/schema_bq_import.json b/data-solutions/gcs-to-bq-with-dataflow/schema_bq_import.json similarity index 100% rename from data-solutions/gcs-to-bq/schema_bq_import.json rename to data-solutions/gcs-to-bq-with-dataflow/schema_bq_import.json diff --git a/data-solutions/gcs-to-bq/schema_df_import.json b/data-solutions/gcs-to-bq-with-dataflow/schema_df_import.json similarity index 100% rename from data-solutions/gcs-to-bq/schema_df_import.json rename to data-solutions/gcs-to-bq-with-dataflow/schema_df_import.json diff --git a/data-solutions/gcs-to-bq/scripts/README.md b/data-solutions/gcs-to-bq-with-dataflow/scripts/README.md similarity index 100% rename from data-solutions/gcs-to-bq/scripts/README.md rename to data-solutions/gcs-to-bq-with-dataflow/scripts/README.md diff --git a/data-solutions/gcs-to-bq/scripts/data_ingestion/README.md b/data-solutions/gcs-to-bq-with-dataflow/scripts/data_ingestion/README.md similarity index 100% rename from data-solutions/gcs-to-bq/scripts/data_ingestion/README.md rename to data-solutions/gcs-to-bq-with-dataflow/scripts/data_ingestion/README.md diff --git a/data-solutions/gcs-to-bq/scripts/data_ingestion/REQUIREMENTS.txt b/data-solutions/gcs-to-bq-with-dataflow/scripts/data_ingestion/REQUIREMENTS.txt similarity index 100% rename from data-solutions/gcs-to-bq/scripts/data_ingestion/REQUIREMENTS.txt rename to data-solutions/gcs-to-bq-with-dataflow/scripts/data_ingestion/REQUIREMENTS.txt diff --git a/data-solutions/gcs-to-bq/scripts/data_ingestion/data_ingestion.py b/data-solutions/gcs-to-bq-with-dataflow/scripts/data_ingestion/data_ingestion.py similarity index 100% rename from data-solutions/gcs-to-bq/scripts/data_ingestion/data_ingestion.py rename to data-solutions/gcs-to-bq-with-dataflow/scripts/data_ingestion/data_ingestion.py diff --git a/data-solutions/gcs-to-bq/scripts/data_ingestion/diagram.png b/data-solutions/gcs-to-bq-with-dataflow/scripts/data_ingestion/diagram.png similarity index 100% rename from data-solutions/gcs-to-bq/scripts/data_ingestion/diagram.png rename to data-solutions/gcs-to-bq-with-dataflow/scripts/data_ingestion/diagram.png diff --git a/data-solutions/gcs-to-bq/scripts/person_details_generator/README.md b/data-solutions/gcs-to-bq-with-dataflow/scripts/person_details_generator/README.md similarity index 100% rename from data-solutions/gcs-to-bq/scripts/person_details_generator/README.md rename to data-solutions/gcs-to-bq-with-dataflow/scripts/person_details_generator/README.md diff --git a/data-solutions/gcs-to-bq/scripts/person_details_generator/REQUIREMENTS.txt b/data-solutions/gcs-to-bq-with-dataflow/scripts/person_details_generator/REQUIREMENTS.txt similarity index 100% rename from data-solutions/gcs-to-bq/scripts/person_details_generator/REQUIREMENTS.txt rename to data-solutions/gcs-to-bq-with-dataflow/scripts/person_details_generator/REQUIREMENTS.txt diff --git a/data-solutions/gcs-to-bq/scripts/person_details_generator/person_details_generator.py b/data-solutions/gcs-to-bq-with-dataflow/scripts/person_details_generator/person_details_generator.py similarity index 100% rename from data-solutions/gcs-to-bq/scripts/person_details_generator/person_details_generator.py rename to data-solutions/gcs-to-bq-with-dataflow/scripts/person_details_generator/person_details_generator.py diff --git a/data-solutions/gcs-to-bq/variables.tf b/data-solutions/gcs-to-bq-with-dataflow/variables.tf similarity index 100% rename from data-solutions/gcs-to-bq/variables.tf rename to data-solutions/gcs-to-bq-with-dataflow/variables.tf diff --git a/data-solutions/gcs-to-bq/versions.tf b/data-solutions/gcs-to-bq-with-dataflow/versions.tf similarity index 100% rename from data-solutions/gcs-to-bq/versions.tf rename to data-solutions/gcs-to-bq-with-dataflow/versions.tf From fd5b903962ad86bd8d7b6a57a12fc0ba9030619a Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Tue, 30 Jun 2020 16:51:56 +0200 Subject: [PATCH 116/129] fix layout --- data-solutions/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/data-solutions/README.md b/data-solutions/README.md index 10845058..b6703203 100644 --- a/data-solutions/README.md +++ b/data-solutions/README.md @@ -9,6 +9,7 @@ They are meant to be used as minimal but complete starting points to create actu ### GCE and GCS CMEK via centralized Cloud KMS This [example](./cmek-via-centralized-kms/) implements [CMEK](https://cloud.google.com/kms/docs/cmek) for GCS and GCE, via keys hosted in KMS running in a centralized project. The example shows the basic resources and permissions for the typical use case of application projects implementing encryption at rest via a centrally managed KMS service. +
### Cloud Storage to Bigquery with Cloud Dataflow This [example](./gcs-to-bq-with-dataflow/) implements [Cloud Storage](https://cloud.google.com/kms/docs/cmek) to Bigquery data import using Cloud Dataflow.All resources use CMEK hosted in Cloud KMS running in a centralized project. The example shows the basic resources and permissions for the typical use case to read, transform and import data from Cloud Storage to Bigquery. From 93817dbc14fd4cf1996f4ccbeeba240d44bf2312 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Tue, 30 Jun 2020 16:53:41 +0200 Subject: [PATCH 117/129] Fix --- data-solutions/README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data-solutions/README.md b/data-solutions/README.md index b6703203..18e43825 100644 --- a/data-solutions/README.md +++ b/data-solutions/README.md @@ -12,4 +12,5 @@ They are meant to be used as minimal but complete starting points to create actu
### Cloud Storage to Bigquery with Cloud Dataflow - This [example](./gcs-to-bq-with-dataflow/) implements [Cloud Storage](https://cloud.google.com/kms/docs/cmek) to Bigquery data import using Cloud Dataflow.All resources use CMEK hosted in Cloud KMS running in a centralized project. The example shows the basic resources and permissions for the typical use case to read, transform and import data from Cloud Storage to Bigquery. + This [example](./gcs-to-bq-with-dataflow/) implements [Cloud Storage](https://cloud.google.com/kms/docs/cmek) to Bigquery data import using Cloud Dataflow. +All resources use CMEK hosted in Cloud KMS running in a centralized project. The example shows the basic resources and permissions for the typical use case to read, transform and import data from Cloud Storage to Bigquery. From 6bc59c602a88f537c347392ada3efc0d9e146003 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Tue, 30 Jun 2020 17:58:51 +0200 Subject: [PATCH 118/129] Fix error in tests --- tests/modules/compute_mig/test_plan.py | 90 +++++++++++++------------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/tests/modules/compute_mig/test_plan.py b/tests/modules/compute_mig/test_plan.py index c581750e..4d95eda8 100644 --- a/tests/modules/compute_mig/test_plan.py +++ b/tests/modules/compute_mig/test_plan.py @@ -21,53 +21,55 @@ FIXTURES_DIR = os.path.join(os.path.dirname(__file__), 'fixture') def test_defaults(plan_runner): - "Test variable defaults." - _, resources = plan_runner(FIXTURES_DIR) - assert len(resources) == 1 - mig = resources[0] - assert mig['type'] == 'google_compute_instance_group_manager' - assert mig['values']['target_size'] == 2 - assert mig['values']['zone'] - _, resources = plan_runner(FIXTURES_DIR, regional='true') - assert len(resources) == 1 - mig = resources[0] - assert mig['type'] == 'google_compute_region_instance_group_manager' - assert mig['values']['target_size'] == 2 - assert mig['values']['region'] + "Test variable defaults." + _, resources = plan_runner(FIXTURES_DIR) + assert len(resources) == 1 + mig = resources[0] + assert mig['type'] == 'google_compute_instance_group_manager' + assert mig['values']['target_size'] == 2 + assert mig['values']['zone'] + _, resources = plan_runner(FIXTURES_DIR, regional='true') + assert len(resources) == 1 + mig = resources[0] + assert mig['type'] == 'google_compute_region_instance_group_manager' + assert mig['values']['target_size'] == 2 + assert mig['values']['region'] def test_health_check(plan_runner): - "Test health check resource." - health_check_config = '{type="tcp", check={port=80}, config=null, logging=false}' - _, resources = plan_runner( - FIXTURES_DIR, health_check_config=health_check_config) - assert len(resources) == 2 - assert any(r['type'] == 'google_compute_health_check' for r in resources) + "Test health check resource." + health_check_config = '{type="tcp", check={port=80}, config=null, logging=false}' + _, resources = plan_runner( + FIXTURES_DIR, health_check_config=health_check_config) + assert len(resources) == 2 + assert any(r['type'] == 'google_compute_health_check' for r in resources) def test_autoscaler(plan_runner): - "Test autoscaler resource." - autoscaler_config = ( - '{' - 'max_replicas=3, min_replicas=1, cooldown_period=60,' - 'cpu_utilization_target=65, load_balancing_utilization_target=null,' - 'metric=null' - '}' - ) - _, resources = plan_runner(FIXTURES_DIR, autoscaler_config=autoscaler_config) - assert len(resources) == 2 - autoscaler = resources[0] - assert autoscaler['type'] == 'google_compute_autoscaler' - assert autoscaler['values']['autoscaling_policy'] == [{ - 'cooldown_period': 60, - 'cpu_utilization': [{'target': 65}], - 'load_balancing_utilization': [], - 'max_replicas': 3, - 'metric': [], - 'min_replicas': 1 - }] - _, resources = plan_runner( - FIXTURES_DIR, autoscaler_config=autoscaler_config, regional='true') - assert len(resources) == 2 - autoscaler = resources[0] - assert autoscaler['type'] == 'google_compute_region_autoscaler' + "Test autoscaler resource." + autoscaler_config = ( + '{' + 'max_replicas=3, min_replicas=1, cooldown_period=60,' + 'cpu_utilization_target=65, load_balancing_utilization_target=null,' + 'metric=null' + '}' + ) + _, resources = plan_runner( + FIXTURES_DIR, autoscaler_config=autoscaler_config) + assert len(resources) == 2 + autoscaler = resources[0] + assert autoscaler['type'] == 'google_compute_autoscaler' + assert autoscaler['values']['autoscaling_policy'] == [{ + 'cooldown_period': 60, + 'cpu_utilization': [{'target': 65}], + 'load_balancing_utilization': [], + 'max_replicas': 3, + 'metric': [], + 'min_replicas': 1, + 'mode': 'ON' + }] + _, resources = plan_runner( + FIXTURES_DIR, autoscaler_config=autoscaler_config, regional='true') + assert len(resources) == 2 + autoscaler = resources[0] + assert autoscaler['type'] == 'google_compute_region_autoscaler' From 8b252fc261af146f9ce712532f34520f7696fa04 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Tue, 30 Jun 2020 18:05:37 +0200 Subject: [PATCH 119/129] Fix --- modules/project/service_accounts.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/project/service_accounts.tf b/modules/project/service_accounts.tf index d4a1be83..7e0f97c1 100644 --- a/modules/project/service_accounts.tf +++ b/modules/project/service_accounts.tf @@ -18,7 +18,7 @@ locals { service_account_cloud_services = "${local.project.number}@cloudservices.gserviceaccount.com" service_accounts_default = { # TODO: Find a better place to store BQ service account - bq = "bq-${google_project.project.number}@bigquery-encryption.iam.gserviceaccount.com" + bq = "bq-${local.project.number}@bigquery-encryption.iam.gserviceaccount.com" compute = "${local.project.number}-compute@developer.gserviceaccount.com" gae = "${local.project.project_id}@appspot.gserviceaccount.com" } From dd47ff6507a651003e4dc93690627637ea530c92 Mon Sep 17 00:00:00 2001 From: Lorenzo Caggioni Date: Tue, 30 Jun 2020 18:08:35 +0200 Subject: [PATCH 120/129] Add License --- .../scripts/data_ingestion/LICENSE | 201 ++++++++++++++++++ .../scripts/person_details_generator/LICENSE | 201 ++++++++++++++++++ 2 files changed, 402 insertions(+) create mode 100644 data-solutions/gcs-to-bq-with-dataflow/scripts/data_ingestion/LICENSE create mode 100644 data-solutions/gcs-to-bq-with-dataflow/scripts/person_details_generator/LICENSE diff --git a/data-solutions/gcs-to-bq-with-dataflow/scripts/data_ingestion/LICENSE b/data-solutions/gcs-to-bq-with-dataflow/scripts/data_ingestion/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/data-solutions/gcs-to-bq-with-dataflow/scripts/data_ingestion/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/data-solutions/gcs-to-bq-with-dataflow/scripts/person_details_generator/LICENSE b/data-solutions/gcs-to-bq-with-dataflow/scripts/person_details_generator/LICENSE new file mode 100644 index 00000000..261eeb9e --- /dev/null +++ b/data-solutions/gcs-to-bq-with-dataflow/scripts/person_details_generator/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. From 49f7b82cc430bc9ebb21affbbed29105eb568f43 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Tue, 30 Jun 2020 20:37:40 +0200 Subject: [PATCH 121/129] fix boilerplate in Python scripts --- .../scripts/data_ingestion/data_ingestion.py | 185 +++++++++--------- .../person_details_generator.py | 44 +++-- 2 files changed, 117 insertions(+), 112 deletions(-) diff --git a/data-solutions/gcs-to-bq-with-dataflow/scripts/data_ingestion/data_ingestion.py b/data-solutions/gcs-to-bq-with-dataflow/scripts/data_ingestion/data_ingestion.py index 54c89cd4..643cdc87 100644 --- a/data-solutions/gcs-to-bq-with-dataflow/scripts/data_ingestion/data_ingestion.py +++ b/data-solutions/gcs-to-bq-with-dataflow/scripts/data_ingestion/data_ingestion.py @@ -1,4 +1,4 @@ -# Copyright 2020 Google Inc. +# Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -11,10 +11,11 @@ # 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. -"""`data_ingestion.py` is a Dataflow pipeline which reads a CSV file and -writes its contents to a BigQuery table adding a timestamp. + +"""Dataflow pipeline. Reads a CSV file and writes to a BQ table adding a timestamp. """ + import argparse import logging import re @@ -24,110 +25,110 @@ from apache_beam.options.pipeline_options import PipelineOptions class DataIngestion: - """A helper class which contains the logic to translate the file into - a format BigQuery will accept.""" + """A helper class which contains the logic to translate the file into + a format BigQuery will accept.""" - def parse_method(self, string_input): - """Translate CSV row to dictionary. - Args: - string_input: A comma separated list of values in the form of - name,surname - Example string_input: lorenzo,caggioni - Returns: - A dict mapping BigQuery column names as keys - example output: - { - 'name': 'mario', - 'surname': 'rossi', - 'age': 30 - } - """ - # Strip out carriage return, newline and quote characters. - values = re.split(",", re.sub('\r\n', '', re.sub('"', '', - string_input))) - row = dict( - zip(('name', 'surname', 'age'), - values)) - return row + def parse_method(self, string_input): + """Translate CSV row to dictionary. + Args: + string_input: A comma separated list of values in the form of + name,surname + Example string_input: lorenzo,caggioni + Returns: + A dict mapping BigQuery column names as keys + example output: + { + 'name': 'mario', + 'surname': 'rossi', + 'age': 30 + } + """ + # Strip out carriage return, newline and quote characters. + values = re.split(",", re.sub('\r\n', '', re.sub('"', '', + string_input))) + row = dict( + zip(('name', 'surname', 'age'), + values)) + return row class InjectTimestamp(beam.DoFn): - """A class which add a timestamp for each row. - Args: - element: A dictionary mapping BigQuery column names - Example: - { - 'name': 'mario', - 'surname': 'rossi', - 'age': 30 - } - Returns: - The input dictionary with a timestamp value added - Example: - { - 'name': 'mario', - 'surname': 'rossi', - 'age': 30 - '_TIMESTAMP': 1545730073 - } - """ + """A class which add a timestamp for each row. + Args: + element: A dictionary mapping BigQuery column names + Example: + { + 'name': 'mario', + 'surname': 'rossi', + 'age': 30 + } + Returns: + The input dictionary with a timestamp value added + Example: + { + 'name': 'mario', + 'surname': 'rossi', + 'age': 30 + '_TIMESTAMP': 1545730073 + } + """ - def process(self, element): - import time - element['_TIMESTAMP'] = int(time.mktime(time.gmtime())) - return [element] + def process(self, element): + import time + element['_TIMESTAMP'] = int(time.mktime(time.gmtime())) + return [element] def run(argv=None): - """The main function which creates the pipeline and runs it.""" + """The main function which creates the pipeline and runs it.""" - parser = argparse.ArgumentParser() + parser = argparse.ArgumentParser() - parser.add_argument( - '--input', - dest='input', - required=False, - help='Input file to read. This can be a local file or ' - 'a file in a Google Storage Bucket.') + parser.add_argument( + '--input', + dest='input', + required=False, + help='Input file to read. This can be a local file or ' + 'a file in a Google Storage Bucket.') - parser.add_argument( - '--output', - dest='output', - required=False, - help='Output BQ table to write results to.') + parser.add_argument( + '--output', + dest='output', + required=False, + help='Output BQ table to write results to.') - # Parse arguments from the command line. - known_args, pipeline_args = parser.parse_known_args(argv) + # Parse arguments from the command line. + known_args, pipeline_args = parser.parse_known_args(argv) - # DataIngestion is a class we built in this script to hold the logic for - # transforming the file into a BigQuery table. - data_ingestion = DataIngestion() + # DataIngestion is a class we built in this script to hold the logic for + # transforming the file into a BigQuery table. + data_ingestion = DataIngestion() - # Initiate the pipeline using the pipeline arguments - p = beam.Pipeline(options=PipelineOptions(pipeline_args)) + # Initiate the pipeline using the pipeline arguments + p = beam.Pipeline(options=PipelineOptions(pipeline_args)) - (p - # Read the file. This is the source of the pipeline. - | 'Read from a File' >> beam.io.ReadFromText(known_args.input) - # Translates CSV row to a dictionary object consumable by BigQuery. - | 'String To BigQuery Row' >> - beam.Map(lambda s: data_ingestion.parse_method(s)) - # Add the timestamp on each row - | 'Inject Timestamp - ' >> beam.ParDo(InjectTimestamp()) - # Write data to Bigquery - | 'Write to BigQuery' >> beam.io.Write( - beam.io.BigQuerySink( - # BigQuery table name. - known_args.output, - # Bigquery table schema - schema='name:STRING,surname:STRING,age:NUMERIC,_TIMESTAMP:TIMESTAMP', - # Creates the table in BigQuery if it does not yet exist. - create_disposition=beam.io.BigQueryDisposition.CREATE_NEVER, - # Deletes all data in the BigQuery table before writing. - write_disposition=beam.io.BigQueryDisposition.WRITE_TRUNCATE))) - p.run().wait_until_finish() + (p + # Read the file. This is the source of the pipeline. + | 'Read from a File' >> beam.io.ReadFromText(known_args.input) + # Translates CSV row to a dictionary object consumable by BigQuery. + | 'String To BigQuery Row' >> + beam.Map(lambda s: data_ingestion.parse_method(s)) + # Add the timestamp on each row + | 'Inject Timestamp - ' >> beam.ParDo(InjectTimestamp()) + # Write data to Bigquery + | 'Write to BigQuery' >> beam.io.Write( + beam.io.BigQuerySink( + # BigQuery table name. + known_args.output, + # Bigquery table schema + schema='name:STRING,surname:STRING,age:NUMERIC,_TIMESTAMP:TIMESTAMP', + # Creates the table in BigQuery if it does not yet exist. + create_disposition=beam.io.BigQueryDisposition.CREATE_NEVER, + # Deletes all data in the BigQuery table before writing. + write_disposition=beam.io.BigQueryDisposition.WRITE_TRUNCATE))) + p.run().wait_until_finish() if __name__ == '__main__': - logging.getLogger().setLevel(logging.INFO) - run() + logging.getLogger().setLevel(logging.INFO) + run() diff --git a/data-solutions/gcs-to-bq-with-dataflow/scripts/person_details_generator/person_details_generator.py b/data-solutions/gcs-to-bq-with-dataflow/scripts/person_details_generator/person_details_generator.py index 366954df..f2694b30 100644 --- a/data-solutions/gcs-to-bq-with-dataflow/scripts/person_details_generator/person_details_generator.py +++ b/data-solutions/gcs-to-bq-with-dataflow/scripts/person_details_generator/person_details_generator.py @@ -1,4 +1,4 @@ -# Copyright 2020 Google Inc. +# Copyright 2020 Google LLC # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -11,10 +11,9 @@ # 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. -"""`person_details_generator.py` is a Python script to generate random -Person PII (name, surname and age) having as input an array of -names and an array of surnames. -""" + +"""Generate random person PIIs based on arrays of names and surnames.""" + import click import logging @@ -23,21 +22,26 @@ import random @click.command() @click.option("--count", default=100, help="Number of generated names.") -@click.option("--output", default=False, help="Name of the output file. Content will be overwriten. If not defined, standard output will be used.") -@click.option("--first_names", default="Lorenzo,Giacomo,Chiara,Miriam", help="String of Names, comma separated. Default 'Lorenzo,Giacomo,Chiara,Miriam'") -@click.option("--last_names", default="Rossi, Bianchi,Brambilla,Caggioni", help="String of Names, comma separated. Default 'Rossi,Bianchi,Brambilla,Caggioni'") -def main(count, output, first_names, last_names): - generated_names = "".join(random.choice(first_names.split(',')) + "," + - random.choice(last_names.split(',')) + "," + - str(random.randint(1, 100)) + "\n" for _ in range(count))[:-1] - if output: - f = open(output, "w") - f.write(generated_names) - f.close() - else: - print(generated_names) +@click.option("--output", default=False, help=( + "Name of the output file. Content will be overwritten. " + "If not defined, standard output will be used.")) +@click.option("--first_names", default="Lorenzo,Giacomo,Chiara,Miriam", help=( + "String of Names, comma separated. Default 'Lorenzo,Giacomo,Chiara,Miriam'")) +@click.option("--last_names", default="Rossi, Bianchi,Brambilla,Caggioni", help=( + "String of Names, comma separated. Default 'Rossi,Bianchi,Brambilla,Caggioni'")) +def main(count=100, output=False, first_names=None, last_names=None): + generated_names = "".join( + random.choice(first_names.split(',')) + "," + + random.choice(last_names.split(',')) + "," + + str(random.randint(1, 100)) + "\n" for _ in range(count))[:-1] + if output: + f = open(output, "w") + f.write(generated_names) + f.close() + else: + print(generated_names) if __name__ == '__main__': - logging.getLogger().setLevel(logging.INFO) - main() + logging.getLogger().setLevel(logging.INFO) + main() From f3f1ce9051ec6e5f10a996caf65af8220329df8f Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Tue, 30 Jun 2020 20:41:47 +0200 Subject: [PATCH 122/129] Update README.md --- .../gcs-to-bq-with-dataflow/README.md | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/data-solutions/gcs-to-bq-with-dataflow/README.md b/data-solutions/gcs-to-bq-with-dataflow/README.md index b4b1a9de..23a4470d 100644 --- a/data-solutions/gcs-to-bq-with-dataflow/README.md +++ b/data-solutions/gcs-to-bq-with-dataflow/README.md @@ -3,9 +3,9 @@ This example creates the infrastructure needed to run a [Cloud Dataflow](https://cloud.google.com/dataflow) pipeline to import data from [GCS](https://cloud.google.com/storage) to [Bigquery](https://cloud.google.com/bigquery). The solution will use: - - internal IP for GCE and Dataflow instances - - CMEK encription for GCS bucket, GCE instances, DataFlow instances and BigQuery Tables - - Cloud NAT to let resource comunicate to internet to run updates and packages installation + - internal IPs for GCE and Dataflow instances + - CMEK encription for GCS bucket, GCE instances, DataFlow instances and BigQuery tables + - Cloud NAT to let resources comunicate to the Internet, run system updates, and install packages The example is designed to match real-world use cases with a minimum amount of resources. It can be used as a starting point for more complex scenarios. @@ -42,33 +42,6 @@ This sample creates several distinct groups of resources: - One dataset encrypted with a CMEK Cryptokey hosted in Cloud KMS - Two tables encrypted with a CMEK Cryptokey hosted in Cloud KMS - -## Variables - -| name | description | type | required | default | -|---|---|:---: |:---:|:---:| -| billing_account | Billing account id used as default for new projects. | string | ✓ | | -| project_kms_name | Name for the new KMS Project. | string | ✓ | | -| project_service_name | Name for the new Service Project. | string | ✓ | | -| root_node | The resource name of the parent Folder or Organization. Must be of the form folders/folder_id or organizations/org_id. | string | ✓ | | -| *location* | The location where resources will be deployed. | string | | europe | -| *region* | The region where resources will be deployed. | string | | europe-west1 | -| *ssh_source_ranges* | IP CIDR ranges that will be allowed to connect via SSH to the onprem instance. | list(string) | | ["0.0.0.0/0"] | -| *vpc_ip_cidr_range* | Ip range used in the subnet deployef in the Service Project. | string | | 10.0.0.0/20 | -| *vpc_name* | Name of the VPC created in the Service Project. | string | | local | -| *vpc_subnet_name* | Name of the subnet created in the Service Project. | string | | subnet | -| *zone* | The zone where resources will be deployed. | string | | europe-west1-b | - -## Outputs - -| name | description | sensitive | -|---|---|:---:| -| bq_tables | Bigquery Tables. | | -| buckets | GCS Bucket Cloud KMS crypto keys. | | -| projects | Project ids. | | -| vm | GCE VMs. | | - - ## Test your environment with Cloud Dataflow You can now connect to the GCE instance with the following command: @@ -135,4 +108,31 @@ gs://my-bucket/person.csv \ schema_bq_import.json ``` -You can check data imported into Google BigQuery from the Google Cloud Console UI. \ No newline at end of file +You can check data imported into Google BigQuery from the Google Cloud Console UI. + + +## Variables + +| name | description | type | required | default | +|---|---|:---: |:---:|:---:| +| billing_account | Billing account id used as default for new projects. | string | ✓ | | +| project_kms_name | Name for the new KMS Project. | string | ✓ | | +| project_service_name | Name for the new Service Project. | string | ✓ | | +| root_node | The resource name of the parent Folder or Organization. Must be of the form folders/folder_id or organizations/org_id. | string | ✓ | | +| *location* | The location where resources will be deployed. | string | | europe | +| *region* | The region where resources will be deployed. | string | | europe-west1 | +| *ssh_source_ranges* | IP CIDR ranges that will be allowed to connect via SSH to the onprem instance. | list(string) | | ["0.0.0.0/0"] | +| *vpc_ip_cidr_range* | Ip range used in the subnet deployef in the Service Project. | string | | 10.0.0.0/20 | +| *vpc_name* | Name of the VPC created in the Service Project. | string | | local | +| *vpc_subnet_name* | Name of the subnet created in the Service Project. | string | | subnet | +| *zone* | The zone where resources will be deployed. | string | | europe-west1-b | + +## Outputs + +| name | description | sensitive | +|---|---|:---:| +| bq_tables | Bigquery Tables. | | +| buckets | GCS Bucket Cloud KMS crypto keys. | | +| projects | Project ids. | | +| vm | GCE VMs. | | + From bd103080df2c6ab4cf1f049299faebc9befcecce Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Tue, 30 Jun 2020 20:44:16 +0200 Subject: [PATCH 123/129] Update variables.tf --- data-solutions/gcs-to-bq-with-dataflow/variables.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data-solutions/gcs-to-bq-with-dataflow/variables.tf b/data-solutions/gcs-to-bq-with-dataflow/variables.tf index fb53dd77..a44f874a 100644 --- a/data-solutions/gcs-to-bq-with-dataflow/variables.tf +++ b/data-solutions/gcs-to-bq-with-dataflow/variables.tf @@ -73,4 +73,4 @@ variable "ssh_source_ranges" { description = "IP CIDR ranges that will be allowed to connect via SSH to the onprem instance." type = list(string) default = ["0.0.0.0/0"] -} \ No newline at end of file +} From 5af022a3eec8a1fe19e2c07e923f83d69f386e59 Mon Sep 17 00:00:00 2001 From: vanessabodard-voi <63779321+vanessabodard-voi@users.noreply.github.com> Date: Thu, 2 Jul 2020 08:28:26 +0200 Subject: [PATCH 124/129] refactor IAM additive bindings variables (#103) * Invert the list for role/member mapping so that member is the key * Add iam_additive_bindings to replace iam_additive_members and iam_additive_roles, change test suite accordingly * attribute 'mode' added as it would error without * Update Readme to reflect the new variable iam_additive_bindings * test branch access * iam_additive_bindings to replace iam_additive roles and iam_additive_members * update foundation samples to new additive bindings format * set bq dataset options in foundation environments to allow destroying * trap exceptions raised during destroy in project module Co-authored-by: Ludovico Magnocavallo --- foundations/business-units/main.tf | 30 ++++++++++-------- foundations/environments/main.tf | 30 ++++++++++-------- foundations/environments/variables.tf | 14 +-------- modules/organization/README.md | 3 +- modules/organization/main.tf | 6 ++-- modules/organization/variables.tf | 10 ++---- modules/project/README.md | 31 +++++++++++++++++-- modules/project/main.tf | 10 +++--- modules/project/outputs.tf | 2 +- modules/project/variables.tf | 11 ++----- tests/modules/organization/fixture/main.tf | 3 +- .../modules/organization/fixture/variables.tf | 6 +--- tests/modules/project/fixture/main.tf | 3 +- tests/modules/project/fixture/variables.tf | 7 +---- 14 files changed, 84 insertions(+), 82 deletions(-) diff --git a/foundations/business-units/main.tf b/foundations/business-units/main.tf index 1a599b8d..b30b5c46 100644 --- a/foundations/business-units/main.tf +++ b/foundations/business-units/main.tf @@ -29,14 +29,15 @@ module "shared-folder" { # Terraform project module "tf-project" { - source = "../../modules/project" - name = "terraform" - parent = module.shared-folder.id - prefix = var.prefix - billing_account = var.billing_account_id - iam_additive_members = { "roles/owner" = var.iam_terraform_owners } - iam_additive_roles = ["roles/owner"] - services = var.project_services + source = "../../modules/project" + name = "terraform" + parent = module.shared-folder.id + prefix = var.prefix + billing_account = var.billing_account_id + iam_additive_bindings = { + for name in var.iam_terraform_owners : (name) => ["roles/owner"] + } + services = var.project_services } # Bootstrap Terraform state GCS bucket @@ -115,6 +116,12 @@ module "audit-dataset" { project_id = module.audit-project.project_id id = "audit_export" friendly_name = "Audit logs export." + # disable delete on destroy for actual use + options = { + default_table_expiration_ms = null + default_partition_expiration_ms = null + delete_contents_on_destroy = true + } } module "audit-log-sinks" { @@ -140,12 +147,9 @@ module "shared-project" { parent = module.shared-folder.id prefix = var.prefix billing_account = var.billing_account_id - iam_additive_members = { - "roles/owner" = var.iam_shared_owners + iam_additive_bindings = { + for name in var.iam_shared_owners : (name) => ["roles/owner"] } - iam_additive_roles = [ - "roles/owner" - ] services = var.project_services } diff --git a/foundations/environments/main.tf b/foundations/environments/main.tf index ee55f161..90b4a8bf 100644 --- a/foundations/environments/main.tf +++ b/foundations/environments/main.tf @@ -19,14 +19,15 @@ # Terraform project module "tf-project" { - source = "../../modules/project" - name = "terraform" - parent = var.root_node - prefix = var.prefix - billing_account = var.billing_account_id - iam_additive_members = { "roles/owner" = var.iam_terraform_owners } - iam_additive_roles = ["roles/owner"] - services = var.project_services + source = "../../modules/project" + name = "terraform" + parent = var.root_node + prefix = var.prefix + billing_account = var.billing_account_id + iam_additive_bindings = { + for name in var.iam_terraform_owners : (name) => ["roles/owner"] + } + services = var.project_services } # per-environment service accounts @@ -130,6 +131,12 @@ module "audit-dataset" { project_id = module.audit-project.project_id id = "audit_export" friendly_name = "Audit logs export." + # disable delete on destroy for actual use + options = { + default_table_expiration_ms = null + default_partition_expiration_ms = null + delete_contents_on_destroy = true + } } module "audit-log-sinks" { @@ -156,12 +163,9 @@ module "sharedsvc-project" { parent = var.root_node prefix = var.prefix billing_account = var.billing_account_id - iam_additive_members = { - "roles/owner" = var.iam_sharedsvc_owners + iam_additive_bindings = { + for name in var.iam_shared_owners : (name) => ["roles/owner"] } - iam_additive_roles = [ - "roles/owner" - ] services = var.project_services } diff --git a/foundations/environments/variables.tf b/foundations/environments/variables.tf index a868140d..5cb74456 100644 --- a/foundations/environments/variables.tf +++ b/foundations/environments/variables.tf @@ -38,18 +38,6 @@ variable "gcs_location" { default = "EU" } -variable "iam_assets_editors" { - description = "Shared assets project editors, in IAM format." - type = list(string) - default = [] -} - -variable "iam_assets_owners" { - description = "Shared assets project owners, in IAM format." - type = list(string) - default = [] -} - variable "iam_audit_viewers" { description = "Audit project viewers, in IAM format." type = list(string) @@ -79,7 +67,7 @@ variable "iam_folder_roles" { ] } -variable "iam_sharedsvc_owners" { +variable "iam_shared_owners" { description = "Shared services project owners, in IAM format." type = list(string) default = [] diff --git a/modules/organization/README.md b/modules/organization/README.md index 53ac2cbb..c95bba8f 100644 --- a/modules/organization/README.md +++ b/modules/organization/README.md @@ -37,8 +37,7 @@ module "org" { |---|---|:---: |:---:|:---:| | org_id | Organization id in nnnnnn format. | number | ✓ | | | *custom_roles* | Map of role name => list of permissions to create in this project. | map(list(string)) | | {} | -| *iam_additive_members* | Map of member lists used to set non authoritative bindings, keyed by role. | map(list(string)) | | {} | -| *iam_additive_roles* | List of roles used to set non authoritative bindings. | list(string) | | [] | +| *iam_additive_bindings* | Map of roles lists used to set non authoritative bindings, keyed by members. | map(list(string)) | | {} | | *iam_audit_config* | Service audit logging configuration. Service as key, map of log permission (eg DATA_READ) and excluded members as value for each service. | map(map(list(string))) | | {} | | *iam_members* | Map of member lists used to set authoritative bindings, keyed by role. | map(list(string)) | | {} | | *iam_roles* | List of roles used to set authoritative bindings. | list(string) | | [] | diff --git a/modules/organization/main.tf b/modules/organization/main.tf index 91e01b5f..a96ff141 100644 --- a/modules/organization/main.tf +++ b/modules/organization/main.tf @@ -16,8 +16,8 @@ locals { iam_additive_pairs = flatten([ - for role in var.iam_additive_roles : [ - for member in lookup(var.iam_additive_members, role, []) : + for member, roles in var.iam_additive_bindings : [ + for role in roles : { role = role, member = member } ] ]) @@ -44,7 +44,7 @@ resource "google_organization_iam_binding" "authoritative" { } resource "google_organization_iam_member" "additive" { - for_each = length(var.iam_additive_roles) > 0 ? local.iam_additive : {} + for_each = length(var.iam_additive_bindings) > 0 ? local.iam_additive : {} org_id = var.org_id role = each.value.role member = each.value.member diff --git a/modules/organization/variables.tf b/modules/organization/variables.tf index 05d636bc..240e920f 100644 --- a/modules/organization/variables.tf +++ b/modules/organization/variables.tf @@ -32,18 +32,12 @@ variable "iam_roles" { default = [] } -variable "iam_additive_members" { - description = "Map of member lists used to set non authoritative bindings, keyed by role." +variable "iam_additive_bindings" { + description = "Map of roles lists used to set non authoritative bindings, keyed by members." type = map(list(string)) default = {} } -variable "iam_additive_roles" { - description = "List of roles used to set non authoritative bindings." - type = list(string) - default = [] -} - variable "iam_audit_config" { description = "Service audit logging configuration. Service as key, map of log permission (eg DATA_READ) and excluded members as value for each service." type = map(map(list(string))) diff --git a/modules/project/README.md b/modules/project/README.md index cd640673..7fd57c01 100644 --- a/modules/project/README.md +++ b/modules/project/README.md @@ -24,6 +24,33 @@ module "project" { } ``` +### Minimal example with IAM additive roles + +```hcl +module "project" { + source = "./modules/project" + name = "project-example" + project_create = false + + iam_additive_bindings = { + "group:usergroup_watermlon_experimentation@lemonadeinc.io" = [ + "roles/viewer", + "roles/storage.objectAdmin" + ], + "group:usergroup_gcp_admin@lemonadeinc.io" = [ + "roles/owner", + ], + "group:usergroup_gcp_privilege_access@lemonadeinc.io" = [ + "roles/editor" + ], + "group:engineering@lemonadeinc.io" = [ + "roles/pubsub.subscriber", + "roles/storage.objectViewer" + ], + } +} +``` + ### Organization policies ```hcl @@ -61,8 +88,7 @@ module "project" { | *auto_create_network* | Whether to create the default network for the project | bool | | false | | *billing_account* | Billing account id. | string | | null | | *custom_roles* | Map of role name => list of permissions to create in this project. | map(list(string)) | | {} | -| *iam_additive_members* | Map of member lists used to set non authoritative bindings, keyed by role. | map(list(string)) | | {} | -| *iam_additive_roles* | List of roles used to set non authoritative bindings. | list(string) | | [] | +| *iam_additive_bindings* | Map of roles list used to set non authoritative bindings, keyed by member. | list(string) | | [] | | *iam_members* | Map of member lists used to set authoritative bindings, keyed by role. | map(list(string)) | | {} | | *iam_roles* | List of roles used to set authoritative bindings. | list(string) | | [] | | *labels* | Resource labels. | map(string) | | {} | @@ -88,3 +114,4 @@ module "project" { | project_id | Project id. | | | service_accounts | Product robot service accounts in project. | | + diff --git a/modules/project/main.tf b/modules/project/main.tf index 637aa8de..a9239970 100644 --- a/modules/project/main.tf +++ b/modules/project/main.tf @@ -16,8 +16,8 @@ locals { iam_additive_pairs = flatten([ - for role in var.iam_additive_roles : [ - for member in lookup(var.iam_additive_members, role, []) : + for member, roles in var.iam_additive_bindings : [ + for role in roles : { role = role, member = member } ] ]) @@ -29,7 +29,9 @@ locals { parent_id = var.parent == null ? null : split("/", var.parent)[1] prefix = var.prefix == null ? "" : "${var.prefix}-" project = ( - var.project_create ? google_project.project.0 : data.google_project.project.0 + var.project_create + ? try(google_project.project.0, null) + : try(data.google_project.project.0, null) ) } @@ -100,7 +102,7 @@ resource "google_project_iam_binding" "authoritative" { } resource "google_project_iam_member" "additive" { - for_each = length(var.iam_additive_roles) > 0 ? local.iam_additive : {} + for_each = length(var.iam_additive_bindings) > 0 ? local.iam_additive : {} project = local.project.project_id role = each.value.role member = each.value.member diff --git a/modules/project/outputs.tf b/modules/project/outputs.tf index 1250f846..2edeecaf 100644 --- a/modules/project/outputs.tf +++ b/modules/project/outputs.tf @@ -16,7 +16,7 @@ output "project_id" { description = "Project id." - value = local.project.project_id + value = try(local.project.project_id, null) depends_on = [ google_project_organization_policy.boolean, google_project_organization_policy.list, diff --git a/modules/project/variables.tf b/modules/project/variables.tf index 6676b76a..44677620 100644 --- a/modules/project/variables.tf +++ b/modules/project/variables.tf @@ -44,18 +44,13 @@ variable "iam_roles" { default = [] } -variable "iam_additive_members" { - description = "Map of member lists used to set non authoritative bindings, keyed by role." + +variable "iam_additive_bindings" { + description = "Map of roles lists used to set non authoritative bindings, keyed by members" type = map(list(string)) default = {} } -variable "iam_additive_roles" { - description = "List of roles used to set non authoritative bindings." - type = list(string) - default = [] -} - variable "labels" { description = "Resource labels." type = map(string) diff --git a/tests/modules/organization/fixture/main.tf b/tests/modules/organization/fixture/main.tf index 20786b5e..63d1f466 100644 --- a/tests/modules/organization/fixture/main.tf +++ b/tests/modules/organization/fixture/main.tf @@ -20,8 +20,7 @@ module "test" { custom_roles = var.custom_roles iam_members = var.iam_members iam_roles = var.iam_roles - iam_additive_members = var.iam_additive_members - iam_additive_roles = var.iam_additive_roles + iam_additive_bindings= var.iam_additive_bindings iam_audit_config = var.iam_audit_config policy_boolean = var.policy_boolean policy_list = var.policy_list diff --git a/tests/modules/organization/fixture/variables.tf b/tests/modules/organization/fixture/variables.tf index 561b446c..148a43b7 100644 --- a/tests/modules/organization/fixture/variables.tf +++ b/tests/modules/organization/fixture/variables.tf @@ -29,15 +29,11 @@ variable "iam_roles" { default = [] } -variable "iam_additive_members" { +variable "iam_additive_bindings" { type = map(list(string)) default = {} } -variable "iam_additive_roles" { - type = list(string) - default = [] -} variable "iam_audit_config" { type = map(map(list(string))) diff --git a/tests/modules/project/fixture/main.tf b/tests/modules/project/fixture/main.tf index 8d8808c2..924b2648 100644 --- a/tests/modules/project/fixture/main.tf +++ b/tests/modules/project/fixture/main.tf @@ -22,8 +22,7 @@ module "test" { custom_roles = var.custom_roles iam_members = var.iam_members iam_roles = var.iam_roles - iam_additive_members = var.iam_additive_members - iam_additive_roles = var.iam_additive_roles + iam_additive_bindings = var.iam_additive_bindings labels = var.labels lien_reason = var.lien_reason oslogin = var.oslogin diff --git a/tests/modules/project/fixture/variables.tf b/tests/modules/project/fixture/variables.tf index 4b859c92..3b36a5fd 100644 --- a/tests/modules/project/fixture/variables.tf +++ b/tests/modules/project/fixture/variables.tf @@ -34,16 +34,11 @@ variable "iam_roles" { default = [] } -variable "iam_additive_members" { +variable "iam_additive_bindings" { type = map(list(string)) default = {} } -variable "iam_additive_roles" { - type = list(string) - default = [] -} - variable "labels" { type = map(string) default = {} From 5fa4ea5518aeaada8eafed90781eb14102dbf28c Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Thu, 2 Jul 2020 08:29:38 +0200 Subject: [PATCH 125/129] regenerate variables/outputs tables in modules --- modules/cloud-function/README.md | 2 +- modules/compute-mig/README.md | 2 +- modules/container-registry/README.md | 2 +- modules/gke-cluster/README.md | 2 +- modules/iam-service-accounts/README.md | 2 +- modules/net-cloudnat/README.md | 4 ++-- modules/net-ilb/README.md | 2 +- modules/project/README.md | 2 +- modules/secret-manager/README.md | 2 +- 9 files changed, 10 insertions(+), 10 deletions(-) diff --git a/modules/cloud-function/README.md b/modules/cloud-function/README.md index fb386a0c..86ae486e 100644 --- a/modules/cloud-function/README.md +++ b/modules/cloud-function/README.md @@ -143,7 +143,7 @@ module "cf-http" { | *iam_roles* | List of roles used to set authoritative bindings. Ignored for template use. | list(string) | | [] | | *labels* | Resource labels | map(string) | | {} | | *prefix* | Optional prefix used for resource names. | string | | null | -| *region* | Region used for all resources. | string | | us-central1 | +| *region* | Region used for all resources. | string | | europe-west1 | | *service_account* | Service account email. Unused if service account is auto-created. | string | | null | | *service_account_create* | Auto-create service account. | bool | | false | | *trigger_config* | Function trigger configuration. Leave null for HTTP trigger. | object({...}) | | null | diff --git a/modules/compute-mig/README.md b/modules/compute-mig/README.md index 918a2a3d..beada11f 100644 --- a/modules/compute-mig/README.md +++ b/modules/compute-mig/README.md @@ -165,7 +165,7 @@ module "nginx-mig" { | project_id | Project id. | string | ✓ | | | *auto_healing_policies* | Auto-healing policies for this group. | object({...}) | | null | | *autoscaler_config* | Optional autoscaler configuration. Only one of 'cpu_utilization_target' 'load_balancing_utilization_target' or 'metric' can be not null. | object({...}) | | null | -| *health_check_config* | Optional auto-created helth check configuration, use the output self-link to set it in the auto healing policy. Refer to examples for usage. | object({...}) | | null | +| *health_check_config* | Optional auto-created health check configuration, use the output self-link to set it in the auto healing policy. Refer to examples for usage. | object({...}) | | null | | *named_ports* | Named ports. | map(number) | | null | | *regional* | Use regional instance group. When set, `location` should be set to the region. | bool | | false | | *target_pools* | Optional list of URLs for target pools to which new instances in the group are added. | list(string) | | [] | diff --git a/modules/container-registry/README.md b/modules/container-registry/README.md index aac0f02c..167f79b3 100644 --- a/modules/container-registry/README.md +++ b/modules/container-registry/README.md @@ -24,7 +24,7 @@ module "container_registry" { | project_id | Registry project id. | string | ✓ | | | *iam_members* | Map of member lists used to set authoritative bindings, keyed by role. | map(list(string)) | | null | | *iam_roles* | List of roles used to set authoritative bindings. | list(string) | | null | -| *location* | Bucket location. Can be US, EU, ASIA or empty | string | | | +| *location* | Registry location. Can be US, EU, ASIA or empty | string | | | ## Outputs diff --git a/modules/gke-cluster/README.md b/modules/gke-cluster/README.md index e081bf70..7442ae53 100644 --- a/modules/gke-cluster/README.md +++ b/modules/gke-cluster/README.md @@ -41,7 +41,7 @@ module "cluster-1" { | secondary_range_pods | Subnet secondary range name used for pods. | string | ✓ | | | secondary_range_services | Subnet secondary range name used for services. | string | ✓ | | | subnetwork | VPC subnetwork name or self link. | string | ✓ | | -| *addons* | Addons enabled in the cluster (true means enabled). | object({...}) | | ... | +| *addons* | Addons enabled in the cluster (true means enabled). | object({...}) | | ... | | *authenticator_security_group* | RBAC security group for Google Groups for GKE, format is gke-security-groups@yourdomain.com. | string | | null | | *cluster_autoscaling* | Enable and configure limits for Node Auto-Provisioning with Cluster Autoscaler. | object({...}) | | ... | | *database_encryption* | Enable and configure GKE application-layer secrets encryption. | object({...}) | | ... | diff --git a/modules/iam-service-accounts/README.md b/modules/iam-service-accounts/README.md index 00be1075..7fafafc9 100644 --- a/modules/iam-service-accounts/README.md +++ b/modules/iam-service-accounts/README.md @@ -40,7 +40,7 @@ module "myproject-default-service-accounts" { | *iam_roles* | List of authoritative roles granted on the service accounts. | list(string) | | [] | | *iam_storage_roles* | Storage roles granted to all service accounts, by bucket name. | map(list(string)) | | {} | | *names* | Names of the service accounts to create. | list(string) | | [] | -| *prefix* | Prefix applied to service account names. | string | | | +| *prefix* | Prefix applied to service account names. | string | | null | ## Outputs diff --git a/modules/net-cloudnat/README.md b/modules/net-cloudnat/README.md index b8bb17ce..89a9c352 100644 --- a/modules/net-cloudnat/README.md +++ b/modules/net-cloudnat/README.md @@ -28,8 +28,8 @@ module "nat" { | *config_timeouts* | Timeout configurations. | object({...}) | | ... | | *router_asn* | Router ASN used for auto-created router. | number | | 64514 | | *router_create* | Create router. | bool | | true | -| *router_name* | Router name, leave blank if router will be created to use auto generated name. | string | | | -| *router_network* | Name of the VPC used for auto-created router. | string | | | +| *router_name* | Router name, leave blank if router will be created to use auto generated name. | string | | null | +| *router_network* | Name of the VPC used for auto-created router. | string | | null | | *subnetworks* | Subnetworks to NAT, only used when config_source_subnets equals LIST_OF_SUBNETWORKS. | list(object({...})) | | [] | ## Outputs diff --git a/modules/net-ilb/README.md b/modules/net-ilb/README.md index a368b8ea..1d90c5aa 100644 --- a/modules/net-ilb/README.md +++ b/modules/net-ilb/README.md @@ -113,7 +113,6 @@ module "ilb" { | name | description | type | required | default | |---|---|:---: |:---:|:---:| | backends | Load balancer backends, balancing mode is one of 'CONNECTION' or 'UTILIZATION'. | list(object({...})) | ✓ | | -| group_configs | Optional unmanaged groups to create. Can be referenced in backends via outputs. | map(object({...})) | ✓ | | | name | Name used for all resources. | string | ✓ | | | network | Network used for resources. | string | ✓ | | | project_id | Project id where resources will be created. | string | ✓ | | @@ -123,6 +122,7 @@ module "ilb" { | *backend_config* | Optional backend configuration. | object({...}) | | null | | *failover_config* | Optional failover configuration. | object({...}) | | null | | *global_access* | Global access, defaults to false if not set. | bool | | null | +| *group_configs* | Optional unmanaged groups to create. Can be referenced in backends via outputs. | map(object({...})) | | {} | | *health_check* | Name of existing health check to use, disables auto-created health check. | string | | null | | *health_check_config* | Configuration of the auto-created helth check. | object({...}) | | ... | | *labels* | Labels set on resources. | map(string) | | {} | diff --git a/modules/project/README.md b/modules/project/README.md index 7fd57c01..db182e04 100644 --- a/modules/project/README.md +++ b/modules/project/README.md @@ -88,7 +88,7 @@ module "project" { | *auto_create_network* | Whether to create the default network for the project | bool | | false | | *billing_account* | Billing account id. | string | | null | | *custom_roles* | Map of role name => list of permissions to create in this project. | map(list(string)) | | {} | -| *iam_additive_bindings* | Map of roles list used to set non authoritative bindings, keyed by member. | list(string) | | [] | +| *iam_additive_bindings* | Map of roles lists used to set non authoritative bindings, keyed by members | map(list(string)) | | {} | | *iam_members* | Map of member lists used to set authoritative bindings, keyed by role. | map(list(string)) | | {} | | *iam_roles* | List of roles used to set authoritative bindings. | list(string) | | [] | | *labels* | Resource labels. | map(string) | | {} | diff --git a/modules/secret-manager/README.md b/modules/secret-manager/README.md index 413fedba..b8224c53 100644 --- a/modules/secret-manager/README.md +++ b/modules/secret-manager/README.md @@ -84,7 +84,7 @@ module "secret-manager" { | *iam_roles* | IAM roles keyed by secret name. | map(list(string)) | | {} | | *labels* | Optional labels for each secret. | map(map(string)) | | {} | | *secrets* | Map of secrets to manage and their locations. If locations is null, automatic management will be set. | map(list(string)) | | {} | -| *versions* | Optional versions to manage for each secret. Version names are only used internally to track each version and must be unique for each secret/version pair. | map(list(object({...}))) | | {} | +| *versions* | Optional versions to manage for each secret. Version names are only used internally to track individual versions. | map(map(object({...}))) | | {} | ## Outputs From b83b0e5a58d9b61c997e4f95bee5180b3adb1d9a Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Thu, 2 Jul 2020 08:30:59 +0200 Subject: [PATCH 126/129] regenerate variables/outputs tables in end to end examples --- foundations/environments/README.md | 4 +--- infrastructure/hub-and-spoke-vpn/README.md | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/foundations/environments/README.md b/foundations/environments/README.md index 91ba7aa4..338c7286 100644 --- a/foundations/environments/README.md +++ b/foundations/environments/README.md @@ -39,12 +39,10 @@ If no shared services are needed, the shared service project module can of cours | root_node | Root node for the new hierarchy, either 'organizations/org_id' or 'folders/folder_id'. | string | ✓ | | | *audit_filter* | Audit log filter used for the log sink. | string | | ... | | *gcs_location* | GCS bucket location. | string | | EU | -| *iam_assets_editors* | Shared assets project editors, in IAM format. | list(string) | | [] | -| *iam_assets_owners* | Shared assets project owners, in IAM format. | list(string) | | [] | | *iam_audit_viewers* | Audit project viewers, in IAM format. | list(string) | | [] | | *iam_billing_config* | Control granting billing user role to service accounts. Target the billing account by default. | object({...}) | | ... | | *iam_folder_roles* | List of roles granted to each service account on its respective folder (excluding XPN roles). | list(string) | | ... | -| *iam_sharedsvc_owners* | Shared services project owners, in IAM format. | list(string) | | [] | +| *iam_shared_owners* | Shared services project owners, in IAM format. | list(string) | | [] | | *iam_terraform_owners* | Terraform project owners, in IAM format. | list(string) | | [] | | *iam_xpn_config* | Control granting Shared VPC creation roles to service accounts. Target the root node by default. | object({...}) | | ... | | *project_services* | Service APIs enabled by default in new projects. | list(string) | | ... | diff --git a/infrastructure/hub-and-spoke-vpn/README.md b/infrastructure/hub-and-spoke-vpn/README.md index 2e39e68c..ab866ca2 100644 --- a/infrastructure/hub-and-spoke-vpn/README.md +++ b/infrastructure/hub-and-spoke-vpn/README.md @@ -42,7 +42,7 @@ If a single router and VPN gateway are used in the hub to manage all tunnels, pa | project_id | Project id for all resources. | string | ✓ | | | *bgp_asn* | BGP ASNs. | map(number) | | ... | | *bgp_custom_advertisements* | BGP custom advertisement IP CIDR ranges. | map(string) | | ... | -| *bgp_interface_ranges* | None | | | ... | +| *bgp_interface_ranges* | BGP interface IP CIDR ranges. | map(string) | | ... | | *ip_ranges* | IP CIDR ranges. | map(string) | | ... | | *regions* | VPC regions. | map(string) | | ... | From 54aff6ee22905104ea3ac987ba54bf526868dd8c Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Thu, 2 Jul 2020 08:35:19 +0200 Subject: [PATCH 127/129] Update CHANGELOG.md --- CHANGELOG.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 03c801f3..55a6d124 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,12 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +## [2.3.0] - 2020-07-02 + - new 'Cloud Storage to Bigquery with Cloud Dataflow' end to end data solution +- **incompatible change** additive IAM bindings are now keyed by identity instead of role, and use a single `iam_additive_bindings` variable, refer to [#103] for details +- set `delete_contents_on_destroy` in the foundations examples audit dataset to allow destroying +- trap errors raised by the `project` module on destroy ## [2.2.0] - 2020-06-29 @@ -112,7 +117,8 @@ All notable changes to this project will be documented in this file. - merge development branch with suite of new modules and end-to-end examples -[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.2.0...HEAD +[Unreleased]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.3.0...HEAD +[2.3.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.2.0...v2.3.0 [2.2.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.1.0...v2.2.0 [2.1.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v2.0.0...v2.1.0 [2.0.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.9.0...v2.0.0 @@ -129,3 +135,4 @@ All notable changes to this project will be documented in this file. [1.1.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v1.0...v1.1 [1.0.0]: https://github.com/terraform-google-modules/cloud-foundation-fabric/compare/v0.1...v1.0 [#82]: https://github.com/terraform-google-modules/cloud-foundation-fabric/pull/82 +[#103]: https://github.com/terraform-google-modules/cloud-foundation-fabric/pull/103 From ceb725bb84deabceb4a913e7bf60e6d5e43c67fa Mon Sep 17 00:00:00 2001 From: Sumeet Chaurasia Date: Thu, 2 Jul 2020 15:11:42 +0530 Subject: [PATCH 128/129] Reserved External IP-Compute VM (#107) --- modules/compute-vm/main.tf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/compute-vm/main.tf b/modules/compute-vm/main.tf index 83121fbd..41804461 100644 --- a/modules/compute-vm/main.tf +++ b/modules/compute-vm/main.tf @@ -135,7 +135,7 @@ resource "google_compute_instance" "default" { iterator = nat_addresses content { nat_ip = nat_addresses.value == null ? null : ( - length(nat_addresses.value) == 0 ? null : nat_addresses.value[each.value] + length(nat_addresses.value) == 0 ? null : nat_addresses.value.external[each.value] ) } } From e1c7595a19c6d35988fc5283d1bcefa50b03eb9b Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Thu, 2 Jul 2020 11:42:12 +0200 Subject: [PATCH 129/129] Update CHANGELOG.md --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 55a6d124..365956b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +- fix external IP assignment in `compute-vm` + ## [2.3.0] - 2020-07-02 - new 'Cloud Storage to Bigquery with Cloud Dataflow' end to end data solution