Merge pull request #153 from terraform-google-modules/terraform-0.13
Add support for Terraform 0.13 features
This commit is contained in:
commit
94e0268e3b
|
@ -40,6 +40,8 @@ steps:
|
||||||
entrypoint: pytest
|
entrypoint: pytest
|
||||||
args:
|
args:
|
||||||
- -vv
|
- -vv
|
||||||
|
- tests/cloud_operations
|
||||||
|
- tests/data_solutions
|
||||||
- tests/foundations
|
- tests/foundations
|
||||||
- tests/networking
|
- tests/networking
|
||||||
env:
|
env:
|
||||||
|
|
|
@ -33,7 +33,7 @@ The current list of modules supports most of the core foundational and networkin
|
||||||
|
|
||||||
Currently available modules:
|
Currently available modules:
|
||||||
|
|
||||||
- **foundational** - [folders](./modules/folders), [log sinks](./modules/logging-sinks), [organization](./modules/organization), [project](./modules/project), [service accounts](./modules/iam-service-accounts)
|
- **foundational** - [folder](./modules/folder), [log sinks](./modules/logging-sinks), [organization](./modules/organization), [project](./modules/project), [service accounts](./modules/iam-service-account)
|
||||||
- **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)
|
- **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)
|
- **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)
|
- **data** - [GCS](./modules/gcs), [BigQuery dataset](./modules/bigquery-dataset), [Pub/Sub](./modules/pubsub), [Datafusion](./modules/datafusion), [Bigtable instance](./modules/bigtable-instance)
|
||||||
|
|
|
@ -41,8 +41,7 @@ module "project" {
|
||||||
"compute.zoneOperations.list"
|
"compute.zoneOperations.list"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
iam_roles = [local.role_id]
|
iam = {
|
||||||
iam_members = {
|
|
||||||
(local.role_id) = [module.service-account.iam_email]
|
(local.role_id) = [module.service-account.iam_email]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,10 +63,7 @@ module "pubsub" {
|
||||||
project_id = module.project.project_id
|
project_id = module.project.project_id
|
||||||
name = var.name
|
name = var.name
|
||||||
subscriptions = { "${var.name}-default" = null }
|
subscriptions = { "${var.name}-default" = null }
|
||||||
iam_roles = [
|
iam = {
|
||||||
"roles/pubsub.publisher"
|
|
||||||
]
|
|
||||||
iam_members = {
|
|
||||||
"roles/pubsub.publisher" = [
|
"roles/pubsub.publisher" = [
|
||||||
"serviceAccount:${module.project.service_accounts.robots.cloudasset}"
|
"serviceAccount:${module.project.service_accounts.robots.cloudasset}"
|
||||||
]
|
]
|
||||||
|
@ -75,9 +71,9 @@ module "pubsub" {
|
||||||
}
|
}
|
||||||
|
|
||||||
module "service-account" {
|
module "service-account" {
|
||||||
source = "../../modules/iam-service-accounts"
|
source = "../../modules/iam-service-account"
|
||||||
project_id = module.project.project_id
|
project_id = module.project.project_id
|
||||||
names = ["${var.name}-cf"]
|
name = "${var.name}-cf"
|
||||||
# iam_project_roles = { (module.project.project_id) = [local.role_id] }
|
# iam_project_roles = { (module.project.project_id) = [local.role_id] }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -77,26 +77,22 @@ module "service-directory" {
|
||||||
project_id = module.project.project_id
|
project_id = module.project.project_id
|
||||||
location = var.region
|
location = var.region
|
||||||
name = var.name
|
name = var.name
|
||||||
iam_members = {
|
iam = {
|
||||||
"roles/servicedirectory.editor" = [
|
"roles/servicedirectory.editor" = [
|
||||||
module.vm-ns-editor.service_account_iam_email
|
module.vm-ns-editor.service_account_iam_email
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
iam_roles = ["roles/servicedirectory.editor"]
|
|
||||||
services = {
|
services = {
|
||||||
app1 = { endpoints = ["vm1", "vm2"], metadata = null }
|
app1 = { endpoints = ["vm1", "vm2"], metadata = null }
|
||||||
app2 = { endpoints = ["vm1", "vm2"], metadata = null }
|
app2 = { endpoints = ["vm1", "vm2"], metadata = null }
|
||||||
}
|
}
|
||||||
service_iam_members = {
|
service_iam = {
|
||||||
app1 = {
|
app1 = {
|
||||||
"roles/servicedirectory.editor" = [
|
"roles/servicedirectory.editor" = [
|
||||||
module.vm-svc-editor.service_account_iam_email
|
module.vm-svc-editor.service_account_iam_email
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
service_iam_roles = {
|
|
||||||
app1 = ["roles/servicedirectory.editor"]
|
|
||||||
}
|
|
||||||
endpoint_config = {
|
endpoint_config = {
|
||||||
"app1/vm1" = { address = "127.0.0.2", port = 80, metadata = {} }
|
"app1/vm1" = { address = "127.0.0.2", port = 80, metadata = {} }
|
||||||
"app1/vm2" = { address = "127.0.0.3", port = 80, metadata = {} }
|
"app1/vm2" = { address = "127.0.0.3", port = 80, metadata = {} }
|
||||||
|
|
|
@ -34,10 +34,7 @@ module "project" {
|
||||||
disable_on_destroy = false,
|
disable_on_destroy = false,
|
||||||
disable_dependent_services = false
|
disable_dependent_services = false
|
||||||
}
|
}
|
||||||
iam_roles = [
|
iam = {
|
||||||
"roles/monitoring.metricWriter",
|
|
||||||
]
|
|
||||||
iam_members = {
|
|
||||||
"roles/monitoring.metricWriter" = [module.cf.service_account_iam_email]
|
"roles/monitoring.metricWriter" = [module.cf.service_account_iam_email]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright 2019 Google LLC
|
# Copyright 2020 Google LLC
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Projects #
|
# Projects #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
module "project" {
|
module "project" {
|
||||||
source = "../../modules/project"
|
source = "../../modules/project"
|
||||||
name = var.project_id
|
name = var.project_id
|
||||||
|
@ -35,9 +36,9 @@ module "project" {
|
||||||
}
|
}
|
||||||
|
|
||||||
module "service-account" {
|
module "service-account" {
|
||||||
source = "../../modules/iam-service-accounts"
|
source = "../../modules/iam-service-account"
|
||||||
project_id = module.project.project_id
|
project_id = module.project.project_id
|
||||||
names = ["${var.name}-cf"]
|
name = "${var.name}-cf"
|
||||||
iam_project_roles = {
|
iam_project_roles = {
|
||||||
(var.project_id) = ["roles/cloudasset.viewer"]
|
(var.project_id) = ["roles/cloudasset.viewer"]
|
||||||
}
|
}
|
||||||
|
@ -46,6 +47,7 @@ module "service-account" {
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Pub/Sub #
|
# Pub/Sub #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
module "pubsub" {
|
module "pubsub" {
|
||||||
source = "../../modules/pubsub"
|
source = "../../modules/pubsub"
|
||||||
project_id = module.project.project_id
|
project_id = module.project.project_id
|
||||||
|
@ -60,6 +62,7 @@ module "pubsub" {
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Cloud Function #
|
# Cloud Function #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
module "cf" {
|
module "cf" {
|
||||||
source = "../../modules/cloud-function"
|
source = "../../modules/cloud-function"
|
||||||
project_id = module.project.project_id
|
project_id = module.project.project_id
|
||||||
|
@ -88,6 +91,7 @@ resource "random_pet" "random" {
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Cloud Scheduler #
|
# Cloud Scheduler #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
resource "google_app_engine_application" "app" {
|
resource "google_app_engine_application" "app" {
|
||||||
project = module.project.project_id
|
project = module.project.project_id
|
||||||
location_id = var.location
|
location_id = var.location
|
||||||
|
@ -116,6 +120,7 @@ resource "google_cloud_scheduler_job" "job" {
|
||||||
###############################################################################
|
###############################################################################
|
||||||
# Bigquery #
|
# Bigquery #
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
module "bq" {
|
module "bq" {
|
||||||
source = "../../modules/bigquery-dataset"
|
source = "../../modules/bigquery-dataset"
|
||||||
project_id = module.project.project_id
|
project_id = module.project.project_id
|
||||||
|
|
|
@ -1,17 +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
|
|
||||||
#
|
|
||||||
# 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"
|
|
||||||
}
|
|
|
@ -79,10 +79,7 @@ module "kms" {
|
||||||
location = var.location
|
location = var.location
|
||||||
}
|
}
|
||||||
keys = { key-gce = null, key-gcs = null }
|
keys = { key-gce = null, key-gcs = null }
|
||||||
key_iam_roles = {
|
key_iam = {
|
||||||
key-gce = ["roles/cloudkms.cryptoKeyEncrypterDecrypter"]
|
|
||||||
}
|
|
||||||
key_iam_members = {
|
|
||||||
key-gce = {
|
key-gce = {
|
||||||
"roles/cloudkms.cryptoKeyEncrypterDecrypter" = [
|
"roles/cloudkms.cryptoKeyEncrypterDecrypter" = [
|
||||||
"serviceAccount:${module.project-service.service_accounts.robots.compute}",
|
"serviceAccount:${module.project-service.service_accounts.robots.compute}",
|
||||||
|
@ -145,11 +142,9 @@ module "kms_vm_example" {
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
module "kms-gcs" {
|
module "kms-gcs" {
|
||||||
source = "../../modules/gcs"
|
source = "../../modules/gcs"
|
||||||
project_id = module.project-service.project_id
|
project_id = module.project-service.project_id
|
||||||
prefix = "my-bucket-001"
|
prefix = "my-bucket-001"
|
||||||
names = ["kms-gcs"]
|
name = "kms-gcs"
|
||||||
encryption_keys = {
|
encryption_key = module.kms.keys.key-gcs.self_link
|
||||||
kms-gcs = module.kms.keys.key-gce.self_link,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,19 +13,13 @@
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
output "bucket" {
|
output "bucket" {
|
||||||
description = "GCS Bucket Cloud KMS crypto keys."
|
description = "GCS Bucket URL."
|
||||||
value = {
|
value = module.kms-gcs.url
|
||||||
for bucket in module.kms-gcs.buckets :
|
|
||||||
bucket.name => bucket.url
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output "bucket_keys" {
|
output "bucket_keys" {
|
||||||
description = "GCS Bucket Cloud KMS crypto keys."
|
description = "GCS Bucket Cloud KMS crypto keys."
|
||||||
value = {
|
value = module.kms-gcs.bucket.encryption
|
||||||
for bucket in module.kms-gcs.buckets :
|
|
||||||
bucket.name => bucket.encryption
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
output "projects" {
|
output "projects" {
|
||||||
|
|
|
@ -57,9 +57,9 @@ module "project-kms" {
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
module "service-account-bq" {
|
module "service-account-bq" {
|
||||||
source = "../../modules/iam-service-accounts"
|
source = "../../modules/iam-service-account"
|
||||||
project_id = module.project-service.project_id
|
project_id = module.project-service.project_id
|
||||||
names = ["bq-test"]
|
name = "bq-test"
|
||||||
iam_project_roles = {
|
iam_project_roles = {
|
||||||
(var.project_service_name) = [
|
(var.project_service_name) = [
|
||||||
"roles/logging.logWriter",
|
"roles/logging.logWriter",
|
||||||
|
@ -70,9 +70,9 @@ module "service-account-bq" {
|
||||||
}
|
}
|
||||||
|
|
||||||
module "service-account-gce" {
|
module "service-account-gce" {
|
||||||
source = "../../modules/iam-service-accounts"
|
source = "../../modules/iam-service-account"
|
||||||
project_id = module.project-service.project_id
|
project_id = module.project-service.project_id
|
||||||
names = ["gce-test"]
|
name = "gce-test"
|
||||||
iam_project_roles = {
|
iam_project_roles = {
|
||||||
(var.project_service_name) = [
|
(var.project_service_name) = [
|
||||||
"roles/logging.logWriter",
|
"roles/logging.logWriter",
|
||||||
|
@ -86,9 +86,9 @@ module "service-account-gce" {
|
||||||
}
|
}
|
||||||
|
|
||||||
module "service-account-df" {
|
module "service-account-df" {
|
||||||
source = "../../modules/iam-service-accounts"
|
source = "../../modules/iam-service-account"
|
||||||
project_id = module.project-service.project_id
|
project_id = module.project-service.project_id
|
||||||
names = ["df-test"]
|
name = "df-test"
|
||||||
iam_project_roles = {
|
iam_project_roles = {
|
||||||
(var.project_service_name) = [
|
(var.project_service_name) = [
|
||||||
"roles/dataflow.worker",
|
"roles/dataflow.worker",
|
||||||
|
@ -120,12 +120,7 @@ module "kms" {
|
||||||
location = var.location
|
location = var.location
|
||||||
}
|
}
|
||||||
keys = { key-gce = null, key-gcs = null, key-bq = null }
|
keys = { key-gce = null, key-gcs = null, key-bq = null }
|
||||||
key_iam_roles = {
|
key_iam = {
|
||||||
key-gce = ["roles/cloudkms.cryptoKeyEncrypterDecrypter"]
|
|
||||||
key-gcs = ["roles/cloudkms.cryptoKeyEncrypterDecrypter"]
|
|
||||||
key-bq = ["roles/cloudkms.cryptoKeyEncrypterDecrypter"]
|
|
||||||
}
|
|
||||||
key_iam_members = {
|
|
||||||
key-gce = {
|
key-gce = {
|
||||||
"roles/cloudkms.cryptoKeyEncrypterDecrypter" = [
|
"roles/cloudkms.cryptoKeyEncrypterDecrypter" = [
|
||||||
"serviceAccount:${module.project-service.service_accounts.robots.compute}",
|
"serviceAccount:${module.project-service.service_accounts.robots.compute}",
|
||||||
|
@ -155,10 +150,7 @@ module "kms-regional" {
|
||||||
location = var.region
|
location = var.region
|
||||||
}
|
}
|
||||||
keys = { key-df = null }
|
keys = { key-df = null }
|
||||||
key_iam_roles = {
|
key_iam = {
|
||||||
key-df = ["roles/cloudkms.cryptoKeyEncrypterDecrypter"]
|
|
||||||
}
|
|
||||||
key_iam_members = {
|
|
||||||
key-df = {
|
key-df = {
|
||||||
"roles/cloudkms.cryptoKeyEncrypterDecrypter" = [
|
"roles/cloudkms.cryptoKeyEncrypterDecrypter" = [
|
||||||
"serviceAccount:${module.project-service.service_accounts.robots.dataflow}",
|
"serviceAccount:${module.project-service.service_accounts.robots.dataflow}",
|
||||||
|
@ -254,38 +246,33 @@ module "vm_example" {
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
module "kms-gcs" {
|
module "kms-gcs" {
|
||||||
source = "../../modules/gcs"
|
source = "../../modules/gcs"
|
||||||
project_id = module.project-service.project_id
|
for_each = {
|
||||||
prefix = module.project-service.project_id
|
|
||||||
names = ["data", "df-tmplocation"]
|
|
||||||
iam_roles = {
|
|
||||||
data = ["roles/storage.admin", "roles/storage.objectViewer"],
|
|
||||||
df-tmplocation = ["roles/storage.admin"]
|
|
||||||
}
|
|
||||||
iam_members = {
|
|
||||||
data = {
|
data = {
|
||||||
"roles/storage.admin" = [
|
members = {
|
||||||
"serviceAccount:${module.service-account-gce.email}",
|
"roles/storage.admin" = [
|
||||||
],
|
"serviceAccount:${module.service-account-gce.email}",
|
||||||
"roles/storage.viewer" = [
|
],
|
||||||
"serviceAccount:${module.service-account-df.email}",
|
"roles/storage.objectViewer" = [
|
||||||
],
|
"serviceAccount:${module.service-account-df.email}",
|
||||||
},
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
df-tmplocation = {
|
df-tmplocation = {
|
||||||
"roles/storage.admin" = [
|
members = {
|
||||||
"serviceAccount:${module.service-account-gce.email}",
|
"roles/storage.admin" = [
|
||||||
"serviceAccount:${module.service-account-df.email}",
|
"serviceAccount:${module.service-account-gce.email}",
|
||||||
]
|
"serviceAccount:${module.service-account-df.email}",
|
||||||
|
]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
encryption_keys = {
|
project_id = module.project-service.project_id
|
||||||
data = module.kms.keys.key-gcs.self_link,
|
prefix = module.project-service.project_id
|
||||||
df-tmplocation = module.kms.keys.key-gcs.self_link,
|
name = each.key
|
||||||
}
|
iam = each.value.members
|
||||||
force_destroy = {
|
encryption_key = module.kms.keys.key-gcs.self_link
|
||||||
data = true,
|
force_destroy = true
|
||||||
df-tmplocation = true,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
@ -297,10 +284,11 @@ module "bigquery-dataset" {
|
||||||
project_id = module.project-service.project_id
|
project_id = module.project-service.project_id
|
||||||
id = "bq_dataset"
|
id = "bq_dataset"
|
||||||
access_roles = {
|
access_roles = {
|
||||||
reader-group = { role = "READER", type = "domain" }
|
reader-group = { role = "READER", type = "service_account" }
|
||||||
owner = { role = "OWNER", type = "user_by_email" }
|
owner = { role = "OWNER", type = "user_by_email" }
|
||||||
}
|
}
|
||||||
access_identities = {
|
access_identities = {
|
||||||
|
reader-group = module.service-account-bq.email
|
||||||
owner = module.service-account-bq.email
|
owner = module.service-account-bq.email
|
||||||
}
|
}
|
||||||
encryption_key = module.kms.keys.key-bq.self_link
|
encryption_key = module.kms.keys.key-bq.self_link
|
||||||
|
|
|
@ -14,13 +14,13 @@
|
||||||
|
|
||||||
output "bq_tables" {
|
output "bq_tables" {
|
||||||
description = "Bigquery Tables."
|
description = "Bigquery Tables."
|
||||||
value = module.bigquery-dataset.table_ids
|
value = module.bigquery-dataset.table_ids
|
||||||
}
|
}
|
||||||
|
|
||||||
output "buckets" {
|
output "buckets" {
|
||||||
description = "GCS Bucket Cloud KMS crypto keys."
|
description = "GCS Bucket Cloud KMS crypto keys."
|
||||||
value = {
|
value = {
|
||||||
for bucket in module.kms-gcs.buckets :
|
for name, bucket in module.kms-gcs :
|
||||||
bucket.name => bucket.url
|
bucket.name => bucket.url
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,9 +21,9 @@
|
||||||
# Shared folder
|
# Shared folder
|
||||||
|
|
||||||
module "shared-folder" {
|
module "shared-folder" {
|
||||||
source = "../../modules/folders"
|
source = "../../modules/folder"
|
||||||
parent = var.root_node
|
parent = var.root_node
|
||||||
names = ["shared"]
|
name = "shared"
|
||||||
}
|
}
|
||||||
|
|
||||||
# Terraform project
|
# Terraform project
|
||||||
|
@ -34,7 +34,7 @@ module "tf-project" {
|
||||||
parent = module.shared-folder.id
|
parent = module.shared-folder.id
|
||||||
prefix = var.prefix
|
prefix = var.prefix
|
||||||
billing_account = var.billing_account_id
|
billing_account = var.billing_account_id
|
||||||
iam_additive_bindings = {
|
iam_additive = {
|
||||||
for name in var.iam_terraform_owners : (name) => ["roles/owner"]
|
for name in var.iam_terraform_owners : (name) => ["roles/owner"]
|
||||||
}
|
}
|
||||||
services = var.project_services
|
services = var.project_services
|
||||||
|
@ -45,7 +45,7 @@ module "tf-project" {
|
||||||
module "tf-gcs-bootstrap" {
|
module "tf-gcs-bootstrap" {
|
||||||
source = "../../modules/gcs"
|
source = "../../modules/gcs"
|
||||||
project_id = module.tf-project.project_id
|
project_id = module.tf-project.project_id
|
||||||
names = ["tf-bootstrap"]
|
name = "tf-bootstrap"
|
||||||
prefix = "${var.prefix}-tf"
|
prefix = "${var.prefix}-tf"
|
||||||
location = var.gcs_defaults.location
|
location = var.gcs_defaults.location
|
||||||
}
|
}
|
||||||
|
@ -96,14 +96,10 @@ module "audit-project" {
|
||||||
parent = var.root_node
|
parent = var.root_node
|
||||||
prefix = var.prefix
|
prefix = var.prefix
|
||||||
billing_account = var.billing_account_id
|
billing_account = var.billing_account_id
|
||||||
iam_members = {
|
iam = {
|
||||||
"roles/bigquery.dataEditor" = [module.audit-log-sinks.writer_identities[0]]
|
"roles/bigquery.dataEditor" = [module.audit-log-sinks.writer_identities[0]]
|
||||||
"roles/viewer" = var.iam_audit_viewers
|
"roles/viewer" = var.iam_audit_viewers
|
||||||
}
|
}
|
||||||
iam_roles = [
|
|
||||||
"roles/bigquery.dataEditor",
|
|
||||||
"roles/viewer"
|
|
||||||
]
|
|
||||||
services = concat(var.project_services, [
|
services = concat(var.project_services, [
|
||||||
"bigquery.googleapis.com",
|
"bigquery.googleapis.com",
|
||||||
])
|
])
|
||||||
|
@ -147,7 +143,7 @@ module "shared-project" {
|
||||||
parent = module.shared-folder.id
|
parent = module.shared-folder.id
|
||||||
prefix = var.prefix
|
prefix = var.prefix
|
||||||
billing_account = var.billing_account_id
|
billing_account = var.billing_account_id
|
||||||
iam_additive_bindings = {
|
iam_additive = {
|
||||||
for name in var.iam_shared_owners : (name) => ["roles/owner"]
|
for name in var.iam_shared_owners : (name) => ["roles/owner"]
|
||||||
}
|
}
|
||||||
services = var.project_services
|
services = var.project_services
|
||||||
|
|
|
@ -33,7 +33,7 @@ If no shared services are needed, the shared service project module can of cours
|
||||||
| name | description | type | required | default |
|
| name | description | type | required | default |
|
||||||
|---|---|:---: |:---:|:---:|
|
|---|---|:---: |:---:|:---:|
|
||||||
| billing_account_id | Billing account id used as to create projects. | <code title="">string</code> | ✓ | |
|
| billing_account_id | Billing account id used as to create projects. | <code title="">string</code> | ✓ | |
|
||||||
| environments | Environment short names. | <code title="list(string)">list(string)</code> | ✓ | |
|
| environments | Environment short names. | <code title="set(string)">set(string)</code> | ✓ | |
|
||||||
| organization_id | Organization id in organizations/nnnnnnnn format. | <code title="">string</code> | ✓ | |
|
| organization_id | Organization id in organizations/nnnnnnnn format. | <code title="">string</code> | ✓ | |
|
||||||
| prefix | Prefix used for resources that need unique names. | <code title="">string</code> | ✓ | |
|
| prefix | Prefix used for resources that need unique names. | <code title="">string</code> | ✓ | |
|
||||||
| root_node | Root node for the new hierarchy, either 'organizations/org_id' or 'folders/folder_id'. | <code title="">string</code> | ✓ | |
|
| root_node | Root node for the new hierarchy, either 'organizations/org_id' or 'folders/folder_id'. | <code title="">string</code> | ✓ | |
|
||||||
|
|
|
@ -24,7 +24,7 @@ module "tf-project" {
|
||||||
parent = var.root_node
|
parent = var.root_node
|
||||||
prefix = var.prefix
|
prefix = var.prefix
|
||||||
billing_account = var.billing_account_id
|
billing_account = var.billing_account_id
|
||||||
iam_additive_bindings = {
|
iam_additive = {
|
||||||
for name in var.iam_terraform_owners : (name) => ["roles/owner"]
|
for name in var.iam_terraform_owners : (name) => ["roles/owner"]
|
||||||
}
|
}
|
||||||
services = var.project_services
|
services = var.project_services
|
||||||
|
@ -33,9 +33,10 @@ module "tf-project" {
|
||||||
# per-environment service accounts
|
# per-environment service accounts
|
||||||
|
|
||||||
module "tf-service-accounts" {
|
module "tf-service-accounts" {
|
||||||
source = "../../modules/iam-service-accounts"
|
source = "../../modules/iam-service-account"
|
||||||
|
for_each = var.environments
|
||||||
project_id = module.tf-project.project_id
|
project_id = module.tf-project.project_id
|
||||||
names = var.environments
|
name = each.value
|
||||||
prefix = var.prefix
|
prefix = var.prefix
|
||||||
iam_billing_roles = {
|
iam_billing_roles = {
|
||||||
(var.billing_account_id) = (
|
(var.billing_account_id) = (
|
||||||
|
@ -49,7 +50,7 @@ module "tf-service-accounts" {
|
||||||
var.iam_xpn_config.grant ? local.sa_xpn_org_roles : []
|
var.iam_xpn_config.grant ? local.sa_xpn_org_roles : []
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
generate_keys = var.service_account_keys
|
generate_key = var.service_account_keys
|
||||||
}
|
}
|
||||||
|
|
||||||
# bootstrap Terraform state GCS bucket
|
# bootstrap Terraform state GCS bucket
|
||||||
|
@ -57,7 +58,7 @@ module "tf-service-accounts" {
|
||||||
module "tf-gcs-bootstrap" {
|
module "tf-gcs-bootstrap" {
|
||||||
source = "../../modules/gcs"
|
source = "../../modules/gcs"
|
||||||
project_id = module.tf-project.project_id
|
project_id = module.tf-project.project_id
|
||||||
names = ["tf-bootstrap"]
|
name = "tf-bootstrap"
|
||||||
prefix = "${var.prefix}-tf"
|
prefix = "${var.prefix}-tf"
|
||||||
location = var.gcs_location
|
location = var.gcs_location
|
||||||
}
|
}
|
||||||
|
@ -66,17 +67,13 @@ module "tf-gcs-bootstrap" {
|
||||||
|
|
||||||
module "tf-gcs-environments" {
|
module "tf-gcs-environments" {
|
||||||
source = "../../modules/gcs"
|
source = "../../modules/gcs"
|
||||||
|
for_each = var.environments
|
||||||
project_id = module.tf-project.project_id
|
project_id = module.tf-project.project_id
|
||||||
names = var.environments
|
name = each.value
|
||||||
prefix = "${var.prefix}-tf"
|
prefix = "${var.prefix}-tf"
|
||||||
location = var.gcs_location
|
location = var.gcs_location
|
||||||
iam_roles = {
|
iam = {
|
||||||
for name in var.environments : (name) => ["roles/storage.objectAdmin"]
|
"roles/storage.objectAdmin" = [module.tf-service-accounts[each.value].iam_email]
|
||||||
}
|
|
||||||
iam_members = {
|
|
||||||
for name in var.environments : (name) => {
|
|
||||||
"roles/storage.objectAdmin" = [module.tf-service-accounts.iam_emails[name]]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,17 +82,13 @@ module "tf-gcs-environments" {
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
module "environment-folders" {
|
module "environment-folders" {
|
||||||
source = "../../modules/folders"
|
source = "../../modules/folder"
|
||||||
parent = var.root_node
|
for_each = var.environments
|
||||||
names = var.environments
|
parent = var.root_node
|
||||||
iam_roles = {
|
name = each.value
|
||||||
for name in var.environments : (name) => local.folder_roles
|
iam = {
|
||||||
}
|
for role in local.folder_roles :
|
||||||
iam_members = {
|
(role) => [module.tf-service-accounts[each.value].iam_email]
|
||||||
for name in var.environments : (name) => {
|
|
||||||
for role in local.folder_roles :
|
|
||||||
(role) => [module.tf-service-accounts.iam_emails[name]]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,14 +104,10 @@ module "audit-project" {
|
||||||
parent = var.root_node
|
parent = var.root_node
|
||||||
prefix = var.prefix
|
prefix = var.prefix
|
||||||
billing_account = var.billing_account_id
|
billing_account = var.billing_account_id
|
||||||
iam_members = {
|
iam = {
|
||||||
"roles/bigquery.dataEditor" = [module.audit-log-sinks.writer_identities[0]]
|
"roles/bigquery.dataEditor" = [module.audit-log-sinks.writer_identities[0]]
|
||||||
"roles/viewer" = var.iam_audit_viewers
|
"roles/viewer" = var.iam_audit_viewers
|
||||||
}
|
}
|
||||||
iam_roles = [
|
|
||||||
"roles/bigquery.dataEditor",
|
|
||||||
"roles/viewer"
|
|
||||||
]
|
|
||||||
services = concat(var.project_services, [
|
services = concat(var.project_services, [
|
||||||
"bigquery.googleapis.com",
|
"bigquery.googleapis.com",
|
||||||
])
|
])
|
||||||
|
@ -163,7 +152,7 @@ module "sharedsvc-project" {
|
||||||
parent = var.root_node
|
parent = var.root_node
|
||||||
prefix = var.prefix
|
prefix = var.prefix
|
||||||
billing_account = var.billing_account_id
|
billing_account = var.billing_account_id
|
||||||
iam_additive_bindings = {
|
iam_additive = {
|
||||||
for name in var.iam_shared_owners : (name) => ["roles/owner"]
|
for name in var.iam_shared_owners : (name) => ["roles/owner"]
|
||||||
}
|
}
|
||||||
services = var.project_services
|
services = var.project_services
|
||||||
|
|
|
@ -24,23 +24,23 @@ output "bootstrap_tf_gcs_bucket" {
|
||||||
|
|
||||||
output "environment_folders" {
|
output "environment_folders" {
|
||||||
description = "Top-level environment folders."
|
description = "Top-level environment folders."
|
||||||
value = module.environment-folders.ids
|
value = { for folder in module.environment-folders : folder.name => folder.id }
|
||||||
}
|
}
|
||||||
|
|
||||||
output "environment_tf_gcs_buckets" {
|
output "environment_tf_gcs_buckets" {
|
||||||
description = "GCS buckets used for each environment Terraform state."
|
description = "GCS buckets used for each environment Terraform state."
|
||||||
value = module.tf-gcs-environments.names
|
value = { for env, bucket in module.tf-gcs-environments : env => bucket.name }
|
||||||
}
|
}
|
||||||
|
|
||||||
output "environment_service_account_keys" {
|
output "environment_service_account_keys" {
|
||||||
description = "Service account keys used to run each environment Terraform modules."
|
description = "Service account keys used to run each environment Terraform modules."
|
||||||
sensitive = true
|
sensitive = true
|
||||||
value = module.tf-service-accounts.keys
|
value = { for env, sa in module.tf-service-accounts : env => sa.key }
|
||||||
}
|
}
|
||||||
|
|
||||||
output "environment_service_accounts" {
|
output "environment_service_accounts" {
|
||||||
description = "Service accounts used to run each environment Terraform modules."
|
description = "Service accounts used to run each environment Terraform modules."
|
||||||
value = module.tf-service-accounts.emails
|
value = { for env, sa in module.tf-service-accounts : env => sa.email }
|
||||||
}
|
}
|
||||||
|
|
||||||
output "audit_logs_bq_dataset" {
|
output "audit_logs_bq_dataset" {
|
||||||
|
|
|
@ -29,7 +29,7 @@ variable "billing_account_id" {
|
||||||
|
|
||||||
variable "environments" {
|
variable "environments" {
|
||||||
description = "Environment short names."
|
description = "Environment short names."
|
||||||
type = list(string)
|
type = set(string)
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "gcs_location" {
|
variable "gcs_location" {
|
||||||
|
|
|
@ -10,11 +10,11 @@ Specific modules also offer support for non-authoritative bindings (e.g. `google
|
||||||
|
|
||||||
## Foundational modules
|
## Foundational modules
|
||||||
|
|
||||||
- [folders](./folders)
|
- [folder](./folder)
|
||||||
- [log sinks](./logging-sinks)
|
- [log sinks](./logging-sinks)
|
||||||
- [organization](./organization)
|
- [organization](./organization)
|
||||||
- [project](./project)
|
- [project](./project)
|
||||||
- [service accounts](./iam-service-accounts)
|
- [service account](./iam-service-account)
|
||||||
|
|
||||||
## Networking modules
|
## Networking modules
|
||||||
|
|
||||||
|
|
|
@ -13,8 +13,7 @@ module "docker_artifact_registry" {
|
||||||
location = "europe-west1"
|
location = "europe-west1"
|
||||||
format = "DOCKER"
|
format = "DOCKER"
|
||||||
id = "myregistry"
|
id = "myregistry"
|
||||||
iam_roles = ["roles/artifactregistry.admin"]
|
iam = {
|
||||||
iam_members = {
|
|
||||||
"roles/artifactregistry.admin" = ["group:cicd@example.com"]
|
"roles/artifactregistry.admin" = ["group:cicd@example.com"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,8 +28,7 @@ module "docker_artifact_registry" {
|
||||||
| project_id | Registry project id. | <code title="">string</code> | ✓ | |
|
| project_id | Registry project id. | <code title="">string</code> | ✓ | |
|
||||||
| *description* | An optional description for the repository | <code title="">string</code> | | <code title="">Terraform-managed registry</code> |
|
| *description* | An optional description for the repository | <code title="">string</code> | | <code title="">Terraform-managed registry</code> |
|
||||||
| *format* | Repository format. One of DOCKER or UNSPECIFIED | <code title="">string</code> | | <code title="">DOCKER</code> |
|
| *format* | Repository format. One of DOCKER or UNSPECIFIED | <code title="">string</code> | | <code title="">DOCKER</code> |
|
||||||
| *iam_members* | Map of member lists used to set authoritative bindings, keyed by role. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *iam* | IAM bindings in {ROLE => [MEMBERS]} format. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *iam_roles* | List of roles used to set authoritative bindings. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
|
||||||
| *labels* | Labels to be attached to the registry. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
| *labels* | Labels to be attached to the registry. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
||||||
| *location* | Registry location. Use `gcloud beta artifacts locations list' to get valid values | <code title="">string</code> | | <code title=""></code> |
|
| *location* | Registry location. Use `gcloud beta artifacts locations list' to get valid values | <code title="">string</code> | | <code title=""></code> |
|
||||||
|
|
||||||
|
|
|
@ -26,10 +26,10 @@ resource "google_artifact_registry_repository" "registry" {
|
||||||
|
|
||||||
resource "google_artifact_registry_repository_iam_binding" "bindings" {
|
resource "google_artifact_registry_repository_iam_binding" "bindings" {
|
||||||
provider = google-beta
|
provider = google-beta
|
||||||
for_each = toset(var.iam_roles)
|
for_each = var.iam
|
||||||
project = var.project_id
|
project = var.project_id
|
||||||
location = google_artifact_registry_repository.registry.location
|
location = google_artifact_registry_repository.registry.location
|
||||||
repository = google_artifact_registry_repository.registry.name
|
repository = google_artifact_registry_repository.registry.name
|
||||||
role = each.value
|
role = each.key
|
||||||
members = lookup(var.iam_members, each.value, [])
|
members = each.value
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,18 +14,12 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
variable "iam_members" {
|
variable "iam" {
|
||||||
description = "Map of member lists used to set authoritative bindings, keyed by role."
|
description = "IAM bindings in {ROLE => [MEMBERS]} format."
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_roles" {
|
|
||||||
description = "List of roles used to set authoritative bindings."
|
|
||||||
type = list(string)
|
|
||||||
default = []
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "location" {
|
variable "location" {
|
||||||
description = "Registry location. Use `gcloud beta artifacts locations list' to get valid values"
|
description = "Registry location. Use `gcloud beta artifacts locations list' to get valid values"
|
||||||
type = string
|
type = string
|
||||||
|
|
|
@ -13,23 +13,21 @@ This module allows managing a single BigTable instance, including access configu
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
|
|
||||||
module "big-table-instance" {
|
module "bigtable-instance" {
|
||||||
source = "./modules/bigtable-instance"
|
source = "./modules/bigtable-instance"
|
||||||
project_id = "my-project"
|
project_id = "my-project"
|
||||||
name = "instance"
|
name = "instance"
|
||||||
cluster_id = "instance"
|
cluster_id = "instance"
|
||||||
instance_type = "PRODUCTION"
|
zone = "europe-west1-b"
|
||||||
tables = {
|
tables = {
|
||||||
test1 = { table_options = null },
|
test1 = null,
|
||||||
test2 = { table_options = {
|
test2 = {
|
||||||
split_keys = ["a", "b", "c"]
|
split_keys = ["a", "b", "c"]
|
||||||
column_family = null
|
column_family = null
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
iam_roles = ["viewer"]
|
iam = {
|
||||||
iam_members = {
|
"roles/bigtable.user" = ["user:viewer@testdomain.com"]
|
||||||
viewer = ["user:viewer@testdomain.com"]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -45,13 +43,12 @@ module "big-table-instance" {
|
||||||
| *cluster_id* | The ID of the Cloud Bigtable cluster. | <code title="">string</code> | | <code title="">europe-west1</code> |
|
| *cluster_id* | The ID of the Cloud Bigtable cluster. | <code title="">string</code> | | <code title="">europe-west1</code> |
|
||||||
| *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. | <code title=""></code> | | <code title="">true</code> |
|
| *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. | <code title=""></code> | | <code title="">true</code> |
|
||||||
| *display_name* | The human-readable display name of the Bigtable instance. | <code title=""></code> | | <code title="">null</code> |
|
| *display_name* | The human-readable display name of the Bigtable instance. | <code title=""></code> | | <code title="">null</code> |
|
||||||
| *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. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *iam* | IAM bindings for topic in {ROLE => [MEMBERS]} format. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *iam_roles* | Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
| *instance_type* | (deprecated) The instance type to create. One of 'DEVELOPMENT' or 'PRODUCTION'. | <code title="">string</code> | | <code title="">null</code> |
|
||||||
| *instance_type* | None | <code title="">string</code> | | <code title="">DEVELOPMENT</code> |
|
|
||||||
| *num_nodes* | The number of nodes in your Cloud Bigtable cluster. | <code title="">number</code> | | <code title="">1</code> |
|
| *num_nodes* | The number of nodes in your Cloud Bigtable cluster. | <code title="">number</code> | | <code title="">1</code> |
|
||||||
| *storage_type* | The storage type to use. | <code title="">string</code> | | <code title="">SSD</code> |
|
| *storage_type* | The storage type to use. | <code title="">string</code> | | <code title="">SSD</code> |
|
||||||
| *table_options_defaults* | Default option of tables created in the BigTable instance. | <code title="object({ split_keys = list(string) column_family = string })">object({...})</code> | | <code title="{ split_keys = [] column_family = null }">...</code> |
|
| *table_options_defaults* | Default option of tables created in the BigTable instance. | <code title="object({ split_keys = list(string) column_family = string })">object({...})</code> | | <code title="{ split_keys = [] column_family = null }">...</code> |
|
||||||
| *tables* | Tables to be created in the BigTable instance. | <code title="map(object({ table_options = object({ split_keys = list(string) column_family = string }) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
| *tables* | Tables to be created in the BigTable instance, options can be null. | <code title="map(object({ split_keys = list(string) column_family = string }))">map(object({...}))</code> | | <code title="">{}</code> |
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,7 @@
|
||||||
|
|
||||||
locals {
|
locals {
|
||||||
tables = {
|
tables = {
|
||||||
for k, v in var.tables : k => v.table_options != null ? v.table_options : var.table_options_defaults
|
for k, v in var.tables : k => v != null ? v : var.table_options_defaults
|
||||||
}
|
|
||||||
|
|
||||||
iam_roles_bindings = {
|
|
||||||
for k in var.iam_roles : k => lookup(var.iam_members, k, [])
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,11 +35,10 @@ resource "google_bigtable_instance" "default" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_bigtable_instance_iam_binding" "default" {
|
resource "google_bigtable_instance_iam_binding" "default" {
|
||||||
for_each = local.iam_roles_bindings
|
for_each = var.iam
|
||||||
|
|
||||||
project = var.project_id
|
project = var.project_id
|
||||||
instance = google_bigtable_instance.default.name
|
instance = google_bigtable_instance.default.name
|
||||||
role = "roles/bigtable.${each.key}"
|
role = each.key
|
||||||
members = each.value
|
members = each.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@ output "id" {
|
||||||
description = "An identifier for the resource with format projects/{{project}}/instances/{{name}}."
|
description = "An identifier for the resource with format projects/{{project}}/instances/{{name}}."
|
||||||
value = google_bigtable_instance.default.id
|
value = google_bigtable_instance.default.id
|
||||||
depends_on = [
|
depends_on = [
|
||||||
google_bigtable_instance_iam_binding,
|
google_bigtable_instance_iam_binding.default,
|
||||||
google_bigtable_table
|
google_bigtable_table.default
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,8 +27,8 @@ output "instance" {
|
||||||
description = "BigTable intance."
|
description = "BigTable intance."
|
||||||
value = google_bigtable_instance.default
|
value = google_bigtable_instance.default
|
||||||
depends_on = [
|
depends_on = [
|
||||||
google_bigtable_instance_iam_binding,
|
google_bigtable_instance_iam_binding.default,
|
||||||
google_bigtable_table
|
google_bigtable_table.default
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,18 +14,6 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
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 "cluster_id" {
|
variable "cluster_id" {
|
||||||
description = "The ID of the Cloud Bigtable cluster."
|
description = "The ID of the Cloud Bigtable cluster."
|
||||||
type = string
|
type = string
|
||||||
|
@ -42,10 +30,16 @@ variable "display_name" {
|
||||||
default = null
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "iam" {
|
||||||
|
description = "IAM bindings for topic in {ROLE => [MEMBERS]} format."
|
||||||
|
type = map(list(string))
|
||||||
|
default = {}
|
||||||
|
}
|
||||||
|
|
||||||
variable "instance_type" {
|
variable "instance_type" {
|
||||||
description = "The instance type to create. One of \"DEVELOPMENT\" or \"PRODUCTION\". Defaults to \"DEVELOPMENT\""
|
description = "(deprecated) The instance type to create. One of 'DEVELOPMENT' or 'PRODUCTION'."
|
||||||
type = string
|
type = string
|
||||||
default = "DEVELOPMENT"
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "name" {
|
variable "name" {
|
||||||
|
@ -71,12 +65,10 @@ variable "storage_type" {
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "tables" {
|
variable "tables" {
|
||||||
description = "Tables to be created in the BigTable instance."
|
description = "Tables to be created in the BigTable instance, options can be null."
|
||||||
type = map(object({
|
type = map(object({
|
||||||
table_options = object({
|
split_keys = list(string)
|
||||||
split_keys = list(string)
|
column_family = string
|
||||||
column_family = string
|
|
||||||
})
|
|
||||||
}))
|
}))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,8 +63,7 @@ module "cf-http" {
|
||||||
source_dir = "my-cf-source-folder"
|
source_dir = "my-cf-source-folder"
|
||||||
output_path = "bundle.zip"
|
output_path = "bundle.zip"
|
||||||
}
|
}
|
||||||
iam_roles = ["roles/cloudfunctions.invoker"]
|
iam = {
|
||||||
iam_members = {
|
|
||||||
"roles/cloudfunctions.invoker" = ["allUsers"]
|
"roles/cloudfunctions.invoker" = ["allUsers"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,8 +136,7 @@ module "cf-http" {
|
||||||
| *bucket_config* | Enable and configure auto-created bucket. Set fields to null to use defaults. | <code title="object({ location = string lifecycle_delete_age = number })">object({...})</code> | | <code title="">null</code> |
|
| *bucket_config* | Enable and configure auto-created bucket. Set fields to null to use defaults. | <code title="object({ location = string lifecycle_delete_age = number })">object({...})</code> | | <code title="">null</code> |
|
||||||
| *environment_variables* | Cloud function environment variables. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
| *environment_variables* | Cloud function environment variables. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
||||||
| *function_config* | Cloud function configuration. | <code title="object({ entry_point = string ingress_settings = string instances = number memory = number runtime = string timeout = number })">object({...})</code> | | <code title="{ entry_point = "main" ingress_settings = null instances = 1 memory = 256 runtime = "python37" timeout = 180 }">...</code> |
|
| *function_config* | Cloud function configuration. | <code title="object({ entry_point = string ingress_settings = string instances = number memory = number runtime = string timeout = number })">object({...})</code> | | <code title="{ entry_point = "main" ingress_settings = null instances = 1 memory = 256 runtime = "python37" timeout = 180 }">...</code> |
|
||||||
| *iam_members* | Map of member lists used to set authoritative bindings, keyed by role. Ignored for template use. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *iam* | IAM bindings for topic in {ROLE => [MEMBERS]} format. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *iam_roles* | List of roles used to set authoritative bindings. Ignored for template use. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
|
||||||
| *ingress_settings* | Control traffic that reaches the cloud function. Allowed values are ALLOW_ALL and ALLOW_INTERNAL_ONLY. | <code title="">string</code> | | <code title="">null</code> |
|
| *ingress_settings* | Control traffic that reaches the cloud function. Allowed values are ALLOW_ALL and ALLOW_INTERNAL_ONLY. | <code title="">string</code> | | <code title="">null</code> |
|
||||||
| *labels* | Resource labels | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
| *labels* | Resource labels | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
||||||
| *prefix* | Optional prefix used for resource names. | <code title="">string</code> | | <code title="">null</code> |
|
| *prefix* | Optional prefix used for resource names. | <code title="">string</code> | | <code title="">null</code> |
|
||||||
|
|
|
@ -95,12 +95,12 @@ resource "google_cloudfunctions_function" "function" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_cloudfunctions_function_iam_binding" "default" {
|
resource "google_cloudfunctions_function_iam_binding" "default" {
|
||||||
for_each = toset(var.iam_roles)
|
for_each = var.iam
|
||||||
project = var.project_id
|
project = var.project_id
|
||||||
region = var.region
|
region = var.region
|
||||||
cloud_function = google_cloudfunctions_function.function.name
|
cloud_function = google_cloudfunctions_function.function.name
|
||||||
role = each.value
|
role = each.key
|
||||||
members = try(var.iam_members[each.value], {})
|
members = each.value
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_storage_bucket" "bucket" {
|
resource "google_storage_bucket" "bucket" {
|
||||||
|
|
|
@ -42,18 +42,6 @@ variable "environment_variables" {
|
||||||
default = {}
|
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" {
|
variable "function_config" {
|
||||||
description = "Cloud function configuration."
|
description = "Cloud function configuration."
|
||||||
type = object({
|
type = object({
|
||||||
|
@ -74,6 +62,12 @@ variable "function_config" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "iam" {
|
||||||
|
description = "IAM bindings for topic in {ROLE => [MEMBERS]} format."
|
||||||
|
type = map(list(string))
|
||||||
|
default = {}
|
||||||
|
}
|
||||||
|
|
||||||
variable "ingress_settings" {
|
variable "ingress_settings" {
|
||||||
description = "Control traffic that reaches the cloud function. Allowed values are ALLOW_ALL and ALLOW_INTERNAL_ONLY."
|
description = "Control traffic that reaches the cloud function. Allowed values are ALLOW_ALL and ALLOW_INTERNAL_ONLY."
|
||||||
type = string
|
type = string
|
||||||
|
|
|
@ -184,8 +184,7 @@ 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. | <code title="object({ encrypt_boot = bool disk_encryption_key_raw = string kms_key_self_link = string })">object({...})</code> | | <code title="">null</code> |
|
| *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. | <code title="object({ encrypt_boot = bool disk_encryption_key_raw = string kms_key_self_link = string })">object({...})</code> | | <code title="">null</code> |
|
||||||
| *group* | Define this variable to create an instance group for instances. Disabled for template use. | <code title="object({ named_ports = map(number) })">object({...})</code> | | <code title="">null</code> |
|
| *group* | Define this variable to create an instance group for instances. Disabled for template use. | <code title="object({ named_ports = map(number) })">object({...})</code> | | <code title="">null</code> |
|
||||||
| *hostname* | Instance FQDN name. | <code title="">string</code> | | <code title="">null</code> |
|
| *hostname* | Instance FQDN name. | <code title="">string</code> | | <code title="">null</code> |
|
||||||
| *iam_members* | Map of member lists used to set authoritative bindings, keyed by role. Ignored for template use. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *iam* | IAM bindings in {ROLE => [MEMBERS]} format. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *iam_roles* | List of roles used to set authoritative bindings. Ignored for template use. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
|
||||||
| *instance_count* | Number of instances to create (only for non-template usage). | <code title="">number</code> | | <code title="">1</code> |
|
| *instance_count* | Number of instances to create (only for non-template usage). | <code title="">number</code> | | <code title="">1</code> |
|
||||||
| *instance_type* | Instance type. | <code title="">string</code> | | <code title="">f1-micro</code> |
|
| *instance_type* | Instance type. | <code title="">string</code> | | <code title="">f1-micro</code> |
|
||||||
| *labels* | Instance labels. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
| *labels* | Instance labels. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
||||||
|
|
|
@ -25,9 +25,9 @@ locals {
|
||||||
for pair in setproduct(keys(local.names), keys(local.attached_disks)) :
|
for pair in setproduct(keys(local.names), keys(local.attached_disks)) :
|
||||||
"${pair[0]}-${pair[1]}" => { disk_name = pair[1], name = pair[0] }
|
"${pair[0]}-${pair[1]}" => { disk_name = pair[1], name = pair[0] }
|
||||||
}
|
}
|
||||||
iam_roles = var.use_instance_template ? {} : {
|
iam_members = var.use_instance_template ? {} : {
|
||||||
for pair in setproduct(var.iam_roles, keys(local.names)) :
|
for pair in setproduct(keys(var.iam), keys(local.names)) :
|
||||||
"${pair.0}/${pair.1}" => { role = pair.0, name = pair.1 }
|
"${pair.0}/${pair.1}" => { role = pair.0, name = pair.1, members = var.iam[pair.0] }
|
||||||
}
|
}
|
||||||
names = (
|
names = (
|
||||||
var.use_instance_template ? { (var.name) = 0 } : {
|
var.use_instance_template ? { (var.name) = 0 } : {
|
||||||
|
@ -196,12 +196,12 @@ resource "google_compute_instance" "default" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_compute_instance_iam_binding" "default" {
|
resource "google_compute_instance_iam_binding" "default" {
|
||||||
for_each = local.iam_roles
|
for_each = local.iam_members
|
||||||
project = var.project_id
|
project = var.project_id
|
||||||
zone = local.zones[each.value.name]
|
zone = local.zones[each.value.name]
|
||||||
instance_name = each.value.name
|
instance_name = each.value.name
|
||||||
role = each.value.role
|
role = each.value.role
|
||||||
members = lookup(var.iam_members, each.value.role, [])
|
members = each.value.members
|
||||||
depends_on = [google_compute_instance.default]
|
depends_on = [google_compute_instance.default]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -90,18 +90,12 @@ variable "hostname" {
|
||||||
default = null
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_members" {
|
variable "iam" {
|
||||||
description = "Map of member lists used to set authoritative bindings, keyed by role. Ignored for template use."
|
description = "IAM bindings in {ROLE => [MEMBERS]} format."
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_roles" {
|
|
||||||
description = "List of roles used to set authoritative bindings. Ignored for template use."
|
|
||||||
type = list(string)
|
|
||||||
default = []
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "instance_count" {
|
variable "instance_count" {
|
||||||
description = "Number of instances to create (only for non-template usage)."
|
description = "Number of instances to create (only for non-template usage)."
|
||||||
type = number
|
type = number
|
||||||
|
|
|
@ -9,8 +9,7 @@ module "container_registry" {
|
||||||
source = "../../modules/container-registry"
|
source = "../../modules/container-registry"
|
||||||
project_id = "myproject"
|
project_id = "myproject"
|
||||||
location = "EU"
|
location = "EU"
|
||||||
iam_roles = ["roles/storage.admin"]
|
iam = {
|
||||||
iam_members = {
|
|
||||||
"roles/storage.admin" = ["group:cicd@example.com"]
|
"roles/storage.admin" = ["group:cicd@example.com"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,8 +21,7 @@ module "container_registry" {
|
||||||
| name | description | type | required | default |
|
| name | description | type | required | default |
|
||||||
|---|---|:---: |:---:|:---:|
|
|---|---|:---: |:---:|:---:|
|
||||||
| project_id | Registry project id. | <code title="">string</code> | ✓ | |
|
| project_id | Registry project id. | <code title="">string</code> | ✓ | |
|
||||||
| *iam_members* | Map of member lists used to set authoritative bindings, keyed by role. | <code title="map(list(string))">map(list(string))</code> | | <code title="">null</code> |
|
| *iam* | IAM bindings for topic in {ROLE => [MEMBERS]} format. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *iam_roles* | List of roles used to set authoritative bindings. | <code title="list(string)">list(string)</code> | | <code title="">null</code> |
|
|
||||||
| *location* | Registry location. Can be US, EU, ASIA or empty | <code title="">string</code> | | <code title=""></code> |
|
| *location* | Registry location. Can be US, EU, ASIA or empty | <code title="">string</code> | | <code title=""></code> |
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
|
|
@ -20,8 +20,8 @@ resource "google_container_registry" "registry" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_storage_bucket_iam_binding" "bindings" {
|
resource "google_storage_bucket_iam_binding" "bindings" {
|
||||||
for_each = toset(var.iam_roles)
|
for_each = var.iam
|
||||||
bucket = google_container_registry.registry.id
|
bucket = google_container_registry.registry.id
|
||||||
role = each.value
|
role = each.key
|
||||||
members = lookup(var.iam_members, each.value, [])
|
members = each.value
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,16 +14,10 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
variable "iam_members" {
|
variable "iam" {
|
||||||
description = "Map of member lists used to set authoritative bindings, keyed by role."
|
description = "IAM bindings for topic in {ROLE => [MEMBERS]} format."
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = null
|
default = {}
|
||||||
}
|
|
||||||
|
|
||||||
variable "iam_roles" {
|
|
||||||
description = "List of roles used to set authoritative bindings."
|
|
||||||
type = list(string)
|
|
||||||
default = null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "location" {
|
variable "location" {
|
||||||
|
|
|
@ -37,7 +37,7 @@ module "private-dns" {
|
||||||
| *peer_network* | Peering network self link, only valid for 'peering' zone types. | <code title="">string</code> | | <code title="">null</code> |
|
| *peer_network* | Peering network self link, only valid for 'peering' zone types. | <code title="">string</code> | | <code title="">null</code> |
|
||||||
| *recordsets* | List of DNS record objects to manage. | <code title="list(object({ name = string type = string ttl = number records = list(string) }))">list(object({...}))</code> | | <code title="">[]</code> |
|
| *recordsets* | List of DNS record objects to manage. | <code title="list(object({ name = string type = string ttl = number records = list(string) }))">list(object({...}))</code> | | <code title="">[]</code> |
|
||||||
| *service_directory_namespace* | Service directory namespace id (URL), only valid for 'service-directory' zone types. | <code title="">string</code> | | <code title="">null</code> |
|
| *service_directory_namespace* | Service directory namespace id (URL), only valid for 'service-directory' zone types. | <code title="">string</code> | | <code title="">null</code> |
|
||||||
| *type* | Type of zone to create, valid values are 'public', 'private', 'forwarding', 'peering', 'service-directory'. | <code title="">string</code> | | <code title="">private</code> |
|
| *type* | Type of zone to create, valid values are 'public', 'private', 'forwarding', 'peering', 'service-directory'. | <code title="">string</code> | | <code title="private validation { condition = contains(["public", "private", "forwarding", "peering", "service-directory"], var.type) error_message = "Zone must be one of 'public', 'private', 'forwarding', 'peering', 'service-directory'." }">...</code> |
|
||||||
| *zone_create* | Create zone. When set to false, uses a data source to reference existing zone. | <code title="">bool</code> | | <code title="">true</code> |
|
| *zone_create* | Create zone. When set to false, uses a data source to reference existing zone. | <code title="">bool</code> | | <code title="">true</code> |
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Copyright 2018 Google LLC
|
* Copyright 2020 Google LLC
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -22,10 +22,10 @@ locals {
|
||||||
zone = (
|
zone = (
|
||||||
var.zone_create
|
var.zone_create
|
||||||
? try(
|
? try(
|
||||||
google_dns_managed_zone.non-public.0, try(
|
google_dns_managed_zone.non-public.0, try(
|
||||||
google_dns_managed_zone.public.0, null
|
google_dns_managed_zone.public.0, null
|
||||||
)
|
|
||||||
)
|
)
|
||||||
|
)
|
||||||
: try(data.google_dns_managed_zone.public.0, null)
|
: try(data.google_dns_managed_zone.public.0, null)
|
||||||
)
|
)
|
||||||
dns_keys = try(
|
dns_keys = try(
|
||||||
|
@ -34,12 +34,12 @@ locals {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_dns_managed_zone" "non-public" {
|
resource "google_dns_managed_zone" "non-public" {
|
||||||
count = (var.zone_create && var.type != "public" ) ? 1 : 0
|
count = (var.zone_create && var.type != "public") ? 1 : 0
|
||||||
provider = google-beta
|
provider = google-beta
|
||||||
project = var.project_id
|
project = var.project_id
|
||||||
name = var.name
|
name = var.name
|
||||||
dns_name = var.domain
|
dns_name = var.domain
|
||||||
description = "Terraform-managed zone."
|
description = var.description
|
||||||
visibility = "private"
|
visibility = "private"
|
||||||
|
|
||||||
dynamic forwarding_config {
|
dynamic forwarding_config {
|
||||||
|
@ -94,12 +94,12 @@ resource "google_dns_managed_zone" "non-public" {
|
||||||
}
|
}
|
||||||
|
|
||||||
data "google_dns_managed_zone" "public" {
|
data "google_dns_managed_zone" "public" {
|
||||||
count = var.zone_create ? 0 : 1
|
count = var.zone_create ? 0 : 1
|
||||||
name = var.name
|
name = var.name
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_dns_managed_zone" "public" {
|
resource "google_dns_managed_zone" "public" {
|
||||||
count = (var.zone_create && var.type == "public" ) ? 1 : 0
|
count = (var.zone_create && var.type == "public") ? 1 : 0
|
||||||
project = var.project_id
|
project = var.project_id
|
||||||
name = var.name
|
name = var.name
|
||||||
dns_name = var.domain
|
dns_name = var.domain
|
||||||
|
@ -132,7 +132,7 @@ resource "google_dns_managed_zone" "public" {
|
||||||
}
|
}
|
||||||
|
|
||||||
data "google_dns_keys" "dns_keys" {
|
data "google_dns_keys" "dns_keys" {
|
||||||
count = var.zone_create && ( var.dnssec_config == {} || var.type != "public" ) ? 0 : 1
|
count = var.zone_create && (var.dnssec_config == {} || var.type != "public") ? 0 : 1
|
||||||
managed_zone = local.zone.id
|
managed_zone = local.zone.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -97,6 +97,10 @@ variable "type" {
|
||||||
description = "Type of zone to create, valid values are 'public', 'private', 'forwarding', 'peering', 'service-directory'."
|
description = "Type of zone to create, valid values are 'public', 'private', 'forwarding', 'peering', 'service-directory'."
|
||||||
type = string
|
type = string
|
||||||
default = "private"
|
default = "private"
|
||||||
|
validation {
|
||||||
|
condition = contains(["public", "private", "forwarding", "peering", "service-directory"], var.type)
|
||||||
|
error_message = "Zone must be one of 'public', 'private', 'forwarding', 'peering', 'service-directory'."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "zone_create" {
|
variable "zone_create" {
|
||||||
|
@ -106,3 +110,4 @@ variable "zone_create" {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
terraform {
|
terraform {
|
||||||
required_version = ">= 0.12.20"
|
required_version = ">= 0.13.0"
|
||||||
required_providers {
|
required_providers {
|
||||||
google = "~> 3.10"
|
google = "~> 3.10"
|
||||||
google-beta = "~> 3.20"
|
google-beta = "~> 3.20"
|
||||||
|
|
|
@ -12,10 +12,8 @@ module "endpoint" {
|
||||||
project_id = "my-project"
|
project_id = "my-project"
|
||||||
service_name = "YOUR-API.endpoints.YOUR-PROJECT-ID.cloud.goog"
|
service_name = "YOUR-API.endpoints.YOUR-PROJECT-ID.cloud.goog"
|
||||||
openapi_config = { "yaml_path" = "openapi.yaml" }
|
openapi_config = { "yaml_path" = "openapi.yaml" }
|
||||||
grpc_config = null
|
iam = {
|
||||||
iam_roles = ["servicemanagement.serviceController"]
|
"servicemanagement.serviceController" = ["serviceAccount:123456890-compute@developer.gserviceaccount.com"]
|
||||||
iam_members = {
|
|
||||||
"servicemanagement.serviceController" = ["serviceAccount:PROJECT_NUMBER-compute@developer.gserviceaccount.com"]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -27,11 +25,10 @@ module "endpoint" {
|
||||||
|
|
||||||
| name | description | type | required | default |
|
| name | description | type | required | default |
|
||||||
|---|---|:---: |:---:|:---:|
|
|---|---|:---: |:---:|:---:|
|
||||||
| grpc_config | The configuration for a gRPC enpoint. Either this or openapi_config must be specified. | <code title="object({ yaml_path = string protoc_output_path = string })">object({...})</code> | ✓ | |
|
|
||||||
| openapi_config | The configuration for an OpenAPI endopoint. Either this or grpc_config must be specified. | <code title="object({ yaml_path = string })">object({...})</code> | ✓ | |
|
| openapi_config | The configuration for an OpenAPI endopoint. Either this or grpc_config must be specified. | <code title="object({ yaml_path = string })">object({...})</code> | ✓ | |
|
||||||
| service_name | The name of the service. Usually of the form '$apiname.endpoints.$projectid.cloud.goog'. | <code title="">string</code> | ✓ | |
|
| service_name | The name of the service. Usually of the form '$apiname.endpoints.$projectid.cloud.goog'. | <code title="">string</code> | ✓ | |
|
||||||
| *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. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *grpc_config* | The configuration for a gRPC enpoint. Either this or openapi_config must be specified. | <code title="object({ yaml_path = string protoc_output_path = string })">object({...})</code> | | <code title="">null</code> |
|
||||||
| *iam_roles* | Authoritative for a given role. Updates the IAM policy to grant a role to a list of members. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
| *iam* | IAM bindings for topic in {ROLE => [MEMBERS]} format. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *project_id* | The project ID that the service belongs to. | <code title="">string</code> | | <code title="">null</code> |
|
| *project_id* | The project ID that the service belongs to. | <code title="">string</code> | | <code title="">null</code> |
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
|
|
@ -14,12 +14,6 @@
|
||||||
* limitations under the License.
|
* 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" {
|
resource "google_endpoints_service" "default" {
|
||||||
project = var.project_id
|
project = var.project_id
|
||||||
service_name = var.service_name
|
service_name = var.service_name
|
||||||
|
@ -29,8 +23,8 @@ resource "google_endpoints_service" "default" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_endpoints_service_iam_binding" "default" {
|
resource "google_endpoints_service_iam_binding" "default" {
|
||||||
for_each = local.iam_roles_bindings
|
for_each = var.iam
|
||||||
service_name = google_endpoints_service.default.service_name
|
service_name = google_endpoints_service.default.service_name
|
||||||
role = "roles/${each.key}"
|
role = each.key
|
||||||
members = each.value
|
members = each.value
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,27 +16,22 @@
|
||||||
|
|
||||||
variable "grpc_config" {
|
variable "grpc_config" {
|
||||||
description = "The configuration for a gRPC enpoint. Either this or openapi_config must be specified."
|
description = "The configuration for a gRPC enpoint. Either this or openapi_config must be specified."
|
||||||
type = object({
|
type = object({
|
||||||
yaml_path = string
|
yaml_path = string
|
||||||
protoc_output_path = string
|
protoc_output_path = string
|
||||||
})
|
})
|
||||||
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_roles" {
|
variable "iam" {
|
||||||
description = "Authoritative for a given role. Updates the IAM policy to grant a role to a list of members."
|
description = "IAM bindings for topic in {ROLE => [MEMBERS]} format."
|
||||||
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))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "openapi_config" {
|
variable "openapi_config" {
|
||||||
description = "The configuration for an OpenAPI endopoint. Either this or grpc_config must be specified."
|
description = "The configuration for an OpenAPI endopoint. Either this or grpc_config must be specified."
|
||||||
type = object({
|
type = object({
|
||||||
yaml_path = string
|
yaml_path = string
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
# Google Cloud Folder Module
|
# Google Cloud Folder Module
|
||||||
|
|
||||||
This module allow creation and management of sets of folders sharing a common parent, and their individual IAM bindings. It also allows setting a common set of organization policies on all folders.
|
This module allows the creation and management of folders together with their individual IAM bindings and organization policies.
|
||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
|
@ -8,16 +8,11 @@ This module allow creation and management of sets of folders sharing a common pa
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
module "folder" {
|
module "folder" {
|
||||||
source = "./modules/folders"
|
source = "./modules/folder"
|
||||||
parent = "organizations/1234567890"
|
parent = "organizations/1234567890"
|
||||||
names = ["Folder one", "Folder two"]
|
name = "Folder name"
|
||||||
iam_members = {
|
iam = {
|
||||||
"Folder one" = {
|
"roles/owner" = ["group:users@example.com"]
|
||||||
"roles/owner" = ["group:users@example.com"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iam_roles = {
|
|
||||||
"Folder one" = ["roles/owner"]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -26,9 +21,9 @@ module "folder" {
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
module "folder" {
|
module "folder" {
|
||||||
source = "./modules/folders"
|
source = "./modules/folder"
|
||||||
parent = "organizations/1234567890"
|
parent = "organizations/1234567890"
|
||||||
names = ["Folder one", "Folder two"]
|
name = "Folder name"
|
||||||
policy_boolean = {
|
policy_boolean = {
|
||||||
"constraints/compute.disableGuestAttributesAccess" = true
|
"constraints/compute.disableGuestAttributesAccess" = true
|
||||||
"constraints/compute.skipDefaultNetworkCreation" = true
|
"constraints/compute.skipDefaultNetworkCreation" = true
|
||||||
|
@ -49,10 +44,9 @@ module "folder" {
|
||||||
|
|
||||||
| name | description | type | required | default |
|
| name | description | type | required | default |
|
||||||
|---|---|:---: |:---:|:---:|
|
|---|---|:---: |:---:|:---:|
|
||||||
| parent | Parent in folders/folder_id or organizations/org_id format. | <code title="">string</code> | ✓ | |
|
| name | Folder name. | <code title="">string</code> | ✓ | |
|
||||||
| *iam_members* | List of IAM members keyed by folder name and role. | <code title="map(map(list(string)))">map(map(list(string)))</code> | | <code title="">null</code> |
|
| parent | Parent in folders/folder_id or organizations/org_id format. | <code title="string validation { condition = can(regex("(organizations|folders)/[0-9]+", var.parent)) error_message = "Parent must be of the form folders/folder_id or organizations/organization_id." }">string</code> | ✓ | |
|
||||||
| *iam_roles* | List of IAM roles keyed by folder name. | <code title="map(list(string))">map(list(string))</code> | | <code title="">null</code> |
|
| *iam* | IAM bindings in {ROLE => [MEMBERS]} format. | <code title="map(set(string))">map(set(string))</code> | | <code title="">{}</code> |
|
||||||
| *names* | Folder names. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
|
||||||
| *policy_boolean* | Map of boolean org policies and enforcement value, set value to null for policy restore. | <code title="map(bool)">map(bool)</code> | | <code title="">{}</code> |
|
| *policy_boolean* | Map of boolean org policies and enforcement value, set value to null for policy restore. | <code title="map(bool)">map(bool)</code> | | <code title="">{}</code> |
|
||||||
| *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. | <code title="map(object({ inherit_from_parent = bool suggested_value = string status = bool values = list(string) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
| *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. | <code title="map(object({ inherit_from_parent = bool suggested_value = string status = bool values = list(string) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
||||||
|
|
||||||
|
@ -60,12 +54,7 @@ module "folder" {
|
||||||
|
|
||||||
| name | description | sensitive |
|
| name | description | sensitive |
|
||||||
|---|---|:---:|
|
|---|---|:---:|
|
||||||
| folder | Folder resource (for single use). | |
|
| folder | Folder resource. | |
|
||||||
| folders | Folder resources. | |
|
| id | Folder id. | |
|
||||||
| id | Folder id (for single use). | |
|
| name | Folder name. | |
|
||||||
| ids | Folder ids. | |
|
|
||||||
| ids_list | List of folder ids. | |
|
|
||||||
| name | Folder name (for single use). | |
|
|
||||||
| names | Folder names. | |
|
|
||||||
| names_list | List of folder names. | |
|
|
||||||
<!-- END TFDOC -->
|
<!-- END TFDOC -->
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Copyright 2018 Google LLC
|
* Copyright 2020 Google LLC
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -14,63 +14,26 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
locals {
|
|
||||||
folders = (
|
|
||||||
local.has_folders
|
|
||||||
? [for name in var.names : google_folder.folders[name]]
|
|
||||||
: []
|
|
||||||
)
|
|
||||||
# needed when destroying
|
|
||||||
has_folders = length(google_folder.folders) > 0
|
|
||||||
iam_pairs = var.iam_roles == null ? [] : flatten([
|
|
||||||
for name, roles in var.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.iam_members == null ? {} : var.iam_members
|
|
||||||
policy_boolean_pairs = {
|
|
||||||
for pair in setproduct(var.names, keys(var.policy_boolean)) :
|
|
||||||
"${pair.0}-${pair.1}" => {
|
|
||||||
folder = pair.0,
|
|
||||||
policy = pair.1,
|
|
||||||
policy_data = var.policy_boolean[pair.1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
policy_list_pairs = {
|
|
||||||
for pair in setproduct(var.names, keys(var.policy_list)) :
|
|
||||||
"${pair.0}-${pair.1}" => {
|
|
||||||
folder = pair.0,
|
|
||||||
policy = pair.1,
|
|
||||||
policy_data = var.policy_list[pair.1]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "google_folder" "folders" {
|
resource "google_folder" "folder" {
|
||||||
for_each = toset(var.names)
|
display_name = var.name
|
||||||
display_name = each.value
|
|
||||||
parent = var.parent
|
parent = var.parent
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_folder_iam_binding" "authoritative" {
|
resource "google_folder_iam_binding" "authoritative" {
|
||||||
for_each = local.iam_keypairs
|
for_each = var.iam
|
||||||
folder = google_folder.folders[each.value.name].name
|
folder = google_folder.folder.name
|
||||||
role = each.value.role
|
role = each.key
|
||||||
members = lookup(
|
members = each.value
|
||||||
lookup(local.iam_members, each.value.name, {}), each.value.role, []
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_folder_organization_policy" "boolean" {
|
resource "google_folder_organization_policy" "boolean" {
|
||||||
for_each = local.policy_boolean_pairs
|
for_each = var.policy_boolean
|
||||||
folder = google_folder.folders[each.value.folder].id
|
folder = google_folder.folder.name
|
||||||
constraint = each.value.policy
|
constraint = each.key
|
||||||
|
|
||||||
dynamic boolean_policy {
|
dynamic boolean_policy {
|
||||||
for_each = each.value.policy_data == null ? [] : [each.value.policy_data]
|
for_each = each.value == null ? [] : [each.value]
|
||||||
iterator = policy
|
iterator = policy
|
||||||
content {
|
content {
|
||||||
enforced = policy.value
|
enforced = policy.value
|
||||||
|
@ -78,7 +41,7 @@ resource "google_folder_organization_policy" "boolean" {
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic restore_policy {
|
dynamic restore_policy {
|
||||||
for_each = each.value.policy_data == null ? [""] : []
|
for_each = each.value == null ? [""] : []
|
||||||
content {
|
content {
|
||||||
default = true
|
default = true
|
||||||
}
|
}
|
||||||
|
@ -86,12 +49,12 @@ resource "google_folder_organization_policy" "boolean" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_folder_organization_policy" "list" {
|
resource "google_folder_organization_policy" "list" {
|
||||||
for_each = local.policy_list_pairs
|
for_each = var.policy_list
|
||||||
folder = google_folder.folders[each.value.folder].id
|
folder = google_folder.folder.name
|
||||||
constraint = each.value.policy
|
constraint = each.key
|
||||||
|
|
||||||
dynamic list_policy {
|
dynamic list_policy {
|
||||||
for_each = each.value.policy_data.status == null ? [] : [each.value.policy_data]
|
for_each = each.value.status == null ? [] : [each.value]
|
||||||
iterator = policy
|
iterator = policy
|
||||||
content {
|
content {
|
||||||
inherit_from_parent = policy.value.inherit_from_parent
|
inherit_from_parent = policy.value.inherit_from_parent
|
||||||
|
@ -130,7 +93,7 @@ resource "google_folder_organization_policy" "list" {
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic restore_policy {
|
dynamic restore_policy {
|
||||||
for_each = each.value.policy_data.status == null ? [true] : []
|
for_each = each.value.status == null ? [true] : []
|
||||||
content {
|
content {
|
||||||
default = true
|
default = true
|
||||||
}
|
}
|
|
@ -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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
output "folder" {
|
||||||
|
description = "Folder resource."
|
||||||
|
value = google_folder.folder
|
||||||
|
}
|
||||||
|
|
||||||
|
output "id" {
|
||||||
|
description = "Folder id."
|
||||||
|
value = google_folder.folder.name
|
||||||
|
depends_on = [
|
||||||
|
google_folder_iam_binding.authoritative,
|
||||||
|
google_folder_organization_policy.boolean,
|
||||||
|
google_folder_organization_policy.list
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
output "name" {
|
||||||
|
description = "Folder name."
|
||||||
|
value = google_folder.folder.display_name
|
||||||
|
}
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Copyright 2018 Google LLC
|
* Copyright 2020 Google LLC
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -14,27 +14,24 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
variable "iam_members" {
|
variable "iam" {
|
||||||
description = "List of IAM members keyed by folder name and role."
|
description = "IAM bindings in {ROLE => [MEMBERS]} format."
|
||||||
type = map(map(list(string)))
|
type = map(set(string))
|
||||||
default = null
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_roles" {
|
variable "name" {
|
||||||
description = "List of IAM roles keyed by folder name."
|
description = "Folder name."
|
||||||
type = map(list(string))
|
type = string
|
||||||
default = null
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "names" {
|
|
||||||
description = "Folder names."
|
|
||||||
type = list(string)
|
|
||||||
default = []
|
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "parent" {
|
variable "parent" {
|
||||||
description = "Parent in folders/folder_id or organizations/org_id format."
|
description = "Parent in folders/folder_id or organizations/org_id format."
|
||||||
type = string
|
type = string
|
||||||
|
validation {
|
||||||
|
condition = can(regex("(organizations|folders)/[0-9]+", var.parent))
|
||||||
|
error_message = "Parent must be of the form folders/folder_id or organizations/organization_id."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "policy_boolean" {
|
variable "policy_boolean" {
|
|
@ -15,5 +15,5 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
terraform {
|
terraform {
|
||||||
required_version = ">= 0.12.6"
|
required_version = ">= 0.13.0"
|
||||||
}
|
}
|
|
@ -36,10 +36,9 @@ module "folders-unit" {
|
||||||
| short_name | Short name used as GCS bucket and service account prefixes, do not use capital letters or spaces. | <code title="">string</code> | ✓ | |
|
| short_name | Short name used as GCS bucket and service account prefixes, do not use capital letters or spaces. | <code title="">string</code> | ✓ | |
|
||||||
| *environments* | Unit environments short names. | <code title="map(string)">map(string)</code> | | <code title="{ non-prod = "Non production" prod = "Production" }">...</code> |
|
| *environments* | Unit environments short names. | <code title="map(string)">map(string)</code> | | <code title="{ non-prod = "Non production" prod = "Production" }">...</code> |
|
||||||
| *gcs_defaults* | Defaults use for the state GCS buckets. | <code title="map(string)">map(string)</code> | | <code title="{ location = "EU" storage_class = "MULTI_REGIONAL" }">...</code> |
|
| *gcs_defaults* | Defaults use for the state GCS buckets. | <code title="map(string)">map(string)</code> | | <code title="{ location = "EU" storage_class = "MULTI_REGIONAL" }">...</code> |
|
||||||
|
| *iam* | IAM bindings for the top-level folder in {ROLE => [MEMBERS]} format. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *iam_billing_config* | Grant billing user role to service accounts, defaults to granting on the billing account. | <code title="object({ grant = bool target_org = bool })">object({...})</code> | | <code title="{ grant = true target_org = false }">...</code> |
|
| *iam_billing_config* | Grant billing user role to service accounts, defaults to granting on the billing account. | <code title="object({ grant = bool target_org = bool })">object({...})</code> | | <code title="{ grant = true target_org = false }">...</code> |
|
||||||
| *iam_enviroment_roles* | IAM roles granted to the environment service account on the environment sub-folder. | <code title="list(string)">list(string)</code> | | <code title="[ "roles/compute.networkAdmin", "roles/owner", "roles/resourcemanager.folderAdmin", "roles/resourcemanager.projectCreator", ]">...</code> |
|
| *iam_enviroment_roles* | IAM roles granted to the environment service account on the environment sub-folder. | <code title="list(string)">list(string)</code> | | <code title="[ "roles/compute.networkAdmin", "roles/owner", "roles/resourcemanager.folderAdmin", "roles/resourcemanager.projectCreator", ]">...</code> |
|
||||||
| *iam_members* | IAM members for roles applied on the unit folder. | <code title="map(list(string))">map(list(string))</code> | | <code title="">null</code> |
|
|
||||||
| *iam_roles* | IAM roles applied on the unit folder. | <code title="list(string)">list(string)</code> | | <code title="">null</code> |
|
|
||||||
| *iam_xpn_config* | Grant Shared VPC creation roles to service accounts, defaults to granting at folder level. | <code title="object({ grant = bool target_org = bool })">object({...})</code> | | <code title="{ grant = true target_org = false }">...</code> |
|
| *iam_xpn_config* | Grant Shared VPC creation roles to service accounts, defaults to granting at folder level. | <code title="object({ grant = bool target_org = bool })">object({...})</code> | | <code title="{ grant = true target_org = false }">...</code> |
|
||||||
| *prefix* | Optional prefix used for GCS bucket names to ensure uniqueness. | <code title="">string</code> | | <code title="">null</code> |
|
| *prefix* | Optional prefix used for GCS bucket names to ensure uniqueness. | <code title="">string</code> | | <code title="">null</code> |
|
||||||
| *service_account_keys* | Generate and store service account keys in the state file. | <code title="">bool</code> | | <code title="">false</code> |
|
| *service_account_keys* | Generate and store service account keys in the state file. | <code title="">bool</code> | | <code title="">false</code> |
|
||||||
|
|
|
@ -16,12 +16,7 @@
|
||||||
|
|
||||||
locals {
|
locals {
|
||||||
folder_roles = concat(var.iam_enviroment_roles, local.sa_xpn_folder_roles)
|
folder_roles = concat(var.iam_enviroment_roles, local.sa_xpn_folder_roles)
|
||||||
iam_members = var.iam_members == null ? {} : var.iam_members
|
iam = var.iam == null ? {} : var.iam
|
||||||
iam_roles = var.iam_roles == null ? [] : var.iam_roles
|
|
||||||
unit_iam_bindings = {
|
|
||||||
for role in local.iam_roles :
|
|
||||||
role => lookup(local.iam_members, role, [])
|
|
||||||
}
|
|
||||||
folder_iam_service_account_bindings = {
|
folder_iam_service_account_bindings = {
|
||||||
for pair in setproduct(keys(var.environments), local.folder_roles) :
|
for pair in setproduct(keys(var.environments), local.folder_roles) :
|
||||||
"${pair.0}-${pair.1}" => { environment = pair.0, role = pair.1 }
|
"${pair.0}-${pair.1}" => { environment = pair.0, role = pair.1 }
|
||||||
|
|
|
@ -34,7 +34,7 @@ resource "google_folder" "environment" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_folder_iam_binding" "unit" {
|
resource "google_folder_iam_binding" "unit" {
|
||||||
for_each = local.unit_iam_bindings
|
for_each = var.iam
|
||||||
folder = google_folder.unit.name
|
folder = google_folder.unit.name
|
||||||
role = each.key
|
role = each.key
|
||||||
members = each.value
|
members = each.value
|
||||||
|
@ -92,9 +92,9 @@ resource "google_storage_bucket" "tfstate" {
|
||||||
var.prefix == null ? "" : "${var.prefix}-",
|
var.prefix == null ? "" : "${var.prefix}-",
|
||||||
"${var.short_name}-${each.key}-tf"
|
"${var.short_name}-${each.key}-tf"
|
||||||
])
|
])
|
||||||
location = var.gcs_defaults.location
|
location = var.gcs_defaults.location
|
||||||
storage_class = var.gcs_defaults.storage_class
|
storage_class = var.gcs_defaults.storage_class
|
||||||
force_destroy = false
|
force_destroy = false
|
||||||
uniform_bucket_level_access = true
|
uniform_bucket_level_access = true
|
||||||
versioning {
|
versioning {
|
||||||
enabled = true
|
enabled = true
|
||||||
|
|
|
@ -42,6 +42,12 @@ variable "gcs_defaults" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
variable "iam" {
|
||||||
|
description = "IAM bindings for the top-level folder in {ROLE => [MEMBERS]} format."
|
||||||
|
type = map(list(string))
|
||||||
|
default = {}
|
||||||
|
}
|
||||||
|
|
||||||
variable "iam_billing_config" {
|
variable "iam_billing_config" {
|
||||||
description = "Grant billing user role to service accounts, defaults to granting on the billing account."
|
description = "Grant billing user role to service accounts, defaults to granting on the billing account."
|
||||||
type = object({
|
type = object({
|
||||||
|
@ -65,18 +71,6 @@ variable "iam_enviroment_roles" {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_members" {
|
|
||||||
description = "IAM members for roles applied on the unit folder."
|
|
||||||
type = map(list(string))
|
|
||||||
default = null
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "iam_roles" {
|
|
||||||
description = "IAM roles applied on the unit folder."
|
|
||||||
type = list(string)
|
|
||||||
default = null
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "iam_xpn_config" {
|
variable "iam_xpn_config" {
|
||||||
description = "Grant Shared VPC creation roles to service accounts, defaults to granting at folder level."
|
description = "Grant Shared VPC creation roles to service accounts, defaults to granting at folder level."
|
||||||
type = object({
|
type = object({
|
||||||
|
|
|
@ -1,78 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright 2018 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 "folder" {
|
|
||||||
description = "Folder resource (for single use)."
|
|
||||||
value = local.has_folders ? local.folders[0] : null
|
|
||||||
}
|
|
||||||
|
|
||||||
output "id" {
|
|
||||||
description = "Folder id (for single use)."
|
|
||||||
value = local.has_folders ? local.folders[0].name : null
|
|
||||||
depends_on = [
|
|
||||||
google_folder_iam_binding.authoritative,
|
|
||||||
google_folder_organization_policy.boolean,
|
|
||||||
google_folder_organization_policy.list
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
output "name" {
|
|
||||||
description = "Folder name (for single use)."
|
|
||||||
value = local.has_folders ? local.folders[0].display_name : null
|
|
||||||
}
|
|
||||||
|
|
||||||
output "folders" {
|
|
||||||
description = "Folder resources."
|
|
||||||
value = local.folders
|
|
||||||
}
|
|
||||||
|
|
||||||
output "ids" {
|
|
||||||
description = "Folder ids."
|
|
||||||
value = (
|
|
||||||
local.has_folders
|
|
||||||
? zipmap(var.names, [for f in local.folders : f.name])
|
|
||||||
: {}
|
|
||||||
)
|
|
||||||
depends_on = [
|
|
||||||
google_folder_iam_binding.authoritative,
|
|
||||||
google_folder_organization_policy.boolean,
|
|
||||||
google_folder_organization_policy.list
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
output "names" {
|
|
||||||
description = "Folder names."
|
|
||||||
value = (
|
|
||||||
local.has_folders
|
|
||||||
? zipmap(var.names, [for f in local.folders : f.display_name])
|
|
||||||
: {}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
output "ids_list" {
|
|
||||||
description = "List of folder ids."
|
|
||||||
value = [for f in local.folders : f.name]
|
|
||||||
depends_on = [
|
|
||||||
google_folder_iam_binding.authoritative,
|
|
||||||
google_folder_organization_policy.boolean,
|
|
||||||
google_folder_organization_policy.list
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
output "names_list" {
|
|
||||||
description = "List of folder names."
|
|
||||||
value = [for f in local.folders : f.display_name]
|
|
||||||
}
|
|
|
@ -7,21 +7,13 @@
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
module "buckets" {
|
module "bucket" {
|
||||||
source = "./modules/gcs"
|
source = "./modules/gcs"
|
||||||
project_id = "myproject"
|
project_id = "myproject"
|
||||||
prefix = "test"
|
prefix = "test"
|
||||||
names = ["bucket-one", "bucket-two"]
|
name = "my-bucket"
|
||||||
bucket_policy_only = {
|
iam = {
|
||||||
bucket-one = false
|
"roles/storage.admin" = ["group:storage@example.com"]
|
||||||
}
|
|
||||||
iam_members = {
|
|
||||||
bucket-two = {
|
|
||||||
"roles/storage.admin" = ["group:storage@example.com"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iam_roles = {
|
|
||||||
bucket-two = ["roles/storage.admin"]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -29,56 +21,38 @@ module "buckets" {
|
||||||
### Example with Cloud KMS
|
### Example with Cloud KMS
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
module "buckets" {
|
module "bucket" {
|
||||||
source = "./modules/gcs"
|
source = "./modules/gcs"
|
||||||
project_id = "myproject"
|
project_id = "myproject"
|
||||||
prefix = "test"
|
prefix = "test"
|
||||||
names = ["bucket-one", "bucket-two"]
|
name = "my-bucket"
|
||||||
bucket_policy_only = {
|
iam = {
|
||||||
bucket-one = false
|
"roles/storage.admin" = ["group:storage@example.com"]
|
||||||
}
|
|
||||||
iam_members = {
|
|
||||||
bucket-two = {
|
|
||||||
"roles/storage.admin" = ["group:storage@example.com"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iam_roles = {
|
|
||||||
bucket-two = ["roles/storage.admin"]
|
|
||||||
}
|
|
||||||
encryption_keys = {
|
|
||||||
bucket-two = local.kms_key.self_link,
|
|
||||||
}
|
}
|
||||||
|
encryption_keys = local.kms_key.self_link
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
### Example with retention policy
|
### Example with retention policy
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
module "buckets" {
|
module "bucket" {
|
||||||
source = "./modules/gcs"
|
source = "./modules/gcs"
|
||||||
project_id = "myproject"
|
project_id = "myproject"
|
||||||
prefix = "test"
|
prefix = "test"
|
||||||
names = ["bucket-one", "bucket-two"]
|
name = "my-bucket"
|
||||||
bucket_policy_only = {
|
iam = {
|
||||||
bucket-one = false
|
"roles/storage.admin" = ["group:storage@example.com"]
|
||||||
}
|
|
||||||
iam_members = {
|
|
||||||
bucket-two = {
|
|
||||||
"roles/storage.admin" = ["group:storage@example.com"]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
iam_roles = {
|
|
||||||
bucket-two = ["roles/storage.admin"]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
retention_policies = {
|
retention_policies = {
|
||||||
bucket-one = { retention_period = 100 , is_locked = true}
|
retention_period = 100
|
||||||
bucket-two = { retention_period = 900 , is_locked = false}
|
is_locked = true
|
||||||
}
|
}
|
||||||
|
|
||||||
logging_config = {
|
logging_config = {
|
||||||
bucket-one = { log_bucket = bucket_name_for_logging , log_object_prefix = null}
|
log_bucket = bucket_name_for_logging
|
||||||
bucket-two = { log_bucket = bucket_name_for_logging , log_object_prefix = "logs_for_bucket_two"}
|
log_object_prefix = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -88,31 +62,25 @@ module "buckets" {
|
||||||
|
|
||||||
| name | description | type | required | default |
|
| name | description | type | required | default |
|
||||||
|---|---|:---: |:---:|:---:|
|
|---|---|:---: |:---:|:---:|
|
||||||
| names | Bucket name suffixes. | <code title="list(string)">list(string)</code> | ✓ | |
|
| name | Bucket name suffix. | <code title="">string</code> | ✓ | |
|
||||||
| project_id | Bucket project id. | <code title="">string</code> | ✓ | |
|
| project_id | Bucket project id. | <code title="">string</code> | ✓ | |
|
||||||
| *uniform_bucket_level_access* | Optional map to enable object ACLs keyed by name, defaults to true. | <code title="map(bool)">map(bool)</code> | | <code title="">{}</code> |
|
| *encryption_key* | KMS key that will be used for encryption. | <code title="">string</code> | | <code title="">null</code> |
|
||||||
| *encryption_keys* | Per-bucket KMS keys that will be used for encryption. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
| *force_destroy* | Optional map to set force destroy keyed by name, defaults to false. | <code title="">bool</code> | | <code title="">false</code> |
|
||||||
| *force_destroy* | Optional map to set force destroy keyed by name, defaults to false. | <code title="map(bool)">map(bool)</code> | | <code title="">{}</code> |
|
| *iam* | IAM bindings in {ROLE => [MEMBERS]} format. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *iam_members* | IAM members keyed by bucket name and role. | <code title="map(map(list(string)))">map(map(list(string)))</code> | | <code title="">{}</code> |
|
|
||||||
| *iam_roles* | IAM roles keyed by bucket name. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
|
||||||
| *labels* | Labels to be attached to all buckets. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
| *labels* | Labels to be attached to all buckets. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
||||||
| *location* | Bucket location. | <code title="">string</code> | | <code title="">EU</code> |
|
| *location* | Bucket location. | <code title="">string</code> | | <code title="">EU</code> |
|
||||||
| *logging_config* | Per-bucket logging. | <code title="map(object({ log_bucket = string log_object_prefix = string }))">map(object({...}))</code> | | <code title="">{}</code> |
|
| *logging_config* | Bucket logging configuration. | <code title="object({ log_bucket = string log_object_prefix = string })">object({...})</code> | | <code title="">null</code> |
|
||||||
| *prefix* | Prefix used to generate the bucket name. | <code title="">string</code> | | <code title="">null</code> |
|
| *prefix* | Prefix used to generate the bucket name. | <code title="">string</code> | | <code title="">null</code> |
|
||||||
| *retention_policies* | Per-bucket retention policy. | <code title="map(object({ retention_period = number is_locked = bool }))">map(object({...}))</code> | | <code title="">{}</code> |
|
| *retention_policy* | Bucket retention policy. | <code title="object({ retention_period = number is_locked = bool })">object({...})</code> | | <code title="">null</code> |
|
||||||
| *storage_class* | Bucket storage class. | <code title="">string</code> | | <code title="">MULTI_REGIONAL</code> |
|
| *storage_class* | Bucket storage class. | <code title="">string</code> | | <code title="MULTI_REGIONAL validation { condition = contains(["STANDARD", "MULTI_REGIONAL", "REGIONAL", "NEARLINE", "COLDLINE", "ARCHIVE"], var.storage_class) error_message = "Storage class must be one of STANDARD, MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, ARCHIVE." }">...</code> |
|
||||||
| *versioning* | Optional map to set versioning keyed by name, defaults to false. | <code title="map(bool)">map(bool)</code> | | <code title="">{}</code> |
|
| *uniform_bucket_level_access* | Allow using object ACLs (false) or not (true, this is the recommended behavior) , defaults to true (which is the recommended practice, but not the behavior of storage API). | <code title="">bool</code> | | <code title="">true</code> |
|
||||||
|
| *versioning* | Enable versioning, defaults to false. | <code title="">bool</code> | | <code title="">false</code> |
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
|
||||||
| name | description | sensitive |
|
| name | description | sensitive |
|
||||||
|---|---|:---:|
|
|---|---|:---:|
|
||||||
| bucket | Bucket resource (for single use). | |
|
| bucket | Bucket resource. | |
|
||||||
| buckets | Bucket resources. | |
|
| name | Bucket name. | |
|
||||||
| name | Bucket name (for single use). | |
|
| url | Bucket URL. | |
|
||||||
| names | Bucket names. | |
|
|
||||||
| names_list | List of bucket names. | |
|
|
||||||
| url | Bucket URL (for single use). | |
|
|
||||||
| urls | Bucket URLs. | |
|
|
||||||
| urls_list | List of bucket URLs. | |
|
|
||||||
<!-- END TFDOC -->
|
<!-- END TFDOC -->
|
||||||
|
|
|
@ -15,85 +15,57 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
locals {
|
locals {
|
||||||
buckets = (
|
|
||||||
local.has_buckets
|
|
||||||
? [for name in var.names : google_storage_bucket.buckets[name]]
|
|
||||||
: []
|
|
||||||
)
|
|
||||||
# needed when destroying
|
|
||||||
has_buckets = length(google_storage_bucket.buckets) > 0
|
|
||||||
iam_pairs = var.iam_roles == null ? [] : flatten([
|
|
||||||
for name, roles in var.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.iam_members == null ? {} : var.iam_members
|
|
||||||
prefix = (
|
prefix = (
|
||||||
var.prefix == null || var.prefix == "" # keep "" for backward compatibility
|
var.prefix == null || var.prefix == "" # keep "" for backward compatibility
|
||||||
? ""
|
? ""
|
||||||
: join("-", [var.prefix, lower(var.location), ""])
|
: join("-", [var.prefix, lower(var.location), ""])
|
||||||
)
|
)
|
||||||
kms_keys = {
|
|
||||||
for name in var.names : name => lookup(var.encryption_keys, name, null)
|
|
||||||
}
|
|
||||||
retention_policy = {
|
|
||||||
for name in var.names : name => lookup(var.retention_policies, name, null)
|
|
||||||
}
|
|
||||||
logging_config = {
|
|
||||||
for name in var.names : name => lookup(var.logging_config, name, null)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_storage_bucket" "buckets" {
|
resource "google_storage_bucket" "bucket" {
|
||||||
for_each = toset(var.names)
|
name = "${local.prefix}${lower(var.name)}"
|
||||||
name = "${local.prefix}${lower(each.key)}"
|
project = var.project_id
|
||||||
project = var.project_id
|
location = var.location
|
||||||
location = var.location
|
storage_class = var.storage_class
|
||||||
storage_class = var.storage_class
|
force_destroy = var.force_destroy
|
||||||
force_destroy = lookup(var.force_destroy, each.key, false)
|
uniform_bucket_level_access = var.uniform_bucket_level_access
|
||||||
uniform_bucket_level_access = lookup(var.uniform_bucket_level_access, each.key, true)
|
|
||||||
versioning {
|
versioning {
|
||||||
enabled = lookup(var.versioning, each.key, false)
|
enabled = var.versioning
|
||||||
}
|
}
|
||||||
labels = merge(var.labels, {
|
labels = merge(var.labels, {
|
||||||
location = lower(var.location)
|
location = lower(var.location)
|
||||||
name = lower(each.key)
|
name = lower(var.name)
|
||||||
storage_class = lower(var.storage_class)
|
storage_class = lower(var.storage_class)
|
||||||
})
|
})
|
||||||
|
|
||||||
dynamic encryption {
|
dynamic encryption {
|
||||||
for_each = local.kms_keys[each.key] == null ? [] : [""]
|
for_each = var.encryption_key == null ? [] : [""]
|
||||||
|
|
||||||
content {
|
content {
|
||||||
default_kms_key_name = local.kms_keys[each.key]
|
default_kms_key_name = var.encryption_key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic retention_policy {
|
dynamic retention_policy {
|
||||||
for_each = local.retention_policy[each.key] == null ? [] : [""]
|
for_each = var.retention_policy == null ? [] : [""]
|
||||||
content {
|
content {
|
||||||
retention_period = local.retention_policy[each.key]["retention_period"]
|
retention_period = var.retention_policy.retention_period
|
||||||
is_locked = local.retention_policy[each.key]["is_locked"]
|
is_locked = var.retention_policy.is_locked
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamic logging {
|
dynamic logging {
|
||||||
for_each = local.logging_config[each.key] == null ? [] : [""]
|
for_each = var.logging_config == null ? [] : [""]
|
||||||
content {
|
content {
|
||||||
log_bucket = local.logging_config[each.key]["log_bucket"]
|
log_bucket = var.logging_config.log_bucket
|
||||||
log_object_prefix = local.logging_config[each.key]["log_object_prefix"]
|
log_object_prefix = var.logging_config.log_object_prefix
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_storage_bucket_iam_binding" "bindings" {
|
resource "google_storage_bucket_iam_binding" "bindings" {
|
||||||
for_each = local.iam_keypairs
|
for_each = var.iam
|
||||||
bucket = google_storage_bucket.buckets[each.value.name].name
|
bucket = google_storage_bucket.bucket.name
|
||||||
role = each.value.role
|
role = each.key
|
||||||
members = lookup(
|
members = each.value
|
||||||
lookup(local.iam_members, each.value.name, {}), each.value.role, []
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Copyright 2018 Google LLC
|
* Copyright 2020 Google LLC
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -15,49 +15,16 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
output "bucket" {
|
output "bucket" {
|
||||||
description = "Bucket resource (for single use)."
|
description = "Bucket resource."
|
||||||
value = local.has_buckets ? local.buckets[0] : null
|
value = google_storage_bucket.bucket
|
||||||
}
|
}
|
||||||
|
|
||||||
output "name" {
|
output "name" {
|
||||||
description = "Bucket name (for single use)."
|
description = "Bucket name."
|
||||||
value = local.has_buckets ? local.buckets[0].name : null
|
value = google_storage_bucket.bucket.name
|
||||||
}
|
}
|
||||||
|
|
||||||
output "url" {
|
output "url" {
|
||||||
description = "Bucket URL (for single use)."
|
description = "Bucket URL."
|
||||||
value = local.has_buckets ? local.buckets[0].url : null
|
value = google_storage_bucket.bucket.url
|
||||||
}
|
|
||||||
|
|
||||||
output "buckets" {
|
|
||||||
description = "Bucket resources."
|
|
||||||
value = local.buckets
|
|
||||||
}
|
|
||||||
|
|
||||||
output "names" {
|
|
||||||
description = "Bucket names."
|
|
||||||
value = (
|
|
||||||
local.has_buckets
|
|
||||||
? zipmap(var.names, [for b in local.buckets : lookup(b, "name", null)])
|
|
||||||
: {}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
output "urls" {
|
|
||||||
description = "Bucket URLs."
|
|
||||||
value = (
|
|
||||||
local.has_buckets
|
|
||||||
? zipmap(var.names, [for b in local.buckets : b.url])
|
|
||||||
: {}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
output "names_list" {
|
|
||||||
description = "List of bucket names."
|
|
||||||
value = [for b in local.buckets : b.name]
|
|
||||||
}
|
|
||||||
|
|
||||||
output "urls_list" {
|
|
||||||
description = "List of bucket URLs."
|
|
||||||
value = [for b in local.buckets : b.name]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Copyright 2018 Google LLC
|
* Copyright 2020 Google LLC
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -15,33 +15,27 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
variable "uniform_bucket_level_access" {
|
variable "uniform_bucket_level_access" {
|
||||||
description = "Optional map to allow using object ACLs (false) or not (true, this is the recommended behavior) , defaults to true (which is the recommended practice, but not the behavior of storage API)."
|
description = "Allow using object ACLs (false) or not (true, this is the recommended behavior) , defaults to true (which is the recommended practice, but not the behavior of storage API)."
|
||||||
type = map(bool)
|
type = bool
|
||||||
default = {}
|
default = true
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "force_destroy" {
|
variable "force_destroy" {
|
||||||
description = "Optional map to set force destroy keyed by name, defaults to false."
|
description = "Optional map to set force destroy keyed by name, defaults to false."
|
||||||
type = map(bool)
|
type = bool
|
||||||
default = {}
|
default = false
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_members" {
|
variable "iam" {
|
||||||
description = "IAM members keyed by bucket name and role."
|
description = "IAM bindings in {ROLE => [MEMBERS]} format."
|
||||||
type = map(map(list(string)))
|
|
||||||
default = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "iam_roles" {
|
|
||||||
description = "IAM roles keyed by bucket name."
|
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "encryption_keys" {
|
variable "encryption_key" {
|
||||||
description = "Per-bucket KMS keys that will be used for encryption."
|
description = "KMS key that will be used for encryption."
|
||||||
type = map(string)
|
type = string
|
||||||
default = {}
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "labels" {
|
variable "labels" {
|
||||||
|
@ -57,17 +51,17 @@ variable "location" {
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "logging_config" {
|
variable "logging_config" {
|
||||||
description = "Per-bucket logging."
|
description = "Bucket logging configuration."
|
||||||
type = map(object({
|
type = object({
|
||||||
log_bucket = string
|
log_bucket = string
|
||||||
log_object_prefix = string
|
log_object_prefix = string
|
||||||
}))
|
})
|
||||||
default = {}
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "names" {
|
variable "name" {
|
||||||
description = "Bucket name suffixes."
|
description = "Bucket name suffix."
|
||||||
type = list(string)
|
type = string
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "prefix" {
|
variable "prefix" {
|
||||||
|
@ -81,23 +75,27 @@ variable "project_id" {
|
||||||
type = string
|
type = string
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "retention_policies" {
|
variable "retention_policy" {
|
||||||
description = "Per-bucket retention policy."
|
description = "Bucket retention policy."
|
||||||
type = map(object({
|
type = object({
|
||||||
retention_period = number
|
retention_period = number
|
||||||
is_locked = bool
|
is_locked = bool
|
||||||
}))
|
})
|
||||||
default = {}
|
default = null
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "storage_class" {
|
variable "storage_class" {
|
||||||
description = "Bucket storage class."
|
description = "Bucket storage class."
|
||||||
type = string
|
type = string
|
||||||
default = "MULTI_REGIONAL"
|
default = "MULTI_REGIONAL"
|
||||||
|
validation {
|
||||||
|
condition = contains(["STANDARD", "MULTI_REGIONAL", "REGIONAL", "NEARLINE", "COLDLINE", "ARCHIVE"], var.storage_class)
|
||||||
|
error_message = "Storage class must be one of STANDARD, MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, ARCHIVE."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "versioning" {
|
variable "versioning" {
|
||||||
description = "Optional map to set versioning keyed by name, defaults to false."
|
description = "Enable versioning, defaults to false."
|
||||||
type = map(bool)
|
type = bool
|
||||||
default = {}
|
default = false
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,5 +15,5 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
terraform {
|
terraform {
|
||||||
required_version = ">= 0.12.6"
|
required_version = ">= 0.13.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,52 @@
|
||||||
|
# Google Service Account Module
|
||||||
|
|
||||||
|
This module allows simplified creation and management of one a service account and its IAM bindings. A key can optionally be generated and will be stored in Terraform state. To use it create a sensitive output in your root modules referencing the `key` output, then extract the private key from the JSON formatted outputs.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```hcl
|
||||||
|
module "myproject-default-service-accounts" {
|
||||||
|
source = "./modules/iam-service-account"
|
||||||
|
project_id = "myproject"
|
||||||
|
name = "vm-default"
|
||||||
|
generate_key = true
|
||||||
|
# authoritative roles granted *on* the service accounts to other identities
|
||||||
|
iam = {
|
||||||
|
"roles/iam.serviceAccountUser" = ["user:foo@example.com"]
|
||||||
|
}
|
||||||
|
# non-authoritative roles granted *to* the service accounts on other resources
|
||||||
|
iam_project_roles = {
|
||||||
|
"myproject" = [
|
||||||
|
"roles/logging.logWriter",
|
||||||
|
"roles/monitoring.metricWriter",
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- BEGIN TFDOC -->
|
||||||
|
## Variables
|
||||||
|
|
||||||
|
| name | description | type | required | default |
|
||||||
|
|---|---|:---: |:---:|:---:|
|
||||||
|
| name | Name of the service account to create. | <code title="">string</code> | ✓ | |
|
||||||
|
| project_id | Project id where service account will be created. | <code title="">string</code> | ✓ | |
|
||||||
|
| *display_name* | Display name of the service account to create. | <code title="">string</code> | | <code title="">Terraform-managed.</code> |
|
||||||
|
| *generate_key* | Generate a key for service account. | <code title="">bool</code> | | <code title="">false</code> |
|
||||||
|
| *iam* | IAM bindings on the service account in {ROLE => [MEMBERS]} format. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
|
| *iam_billing_roles* | Project roles granted to the service account, by billing account id. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
|
| *iam_folder_roles* | Project roles granted to the service account, by folder id. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
|
| *iam_organization_roles* | Project roles granted to the service account, by organization id. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
|
| *iam_project_roles* | Project roles granted to the service account, by project id. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
|
| *iam_storage_roles* | Storage roles granted to the service account, by bucket name. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
|
| *prefix* | Prefix applied to service account names. | <code title="">string</code> | | <code title="">null</code> |
|
||||||
|
|
||||||
|
## Outputs
|
||||||
|
|
||||||
|
| name | description | sensitive |
|
||||||
|
|---|---|:---:|
|
||||||
|
| email | Service account email. | |
|
||||||
|
| iam_email | IAM-format service account email. | |
|
||||||
|
| key | Service account key. | ✓ |
|
||||||
|
| service_account | Service account resource. | |
|
||||||
|
<!-- END TFDOC -->
|
|
@ -0,0 +1,124 @@
|
||||||
|
/**
|
||||||
|
* 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_billing_pairs = flatten([
|
||||||
|
for entity, roles in var.iam_billing_roles : [
|
||||||
|
for role in roles : [
|
||||||
|
{ entity = entity, role = role }
|
||||||
|
]
|
||||||
|
]
|
||||||
|
])
|
||||||
|
iam_folder_pairs = flatten([
|
||||||
|
for entity, roles in var.iam_folder_roles : [
|
||||||
|
for role in roles : [
|
||||||
|
{ entity = entity, role = role }
|
||||||
|
]
|
||||||
|
]
|
||||||
|
])
|
||||||
|
iam_organization_pairs = flatten([
|
||||||
|
for entity, roles in var.iam_organization_roles : [
|
||||||
|
for role in roles : [
|
||||||
|
{ entity = entity, role = role }
|
||||||
|
]
|
||||||
|
]
|
||||||
|
])
|
||||||
|
iam_project_pairs = flatten([
|
||||||
|
for entity, roles in var.iam_project_roles : [
|
||||||
|
for role in roles : [
|
||||||
|
{ entity = entity, role = role }
|
||||||
|
]
|
||||||
|
]
|
||||||
|
])
|
||||||
|
iam_storage_pairs = flatten([
|
||||||
|
for entity, roles in var.iam_storage_roles : [
|
||||||
|
for role in roles : [
|
||||||
|
{ entity = entity, role = role }
|
||||||
|
]
|
||||||
|
]
|
||||||
|
])
|
||||||
|
key = var.generate_key ? google_service_account_key.key["1"] : {}
|
||||||
|
prefix = var.prefix != null ? "${var.prefix}-" : ""
|
||||||
|
resource_iam_email = "serviceAccount:${google_service_account.service_account.email}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_service_account" "service_account" {
|
||||||
|
project = var.project_id
|
||||||
|
account_id = "${local.prefix}${var.name}"
|
||||||
|
display_name = var.display_name
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_service_account_key" "key" {
|
||||||
|
for_each = var.generate_key ? { 1 = 1 } : {}
|
||||||
|
service_account_id = google_service_account.service_account.email
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_service_account_iam_binding" "roles" {
|
||||||
|
for_each = var.iam
|
||||||
|
service_account_id = google_service_account.service_account.name
|
||||||
|
role = each.key
|
||||||
|
members = each.value
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_billing_account_iam_member" "billing-roles" {
|
||||||
|
for_each = {
|
||||||
|
for pair in local.iam_billing_pairs :
|
||||||
|
"${pair.entity}-${pair.role}" => pair
|
||||||
|
}
|
||||||
|
billing_account_id = each.value.entity
|
||||||
|
role = each.value.role
|
||||||
|
member = local.resource_iam_email
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_folder_iam_member" "folder-roles" {
|
||||||
|
for_each = {
|
||||||
|
for pair in local.iam_folder_pairs :
|
||||||
|
"${pair.entity}-${pair.role}" => pair
|
||||||
|
}
|
||||||
|
folder = each.value.entity
|
||||||
|
role = each.value.role
|
||||||
|
member = local.resource_iam_email
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_organization_iam_member" "organization-roles" {
|
||||||
|
for_each = {
|
||||||
|
for pair in local.iam_organization_pairs :
|
||||||
|
"${pair.entity}-${pair.role}" => pair
|
||||||
|
}
|
||||||
|
org_id = each.value.entity
|
||||||
|
role = each.value.role
|
||||||
|
member = local.resource_iam_email
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_project_iam_member" "project-roles" {
|
||||||
|
for_each = {
|
||||||
|
for pair in local.iam_project_pairs :
|
||||||
|
"${pair.entity}-${pair.role}" => pair
|
||||||
|
}
|
||||||
|
project = each.value.entity
|
||||||
|
role = each.value.role
|
||||||
|
member = local.resource_iam_email
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "google_storage_bucket_iam_member" "bucket-roles" {
|
||||||
|
for_each = {
|
||||||
|
for pair in local.iam_storage_pairs :
|
||||||
|
"${pair.entity}-${pair.role}" => pair
|
||||||
|
}
|
||||||
|
bucket = each.value.entity
|
||||||
|
role = each.value.role
|
||||||
|
member = local.resource_iam_email
|
||||||
|
}
|
|
@ -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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
output "service_account" {
|
||||||
|
description = "Service account resource."
|
||||||
|
value = google_service_account.service_account
|
||||||
|
}
|
||||||
|
|
||||||
|
output "email" {
|
||||||
|
description = "Service account email."
|
||||||
|
value = google_service_account.service_account.email
|
||||||
|
}
|
||||||
|
|
||||||
|
output "iam_email" {
|
||||||
|
description = "IAM-format service account email."
|
||||||
|
value = local.resource_iam_email
|
||||||
|
}
|
||||||
|
|
||||||
|
output "key" {
|
||||||
|
description = "Service account key."
|
||||||
|
sensitive = true
|
||||||
|
value = local.key
|
||||||
|
}
|
|
@ -14,58 +14,57 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
variable "generate_keys" {
|
variable "generate_key" {
|
||||||
description = "Generate keys for service accounts."
|
description = "Generate a key for service account."
|
||||||
type = bool
|
type = bool
|
||||||
default = false
|
default = false
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_members" {
|
variable "iam" {
|
||||||
description = "Map of member lists which are granted authoritative roles on the service accounts, keyed by role."
|
description = "IAM bindings on the service account in {ROLE => [MEMBERS]} format."
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_roles" {
|
|
||||||
description = "List of authoritative roles granted on the service accounts."
|
|
||||||
type = list(string)
|
|
||||||
default = []
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "iam_billing_roles" {
|
variable "iam_billing_roles" {
|
||||||
description = "Project roles granted to all service accounts, by billing account id."
|
description = "Project roles granted to the service account, by billing account id."
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_folder_roles" {
|
variable "iam_folder_roles" {
|
||||||
description = "Project roles granted to all service accounts, by folder id."
|
description = "Project roles granted to the service account, by folder id."
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_organization_roles" {
|
variable "iam_organization_roles" {
|
||||||
description = "Project roles granted to all service accounts, by organization id."
|
description = "Project roles granted to the service account, by organization id."
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_project_roles" {
|
variable "iam_project_roles" {
|
||||||
description = "Project roles granted to all service accounts, by project id."
|
description = "Project roles granted to the service account, by project id."
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_storage_roles" {
|
variable "iam_storage_roles" {
|
||||||
description = "Storage roles granted to all service accounts, by bucket name."
|
description = "Storage roles granted to the service account, by bucket name."
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "names" {
|
variable "name" {
|
||||||
description = "Names of the service accounts to create."
|
description = "Name of the service account to create."
|
||||||
type = list(string)
|
type = string
|
||||||
default = []
|
}
|
||||||
|
|
||||||
|
variable "display_name" {
|
||||||
|
description = "Display name of the service account to create."
|
||||||
|
type = string
|
||||||
|
default = "Terraform-managed."
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "prefix" {
|
variable "prefix" {
|
|
@ -1,59 +0,0 @@
|
||||||
# Google Service Accounts Module
|
|
||||||
|
|
||||||
This module allows simplified creation and management of one or more service accounts and their IAM bindings. Keys can optionally be generated and will be stored in Terraform state. To use them create a sensitive output in your root modules referencing the `keys` or `key` outputs, then extract the private key from the JSON formatted outputs.
|
|
||||||
|
|
||||||
## Example
|
|
||||||
|
|
||||||
```hcl
|
|
||||||
module "myproject-default-service-accounts" {
|
|
||||||
source = "./modules/iam-service-accounts"
|
|
||||||
project_id = "myproject"
|
|
||||||
names = ["vm-default", "gke-node-default"]
|
|
||||||
generate_keys = true
|
|
||||||
# authoritative roles granted *on* the service accounts to other identities
|
|
||||||
iam_roles = ["roles/iam.serviceAccountUser"]
|
|
||||||
iam_members = {
|
|
||||||
"roles/iam.serviceAccountUser" = ["user:foo@example.com"]
|
|
||||||
}
|
|
||||||
# non-authoritative roles granted *to* the service accounts on other resources
|
|
||||||
iam_project_roles = {
|
|
||||||
"myproject" = [
|
|
||||||
"roles/logging.logWriter",
|
|
||||||
"roles/monitoring.metricWriter",
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- BEGIN TFDOC -->
|
|
||||||
## Variables
|
|
||||||
|
|
||||||
| name | description | type | required | default |
|
|
||||||
|---|---|:---: |:---:|:---:|
|
|
||||||
| project_id | Project id where service account will be created. | <code title="">string</code> | ✓ | |
|
|
||||||
| *generate_keys* | Generate keys for service accounts. | <code title="">bool</code> | | <code title="">false</code> |
|
|
||||||
| *iam_billing_roles* | Project roles granted to all service accounts, by billing account id. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
|
||||||
| *iam_folder_roles* | Project roles granted to all service accounts, by folder id. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
|
||||||
| *iam_members* | Map of member lists which are granted authoritative roles on the service accounts, keyed by role. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
|
||||||
| *iam_organization_roles* | Project roles granted to all service accounts, by organization id. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
|
||||||
| *iam_project_roles* | Project roles granted to all service accounts, by project id. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
|
||||||
| *iam_roles* | List of authoritative roles granted on the service accounts. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
|
||||||
| *iam_storage_roles* | Storage roles granted to all service accounts, by bucket name. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
|
||||||
| *names* | Names of the service accounts to create. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
|
||||||
| *prefix* | Prefix applied to service account names. | <code title="">string</code> | | <code title="">null</code> |
|
|
||||||
|
|
||||||
## Outputs
|
|
||||||
|
|
||||||
| name | description | sensitive |
|
|
||||||
|---|---|:---:|
|
|
||||||
| email | Service account email (for single use). | |
|
|
||||||
| emails | Service account emails. | |
|
|
||||||
| emails_list | Service account emails. | |
|
|
||||||
| iam_email | IAM-format service account email (for single use). | |
|
|
||||||
| iam_emails | IAM-format service account emails. | |
|
|
||||||
| iam_emails_list | IAM-format service account emails. | |
|
|
||||||
| key | Service account key (for single use). | |
|
|
||||||
| keys | Map of service account keys. | ✓ |
|
|
||||||
| service_account | Service account resource (for single use). | |
|
|
||||||
| service_accounts | Service account resources. | |
|
|
||||||
<!-- END TFDOC -->
|
|
|
@ -1,136 +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_pairs = {
|
|
||||||
for pair in setproduct(var.names, var.iam_roles) :
|
|
||||||
"${pair.0}-${pair.1}" => { name = pair.0, role = pair.1 }
|
|
||||||
}
|
|
||||||
iam_billing_pairs = flatten([
|
|
||||||
for entity, roles in var.iam_billing_roles : [
|
|
||||||
for role in roles : [
|
|
||||||
for name in var.names : { entity = entity, role = role, name = name }
|
|
||||||
]
|
|
||||||
]
|
|
||||||
])
|
|
||||||
iam_folder_pairs = flatten([
|
|
||||||
for entity, roles in var.iam_folder_roles : [
|
|
||||||
for role in roles : [
|
|
||||||
for name in var.names : { entity = entity, role = role, name = name }
|
|
||||||
]
|
|
||||||
]
|
|
||||||
])
|
|
||||||
iam_organization_pairs = flatten([
|
|
||||||
for entity, roles in var.iam_organization_roles : [
|
|
||||||
for role in roles : [
|
|
||||||
for name in var.names : { entity = entity, role = role, name = name }
|
|
||||||
]
|
|
||||||
]
|
|
||||||
])
|
|
||||||
iam_project_pairs = flatten([
|
|
||||||
for entity, roles in var.iam_project_roles : [
|
|
||||||
for role in roles : [
|
|
||||||
for name in var.names : { entity = entity, role = role, name = name }
|
|
||||||
]
|
|
||||||
]
|
|
||||||
])
|
|
||||||
iam_storage_pairs = flatten([
|
|
||||||
for entity, roles in var.iam_storage_roles : [
|
|
||||||
for role in roles : [
|
|
||||||
for name in var.names : { entity = entity, role = role, name = name }
|
|
||||||
]
|
|
||||||
]
|
|
||||||
])
|
|
||||||
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 google_service_account.service_accounts :
|
|
||||||
name => "serviceAccount:${resource.email}"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "google_service_account" "service_accounts" {
|
|
||||||
for_each = toset(var.names)
|
|
||||||
project = var.project_id
|
|
||||||
account_id = "${local.prefix}${lower(each.value)}"
|
|
||||||
display_name = "Terraform-managed."
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "google_service_account_key" "keys" {
|
|
||||||
for_each = var.generate_keys ? toset(var.names) : toset([])
|
|
||||||
service_account_id = google_service_account.service_accounts[each.value].email
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "google_service_account_iam_binding" "sa-roles" {
|
|
||||||
for_each = local.iam_pairs
|
|
||||||
service_account_id = google_service_account.service_accounts[each.value.name].name
|
|
||||||
role = each.value.role
|
|
||||||
members = lookup(var.iam_members, each.value.role, [])
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "google_billing_account_iam_member" "roles" {
|
|
||||||
for_each = {
|
|
||||||
for pair in local.iam_billing_pairs :
|
|
||||||
"${pair.name}-${pair.entity}-${pair.role}" => pair
|
|
||||||
}
|
|
||||||
billing_account_id = each.value.entity
|
|
||||||
role = each.value.role
|
|
||||||
member = local.resource_iam_emails[each.value.name]
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "google_folder_iam_member" "roles" {
|
|
||||||
for_each = {
|
|
||||||
for pair in local.iam_folder_pairs :
|
|
||||||
"${pair.name}-${pair.entity}-${pair.role}" => pair
|
|
||||||
}
|
|
||||||
folder = each.value.entity
|
|
||||||
role = each.value.role
|
|
||||||
member = local.resource_iam_emails[each.value.name]
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "google_organization_iam_member" "roles" {
|
|
||||||
for_each = {
|
|
||||||
for pair in local.iam_organization_pairs :
|
|
||||||
"${pair.name}-${pair.entity}-${pair.role}" => pair
|
|
||||||
}
|
|
||||||
org_id = each.value.entity
|
|
||||||
role = each.value.role
|
|
||||||
member = local.resource_iam_emails[each.value.name]
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "google_project_iam_member" "project-roles" {
|
|
||||||
for_each = {
|
|
||||||
for pair in local.iam_project_pairs :
|
|
||||||
"${pair.name}-${pair.entity}-${pair.role}" => pair
|
|
||||||
}
|
|
||||||
project = each.value.entity
|
|
||||||
role = each.value.role
|
|
||||||
member = local.resource_iam_emails[each.value.name]
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "google_storage_bucket_iam_member" "bucket-roles" {
|
|
||||||
for_each = {
|
|
||||||
for pair in local.iam_storage_pairs :
|
|
||||||
"${pair.name}-${pair.entity}-${pair.role}" => pair
|
|
||||||
}
|
|
||||||
bucket = each.value.entity
|
|
||||||
role = each.value.role
|
|
||||||
member = local.resource_iam_emails[each.value.name]
|
|
||||||
}
|
|
||||||
|
|
||||||
# TODO(ludoo): link from README
|
|
||||||
# ref: https://cloud.google.com/vpc/docs/shared-vpc
|
|
|
@ -1,75 +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_account" {
|
|
||||||
description = "Service account resource (for single use)."
|
|
||||||
value = local.resource
|
|
||||||
}
|
|
||||||
|
|
||||||
output "service_accounts" {
|
|
||||||
description = "Service account resources."
|
|
||||||
value = google_service_account.service_accounts
|
|
||||||
}
|
|
||||||
|
|
||||||
output "email" {
|
|
||||||
description = "Service account email (for single use)."
|
|
||||||
value = try(local.resource.email, null)
|
|
||||||
}
|
|
||||||
|
|
||||||
output "iam_email" {
|
|
||||||
description = "IAM-format service account email (for single use)."
|
|
||||||
value = try("serviceAccount:${local.resource.email}", null)
|
|
||||||
}
|
|
||||||
|
|
||||||
output "key" {
|
|
||||||
description = "Service account key (for single use)."
|
|
||||||
value = try(local.keys[var.names[0]], null)
|
|
||||||
}
|
|
||||||
|
|
||||||
output "emails" {
|
|
||||||
description = "Service account emails."
|
|
||||||
value = {
|
|
||||||
for name, resource in google_service_account.service_accounts :
|
|
||||||
name => resource.email
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
output "iam_emails" {
|
|
||||||
description = "IAM-format service account emails."
|
|
||||||
value = local.resource_iam_emails
|
|
||||||
}
|
|
||||||
|
|
||||||
output "emails_list" {
|
|
||||||
description = "Service account emails."
|
|
||||||
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 google_service_account.service_accounts :
|
|
||||||
"serviceAccount:${resource.email}"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
output "keys" {
|
|
||||||
description = "Map of service account keys."
|
|
||||||
sensitive = true
|
|
||||||
value = local.keys
|
|
||||||
}
|
|
|
@ -16,8 +16,7 @@ In this module **no lifecycle blocks are set on resources to prevent destroy**,
|
||||||
module "kms" {
|
module "kms" {
|
||||||
source = "../modules/kms"
|
source = "../modules/kms"
|
||||||
project_id = "my-project"
|
project_id = "my-project"
|
||||||
iam_roles = ["roles/owner"]
|
iam = {
|
||||||
iam_members = {
|
|
||||||
"roles/owner" = ["user:user1@example.com"]
|
"roles/owner" = ["user:user1@example.com"]
|
||||||
}
|
}
|
||||||
keyring = { location = "europe-west1", name = "test" }
|
keyring = { location = "europe-west1", name = "test" }
|
||||||
|
@ -32,10 +31,7 @@ module "kms" {
|
||||||
module "kms" {
|
module "kms" {
|
||||||
source = "../modules/kms"
|
source = "../modules/kms"
|
||||||
project_id = "my-project"
|
project_id = "my-project"
|
||||||
key_iam_roles = {
|
key_iam = {
|
||||||
key-a = ["roles/owner"]
|
|
||||||
}
|
|
||||||
key_iam_members = {
|
|
||||||
key-a = {
|
key-a = {
|
||||||
"roles/owner" = ["user:user1@example.com"]
|
"roles/owner" = ["user:user1@example.com"]
|
||||||
}
|
}
|
||||||
|
@ -76,10 +72,8 @@ module "kms" {
|
||||||
|---|---|:---: |:---:|:---:|
|
|---|---|:---: |:---:|:---:|
|
||||||
| keyring | Keyring attributes. | <code title="object({ location = string name = string })">object({...})</code> | ✓ | |
|
| keyring | Keyring attributes. | <code title="object({ location = string name = string })">object({...})</code> | ✓ | |
|
||||||
| project_id | Project id where the keyring will be created. | <code title="">string</code> | ✓ | |
|
| project_id | Project id where the keyring will be created. | <code title="">string</code> | ✓ | |
|
||||||
| *iam_members* | Keyring IAM members. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *iam* | Keyring IAM bindings for topic in {ROLE => [MEMBERS]} format. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *iam_roles* | Keyring IAM roles. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
| *key_iam* | Key IAM bindings for topic in {KEY => {ROLE => [MEMBERS]}} format. | <code title="map(map(list(string)))">map(map(list(string)))</code> | | <code title="">{}</code> |
|
||||||
| *key_iam_members* | IAM members keyed by key name and role. | <code title="map(map(list(string)))">map(map(list(string)))</code> | | <code title="">{}</code> |
|
|
||||||
| *key_iam_roles* | IAM roles keyed by key name. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
|
||||||
| *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. | <code title="map(object({ purpose = string version_template = object({ algorithm = string protection_level = string }) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
| *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. | <code title="map(object({ purpose = string version_template = object({ algorithm = string protection_level = string }) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
||||||
| *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. | <code title="object({ purpose = string version_template = object({ algorithm = string protection_level = string }) })">object({...})</code> | | <code title="{ purpose = null version_template = null }">...</code> |
|
| *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. | <code title="object({ purpose = string version_template = object({ algorithm = string protection_level = string }) })">object({...})</code> | | <code title="{ purpose = null version_template = null }">...</code> |
|
||||||
| *keyring_create* | Set to false to manage keys and IAM bindings in an existing keyring. | <code title="">bool</code> | | <code title="">true</code> |
|
| *keyring_create* | Set to false to manage keys and IAM bindings in an existing keyring. | <code title="">bool</code> | | <code title="">true</code> |
|
||||||
|
|
|
@ -15,14 +15,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
locals {
|
locals {
|
||||||
key_iam_pairs = flatten([
|
key_iam_members = flatten([
|
||||||
for name, roles in var.key_iam_roles :
|
for key, roles in var.key_iam : [
|
||||||
[for role in roles : { name = name, role = role }]
|
for role, members in roles : {
|
||||||
|
key = key
|
||||||
|
role = role
|
||||||
|
members = members
|
||||||
|
}
|
||||||
|
]
|
||||||
])
|
])
|
||||||
key_iam_keypairs = {
|
|
||||||
for pair in local.key_iam_pairs :
|
|
||||||
"${pair.name}-${pair.role}" => pair
|
|
||||||
}
|
|
||||||
key_purpose = {
|
key_purpose = {
|
||||||
for key, attrs in var.keys : key => try(
|
for key, attrs in var.keys : key => try(
|
||||||
var.key_purpose[key], var.key_purpose_defaults
|
var.key_purpose[key], var.key_purpose_defaults
|
||||||
|
@ -47,16 +48,13 @@ resource "google_kms_key_ring" "default" {
|
||||||
project = var.project_id
|
project = var.project_id
|
||||||
name = var.keyring.name
|
name = var.keyring.name
|
||||||
location = var.keyring.location
|
location = var.keyring.location
|
||||||
# lifecycle {
|
|
||||||
# prevent_destroy = true
|
|
||||||
# }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_kms_key_ring_iam_binding" "default" {
|
resource "google_kms_key_ring_iam_binding" "default" {
|
||||||
for_each = toset(var.iam_roles)
|
for_each = var.iam
|
||||||
key_ring_id = local.keyring.self_link
|
key_ring_id = local.keyring.self_link
|
||||||
role = each.value
|
role = each.key
|
||||||
members = lookup(var.iam_members, each.value, [])
|
members = each.value
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_kms_crypto_key" "default" {
|
resource "google_kms_crypto_key" "default" {
|
||||||
|
@ -73,16 +71,14 @@ resource "google_kms_crypto_key" "default" {
|
||||||
protection_level = local.key_purpose[each.key].version_template.protection_level
|
protection_level = local.key_purpose[each.key].version_template.protection_level
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# lifecycle {
|
|
||||||
# prevent_destroy = true
|
|
||||||
# }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_kms_crypto_key_iam_binding" "default" {
|
resource "google_kms_crypto_key_iam_binding" "default" {
|
||||||
for_each = local.key_iam_keypairs
|
for_each = {
|
||||||
|
for binding in local.key_iam_members :
|
||||||
|
"${binding.key}.${binding.role}" => binding
|
||||||
|
}
|
||||||
role = each.value.role
|
role = each.value.role
|
||||||
crypto_key_id = google_kms_crypto_key.default[each.value.name].self_link
|
crypto_key_id = google_kms_crypto_key.default[each.value.key].self_link
|
||||||
members = lookup(
|
members = each.value.members
|
||||||
lookup(var.key_iam_members, each.value.name, {}), each.value.role, []
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Copyright 2018 Google LLC
|
* Copyright 2020 Google LLC
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Copyright 2018 Google LLC
|
* Copyright 2020 Google LLC
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -14,30 +14,18 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
variable "iam_members" {
|
variable "iam" {
|
||||||
description = "Keyring IAM members."
|
description = "Keyring IAM bindings for topic in {ROLE => [MEMBERS]} format."
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_roles" {
|
variable "key_iam" {
|
||||||
description = "Keyring IAM roles."
|
description = "Key IAM bindings for topic in {KEY => {ROLE => [MEMBERS]}} format."
|
||||||
type = list(string)
|
|
||||||
default = []
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "key_iam_members" {
|
|
||||||
description = "IAM members keyed by key name and role."
|
|
||||||
type = map(map(list(string)))
|
type = map(map(list(string)))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "key_iam_roles" {
|
|
||||||
description = "IAM roles keyed by key name."
|
|
||||||
type = map(list(string))
|
|
||||||
default = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "key_purpose" {
|
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."
|
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({
|
type = map(object({
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Copyright 2018 Google LLC
|
* Copyright 2020 Google LLC
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -21,7 +21,7 @@ module "peering" {
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
If you need to create more than one peering for the same VPC Network `(A -> B, A -> C)` you have to use output from the first module as a dependency for the second one to keep order of peering creation (It is not currently possible to create more than one peering connection for a VPC Network at the same time).
|
If you need to create more than one peering for the same VPC Network `(A -> B, A -> C)` you use a `depends_on` for second one to keep order of peering creation (It is not currently possible to create more than one peering connection for a VPC Network at the same time).
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
module "peering-a-b" {
|
module "peering-a-b" {
|
||||||
|
@ -39,7 +39,7 @@ module "peering-a-c" {
|
||||||
local_network = "<A NETWORK SELF LINK>"
|
local_network = "<A NETWORK SELF LINK>"
|
||||||
peer_network = "<C NETWORK SELF LINK>"
|
peer_network = "<C NETWORK SELF LINK>"
|
||||||
|
|
||||||
module_depends_on = [module.peering-a-b.complete]
|
depends_on = [ module.peering-a-b ]
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -52,7 +52,6 @@ module "peering-a-c" {
|
||||||
| peer_network | Resource link of the peer network. | <code title="">string</code> | ✓ | |
|
| peer_network | Resource link of the peer network. | <code title="">string</code> | ✓ | |
|
||||||
| *export_local_custom_routes* | Export custom routes to peer network from local network. | <code title="">bool</code> | | <code title="">false</code> |
|
| *export_local_custom_routes* | Export custom routes to peer network from local network. | <code title="">bool</code> | | <code title="">false</code> |
|
||||||
| *export_peer_custom_routes* | Export custom routes to local network from peer network. | <code title="">bool</code> | | <code title="">false</code> |
|
| *export_peer_custom_routes* | Export custom routes to local network from peer network. | <code title="">bool</code> | | <code title="">false</code> |
|
||||||
| *module_depends_on* | List of modules or resources this module depends on. | <code title="">list</code> | | <code title="">[]</code> |
|
|
||||||
| *peer_create_peering* | Create the peering on the remote side. If false, only the peering from this network to the remote network is created. | <code title="">bool</code> | | <code title="">true</code> |
|
| *peer_create_peering* | Create the peering on the remote side. If false, only the peering from this network to the remote network is created. | <code title="">bool</code> | | <code title="">true</code> |
|
||||||
| *prefix* | Name prefix for the network peerings. | <code title="">string</code> | | <code title="">network-peering</code> |
|
| *prefix* | Name prefix for the network peerings. | <code title="">string</code> | | <code title="">network-peering</code> |
|
||||||
|
|
||||||
|
@ -60,7 +59,6 @@ module "peering-a-c" {
|
||||||
|
|
||||||
| name | description | sensitive |
|
| name | description | sensitive |
|
||||||
|---|---|:---:|
|
|---|---|:---:|
|
||||||
| complete | Output to be used as a module dependency. | |
|
|
||||||
| local_network_peering | Network peering resource. | |
|
| local_network_peering | Network peering resource. | |
|
||||||
| peer_network_peering | Peer network peering resource. | |
|
| peer_network_peering | Peer network peering resource. | |
|
||||||
<!-- END TFDOC -->
|
<!-- END TFDOC -->
|
|
@ -25,8 +25,6 @@ resource "google_compute_network_peering" "local_network_peering" {
|
||||||
peer_network = var.peer_network
|
peer_network = var.peer_network
|
||||||
export_custom_routes = var.export_local_custom_routes
|
export_custom_routes = var.export_local_custom_routes
|
||||||
import_custom_routes = var.export_peer_custom_routes
|
import_custom_routes = var.export_peer_custom_routes
|
||||||
|
|
||||||
depends_on = [null_resource.module_depends_on]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_compute_network_peering" "peer_network_peering" {
|
resource "google_compute_network_peering" "peer_network_peering" {
|
||||||
|
@ -37,15 +35,5 @@ resource "google_compute_network_peering" "peer_network_peering" {
|
||||||
export_custom_routes = var.export_peer_custom_routes
|
export_custom_routes = var.export_peer_custom_routes
|
||||||
import_custom_routes = var.export_local_custom_routes
|
import_custom_routes = var.export_local_custom_routes
|
||||||
|
|
||||||
depends_on = [null_resource.module_depends_on, google_compute_network_peering.local_network_peering]
|
depends_on = [google_compute_network_peering.local_network_peering]
|
||||||
}
|
|
||||||
|
|
||||||
resource "null_resource" "module_depends_on" {
|
|
||||||
triggers = {
|
|
||||||
value = length(var.module_depends_on)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resource "null_resource" "complete" {
|
|
||||||
depends_on = [google_compute_network_peering.local_network_peering, google_compute_network_peering.peer_network_peering]
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,3 @@ output "peer_network_peering" {
|
||||||
description = "Peer network peering resource."
|
description = "Peer network peering resource."
|
||||||
value = google_compute_network_peering.peer_network_peering
|
value = google_compute_network_peering.peer_network_peering
|
||||||
}
|
}
|
||||||
|
|
||||||
output "complete" {
|
|
||||||
description = "Output to be used as a module dependency."
|
|
||||||
value = null_resource.complete.id
|
|
||||||
}
|
|
||||||
|
|
|
@ -42,12 +42,6 @@ variable "export_local_custom_routes" {
|
||||||
default = false
|
default = false
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "module_depends_on" {
|
|
||||||
description = "List of modules or resources this module depends on."
|
|
||||||
type = list
|
|
||||||
default = []
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "peer_create_peering" {
|
variable "peer_create_peering" {
|
||||||
description = "Create the peering on the remote side. If false, only the peering from this network to the remote network is created."
|
description = "Create the peering on the remote side. If false, only the peering from this network to the remote network is created."
|
||||||
type = bool
|
type = bool
|
||||||
|
|
|
@ -86,13 +86,7 @@ module "vpc-host" {
|
||||||
local.service_project_1.project_id,
|
local.service_project_1.project_id,
|
||||||
local.service_project_2.project_id
|
local.service_project_2.project_id
|
||||||
]
|
]
|
||||||
iam_roles = {
|
iam = {
|
||||||
"europe-west1/subnet-1" = [
|
|
||||||
"roles/compute.networkUser",
|
|
||||||
"roles/compute.securityAdmin"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
iam_members = {
|
|
||||||
"europe-west1/subnet-1" = {
|
"europe-west1/subnet-1" = {
|
||||||
"roles/compute.networkUser" = [
|
"roles/compute.networkUser" = [
|
||||||
local.service_project_1.cloudsvc_sa,
|
local.service_project_1.cloudsvc_sa,
|
||||||
|
@ -116,14 +110,13 @@ module "vpc-host" {
|
||||||
| *auto_create_subnetworks* | Set to true to create an auto mode subnet, defaults to custom mode. | <code title="">bool</code> | | <code title="">false</code> |
|
| *auto_create_subnetworks* | Set to true to create an auto mode subnet, defaults to custom mode. | <code title="">bool</code> | | <code title="">false</code> |
|
||||||
| *delete_default_routes_on_create* | Set to true to delete the default routes at creation time. | <code title="">bool</code> | | <code title="">false</code> |
|
| *delete_default_routes_on_create* | Set to true to delete the default routes at creation time. | <code title="">bool</code> | | <code title="">false</code> |
|
||||||
| *description* | An optional description of this resource (triggers recreation on change). | <code title="">string</code> | | <code title="">Terraform-managed.</code> |
|
| *description* | An optional description of this resource (triggers recreation on change). | <code title="">string</code> | | <code title="">Terraform-managed.</code> |
|
||||||
| *iam_members* | List of IAM members keyed by subnet 'region/name' and role. | <code title="map(map(list(string)))">map(map(list(string)))</code> | | <code title="">{}</code> |
|
| *iam* | Subnet IAM bindings in {REGION/NAME => {ROLE => [MEMBERS]} format. | <code title="map(map(list(string)))">map(map(list(string)))</code> | | <code title="">{}</code> |
|
||||||
| *iam_roles* | List of IAM roles keyed by subnet 'region/name'. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
|
||||||
| *log_config_defaults* | Default configuration for flow logs when enabled. | <code title="object({ aggregation_interval = string flow_sampling = number metadata = string })">object({...})</code> | | <code title="{ aggregation_interval = "INTERVAL_5_SEC" flow_sampling = 0.5 metadata = "INCLUDE_ALL_METADATA" }">...</code> |
|
| *log_config_defaults* | Default configuration for flow logs when enabled. | <code title="object({ aggregation_interval = string flow_sampling = number metadata = string })">object({...})</code> | | <code title="{ aggregation_interval = "INTERVAL_5_SEC" flow_sampling = 0.5 metadata = "INCLUDE_ALL_METADATA" }">...</code> |
|
||||||
| *log_configs* | Map keyed by subnet 'region/name' of optional configurations for flow logs when enabled. | <code title="map(map(string))">map(map(string))</code> | | <code title="">{}</code> |
|
| *log_configs* | Map keyed by subnet 'region/name' of optional configurations for flow logs when enabled. | <code title="map(map(string))">map(map(string))</code> | | <code title="">{}</code> |
|
||||||
| *peering_config* | VPC peering configuration. | <code title="object({ peer_vpc_self_link = string export_routes = bool import_routes = bool })">object({...})</code> | | <code title="">null</code> |
|
| *peering_config* | VPC peering configuration. | <code title="object({ peer_vpc_self_link = string export_routes = bool import_routes = bool })">object({...})</code> | | <code title="">null</code> |
|
||||||
| *peering_create_remote_end* | Skip creation of peering on the remote end when using peering_config | <code title="">bool</code> | | <code title="">true</code> |
|
| *peering_create_remote_end* | Skip creation of peering on the remote end when using peering_config | <code title="">bool</code> | | <code title="">true</code> |
|
||||||
| *routes* | Network routes, keyed by name. | <code title="map(object({ dest_range = string priority = number tags = list(string) next_hop_type = string # gateway, instance, ip, vpn_tunnel, ilb next_hop = string }))">map(object({...}))</code> | | <code title="">{}</code> |
|
| *routes* | Network routes, keyed by name. | <code title="map(object({ dest_range = string priority = number tags = list(string) next_hop_type = string # gateway, instance, ip, vpn_tunnel, ilb next_hop = string }))">map(object({...}))</code> | | <code title="">{}</code> |
|
||||||
| *routing_mode* | The network routing mode (default 'GLOBAL') | <code title="">string</code> | | <code title="">GLOBAL</code> |
|
| *routing_mode* | The network routing mode (default 'GLOBAL') | <code title="">string</code> | | <code title="GLOBAL validation { condition = var.routing_mode == "GLOBAL" || var.routing_mode == "REGIONAL" error_message = "Routing type must be GLOBAL or REGIONAL." }">...</code> |
|
||||||
| *shared_vpc_host* | Enable shared VPC for this project. | <code title="">bool</code> | | <code title="">false</code> |
|
| *shared_vpc_host* | Enable shared VPC for this project. | <code title="">bool</code> | | <code title="">false</code> |
|
||||||
| *shared_vpc_service_projects* | Shared VPC service projects to register with this host | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
| *shared_vpc_service_projects* | Shared VPC service projects to register with this host | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
||||||
| *subnet_descriptions* | Optional map of subnet descriptions, keyed by subnet 'region/name'. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
| *subnet_descriptions* | Optional map of subnet descriptions, keyed by subnet 'region/name'. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
||||||
|
|
|
@ -15,15 +15,17 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
locals {
|
locals {
|
||||||
iam_members = var.iam_members == null ? {} : var.iam_members
|
iam_members = var.iam == null ? {} : var.iam
|
||||||
iam_pairs = var.iam_roles == null ? [] : flatten([
|
subnet_iam_members = flatten([
|
||||||
for subnet, roles in var.iam_roles :
|
for subnet, roles in local.iam_members : [
|
||||||
[for role in roles : { subnet = subnet, role = role }]
|
for role, members in roles : {
|
||||||
|
subnet = subnet
|
||||||
|
role = role
|
||||||
|
members = members
|
||||||
|
}
|
||||||
|
]
|
||||||
])
|
])
|
||||||
iam_keypairs = {
|
|
||||||
for pair in local.iam_pairs :
|
|
||||||
"${pair.subnet}-${pair.role}" => pair
|
|
||||||
}
|
|
||||||
log_configs = var.log_configs == null ? {} : var.log_configs
|
log_configs = var.log_configs == null ? {} : var.log_configs
|
||||||
peer_network = (
|
peer_network = (
|
||||||
var.peering_config == null
|
var.peering_config == null
|
||||||
|
@ -152,14 +154,15 @@ resource "google_compute_subnetwork" "subnetwork" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_compute_subnetwork_iam_binding" "binding" {
|
resource "google_compute_subnetwork_iam_binding" "binding" {
|
||||||
for_each = local.iam_keypairs
|
for_each = {
|
||||||
|
for binding in local.subnet_iam_members :
|
||||||
|
"${binding.subnet}.${binding.role}" => binding
|
||||||
|
}
|
||||||
project = var.project_id
|
project = var.project_id
|
||||||
subnetwork = google_compute_subnetwork.subnetwork[each.value.subnet].name
|
subnetwork = google_compute_subnetwork.subnetwork[each.value.subnet].name
|
||||||
region = google_compute_subnetwork.subnetwork[each.value.subnet].region
|
region = google_compute_subnetwork.subnetwork[each.value.subnet].region
|
||||||
role = each.value.role
|
role = each.value.role
|
||||||
members = lookup(
|
members = each.value.members
|
||||||
lookup(local.iam_members, each.value.subnet, {}), each.value.role, []
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_compute_route" "gateway" {
|
resource "google_compute_route" "gateway" {
|
||||||
|
|
|
@ -32,14 +32,8 @@ variable "description" {
|
||||||
default = "Terraform-managed."
|
default = "Terraform-managed."
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_roles" {
|
variable "iam" {
|
||||||
description = "List of IAM roles keyed by subnet 'region/name'."
|
description = "Subnet IAM bindings in {REGION/NAME => {ROLE => [MEMBERS]} format."
|
||||||
type = map(list(string))
|
|
||||||
default = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "iam_members" {
|
|
||||||
description = "List of IAM members keyed by subnet 'region/name' and role."
|
|
||||||
type = map(map(list(string)))
|
type = map(map(list(string)))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
@ -106,6 +100,11 @@ variable "routing_mode" {
|
||||||
description = "The network routing mode (default 'GLOBAL')"
|
description = "The network routing mode (default 'GLOBAL')"
|
||||||
type = string
|
type = string
|
||||||
default = "GLOBAL"
|
default = "GLOBAL"
|
||||||
|
validation {
|
||||||
|
condition = var.routing_mode == "GLOBAL" || var.routing_mode == "REGIONAL"
|
||||||
|
error_message = "Routing type must be GLOBAL or REGIONAL."
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "shared_vpc_host" {
|
variable "shared_vpc_host" {
|
||||||
|
|
|
@ -15,5 +15,5 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
terraform {
|
terraform {
|
||||||
required_version = ">= 0.12.6"
|
required_version = ">= 0.13.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,8 +13,7 @@ This module allows managing several organization properties:
|
||||||
module "org" {
|
module "org" {
|
||||||
source = "./modules/organization"
|
source = "./modules/organization"
|
||||||
org_id = 1234567890
|
org_id = 1234567890
|
||||||
iam_roles = ["roles/projectCreator"]
|
iam = { "roles/projectCreator" = ["group:cloud-admins@example.org"] }
|
||||||
iam_members = { "roles/projectCreator" = ["group:cloud-admins@example.org"] }
|
|
||||||
policy_boolean = {
|
policy_boolean = {
|
||||||
"constraints/compute.disableGuestAttributesAccess" = true
|
"constraints/compute.disableGuestAttributesAccess" = true
|
||||||
"constraints/compute.skipDefaultNetworkCreation" = true
|
"constraints/compute.skipDefaultNetworkCreation" = true
|
||||||
|
@ -37,10 +36,9 @@ module "org" {
|
||||||
|---|---|:---: |:---:|:---:|
|
|---|---|:---: |:---:|:---:|
|
||||||
| org_id | Organization id in nnnnnn format. | <code title="">number</code> | ✓ | |
|
| org_id | Organization id in nnnnnn format. | <code title="">number</code> | ✓ | |
|
||||||
| *custom_roles* | Map of role name => list of permissions to create in this project. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *custom_roles* | Map of role name => list of permissions to create in this project. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *iam_additive_bindings* | Map of roles lists used to set non authoritative bindings, keyed by members. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *iam* | IAM bindings, in {ROLE => [MEMBERS]} format. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
|
| *iam_additive* | Non authoritative IAM bindings, in {ROLE => [MEMBERS]} format. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *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. | <code title="map(map(list(string)))">map(map(list(string)))</code> | | <code title="">{}</code> |
|
| *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. | <code title="map(map(list(string)))">map(map(list(string)))</code> | | <code title="">{}</code> |
|
||||||
| *iam_members* | Map of member lists used to set authoritative bindings, keyed by role. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
|
||||||
| *iam_roles* | List of roles used to set authoritative bindings. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
|
||||||
| *policy_boolean* | Map of boolean org policies and enforcement value, set value to null for policy restore. | <code title="map(bool)">map(bool)</code> | | <code title="">{}</code> |
|
| *policy_boolean* | Map of boolean org policies and enforcement value, set value to null for policy restore. | <code title="map(bool)">map(bool)</code> | | <code title="">{}</code> |
|
||||||
| *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. | <code title="map(object({ inherit_from_parent = bool suggested_value = string status = bool values = list(string) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
| *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. | <code title="map(object({ inherit_from_parent = bool suggested_value = string status = bool values = list(string) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
locals {
|
locals {
|
||||||
iam_additive_pairs = flatten([
|
iam_additive_pairs = flatten([
|
||||||
for member, roles in var.iam_additive_bindings : [
|
for member, roles in var.iam_additive : [
|
||||||
for role in roles :
|
for role in roles :
|
||||||
{ role = role, member = member }
|
{ role = role, member = member }
|
||||||
]
|
]
|
||||||
|
@ -37,14 +37,14 @@ resource "google_organization_iam_custom_role" "roles" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_organization_iam_binding" "authoritative" {
|
resource "google_organization_iam_binding" "authoritative" {
|
||||||
for_each = toset(var.iam_roles)
|
for_each = var.iam
|
||||||
org_id = var.org_id
|
org_id = var.org_id
|
||||||
role = each.value
|
role = each.key
|
||||||
members = lookup(var.iam_members, each.value, [])
|
members = each.value
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_organization_iam_member" "additive" {
|
resource "google_organization_iam_member" "additive" {
|
||||||
for_each = length(var.iam_additive_bindings) > 0 ? local.iam_additive : {}
|
for_each = length(var.iam_additive) > 0 ? local.iam_additive : {}
|
||||||
org_id = var.org_id
|
org_id = var.org_id
|
||||||
role = each.value.role
|
role = each.value.role
|
||||||
member = each.value.member
|
member = each.value.member
|
||||||
|
|
|
@ -20,20 +20,14 @@ variable "custom_roles" {
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_members" {
|
variable "iam" {
|
||||||
description = "Map of member lists used to set authoritative bindings, keyed by role."
|
description = "IAM bindings, in {ROLE => [MEMBERS]} format."
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_roles" {
|
variable "iam_additive" {
|
||||||
description = "List of roles used to set authoritative bindings."
|
description = "Non authoritative IAM bindings, in {ROLE => [MEMBERS]} format."
|
||||||
type = list(string)
|
|
||||||
default = []
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "iam_additive_bindings" {
|
|
||||||
description = "Map of roles lists used to set non authoritative bindings, keyed by members."
|
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,7 @@ module "project" {
|
||||||
"container.googleapis.com",
|
"container.googleapis.com",
|
||||||
"stackdriver.googleapis.com"
|
"stackdriver.googleapis.com"
|
||||||
]
|
]
|
||||||
iam_roles = ["roles/container.hostServiceAgentUser"]
|
iam = {
|
||||||
iam_members = {
|
|
||||||
"roles/container.hostServiceAgentUser" = [
|
"roles/container.hostServiceAgentUser" = [
|
||||||
"serviceAccount:${var.gke_service_account}"
|
"serviceAccount:${var.gke_service_account}"
|
||||||
]
|
]
|
||||||
|
@ -32,7 +31,7 @@ module "project" {
|
||||||
name = "project-example"
|
name = "project-example"
|
||||||
project_create = false
|
project_create = false
|
||||||
|
|
||||||
iam_additive_bindings = {
|
iam_additive = {
|
||||||
"group:usergroup_watermlon_experimentation@lemonadeinc.io" = [
|
"group:usergroup_watermlon_experimentation@lemonadeinc.io" = [
|
||||||
"roles/viewer",
|
"roles/viewer",
|
||||||
"roles/storage.objectAdmin"
|
"roles/storage.objectAdmin"
|
||||||
|
@ -88,15 +87,14 @@ module "project" {
|
||||||
| *auto_create_network* | Whether to create the default network for the project | <code title="">bool</code> | | <code title="">false</code> |
|
| *auto_create_network* | Whether to create the default network for the project | <code title="">bool</code> | | <code title="">false</code> |
|
||||||
| *billing_account* | Billing account id. | <code title="">string</code> | | <code title="">null</code> |
|
| *billing_account* | Billing account id. | <code title="">string</code> | | <code title="">null</code> |
|
||||||
| *custom_roles* | Map of role name => list of permissions to create in this project. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *custom_roles* | Map of role name => list of permissions to create in this project. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *iam_additive_bindings* | Map of roles lists used to set non authoritative bindings, keyed by members | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *iam* | IAM bindings in {ROLE => [MEMBERS]} format. | <code title="map(set(string))">map(set(string))</code> | | <code title="">{}</code> |
|
||||||
| *iam_members* | Map of member lists used to set authoritative bindings, keyed by role. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *iam_additive* | IAM additive bindings in {ROLE => [MEMBERS]} format. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *iam_roles* | List of roles used to set authoritative bindings. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
|
||||||
| *labels* | Resource labels. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
| *labels* | Resource labels. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
||||||
| *lien_reason* | If non-empty, creates a project lien with this description. | <code title="">string</code> | | <code title=""></code> |
|
| *lien_reason* | If non-empty, creates a project lien with this description. | <code title="">string</code> | | <code title=""></code> |
|
||||||
| *oslogin* | Enable OS Login. | <code title="">bool</code> | | <code title="">false</code> |
|
| *oslogin* | Enable OS Login. | <code title="">bool</code> | | <code title="">false</code> |
|
||||||
| *oslogin_admins* | List of IAM-style identities that will be granted roles necessary for OS Login administrators. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
| *oslogin_admins* | List of IAM-style identities that will be granted roles necessary for OS Login administrators. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
||||||
| *oslogin_users* | List of IAM-style identities that will be granted roles necessary for OS Login users. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
| *oslogin_users* | List of IAM-style identities that will be granted roles necessary for OS Login users. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
||||||
| *parent* | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | <code title="">string</code> | | <code title="">null</code> |
|
| *parent* | Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format. | <code title="">string</code> | | <code title="null validation { condition = var.parent == null || can(regex("(organizations|folders)/[0-9]+", var.parent)) error_message = "Parent must be of the form folders/folder_id or organizations/organization_id." }">...</code> |
|
||||||
| *policy_boolean* | Map of boolean org policies and enforcement value, set value to null for policy restore. | <code title="map(bool)">map(bool)</code> | | <code title="">{}</code> |
|
| *policy_boolean* | Map of boolean org policies and enforcement value, set value to null for policy restore. | <code title="map(bool)">map(bool)</code> | | <code title="">{}</code> |
|
||||||
| *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. | <code title="map(object({ inherit_from_parent = bool suggested_value = string status = bool values = list(string) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
| *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. | <code title="map(object({ inherit_from_parent = bool suggested_value = string status = bool values = list(string) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
||||||
| *prefix* | Prefix used to generate project id and name. | <code title="">string</code> | | <code title="">null</code> |
|
| *prefix* | Prefix used to generate project id and name. | <code title="">string</code> | | <code title="">null</code> |
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Copyright 2018 Google LLC
|
* Copyright 2020 Google LLC
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
locals {
|
locals {
|
||||||
iam_additive_pairs = flatten([
|
iam_additive_pairs = flatten([
|
||||||
for member, roles in var.iam_additive_bindings : [
|
for member, roles in var.iam_additive : [
|
||||||
for role in roles :
|
for role in roles :
|
||||||
{ role = role, member = member }
|
{ role = role, member = member }
|
||||||
]
|
]
|
||||||
|
@ -91,10 +91,10 @@ resource "google_project_service" "project_services" {
|
||||||
# - additive (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" {
|
resource "google_project_iam_binding" "authoritative" {
|
||||||
for_each = toset(var.iam_roles)
|
for_each = var.iam
|
||||||
project = local.project.project_id
|
project = local.project.project_id
|
||||||
role = each.value
|
role = each.key
|
||||||
members = lookup(var.iam_members, each.value, [])
|
members = each.value
|
||||||
depends_on = [
|
depends_on = [
|
||||||
google_project_service.project_services,
|
google_project_service.project_services,
|
||||||
google_project_iam_custom_role.roles
|
google_project_iam_custom_role.roles
|
||||||
|
@ -102,7 +102,7 @@ resource "google_project_iam_binding" "authoritative" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_project_iam_member" "additive" {
|
resource "google_project_iam_member" "additive" {
|
||||||
for_each = length(var.iam_additive_bindings) > 0 ? local.iam_additive : {}
|
for_each = length(var.iam_additive) > 0 ? local.iam_additive : {}
|
||||||
project = local.project.project_id
|
project = local.project.project_id
|
||||||
role = each.value.role
|
role = each.value.role
|
||||||
member = each.value.member
|
member = each.value.member
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Copyright 2018 Google LLC
|
* Copyright 2020 Google LLC
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -32,21 +32,14 @@ variable "custom_roles" {
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_members" {
|
variable "iam" {
|
||||||
description = "Map of member lists used to set authoritative bindings, keyed by role."
|
description = "IAM bindings in {ROLE => [MEMBERS]} format."
|
||||||
type = map(list(string))
|
type = map(set(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_roles" {
|
variable "iam_additive" {
|
||||||
description = "List of roles used to set authoritative bindings."
|
description = "IAM additive bindings in {ROLE => [MEMBERS]} format."
|
||||||
type = list(string)
|
|
||||||
default = []
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
variable "iam_additive_bindings" {
|
|
||||||
description = "Map of roles lists used to set non authoritative bindings, keyed by members"
|
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
@ -90,6 +83,10 @@ variable "parent" {
|
||||||
description = "Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format."
|
description = "Parent folder or organization in 'folders/folder_id' or 'organizations/org_id' format."
|
||||||
type = string
|
type = string
|
||||||
default = null
|
default = null
|
||||||
|
validation {
|
||||||
|
condition = var.parent == null || can(regex("(organizations|folders)/[0-9]+", var.parent))
|
||||||
|
error_message = "Parent must be of the form folders/folder_id or organizations/organization_id."
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "policy_boolean" {
|
variable "policy_boolean" {
|
||||||
|
|
|
@ -15,5 +15,5 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
terraform {
|
terraform {
|
||||||
required_version = ">= 0.12.6"
|
required_version = ">= 0.13.0"
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,7 @@ module "pubsub" {
|
||||||
source = "./modules/pubsub"
|
source = "./modules/pubsub"
|
||||||
project_id = "my-project"
|
project_id = "my-project"
|
||||||
name = "my-topic"
|
name = "my-topic"
|
||||||
iam_roles = [
|
iam = {
|
||||||
"roles/pubsub.viewer",
|
|
||||||
"roles/pubsub.subscriber"
|
|
||||||
]
|
|
||||||
iam_members = {
|
|
||||||
"roles/pubsub.viewer" = ["group:foo@example.com"]
|
"roles/pubsub.viewer" = ["group:foo@example.com"]
|
||||||
"roles/pubsub.subscriber" = ["user:user1@example.com"]
|
"roles/pubsub.subscriber" = ["user:user1@example.com"]
|
||||||
}
|
}
|
||||||
|
@ -30,7 +26,7 @@ Subscriptions are defined with the `subscriptions` variable, allowing optional c
|
||||||
```hcl
|
```hcl
|
||||||
module "pubsub" {
|
module "pubsub" {
|
||||||
source = "./modules/pubsub"
|
source = "./modules/pubsub"
|
||||||
project_id = "my-project
|
project_id = "my-project"
|
||||||
name = "my-topic"
|
name = "my-topic"
|
||||||
subscriptions = {
|
subscriptions = {
|
||||||
test-pull = null
|
test-pull = null
|
||||||
|
@ -54,7 +50,7 @@ Push subscriptions need extra configuration in the `push_configs` variable.
|
||||||
```hcl
|
```hcl
|
||||||
module "pubsub" {
|
module "pubsub" {
|
||||||
source = "./modules/pubsub"
|
source = "./modules/pubsub"
|
||||||
project_id = "my-project
|
project_id = "my-project"
|
||||||
name = "my-topic"
|
name = "my-topic"
|
||||||
subscriptions = {
|
subscriptions = {
|
||||||
test-push = null
|
test-push = null
|
||||||
|
@ -74,16 +70,13 @@ module "pubsub" {
|
||||||
```hcl
|
```hcl
|
||||||
module "pubsub" {
|
module "pubsub" {
|
||||||
source = "./modules/pubsub"
|
source = "./modules/pubsub"
|
||||||
project_id = "my-project
|
project_id = "my-project"
|
||||||
name = "my-topic"
|
name = "my-topic"
|
||||||
subscriptions = {
|
subscriptions = {
|
||||||
test-1 = null
|
test-1 = null
|
||||||
test-1 = null
|
test-1 = null
|
||||||
}
|
}
|
||||||
subscription_iam_roles = {
|
subscription_iam = {
|
||||||
test-1 = ["roles/pubsub.subscriber"]
|
|
||||||
}
|
|
||||||
subscription_iam_members = {
|
|
||||||
test-1 = {
|
test-1 = {
|
||||||
"roles/pubsub.subscriber" = ["user:user1@ludomagno.net"]
|
"roles/pubsub.subscriber" = ["user:user1@ludomagno.net"]
|
||||||
}
|
}
|
||||||
|
@ -100,14 +93,12 @@ module "pubsub" {
|
||||||
| project_id | Project used for resources. | <code title="">string</code> | ✓ | |
|
| project_id | Project used for resources. | <code title="">string</code> | ✓ | |
|
||||||
| *dead_letter_configs* | Per-subscription dead letter policy configuration. | <code title="map(object({ topic = string max_delivery_attemps = number }))">map(object({...}))</code> | | <code title="">{}</code> |
|
| *dead_letter_configs* | Per-subscription dead letter policy configuration. | <code title="map(object({ topic = string max_delivery_attemps = number }))">map(object({...}))</code> | | <code title="">{}</code> |
|
||||||
| *defaults* | Subscription defaults for options. | <code title="object({ ack_deadline_seconds = number message_retention_duration = number retain_acked_messages = bool expiration_policy_ttl = string })">object({...})</code> | | <code title="{ ack_deadline_seconds = null message_retention_duration = null retain_acked_messages = null expiration_policy_ttl = null }">...</code> |
|
| *defaults* | Subscription defaults for options. | <code title="object({ ack_deadline_seconds = number message_retention_duration = number retain_acked_messages = bool expiration_policy_ttl = string })">object({...})</code> | | <code title="{ ack_deadline_seconds = null message_retention_duration = null retain_acked_messages = null expiration_policy_ttl = null }">...</code> |
|
||||||
| *iam_members* | IAM members for each topic role. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *iam* | IAM bindings for topic in {ROLE => [MEMBERS]} format. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *iam_roles* | IAM roles for topic. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
|
||||||
| *kms_key* | KMS customer managed encryption key. | <code title="">string</code> | | <code title="">null</code> |
|
| *kms_key* | KMS customer managed encryption key. | <code title="">string</code> | | <code title="">null</code> |
|
||||||
| *labels* | Labels. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
| *labels* | Labels. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
||||||
| *push_configs* | Push subscription configurations. | <code title="map(object({ attributes = map(string) endpoint = string oidc_token = object({ audience = string service_account_email = string }) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
| *push_configs* | Push subscription configurations. | <code title="map(object({ attributes = map(string) endpoint = string oidc_token = object({ audience = string service_account_email = string }) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
||||||
| *regions* | List of regions used to set persistence policy. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
| *regions* | List of regions used to set persistence policy. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
||||||
| *subscription_iam_members* | IAM members for each subscription and role. | <code title="map(map(list(string)))">map(map(list(string)))</code> | | <code title="">{}</code> |
|
| *subscription_iam* | IAM bindings for subscriptions in {SUBSCRIPTION => {ROLE => [MEMBERS]}} format. | <code title="map(map(list(string)))">map(map(list(string)))</code> | | <code title="">{}</code> |
|
||||||
| *subscription_iam_roles* | IAM roles for each subscription. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
|
||||||
| *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. | <code title="map(object({ labels = map(string) options = object({ ack_deadline_seconds = number message_retention_duration = number retain_acked_messages = bool expiration_policy_ttl = string }) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
| *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. | <code title="map(object({ labels = map(string) options = object({ ack_deadline_seconds = number message_retention_duration = number retain_acked_messages = bool expiration_policy_ttl = string }) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
|
|
@ -15,17 +15,15 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
locals {
|
locals {
|
||||||
iam_pairs = var.subscription_iam_roles == null ? [] : flatten([
|
sub_iam_members = flatten([
|
||||||
for name, roles in var.subscription_iam_roles :
|
for sub, roles in var.subscription_iam : [
|
||||||
[for role in roles : { name = name, role = role }]
|
for role, members in roles : {
|
||||||
|
sub = sub
|
||||||
|
role = role
|
||||||
|
members = members
|
||||||
|
}
|
||||||
|
]
|
||||||
])
|
])
|
||||||
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 = {
|
oidc_config = {
|
||||||
for k, v in var.push_configs : k => v.oidc_token
|
for k, v in var.push_configs : k => v.oidc_token
|
||||||
}
|
}
|
||||||
|
@ -52,11 +50,11 @@ resource "google_pubsub_topic" "default" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_pubsub_topic_iam_binding" "default" {
|
resource "google_pubsub_topic_iam_binding" "default" {
|
||||||
for_each = toset(var.iam_roles)
|
for_each = var.iam
|
||||||
project = var.project_id
|
project = var.project_id
|
||||||
topic = google_pubsub_topic.default.name
|
topic = google_pubsub_topic.default.name
|
||||||
role = each.value
|
role = each.key
|
||||||
members = lookup(var.iam_members, each.value, [])
|
members = each.value
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_pubsub_subscription" "default" {
|
resource "google_pubsub_subscription" "default" {
|
||||||
|
@ -103,11 +101,12 @@ resource "google_pubsub_subscription" "default" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_pubsub_subscription_iam_binding" "default" {
|
resource "google_pubsub_subscription_iam_binding" "default" {
|
||||||
for_each = local.iam_keypairs
|
for_each = {
|
||||||
|
for binding in local.sub_iam_members :
|
||||||
|
"${binding.sub}.${binding.role}" => binding
|
||||||
|
}
|
||||||
project = var.project_id
|
project = var.project_id
|
||||||
subscription = google_pubsub_subscription.default[each.value.name].name
|
subscription = google_pubsub_subscription.default[each.value.sub].name
|
||||||
role = each.value.role
|
role = each.value.role
|
||||||
members = lookup(
|
members = each.value.members
|
||||||
lookup(local.iam_members, each.value.name, {}), each.value.role, []
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,18 +39,12 @@ variable "defaults" {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_members" {
|
variable "iam" {
|
||||||
description = "IAM members for each topic role."
|
description = "IAM bindings for topic in {ROLE => [MEMBERS]} format."
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_roles" {
|
|
||||||
description = "IAM roles for topic."
|
|
||||||
type = list(string)
|
|
||||||
default = []
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "kms_key" {
|
variable "kms_key" {
|
||||||
description = "KMS customer managed encryption key."
|
description = "KMS customer managed encryption key."
|
||||||
type = string
|
type = string
|
||||||
|
@ -107,14 +101,8 @@ variable "subscriptions" {
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "subscription_iam_members" {
|
variable "subscription_iam" {
|
||||||
description = "IAM members for each subscription and role."
|
description = "IAM bindings for subscriptions in {SUBSCRIPTION => {ROLE => [MEMBERS]}} format."
|
||||||
type = map(map(list(string)))
|
type = map(map(list(string)))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "subscription_iam_roles" {
|
|
||||||
description = "IAM roles for each subscription."
|
|
||||||
type = map(list(string))
|
|
||||||
default = {}
|
|
||||||
}
|
|
||||||
|
|
|
@ -25,7 +25,7 @@ module "secret-manager" {
|
||||||
|
|
||||||
### Secret IAM bindings
|
### Secret IAM bindings
|
||||||
|
|
||||||
IAM bindings can be set per secret in the same way as for most other modules supporting IAM, via `iam_roles` and `iam_members` variables.
|
IAM bindings can be set per secret in the same way as for most other modules supporting IAM, using the `iam` variable.
|
||||||
|
|
||||||
```hcl
|
```hcl
|
||||||
module "secret-manager" {
|
module "secret-manager" {
|
||||||
|
@ -35,11 +35,7 @@ module "secret-manager" {
|
||||||
test-auto = null
|
test-auto = null
|
||||||
test-manual = ["europe-west1", "europe-west4"]
|
test-manual = ["europe-west1", "europe-west4"]
|
||||||
}
|
}
|
||||||
iam_roles = {
|
iam = {
|
||||||
test-auto = ["roles/secretmanager.secretAccessor"]
|
|
||||||
test-manual = ["roles/secretmanager.secretAccessor"]
|
|
||||||
}
|
|
||||||
iam_members = {
|
|
||||||
test-auto = {
|
test-auto = {
|
||||||
"roles/secretmanager.secretAccessor" = ["group:auto-readers@example.com"]
|
"roles/secretmanager.secretAccessor" = ["group:auto-readers@example.com"]
|
||||||
}
|
}
|
||||||
|
@ -80,8 +76,7 @@ module "secret-manager" {
|
||||||
| name | description | type | required | default |
|
| name | description | type | required | default |
|
||||||
|---|---|:---: |:---:|:---:|
|
|---|---|:---: |:---:|:---:|
|
||||||
| project_id | Project id where the keyring will be created. | <code title="">string</code> | ✓ | |
|
| project_id | Project id where the keyring will be created. | <code title="">string</code> | ✓ | |
|
||||||
| *iam_members* | IAM members keyed by secret name and role. | <code title="map(map(list(string)))">map(map(list(string)))</code> | | <code title="">{}</code> |
|
| *iam* | IAM bindings in {SECRET => {ROLE => [MEMBERS]}} format. | <code title="map(map(list(string)))">map(map(list(string)))</code> | | <code title="">{}</code> |
|
||||||
| *iam_roles* | IAM roles keyed by secret name. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
|
||||||
| *labels* | Optional labels for each secret. | <code title="map(map(string))">map(map(string))</code> | | <code title="">{}</code> |
|
| *labels* | Optional labels for each secret. | <code title="map(map(string))">map(map(string))</code> | | <code title="">{}</code> |
|
||||||
| *secrets* | Map of secrets to manage and their locations. If locations is null, automatic management will be set. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *secrets* | Map of secrets to manage and their locations. If locations is null, automatic management will be set. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *versions* | Optional versions to manage for each secret. Version names are only used internally to track individual versions. | <code title="map(map(object({ enabled = bool data = string })))">map(map(object({...})))</code> | | <code title="">{}</code> |
|
| *versions* | Optional versions to manage for each secret. Version names are only used internally to track individual versions. | <code title="map(map(object({ enabled = bool data = string })))">map(map(object({...})))</code> | | <code title="">{}</code> |
|
||||||
|
|
|
@ -16,13 +16,15 @@
|
||||||
|
|
||||||
locals {
|
locals {
|
||||||
# distinct is needed to make the expanding function argument work
|
# distinct is needed to make the expanding function argument work
|
||||||
iam_pairs = flatten([
|
iam = flatten([
|
||||||
for name, roles in var.iam_roles :
|
for secret, roles in var.iam : [
|
||||||
[for role in roles : { name = name, role = role }]
|
for role, members in roles : {
|
||||||
|
secret = secret
|
||||||
|
role = role
|
||||||
|
members = members
|
||||||
|
}
|
||||||
|
]
|
||||||
])
|
])
|
||||||
iam_keypairs = {
|
|
||||||
for pair in local.iam_pairs : "${pair.name}-${pair.role}" => pair
|
|
||||||
}
|
|
||||||
version_pairs = flatten([
|
version_pairs = flatten([
|
||||||
for secret, versions in var.versions : [
|
for secret, versions in var.versions : [
|
||||||
for name, attrs in versions : merge(attrs, { name = name, secret = secret })
|
for name, attrs in versions : merge(attrs, { name = name, secret = secret })
|
||||||
|
@ -73,11 +75,11 @@ resource "google_secret_manager_secret_version" "default" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_secret_manager_secret_iam_binding" "default" {
|
resource "google_secret_manager_secret_iam_binding" "default" {
|
||||||
provider = google-beta
|
provider = google-beta
|
||||||
for_each = local.iam_keypairs
|
for_each = {
|
||||||
|
for binding in local.iam : "${binding.secret}.${binding.role}" => binding
|
||||||
|
}
|
||||||
role = each.value.role
|
role = each.value.role
|
||||||
secret_id = google_secret_manager_secret.default[each.value.name].id
|
secret_id = google_secret_manager_secret.default[each.value.secret].id
|
||||||
members = lookup(
|
members = each.value.members
|
||||||
lookup(var.iam_members, each.value.name, {}), each.value.role, []
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Copyright 2018 Google LLC
|
* Copyright 2020 Google LLC
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* Copyright 2018 Google LLC
|
* Copyright 2020 Google LLC
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -14,18 +14,12 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
variable "iam_members" {
|
variable "iam" {
|
||||||
description = "IAM members keyed by secret name and role."
|
description = "IAM bindings in {SECRET => {ROLE => [MEMBERS]}} format."
|
||||||
type = map(map(list(string)))
|
type = map(map(list(string)))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_roles" {
|
|
||||||
description = "IAM roles keyed by secret name."
|
|
||||||
type = map(list(string))
|
|
||||||
default = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "labels" {
|
variable "labels" {
|
||||||
description = "Optional labels for each secret."
|
description = "Optional labels for each secret."
|
||||||
type = map(map(string))
|
type = map(map(string))
|
||||||
|
|
|
@ -15,14 +15,11 @@ module "service-directory" {
|
||||||
project_id = "my-project"
|
project_id = "my-project"
|
||||||
location = "europe-west1"
|
location = "europe-west1"
|
||||||
name = "sd-1"
|
name = "sd-1"
|
||||||
iam_members = {
|
iam = {
|
||||||
"roles/servicedirectory.editor" = [
|
"roles/servicedirectory.editor" = [
|
||||||
"serviceAccount:namespace-editor@example.com"
|
"serviceAccount:namespace-editor@example.com"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
iam_roles = [
|
|
||||||
"roles/servicedirectory.editor"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -40,16 +37,13 @@ module "service-directory" {
|
||||||
metadata = null
|
metadata = null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
service_iam_members = {
|
service_iam = {
|
||||||
one = {
|
one = {
|
||||||
"roles/servicedirectory.editor" = [
|
"roles/servicedirectory.editor" = [
|
||||||
"serviceAccount:service-editor.example.com"
|
"serviceAccount:service-editor.example.com"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
service_iam_roles = {
|
|
||||||
one = ["roles/servicedirectory.editor"]
|
|
||||||
}
|
|
||||||
endpoint_config = {
|
endpoint_config = {
|
||||||
"one/first" = { address = "127.0.0.1", port = 80, metadata = {} }
|
"one/first" = { address = "127.0.0.1", port = 80, metadata = {} }
|
||||||
"one/second" = { address = "127.0.0.2", port = 80, metadata = {} }
|
"one/second" = { address = "127.0.0.2", port = 80, metadata = {} }
|
||||||
|
@ -67,14 +61,11 @@ module "service-directory" {
|
||||||
project_id = "my-project"
|
project_id = "my-project"
|
||||||
location = "europe-west1"
|
location = "europe-west1"
|
||||||
name = "apps"
|
name = "apps"
|
||||||
iam_members = {
|
iam = {
|
||||||
"roles/servicedirectory.editor" = [
|
"roles/servicedirectory.editor" = [
|
||||||
"serviceAccount:namespace-editor@example.com"
|
"serviceAccount:namespace-editor@example.com"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
iam_roles = [
|
|
||||||
"roles/servicedirectory.editor"
|
|
||||||
]
|
|
||||||
services = {
|
services = {
|
||||||
app1 = { endpoints = ["one"], metadata = null }
|
app1 = { endpoints = ["one"], metadata = null }
|
||||||
}
|
}
|
||||||
|
@ -104,11 +95,9 @@ module "dns-sd" {
|
||||||
| name | Namespace name. | <code title="">string</code> | ✓ | |
|
| name | Namespace name. | <code title="">string</code> | ✓ | |
|
||||||
| project_id | Project used for resources. | <code title="">string</code> | ✓ | |
|
| project_id | Project used for resources. | <code title="">string</code> | ✓ | |
|
||||||
| *endpoint_config* | Map of endpoint attributes, keys are in service/endpoint format. | <code title="map(object({ address = string port = number metadata = map(string) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
| *endpoint_config* | Map of endpoint attributes, keys are in service/endpoint format. | <code title="map(object({ address = string port = number metadata = map(string) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
||||||
| *iam_members* | IAM members for each namespace role. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *iam* | IAM bindings for namespace, in {ROLE => [MEMBERS]} format. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *iam_roles* | IAM roles for the namespace. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
|
||||||
| *labels* | Labels. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
| *labels* | Labels. | <code title="map(string)">map(string)</code> | | <code title="">{}</code> |
|
||||||
| *service_iam_members* | IAM members for each service and role. | <code title="map(map(list(string)))">map(map(list(string)))</code> | | <code title="">{}</code> |
|
| *service_iam* | IAM bindings for services, in {SERVICE => {ROLE => [MEMBERS]}} format. | <code title="map(map(list(string)))">map(map(list(string)))</code> | | <code title="">{}</code> |
|
||||||
| *service_iam_roles* | IAM roles for each service. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
|
||||||
| *services* | Service configuration, using service names as keys. | <code title="map(object({ endpoints = list(string) metadata = map(string) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
| *services* | Service configuration, using service names as keys. | <code title="map(object({ endpoints = list(string) metadata = map(string) }))">map(object({...}))</code> | | <code title="">{}</code> |
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
|
|
@ -23,17 +23,14 @@ locals {
|
||||||
endpoints = {
|
endpoints = {
|
||||||
for ep in local.endpoint_list : "${ep.service}/${ep.endpoint}" => ep
|
for ep in local.endpoint_list : "${ep.service}/${ep.endpoint}" => ep
|
||||||
}
|
}
|
||||||
iam_pairs = var.service_iam_roles == null ? [] : flatten([
|
iam_pairs = var.service_iam == null ? [] : flatten([
|
||||||
for name, roles in var.service_iam_roles :
|
for name, bindings in var.service_iam :
|
||||||
[for role in roles : { name = name, role = role }]
|
[for role in keys(bindings) : { name = name, role = role }]
|
||||||
])
|
])
|
||||||
iam_keypairs = {
|
iam_keypairs = {
|
||||||
for pair in local.iam_pairs :
|
for pair in local.iam_pairs :
|
||||||
"${pair.name}-${pair.role}" => pair
|
"${pair.name}-${pair.role}" => pair
|
||||||
}
|
}
|
||||||
iam_members = (
|
|
||||||
var.service_iam_members == null ? {} : var.service_iam_members
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_service_directory_namespace" "default" {
|
resource "google_service_directory_namespace" "default" {
|
||||||
|
@ -46,10 +43,10 @@ resource "google_service_directory_namespace" "default" {
|
||||||
|
|
||||||
resource "google_service_directory_namespace_iam_binding" "default" {
|
resource "google_service_directory_namespace_iam_binding" "default" {
|
||||||
provider = google-beta
|
provider = google-beta
|
||||||
for_each = toset(var.iam_roles)
|
for_each = var.iam
|
||||||
name = google_service_directory_namespace.default.name
|
name = google_service_directory_namespace.default.name
|
||||||
role = each.value
|
role = each.key
|
||||||
members = lookup(var.iam_members, each.value, [])
|
members = each.value
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_service_directory_service" "default" {
|
resource "google_service_directory_service" "default" {
|
||||||
|
@ -66,7 +63,7 @@ resource "google_service_directory_service_iam_binding" "default" {
|
||||||
name = google_service_directory_service.default[each.value.name].name
|
name = google_service_directory_service.default[each.value.name].name
|
||||||
role = each.value.role
|
role = each.value.role
|
||||||
members = lookup(
|
members = lookup(
|
||||||
lookup(local.iam_members, each.value.name, {}), each.value.role, []
|
lookup(var.service_iam, each.value.name, {}), each.value.role, []
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,18 +25,12 @@ variable "endpoint_config" {
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_members" {
|
variable "iam" {
|
||||||
description = "IAM members for each namespace role."
|
description = "IAM bindings for namespace, in {ROLE => [MEMBERS]} format."
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_roles" {
|
|
||||||
description = "IAM roles for the namespace."
|
|
||||||
type = list(string)
|
|
||||||
default = []
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "labels" {
|
variable "labels" {
|
||||||
description = "Labels."
|
description = "Labels."
|
||||||
type = map(string)
|
type = map(string)
|
||||||
|
@ -58,18 +52,12 @@ variable "project_id" {
|
||||||
type = string
|
type = string
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "service_iam_members" {
|
variable "service_iam" {
|
||||||
description = "IAM members for each service and role."
|
description = "IAM bindings for services, in {SERVICE => {ROLE => [MEMBERS]}} format."
|
||||||
type = map(map(list(string)))
|
type = map(map(list(string)))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "service_iam_roles" {
|
|
||||||
description = "IAM roles for each service."
|
|
||||||
type = map(list(string))
|
|
||||||
default = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "services" {
|
variable "services" {
|
||||||
description = "Service configuration, using service names as keys."
|
description = "Service configuration, using service names as keys."
|
||||||
type = map(object({
|
type = map(object({
|
||||||
|
|
|
@ -12,8 +12,7 @@ module "repo" {
|
||||||
source e = "./modules/source-repository"
|
source e = "./modules/source-repository"
|
||||||
project_id = "my-project"
|
project_id = "my-project"
|
||||||
name = "my-repo"
|
name = "my-repo"
|
||||||
iam_roles = ["roles/source.reader"]
|
iam = {
|
||||||
iam_members = {
|
|
||||||
"roles/source.reader" = ["user:foo@example.com"]
|
"roles/source.reader" = ["user:foo@example.com"]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,10 +23,9 @@ module "repo" {
|
||||||
|
|
||||||
| name | description | type | required | default |
|
| name | description | type | required | default |
|
||||||
|---|---|:---: |:---:|:---:|
|
|---|---|:---: |:---:|:---:|
|
||||||
| name | Repository topic name. | <code title="">string</code> | ✓ | |
|
| name | Repository name. | <code title="">string</code> | ✓ | |
|
||||||
| project_id | Project used for resources. | <code title="">string</code> | ✓ | |
|
| project_id | Project used for resources. | <code title="">string</code> | ✓ | |
|
||||||
| *iam_members* | IAM members for each topic role. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
| *iam* | IAM bindings in {ROLE => [MEMBERS]} format. | <code title="map(list(string))">map(list(string))</code> | | <code title="">{}</code> |
|
||||||
| *iam_roles* | IAM roles for topic. | <code title="list(string)">list(string)</code> | | <code title="">[]</code> |
|
|
||||||
|
|
||||||
## Outputs
|
## Outputs
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,11 @@ resource "google_sourcerepo_repository" "default" {
|
||||||
}
|
}
|
||||||
|
|
||||||
resource "google_sourcerepo_repository_iam_binding" "default" {
|
resource "google_sourcerepo_repository_iam_binding" "default" {
|
||||||
for_each = toset(var.iam_roles)
|
for_each = var.iam
|
||||||
project = var.project_id
|
project = var.project_id
|
||||||
repository = google_sourcerepo_repository.default.name
|
repository = google_sourcerepo_repository.default.name
|
||||||
role = each.value
|
role = each.key
|
||||||
members = lookup(var.iam_members, each.value, [])
|
members = each.value
|
||||||
|
|
||||||
depends_on = [
|
depends_on = [
|
||||||
google_sourcerepo_repository.default
|
google_sourcerepo_repository.default
|
||||||
|
|
|
@ -19,19 +19,13 @@ variable "project_id" {
|
||||||
type = string
|
type = string
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_members" {
|
variable "iam" {
|
||||||
description = "IAM members for each topic role."
|
description = "IAM bindings in {ROLE => [MEMBERS]} format."
|
||||||
type = map(list(string))
|
type = map(list(string))
|
||||||
default = {}
|
default = {}
|
||||||
}
|
}
|
||||||
|
|
||||||
variable "iam_roles" {
|
|
||||||
description = "IAM roles for topic."
|
|
||||||
type = list(string)
|
|
||||||
default = []
|
|
||||||
}
|
|
||||||
|
|
||||||
variable "name" {
|
variable "name" {
|
||||||
description = "Repository topic name."
|
description = "Repository name."
|
||||||
type = string
|
type = string
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,7 @@ module "hub-to-spoke-2-peering" {
|
||||||
peer_network = module.vpc-spoke-2.self_link
|
peer_network = module.vpc-spoke-2.self_link
|
||||||
export_local_custom_routes = true
|
export_local_custom_routes = true
|
||||||
export_peer_custom_routes = false
|
export_peer_custom_routes = false
|
||||||
module_depends_on = [module.hub-to-spoke-1-peering.complete]
|
depends_on = [module.hub-to-spoke-1-peering]
|
||||||
}
|
}
|
||||||
|
|
||||||
################################################################################
|
################################################################################
|
||||||
|
@ -180,9 +180,9 @@ module "vm-spoke-2" {
|
||||||
}
|
}
|
||||||
|
|
||||||
module "service-account-gce" {
|
module "service-account-gce" {
|
||||||
source = "../../modules/iam-service-accounts"
|
source = "../../modules/iam-service-account"
|
||||||
project_id = var.project_id
|
project_id = var.project_id
|
||||||
names = ["gce-test"]
|
name = "gce-test"
|
||||||
iam_project_roles = {
|
iam_project_roles = {
|
||||||
(var.project_id) = [
|
(var.project_id) = [
|
||||||
"roles/container.developer",
|
"roles/container.developer",
|
||||||
|
@ -232,9 +232,9 @@ module "cluster-1-nodepool-1" {
|
||||||
# project level, with no risk of conflicts with pre-existing roles
|
# project level, with no risk of conflicts with pre-existing roles
|
||||||
|
|
||||||
module "service-account-gke-node" {
|
module "service-account-gke-node" {
|
||||||
source = "../../modules/iam-service-accounts"
|
source = "../../modules/iam-service-account"
|
||||||
project_id = var.project_id
|
project_id = var.project_id
|
||||||
names = ["gke-node"]
|
name = "gke-node"
|
||||||
iam_project_roles = {
|
iam_project_roles = {
|
||||||
(var.project_id) = [
|
(var.project_id) = [
|
||||||
"roles/logging.logWriter", "roles/monitoring.metricWriter",
|
"roles/logging.logWriter", "roles/monitoring.metricWriter",
|
||||||
|
|
|
@ -37,9 +37,9 @@ module "project" {
|
||||||
}
|
}
|
||||||
|
|
||||||
module "service-accounts" {
|
module "service-accounts" {
|
||||||
source = "../../modules/iam-service-accounts"
|
source = "../../modules/iam-service-account"
|
||||||
project_id = module.project.project_id
|
project_id = module.project.project_id
|
||||||
names = ["${local.prefix}gce-vm"]
|
name = "${local.prefix}gce-vm"
|
||||||
iam_project_roles = {
|
iam_project_roles = {
|
||||||
(var.project_id) = [
|
(var.project_id) = [
|
||||||
"roles/logging.logWriter",
|
"roles/logging.logWriter",
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue