diff --git a/foundations/business-units/README.md b/foundations/business-units/README.md
index 684579bc06..70c2297cb5 100644
--- a/foundations/business-units/README.md
+++ b/foundations/business-units/README.md
@@ -19,7 +19,7 @@ This sample creates several distinct groups of resources:
- one project in the shared folder to set up and host centralized audit log exports
- one project in the shared folder to hold services used across environments like GCS, GCR, KMS, Cloud Build, etc.
-The number of resources in this sample is kept to a minimum so as to make it generally applicable, more resources can be easily added by leveraging the full array of [Cloud Foundation Toolkit modules](https://github.com/terraform-google-modules), especially in the shared services project.
+The number of resources in this sample is kept to a minimum so as to make it generally applicable, more resources can be easily added by leveraging other [modules from our bundle](../../modules/), or from other sources like the [CFT suite](https://github.com/terraform-google-modules).
## Shared services
@@ -31,37 +31,34 @@ This sample uses a top-level folder to encapsulate projects that host resources
| name | description | type | required | default |
|---|---|:---: |:---:|:---:|
| billing_account_id | Billing account id used as default for new projects. | string
| ✓ | |
-| business_unit_1_name | Business unit 1 short name. | string
| ✓ | |
-| business_unit_2_name | Business unit 2 short name. | string
| ✓ | |
-| business_unit_3_name | Business unit 3 short name. | string
| ✓ | |
-| environments | Environment short names. | list(string)
| ✓ | |
| organization_id | Organization id. | string
| ✓ | |
| prefix | Prefix used for resources that need unique names. | string
| ✓ | |
| root_node | Root node for the new hierarchy, either 'organizations/org_id' or 'folders/folder_id'. | string
| ✓ | |
-| *audit_viewers* | Audit project viewers, in IAM format. | list(string)
| | []
|
-| *gcs_location* | GCS bucket location. | string
| | EU
|
+| *audit_filter* | Audit log filter used for the log sink. | string
| | ...
|
+| *business_unit_bi* | Business unit BI configuration. | object({...})
| | ...
|
+| *business_unit_ml* | Business unit ML configuration. | object({...})
| | ...
|
+| *environments* | Environment short names. | map(string)
| | ...
|
+| *gcs_defaults* | Defaults use for the state GCS buckets. | map(string)
| | ...
|
| *generate_service_account_keys* | Generate and store service account keys in the state file. | bool
| | false
|
+| *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_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)
| | ...
|
-| *shared_bindings_members* | List of comma-delimited IAM-format members for the additional shared project bindings. | list(string)
| | []
|
-| *shared_bindings_roles* | List of roles for additional shared project bindings. | list(string)
| | []
|
+| *service_account_keys* | Generate and store service account keys in the state file. | bool
| | false
|
| *terraform_owners* | Terraform project owners, in IAM format. | list(string)
| | []
|
## Outputs
| name | description | sensitive |
|---|---|:---:|
-| audit_logs_bq_dataset | Bigquery dataset for the audit logs export. | |
| audit_logs_project | Project that holds the audit logs export resources. | |
| bootstrap_tf_gcs_bucket | GCS bucket used for the bootstrap Terraform state. | |
-| business_unit_1_environment_folders_ids | Business unit 1 environment folders. | |
-| business_unit_1_folder_id | Business unit 1 top-level folder ID. | |
-| business_unit_2_environment_folders_ids | Business unit 2 environment folders. | |
-| business_unit_2_folder_id | Business unit 2 top-level folder ID. | |
-| business_unit_3_environment_folders_ids | Business unit 3 environment folders. | |
-| business_unit_3_folder_id | Business unit 3 top-level folder ID. | |
-| environment_service_account_keys | Service account keys used to run each environment Terraform modules. | ✓ |
-| environment_service_accounts | Service accounts used to run each environment Terraform modules. | |
-| environment_tf_gcs_buckets | GCS buckets used for each environment Terraform state. | |
+| bu_bi | Business Unit BI attributes. | |
+| bu_bi_sa_keys | Business Unit BI Service Accoutns keys. | ✓ |
+| bu_ml | Business Unit ML attributes. | |
+| bu_ml_sa_keys | Business Unit ML Service Accoutns keys. | ✓ |
| shared_folder_id | Shared folder ID. | |
| shared_resources_project | Project that holdes resources shared across business units. | |
| terraform_project | Project that holds the base Terraform resources. | |
diff --git a/foundations/business-units/main.tf b/foundations/business-units/main.tf
index ea61923130..ec342cfd3a 100644
--- a/foundations/business-units/main.tf
+++ b/foundations/business-units/main.tf
@@ -1,18 +1,18 @@
-# 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
-#
-# 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.
-
-# TODO(averbukh): simplify log-sink parameters once https://github.com/terraform-google-modules/terraform-google-log-export/issues/28 is done.
+/**
+ * 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 {
parent_numeric_id = element(split("/", var.root_node), 1)
@@ -37,14 +37,14 @@ 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_nonauth_members = { "roles/owner" = var.iam_terraform_owners }
- iam_nonauth_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_members = { "roles/owner" = var.iam_terraform_owners }
+ iam_additive_roles = ["roles/owner"]
+ services = var.project_services
}
# Bootstrap Terraform state GCS bucket
@@ -73,11 +73,13 @@ module "busines-unit-bi" {
gcs_defaults = var.gcs_defaults
iam_roles = var.business_unit_bi.iam_roles
iam_members = var.business_unit_bi.iam_members
+ iam_xpn_config = var.iam_xpn_config
+ iam_billing_config = var.iam_billing_config
organization_id = var.organization_id
- parent = var.root_node
+ root_node = var.root_node
prefix = var.prefix
environments = var.environments
- generate_keys = var.generate_keys
+ service_account_keys = var.service_account_keys
}
# Business unit ML
@@ -92,11 +94,13 @@ module "busines-unit-ml" {
gcs_defaults = var.gcs_defaults
iam_roles = var.business_unit_ml.iam_roles
iam_members = var.business_unit_ml.iam_members
+ iam_xpn_config = var.iam_xpn_config
+ iam_billing_config = var.iam_billing_config
organization_id = var.organization_id
- parent = var.root_node
+ root_node = var.root_node
prefix = var.prefix
environments = var.environments
- generate_keys = var.generate_keys
+ service_account_keys = var.service_account_keys
}
###############################################################################
@@ -163,10 +167,10 @@ module "shared-project" {
parent = module.shared-folder.id
prefix = var.prefix
billing_account = var.billing_account_id
- iam_members = {
+ iam_additive_members = {
"roles/owner" = var.iam_shared_owners
}
- iam_roles = [
+ iam_additive_roles = [
"roles/owner"
]
services = var.project_services
diff --git a/foundations/business-units/outputs.tf b/foundations/business-units/outputs.tf
index a1174a1876..e2e16a4b12 100644
--- a/foundations/business-units/outputs.tf
+++ b/foundations/business-units/outputs.tf
@@ -1,16 +1,18 @@
-# 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
-#
-# 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.
+/**
+ * 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 "terraform_project" {
description = "Project that holds the base Terraform resources."
@@ -29,24 +31,34 @@ output "shared_folder_id" {
output "bu_ml" {
description = "Business Unit ML attributes."
- value = module.busines-unit-ml.unit
+ value = {
+ unit_folder = module.busines-unit-ml.unit_folder,
+ env_gcs_buckets = module.busines-unit-ml.env_gcs_buckets
+ env_folders = module.busines-unit-ml.env_folders
+ env_service_accounts = module.busines-unit-ml.env_service_accounts
+ }
}
output "bu_ml_sa_keys" {
description = "Business Unit ML Service Accoutns keys."
- sensitive = true
- value = module.busines-unit-ml.keys
+ sensitive = true
+ value = module.busines-unit-ml.env_sa_keys
}
output "bu_bi" {
description = "Business Unit BI attributes."
- value = module.busines-unit-bi.unit
+ value = {
+ unit_folder = module.busines-unit-bi.unit_folder,
+ env_gcs_buckets = module.busines-unit-bi.env_gcs_buckets
+ env_folders = module.busines-unit-bi.env_folders
+ env_service_accounts = module.busines-unit-bi.env_service_accounts
+ }
}
output "bu_bi_sa_keys" {
description = "Business Unit BI Service Accoutns keys."
- sensitive = true
- value = module.busines-unit-bi.keys
+ sensitive = true
+ value = module.busines-unit-bi.env_sa_keys
}
output "audit_logs_project" {
@@ -60,4 +72,4 @@ output "shared_resources_project" {
}
# Add further outputs here for the additional modules that manage shared
-# resources, like GCR, GCS buckets, KMS, etc.
\ No newline at end of file
+# resources, like GCR, GCS buckets, KMS, etc.
diff --git a/foundations/business-units/providers.tf b/foundations/business-units/providers.tf
index b166f75dc4..d57e94c5de 100644
--- a/foundations/business-units/providers.tf
+++ b/foundations/business-units/providers.tf
@@ -1,15 +1,17 @@
-# 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
-#
-# 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.
+/**
+ * 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.
+ */
-provider "google" {}
\ No newline at end of file
+provider "google" {}
diff --git a/foundations/business-units/terraform.tfvars.sample b/foundations/business-units/terraform.tfvars.sample
new file mode 100644
index 0000000000..2d05f977ae
--- /dev/null
+++ b/foundations/business-units/terraform.tfvars.sample
@@ -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
+#
+# 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.
+
+billing_account_id = "014617-19UCBC-AF02D9"
+organization_id= "500001140800"
+prefix = "xyz"
+root_node = "folders/9572793983696"
+generate_keys = true
diff --git a/foundations/business-units/variables.tf b/foundations/business-units/variables.tf
index 63dda9b4aa..0a3e3e06d4 100644
--- a/foundations/business-units/variables.tf
+++ b/foundations/business-units/variables.tf
@@ -1,16 +1,18 @@
-# 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
-#
-# 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.
+/**
+ * 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 "audit_filter" {
description = "Audit log filter used for the log sink."
@@ -84,8 +86,8 @@ variable "environments" {
description = "Environment short names."
type = map(string)
default = {
- dev = "Development",
- test = "Testing",
+ dev = "Development",
+ test = "Testing",
prod = "Production"
}
}
@@ -147,8 +149,32 @@ variable "iam_terraform_owners" {
default = []
}
-variable "generate_keys" {
- description = "Generate keys for service accounts."
+variable "service_account_keys" {
+ description = "Generate and store service account keys in the state file."
type = bool
default = false
}
+
+variable "iam_xpn_config" {
+ description = "Control granting Shared VPC creation roles to service accounts. Target the root node by default."
+ type = object({
+ grant = bool
+ target_org = bool
+ })
+ default = {
+ grant = true
+ target_org = false
+ }
+}
+
+variable "iam_billing_config" {
+ description = "Control granting billing user role to service accounts. Target the billing account by default."
+ type = object({
+ grant = bool
+ target_org = bool
+ })
+ default = {
+ grant = true
+ target_org = false
+ }
+}
diff --git a/foundations/business-units/versions.tf b/foundations/business-units/versions.tf
index 4eb1500c5a..bc4c2a9d71 100644
--- a/foundations/business-units/versions.tf
+++ b/foundations/business-units/versions.tf
@@ -1,17 +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
-#
-# 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.
+/**
+ * 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"
+ required_version = ">= 0.12.6"
}
diff --git a/foundations/environments/README.md b/foundations/environments/README.md
index 3e13134f20..f3451777a5 100644
--- a/foundations/environments/README.md
+++ b/foundations/environments/README.md
@@ -17,7 +17,7 @@ This sample creates several distinct groups of resources:
- one top-level project to set up and host centralized audit log exports (optional)
- one top-level shared services project
-The number of resources in this sample is kept to a minimum so as to make it more generally applicable, further resources can be easily added by leveraging the full array of [Cloud Foundation Toolkit modules](https://github.com/terraform-google-modules), especially in the shared services project.
+The number of resources in this sample is kept to a minimum so as to make it generally applicable, more resources can be easily added by leveraging other [modules from our bundle](../../modules/), or from other sources like the [CFT suite](https://github.com/terraform-google-modules).
## Shared services project
@@ -32,20 +32,23 @@ If no shared services are needed, the shared service project module can of cours
| name | description | type | required | default |
|---|---|:---: |:---:|:---:|
-| billing_account_id | Billing account id used as default for new projects. | string
| ✓ | |
+| billing_account_id | Billing account id used as to create projects. | string
| ✓ | |
| environments | Environment short names. | list(string)
| ✓ | |
-| organization_id | Organization id. | string
| ✓ | |
| prefix | Prefix used for resources that need unique names. | string
| ✓ | |
| root_node | Root node for the new hierarchy, either 'organizations/org_id' or 'folders/folder_id'. | string
| ✓ | |
-| *audit_viewers* | Audit project viewers, in IAM format. | list(string)
| | []
|
+| *audit_filter* | Audit log filter used for the log sink. | string
| | ...
|
| *gcs_location* | GCS bucket location. | string
| | EU
|
-| *generate_service_account_keys* | Generate and store service account keys in the state file. | bool
| | false
|
-| *grant_xpn_folder_roles* | Grant roles needed for Shared VPC creation to service accounts at the environment folder level. | bool
| | true
|
-| *grant_xpn_org_roles* | Grant roles needed for Shared VPC creation to service accounts at the organization level. | bool
| | false
|
+| *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_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({...})
| | ...
|
+| *organization_id* | Organization id. | string
| | null
|
| *project_services* | Service APIs enabled by default in new projects. | list(string)
| | ...
|
-| *shared_bindings_members* | List of comma-delimited IAM-format members for the additional shared project bindings. | list(string)
| | []
|
-| *shared_bindings_roles* | List of roles for additional shared project bindings. | list(string)
| | []
|
-| *terraform_owners* | Terraform project owners, in IAM format. | list(string)
| | []
|
+| *service_account_keys* | Generate and store service account keys in the state file. | bool
| | true
|
## Outputs
@@ -59,5 +62,4 @@ If no shared services are needed, the shared service project module can of cours
| environment_service_accounts | Service accounts used to run each environment Terraform modules. | |
| environment_tf_gcs_buckets | GCS buckets used for each environment Terraform state. | |
| shared_resources_project | Project that holdes resources shared across environments. | |
-| terraform_project | Project that holds the base Terraform resources. | |
diff --git a/foundations/environments/main.tf b/foundations/environments/main.tf
index 6332e34596..754b461a0e 100644
--- a/foundations/environments/main.tf
+++ b/foundations/environments/main.tf
@@ -19,14 +19,14 @@
# Terraform project
module "tf-project" {
- source = "../../modules/project"
- name = "terraform"
- parent = var.root_node
- prefix = var.prefix
- billing_account = var.billing_account_id
- iam_nonauth_members = { "roles/owner" = var.iam_terraform_owners }
- iam_nonauth_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_members = { "roles/owner" = var.iam_terraform_owners }
+ iam_additive_roles = ["roles/owner"]
+ services = var.project_services
}
# per-environment service accounts
@@ -163,10 +163,10 @@ module "sharedsvc-project" {
parent = var.root_node
prefix = var.prefix
billing_account = var.billing_account_id
- iam_members = {
+ iam_additive_members = {
"roles/owner" = var.iam_sharedsvc_owners
}
- iam_roles = [
+ iam_additive_roles = [
"roles/owner"
]
services = var.project_services
diff --git a/foundations/environments/variables.tf b/foundations/environments/variables.tf
index f84890a21e..6bdafadf03 100644
--- a/foundations/environments/variables.tf
+++ b/foundations/environments/variables.tf
@@ -95,7 +95,7 @@ variable "iam_xpn_config" {
description = "Control granting Shared VPC creation roles to service accounts. Target the root node by default."
type = object({
grant = bool
- target_org = string
+ target_org = bool
})
default = {
grant = true
diff --git a/modules/folders-unit/README.md b/modules/folders-unit/README.md
index 48edcfbaf8..2524653884 100644
--- a/modules/folders-unit/README.md
+++ b/modules/folders-unit/README.md
@@ -1,23 +1,26 @@
# Google Cloud Unit Folders Module
-This module allow creation and management of sets of folders (environments) and a common parent (unit), and their environment specific Service Accounts, IAM bindings, GCS buckets.
+This module allow creation and management of a set of folders (environments) and a common parent folder (unit), their environment specific Service Accounts, IAM bindings, GCS buckets.
## Example
```hcl
-module "folder" {
- source = "./modules/folders-ubit"
- parent = "organizations/1234567890"
- name = "Magic Unit"
- environments = ["dev", "test", "prod"]
- iam_members = {
- "Folder one" = {
- "roles/owner" => ["group:users@example.com"]
- }
- }
- iam_roles = {
- "Folder one" = ["roles/owner"]
+module "folders-unit" {
+ source = "../../modules/folders-unit"
+
+ name = "Business Intelligence"
+ short_name = "bi"
+ automation_project_id = "automation-project-394yr923811"
+ billing_account_id = "015617-16GHBC-AF02D9"
+ organization_id = "506128240800"
+ root_node = "folders/93469270123701"
+ prefix = "unique-prefix"
+ environments = {
+ dev = "Development",
+ test = "Testing",
+ prod = "Production"
}
+ service_account_keys = true
}
```
@@ -26,21 +29,29 @@ module "folder" {
| name | description | type | required | default |
|---|---|:---: |:---:|:---:|
-| parent | Parent in folders/folder_id or organizations/org_id format. | string
| ✓ | |
-| *iam_members* | List of IAM members keyed by folder name and role. | map(map(list(string)))
| | null
|
-| *iam_roles* | List of IAM roles keyed by folder name. | map(list(string))
| | null
|
-| *names* | Folder names. | list(string)
| | []
|
+| automation_project_id | Project id used for automation service accounts. | string
| ✓ | |
+| billing_account_id | Country billing account account. | string
| ✓ | |
+| iam_members | IAM members for roles applied on the unit folder. | map(list(string))
| ✓ | |
+| iam_roles | IAM roles applied on the unit folder. | list(string)
| ✓ | |
+| name | Top folder name. | string
| ✓ | |
+| organization_id | Organization id. | string
| ✓ | |
+| prefix | Prefix used for GCS bucket names. | string
| ✓ | |
+| root_node | Root node in folders/folder_id or organizations/org_id format. | string
| ✓ | |
+| short_name | Short name. | string
| ✓ | |
+| *environments* | Unit environments short names. | map(string)
| | ...
|
+| *gcs_defaults* | Defaults use for the state GCS buckets. | map(string)
| | ...
|
+| *iam_billing_config* | Control granting billing user role to service accounts. Target the billing account by default. | object({...})
| | ...
|
+| *iam_enviroment_roles* | IAM roles granted to service accounts on the environment sub-folders. | list(string)
| | ...
|
+| *iam_xpn_config* | Control granting Shared VPC creation roles to service accounts. Target the root node by default. | object({...})
| | ...
|
+| *service_account_keys* | Generate and store service account keys in the state file. | bool
| | false
|
## Outputs
| name | description | sensitive |
|---|---|:---:|
-| folder | Folder resource (for single use). | |
-| folders | Folder resources. | |
-| id | Folder id (for single use). | |
-| ids | Folder ids. | |
-| ids_list | List of folder ids. | |
-| name | Folder name (for single use). | |
-| names | Folder names. | |
-| names_list | List of folder names. | |
+| env_folders | Unit environments folders. | |
+| env_gcs_buckets | Unit environments tfstate gcs buckets. | |
+| env_sa_keys | Unit environments service account keys. | ✓ |
+| env_service_accounts | Unit environments service accounts. | |
+| unit_folder | Unit top level folder. | |
diff --git a/modules/folders-unit/locals.tf b/modules/folders-unit/locals.tf
new file mode 100644
index 0000000000..4bc6bb1c54
--- /dev/null
+++ b/modules/folders-unit/locals.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.
+ */
+
+locals {
+ folder_roles = concat(var.iam_enviroment_roles, local.sa_xpn_folder_roles)
+ unit_iam_bindings = {
+ for role in var.iam_roles :
+ role => lookup(var.iam_members, role, [])
+ }
+ folder_iam_service_account_bindings = {
+ for pair in setproduct(keys(var.environments), local.folder_roles) :
+ "${pair.0}-${pair.1}" => { environment = pair.0, role = pair.1 }
+ }
+ org_iam_service_account_bindings = {
+ for pair in setproduct(keys(var.environments), concat(
+ local.sa_xpn_org_roles,
+ local.sa_billing_org_roles,
+ local.sa_billing_org_roles)) :
+ "${pair.0}-${pair.1}" => { environment = pair.0, role = pair.1 }
+ }
+ billing_iam_service_account_bindings = {
+ for pair in setproduct(keys(var.environments), local.sa_billing_account_roles) :
+ "${pair.0}-${pair.1}" => { environment = pair.0, role = pair.1 }
+ }
+ service_accounts = {
+ for key, sa in google_service_account.environment :
+ key => "serviceAccount:${sa.email}"
+ }
+ sa_billing_account_roles = (
+ var.iam_billing_config.target_org ? [] : ["roles/billing.user"]
+ )
+ sa_billing_org_roles = (
+ ! var.iam_billing_config.target_org ? [] : ["roles/billing.user"]
+ )
+ sa_xpn_folder_roles = (
+ local.sa_xpn_target_org ? [] : ["roles/compute.xpnAdmin"]
+ )
+ sa_xpn_org_roles = (
+ local.sa_xpn_target_org
+ ? ["roles/compute.xpnAdmin", "roles/resourcemanager.organizationViewer"]
+ : ["roles/resourcemanager.organizationViewer"]
+ )
+ sa_xpn_target_org = (
+ var.iam_xpn_config.target_org
+ ||
+ substr(var.root_node, 0, 13) == "organizations"
+ )
+}
diff --git a/modules/folders-unit/main.tf b/modules/folders-unit/main.tf
index 0d4a30a311..b553b11ab6 100644
--- a/modules/folders-unit/main.tf
+++ b/modules/folders-unit/main.tf
@@ -14,29 +14,13 @@
* limitations under the License.
*/
-locals {
-
- iam_bindings = {
- for role in var.iam_roles :
- role => lookup(var.iam_members, role, [])
- }
- iam_service_account_bindings = {
- for pair in setproduct(keys(var.environments), var.iam_enviroment_roles) :
- "${pair.0}-${pair.1}" => { environment = pair.0, role = pair.1 }
- }
- service_accounts = {
- for key, sa in google_service_account.environment :
- key => "serviceAccount:${sa.email}"
- }
-}
-
################################################################################
# Folders and folder IAM #
################################################################################
resource "google_folder" "unit" {
display_name = var.name
- parent = var.parent
+ parent = var.root_node
}
resource "google_folder" "environment" {
@@ -45,15 +29,15 @@ resource "google_folder" "environment" {
parent = google_folder.unit.name
}
-resource "google_folder_iam_binding" "authoritative" {
- for_each = local.iam_bindings
+resource "google_folder_iam_binding" "unit" {
+ for_each = local.unit_iam_bindings
folder = google_folder.unit.name
role = each.key
members = each.value
}
resource "google_folder_iam_binding" "environment" {
- for_each = local.iam_service_account_bindings
+ for_each = local.folder_iam_service_account_bindings
folder = google_folder.environment[each.value.environment].name
role = each.value.role
members = [
@@ -62,7 +46,25 @@ resource "google_folder_iam_binding" "environment" {
}
################################################################################
-# Service Accounts and SA IAM #
+# Billing Account and Org level IAM Bindings #
+################################################################################
+
+resource "google_organization_iam_member" "org_iam_member" {
+ for_each = local.org_iam_service_account_bindings
+ org_id = var.organization_id
+ role = each.value.role
+ member = "serviceAccount:${google_service_account.environment[each.value.environment].email}"
+}
+
+resource "google_billing_account_iam_member" "billing_iam_member" {
+ for_each = local.billing_iam_service_account_bindings
+ billing_account_id = var.billing_account_id
+ role = each.value.role
+ member = "serviceAccount:${google_service_account.environment[each.value.environment].email}"
+}
+
+################################################################################
+# Service Accounts #
################################################################################
resource "google_service_account" "environment" {
@@ -73,20 +75,10 @@ resource "google_service_account" "environment" {
}
resource "google_service_account_key" "keys" {
- for_each = var.generate_keys ? var.environments : {}
+ for_each = var.service_account_keys ? var.environments : {}
service_account_id = google_service_account.environment[each.key].email
}
-resource "google_billing_account_iam_member" "billing-user" {
- for_each = local.service_accounts
- billing_account_id = var.billing_account_id
- role = "roles/billing.user"
- member = each.value
-}
-
-# TODO: remember to add org-level roles if the service accounts need to manage
-# Shared VPC inside the Prod/Non-prod folders
-
################################################################################
# GCS and GCS IAM #
################################################################################
diff --git a/modules/folders-unit/outputs.tf b/modules/folders-unit/outputs.tf
index bc526f7c15..520712f50a 100644
--- a/modules/folders-unit/outputs.tf
+++ b/modules/folders-unit/outputs.tf
@@ -14,35 +14,46 @@
* limitations under the License.
*/
-output "unit" {
- description = "Unit attributes."
+output "unit_folder" {
+ description = "Unit top level folder."
value = {
- name = var.name
- folder = google_folder.unit.name
- tf_gcs_buckets = {
- for env in keys(var.environments)
- : env => google_storage_bucket.tfstate[env].name
- }
- env_folders = {
- for key, folder in google_folder.environment
- : key => folder.name
- }
- service_accounts = {
- for key, sa in google_service_account.environment
- : key => sa.email
- }
+ id = google_folder.unit.name,
+ name = google_folder.unit.display_name
+ }
+}
+
+output "env_gcs_buckets" {
+ description = "Unit environments tfstate gcs buckets."
+ value = {
+ for key, bucket in google_storage_bucket.tfstate
+ : key => bucket.name
}
}
-output "keys" {
- description = "Service account keys."
- sensitive = true
- value = (
- var.generate_keys ? {
- for env in keys(var.environments) :
- env => lookup(google_service_account_key.keys, env, null)
- } : {}
- )
+output "env_folders" {
+ description = "Unit environments folders."
+ value = {
+ for key, folder in google_folder.environment
+ : key => {
+ id = folder.name,
+ name = folder.display_name
+ }
+ }
}
+output "env_service_accounts" {
+ description = "Unit environments service accounts."
+ value = {
+ for key, sa in google_service_account.environment
+ : key => sa.email
+ }
+}
+output "env_sa_keys" {
+ description = "Unit environments service account keys."
+ sensitive = true
+ value = {
+ for key, sa_key in google_service_account_key.keys :
+ key => sa_key.private_key
+ }
+}
diff --git a/modules/folders-unit/variables.tf b/modules/folders-unit/variables.tf
index d78a66b8a2..9b825237c1 100644
--- a/modules/folders-unit/variables.tf
+++ b/modules/folders-unit/variables.tf
@@ -19,8 +19,8 @@ variable "organization_id" {
type = string
}
-variable "parent" {
- description = "Parent in folders/folder_id or organizations/org_id format."
+variable "root_node" {
+ description = "Root node in folders/folder_id or organizations/org_id format."
type = string
}
@@ -33,9 +33,9 @@ variable "environments" {
description = "Unit environments short names."
type = map(string)
default = {
- dev = "development",
- test = "Testing",
- prod = "Production"
+ dev = "development",
+ test = "Testing",
+ prod = "Production"
}
}
@@ -55,8 +55,8 @@ variable "name" {
}
variable "short_name" {
- description = "Short name."
- type = string
+ description = "Short name."
+ type = string
}
variable "gcs_defaults" {
@@ -89,8 +89,32 @@ variable "iam_enviroment_roles" {
]
}
-variable "generate_keys" {
- description = "Generate keys for service accounts."
+variable "service_account_keys" {
+ description = "Generate and store service account keys in the state file."
type = bool
default = false
}
+
+variable "iam_xpn_config" {
+ description = "Control granting Shared VPC creation roles to service accounts. Target the root node by default."
+ type = object({
+ grant = bool
+ target_org = bool
+ })
+ default = {
+ grant = true
+ target_org = false
+ }
+}
+
+variable "iam_billing_config" {
+ description = "Control granting billing user role to service accounts. Target the billing account by default."
+ type = object({
+ grant = bool
+ target_org = bool
+ })
+ default = {
+ grant = true
+ target_org = false
+ }
+}
diff --git a/modules/folders/main.tf b/modules/folders/main.tf
index 3b2bbe8b97..9e55b4ce79 100644
--- a/modules/folders/main.tf
+++ b/modules/folders/main.tf
@@ -33,15 +33,6 @@ resource "google_folder" "folders" {
parent = var.parent
}
-# give project creation access to service accounts
-# https://cloud.google.com/resource-manager/docs/access-control-folders#granting_folder-specific_roles_to_enable_project_creation
-# - external users need to have accepted the invitation email to join
-# "roles/owner",
-# "roles/resourcemanager.folderViewer",
-# "roles/resourcemanager.projectCreator",
-# "roles/compute.networkAdmin",
-
-
resource "google_folder_iam_binding" "authoritative" {
for_each = local.iam_keypairs
folder = google_folder.folders[each.value.name].name
@@ -51,9 +42,3 @@ resource "google_folder_iam_binding" "authoritative" {
)
}
-# resource "google_folder_iam_member" "non_authoritative" {
-# for_each = length(var.iam_non_authoritative_roles) > 0 ? local.iam_non_authoritative : {}
-# folder = google_project.project.project_id
-# role = each.value.role
-# member = each.value.member
-# }
diff --git a/modules/net-vpc/README.md b/modules/net-vpc/README.md
index 6c7884f860..7259abf157 100644
--- a/modules/net-vpc/README.md
+++ b/modules/net-vpc/README.md
@@ -25,6 +25,7 @@ module "vpc" {
subnet-2 = {
ip_cidr_range = "10.0.16.0/24"
region = "europe-west1"
+ secondary_ip_range = {}
}
}
}
diff --git a/modules/project/main.tf b/modules/project/main.tf
index b684ed0cb0..e6d8bab679 100644
--- a/modules/project/main.tf
+++ b/modules/project/main.tf
@@ -19,14 +19,14 @@ locals {
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_nonauth_pairs = flatten([
- for role in var.iam_nonauth_roles : [
- for member in lookup(var.iam_nonauth_members, role, []) :
+ iam_additive_pairs = flatten([
+ for role in var.iam_additive_roles : [
+ for member in lookup(var.iam_additive_members, role, []) :
{ role = role, member = member }
]
])
- iam_nonauth = {
- for pair in local.iam_nonauth_pairs :
+ iam_additive = {
+ for pair in local.iam_additive_pairs :
"${pair.role}-${pair.member}" => pair
}
parent_type = split("/", var.parent)[0]
@@ -81,7 +81,7 @@ resource "google_project_service" "project_services" {
# IAM notes:
# - external users need to have accepted the invitation email to join
# - oslogin roles also require role to list instances
-# - non-authoritative roles might fail due to dynamic values
+# - additive (non-authoritative) roles might fail due to dynamic values
resource "google_project_iam_binding" "authoritative" {
for_each = toset(var.iam_roles)
@@ -90,8 +90,8 @@ resource "google_project_iam_binding" "authoritative" {
members = lookup(var.iam_members, each.value, [])
}
-resource "google_project_iam_member" "non_authoritative" {
- for_each = length(var.iam_nonauth_roles) > 0 ? local.iam_nonauth : {}
+resource "google_project_iam_member" "additive" {
+ for_each = length(var.iam_additive_roles) > 0 ? local.iam_additive : {}
project = google_project.project.project_id
role = each.value.role
member = each.value.member
diff --git a/modules/project/variables.tf b/modules/project/variables.tf
index fb71debd6a..b9ecc8645a 100644
--- a/modules/project/variables.tf
+++ b/modules/project/variables.tf
@@ -44,13 +44,13 @@ variable "iam_roles" {
default = []
}
-variable "iam_nonauth_members" {
+variable "iam_additive_members" {
description = "Map of member lists used to set non authoritative bindings, keyed by role."
type = map(list(string))
default = {}
}
-variable "iam_nonauth_roles" {
+variable "iam_additive_roles" {
description = "List of roles used to set non authoritative bindings."
type = list(string)
default = []