From e4fa25f22d67f88aa2b46089d0ad4cba53a3dc99 Mon Sep 17 00:00:00 2001 From: Ludovico Magnocavallo Date: Sat, 7 Sep 2019 05:44:24 +0200 Subject: [PATCH] Organization sample: environments (Almanac bootstrap port) * add gitignore file * data and infra skeletons * org skeleton * org environments sample skeleton * Organization teams sample skeleton. * Organization env sample GCS for tf state. * org env: service accounts and GCS roles * org env: folders * org env: audit export * org env: shared project * org env: switch to released 3.1.0 project module version * rename organization top-level folder to organization-bootstrap * org env: use folders module with better outputs, module outputs * org env: switch the service accounts module to v2.0.0. * Merge ludo's branch from forked repo (#2) * org env: update gcs, sa, project modules * Use correct folder ID in format without prefix * org env: update folders module version, improve comments * org env: initial work on README, diagram, add variable for xpn roles * org env: update roles in README, backend file * org env: README changes * org env: README changes * org env: README changes * org env: README changes * org env: add IAM variables for audit and shared projects * org env: address README TODOs * org env: minor README changes * org env: minor README changes * org env: minor README changes * org env: simplify the sample's README by moving general considerations into the section README * Org examples README changes * org env: simplify initial state management, add comment for shared folder * org env: change state instructions to copy and rename instead of renaming backend file * org env: add a section in the README file to explain shared services, and detail options * fix comment for shared services project --- .gitignore | 8 + data/README.md | 0 infrastructure/README.md | 0 organization-bootstrap/README.md | 40 +++++ organization-bootstrap/environments/README.md | 63 +++++++ .../environments/backend.tf.sample | 23 +++ .../environments/diagram.png | Bin 0 -> 57325 bytes organization-bootstrap/environments/main.tf | 160 ++++++++++++++++++ .../environments/outputs.tf | 62 +++++++ .../environments/providers.tf | 1 + .../environments/variables.tf | 85 ++++++++++ .../environments/versions.tf | 4 + organization-bootstrap/teams/README.md | 0 13 files changed, 446 insertions(+) create mode 100644 .gitignore create mode 100644 data/README.md create mode 100644 infrastructure/README.md create mode 100644 organization-bootstrap/README.md create mode 100644 organization-bootstrap/environments/README.md create mode 100644 organization-bootstrap/environments/backend.tf.sample create mode 100644 organization-bootstrap/environments/diagram.png create mode 100644 organization-bootstrap/environments/main.tf create mode 100644 organization-bootstrap/environments/outputs.tf create mode 100644 organization-bootstrap/environments/providers.tf create mode 100644 organization-bootstrap/environments/variables.tf create mode 100644 organization-bootstrap/environments/versions.tf create mode 100644 organization-bootstrap/teams/README.md diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..30f62292e --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +**/.terraform +**/terraform.tfstate* +**/terraform.tfvars +.idea +.vscode +backend-config.hcl +credentials.json +key.json diff --git a/data/README.md b/data/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/infrastructure/README.md b/infrastructure/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/organization-bootstrap/README.md b/organization-bootstrap/README.md new file mode 100644 index 000000000..b8799d9c8 --- /dev/null +++ b/organization-bootstrap/README.md @@ -0,0 +1,40 @@ +# Organization-level bootstrap samples + +This set of Terraform root modules is designed with two main purposes in mind: automating the organizational layout, and bootstrapping the initial resources and the corresponding IAM roles, which will then be used to automate the actual infrastructure. + +Despite being fairly generic, these modules closely match some of the initial automation stages we have implemented in actual customer engagements, and are purposely kept simple to offer a good starting point for further customizations. + +There are several advantages in using an initial stage like the ones provided here: + +- automate and parameterize creation of the organizational layout, documenting it through code +- use a single declarative tool to create and manage both prerequisites and the actual infrastructure, eliminating the need for manual commands, scripts or external tools +- enforce separation of duties at the environment (or tenant in multi-tenant architectures) level, by automating creation of per-environment Terraform service accounts, their IAM roles, and GCS buckets to hold state +- decouple and document the use of organization-level permissions from the day to day management of the actual infrastructure, by assigning a minimum but sufficient set of high level IAM roles to Terraform service accounts in an initial stage +- provide a sane place for the creation and management of shared resources that are not tied to a specific environment + +## Operational considerations + +This specific type of preliminary automation stage is usually fairly static, only changing when a new environment or shared resource is added or modified, and lends itself well to being applied manually by organization administrators. One secondary advantage of running this initial stage manually, is eliminating the need to create and manage automation credentials that embed sensitive permissions scoped at the organization or root folder level. + +### IAM roles + +This type of automation stage needs very specific IAM roles on the root node (organization or folder), and additional roles at the organization level if the generated service accounts for automation need to be able to create and manage Shared VPC. The needed roles are: + +- on the root node Project Creator, Folder Administrator, Logging Administrator +- on the billing account or organization Billing Account Administrator +- on the organization Organization Administrator, if Shared VPC needs to be managed by the automation service accounts + +### State + +This type of stage creates the prerequisites for Terraform automation including the GCS bucket used for its own remote state, so some care needs to be used when running it for the first time, when its GCS bucket has not yet been created. + +After the first successful `terraform apply`, copy the `backend.tf.sample` file +to `backend.tf`, then set the bucket name to the one shown in the `bootstrap_tf_gcs_bucket` output in the new file. Once that is done, run `terraform apply` again to transfer local state to the remote GCS bucket. From then on, state will be remote. + +### Things to be aware of + +Using `count` in Terraform resources has the [well-known limitation](https://github.com/hashicorp/terraform/issues/18767) that changing the variable controlling `count` results in the potential unwanted deletion of resources. + +These samples use `count` on the `environments` list variable to manage multiples for key resources like service accounts, GCS buckets, and IAM roles. Environment names are usually stable, but care must still be taken in defining the initial list so that names are final, and names for temporary environments (if any are needed) are last so they don't trigger recreation of resources based on the following elements in the list. + +This issue will be addressed in a future release of these examples, by replacing `count` with the new `foreach` construct [introduced in Terraform 0.12.6](https://twitter.com/mitchellh/status/1156661893789966336?lang=en) that uses key-based indexing. diff --git a/organization-bootstrap/environments/README.md b/organization-bootstrap/environments/README.md new file mode 100644 index 000000000..0d673dc14 --- /dev/null +++ b/organization-bootstrap/environments/README.md @@ -0,0 +1,63 @@ +# Environment-based organizational sample + +This sample creates an organizational layout with a single level, where each folder is usually mapped to one infrastructure environment (test, dev, etc.). It also sets up all prerequisites for automation (GCS state buckets, service accounts, etc.), and the correct roles on those to enforce separation of duties at the environment level. + +This layout is well suited for medium-sized infrastructures managed by a small set of teams, where the complexity in application resource ownership and access roles is mostly dealt with at the project level, and/or in the individual services (GKE, Cloud SQL, etc.). Its simplicity also makes it a good starting point for more complex or specialized layouts. + +![High-level diagram](diagram.png "High-level diagram") + +Refer to the [section-level README](../README.md) for general considerations about this type of samples, and usage instructions. + +## Managed resources and services + +This sample creates several distinct groups of resources: + +- one folder per environment +- one top-level project to hold Terraform-related resources +- one top-level project to set up and host centralized audit log exports (optional) +- one top-level shared services project + +The number of resources in this sample is kept to a minimum so as to make it more generally applicable, further resources can be easily added by leveraging the full array of [Cloud Foundation Toolkit modules](https://github.com/terraform-google-modules), especially in the shared services project. + +## Shared services project + +This sample contains a single, top-level project used to host services shared across environments (eg GCS, GCR, KMS, Cloud Build, etc.). In our experience, that is enough for many customers, especially those using this organizational layout. + +For more complex setups where multiple shared services projects are needed to encapsulate a larger number of resources, shared services should be treated as an extra environment so that they can be managed by a dedicated set of Terraform files, using a separate service account and GCS bucket, with a folder to contain shared projects. + +If no shared services are needed, the shared service project module can of course be removed from `main.tf`. + + +## Inputs + +| Name | Description | Type | Default | Required | +|------|-------------|:----:|:-----:|:-----:| +| audit\_viewers | Audit project viewers, in IAM format. | list | `` | no | +| billing\_account\_id | Billing account id used as default for new projects. | string | n/a | yes | +| environments | Environment short names. | list(string) | n/a | yes | +| gcs\_location | GCS bucket location. | string | `"EU"` | no | +| generate\_service\_account\_keys | Generate and store service account keys in the state file. | string | `"false"` | no | +| grant\_xpn\_roles | Grant roles needed for Shared VPC creation to service accounts. | string | `"true"` | no | +| organization\_id | Organization id. | string | n/a | yes | +| prefix | Prefix used for resources that need unique names. | string | n/a | yes | +| project\_services | Service APIs enabled by default in new projects. | list | `` | no | +| root\_node | Root node for the new hierarchy, either 'organizations/org_id' or 'folders/folder_id'. | string | n/a | yes | +| shared\_bindings\_members | List of comma-delimited IAM-format members for the additional shared project bindings. | list | `` | no | +| shared\_bindings\_roles | List of roles for additional shared project bindings. | list | `` | no | +| terraform\_owners | Terraform project owners, in IAM format. | list | `` | no | + +## Outputs + +| Name | Description | +|------|-------------| +| audit\_logs\_bq\_dataset | Bigquery dataset for the audit logs export. | +| audit\_logs\_project | Project that holds the audit logs export resources. | +| bootstrap\_tf\_gcs\_bucket | GCS bucket used for the bootstrap Terraform state. | +| environment\_folders | Top-level environment folders. | +| environment\_service\_account\_keys | Service account keys used to run each environment Terraform modules. | +| environment\_service\_accounts | Service accounts used to run each environment Terraform modules. | +| environment\_tf\_gcs\_buckets | GCS buckets used for each environment Terraform state. | +| shared\_resources\_project | Project that holdes resources shared across environments. | +| terraform\_project | Project that holds the base Terraform resources. | + + diff --git a/organization-bootstrap/environments/backend.tf.sample b/organization-bootstrap/environments/backend.tf.sample new file mode 100644 index 000000000..511f887e6 --- /dev/null +++ b/organization-bootstrap/environments/backend.tf.sample @@ -0,0 +1,23 @@ +# Copyright 2019 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +terraform { + backend "gcs" { + # once initial apply has completed, copy this file to `backend.tf` then + # set the `bucket` value to the `bootstrap_tf_gcs_bucket` output, then + # run apply again to transfer state + bucket = "" + } +} diff --git a/organization-bootstrap/environments/diagram.png b/organization-bootstrap/environments/diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..ac6d79364a2490ad01572194d48d65ef971ff4ae GIT binary patch literal 57325 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 S=6{f900K`}KbLh*2~7aSqXA(6 literal 0 HcmV?d00001 diff --git a/organization-bootstrap/environments/main.tf b/organization-bootstrap/environments/main.tf new file mode 100644 index 000000000..9b5ef5736 --- /dev/null +++ b/organization-bootstrap/environments/main.tf @@ -0,0 +1,160 @@ +# Copyright 2019 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +############################################################################### +# Terraform top-level resources # +############################################################################### + +# Terraform project + +module "project-tf" { + source = "terraform-google-modules/project-factory/google//modules/fabric-project" + version = "3.2.0" + parent = var.root_node + billing_account = var.billing_account_id + prefix = var.prefix + name = "terraform" + lien_reason = "terraform" + owners = var.terraform_owners + activate_apis = var.project_services +} + +# per-environment service accounts + +module "service-accounts-tf-environments" { + source = "terraform-google-modules/service-accounts/google" + version = "2.0.0" + project_id = module.project-tf.project_id + org_id = var.organization_id + billing_account_id = var.billing_account_id + prefix = var.prefix + names = var.environments + grant_billing_role = true + grant_xpn_roles = var.grant_xpn_roles + generate_keys = var.generate_service_account_keys +} + +# bootstrap Terraform state GCS bucket + +module "gcs-tf-bootstrap" { + source = "terraform-google-modules/cloud-storage/google" + version = "1.0.0" + project_id = module.project-tf.project_id + prefix = "${var.prefix}-tf" + names = ["tf-bootstrap"] + location = var.gcs_location +} + +# per-environment Terraform state GCS buckets + +module "gcs-tf-environments" { + source = "terraform-google-modules/cloud-storage/google" + version = "1.0.0" + project_id = module.project-tf.project_id + prefix = "${var.prefix}-tf" + names = var.environments + location = var.gcs_location + set_admin_roles = true + bucket_admins = zipmap( + var.environments, + module.service-accounts-tf-environments.iam_emails_list + ) +} + +############################################################################### +# Top-level folders # +############################################################################### + +# TODO(ludomagno): move XPN admin role here after checking it now works on folders + +module "folders-top-level" { + source = "terraform-google-modules/folders/google" + version = "2.0.0" + parent = var.root_node + names = var.environments + set_roles = true + per_folder_admins = module.service-accounts-tf-environments.iam_emails_list + folder_admin_roles = [ + "roles/resourcemanager.folderViewer", + "roles/resourcemanager.projectCreator", + "roles/owner", + "roles/compute.networkAdmin", + ] +} + +############################################################################### +# Audit log exports # +############################################################################### + +# audit logs project + +module "project-audit" { + source = "terraform-google-modules/project-factory/google//modules/fabric-project" + version = "3.2.0" + parent = var.root_node + billing_account = var.billing_account_id + prefix = var.prefix + name = "audit" + lien_reason = "audit" + activate_apis = var.project_services + viewers = var.audit_viewers +} + +# audit logs destination on BigQuery + +module "bq-audit-export" { + source = "terraform-google-modules/log-export/google//modules/bigquery" + version = "3.0.0" + project_id = module.project-audit.project_id + dataset_name = "logs_audit_${replace(var.environments[0], "-", "_")}" + log_sink_writer_identity = module.log-sink-audit.writer_identity +} + +# audit log sink +# set the organization as parent to export audit logs for all environments + +module "log-sink-audit" { + source = "terraform-google-modules/log-export/google" + version = "3.0.0" + filter = "logName: \"/logs/cloudaudit.googleapis.com%2Factivity\" OR logName: \"/logs/cloudaudit.googleapis.com%2Fsystem_event\"" + log_sink_name = "logs-audit-${var.environments[0]}" + parent_resource_type = "folder" + parent_resource_id = split("/", module.folders-top-level.ids_list[0])[1] + include_children = "true" + unique_writer_identity = "true" + destination_uri = "${module.bq-audit-export.destination_uri}" +} + +############################################################################### +# Shared resources (GCR, GCS, KMS, etc.) # +############################################################################### + +# shared resources project +# see the README file for additional options on managing shared services + +module "project-shared-resources" { + source = "terraform-google-modules/project-factory/google//modules/fabric-project" + version = "3.2.0" + parent = var.root_node + billing_account = var.billing_account_id + prefix = var.prefix + name = "shared" + lien_reason = "shared" + activate_apis = var.project_services + extra_bindings_roles = var.shared_bindings_roles + extra_bindings_members = var.shared_bindings_members +} + +# Add further modules here for resources that are common to all environments +# like GCS buckets (used to hold shared assets), Container Registry, KMS, etc. diff --git a/organization-bootstrap/environments/outputs.tf b/organization-bootstrap/environments/outputs.tf new file mode 100644 index 000000000..cca71987d --- /dev/null +++ b/organization-bootstrap/environments/outputs.tf @@ -0,0 +1,62 @@ +# Copyright 2019 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +output "terraform_project" { + description = "Project that holds the base Terraform resources." + value = module.project-tf.project_id +} + +output "bootstrap_tf_gcs_bucket" { + description = "GCS bucket used for the bootstrap Terraform state." + value = module.gcs-tf-bootstrap.name +} + +output "environment_folders" { + description = "Top-level environment folders." + value = module.folders-top-level.ids +} + +output "environment_tf_gcs_buckets" { + description = "GCS buckets used for each environment Terraform state." + value = module.gcs-tf-environments.names +} + +output "environment_service_account_keys" { + description = "Service account keys used to run each environment Terraform modules." + sensitive = true + value = module.service-accounts-tf-environments.keys +} + +output "environment_service_accounts" { + description = "Service accounts used to run each environment Terraform modules." + value = module.service-accounts-tf-environments.emails +} + +output "audit_logs_bq_dataset" { + description = "Bigquery dataset for the audit logs export." + value = module.bq-audit-export.resource_name +} + +output "audit_logs_project" { + description = "Project that holds the audit logs export resources." + value = module.project-audit.project_id +} + +output "shared_resources_project" { + description = "Project that holdes resources shared across environments." + value = module.project-shared-resources.project_id +} + +# Add further outputs here for the additional modules that manage shared +# resources, like GCR, GCS buckets, KMS, etc. diff --git a/organization-bootstrap/environments/providers.tf b/organization-bootstrap/environments/providers.tf new file mode 100644 index 000000000..33091732e --- /dev/null +++ b/organization-bootstrap/environments/providers.tf @@ -0,0 +1 @@ +provider "google" {} diff --git a/organization-bootstrap/environments/variables.tf b/organization-bootstrap/environments/variables.tf new file mode 100644 index 000000000..42d2ca250 --- /dev/null +++ b/organization-bootstrap/environments/variables.tf @@ -0,0 +1,85 @@ +variable "audit_viewers" { + description = "Audit project viewers, in IAM format." + default = [] +} + +variable "billing_account_id" { + description = "Billing account id used as default for new projects." + type = string +} + +variable "environments" { + description = "Environment short names." + type = list(string) +} + +variable "generate_service_account_keys" { + description = "Generate and store service account keys in the state file." + default = false +} + +variable "gcs_location" { + description = "GCS bucket location." + default = "EU" +} + +variable "grant_xpn_roles" { + description = "Grant roles needed for Shared VPC creation to service accounts." + default = true +} + + +variable "organization_id" { + description = "Organization id." + type = string +} + +variable "prefix" { + description = "Prefix used for resources that need unique names." + type = string +} + +variable "root_node" { + description = "Root node for the new hierarchy, either 'organizations/org_id' or 'folders/folder_id'." + type = string +} + +variable "shared_bindings_members" { + description = "List of comma-delimited IAM-format members for the additional shared project bindings." + # example: ["user:a@example.com,b@example.com", "user:c@example.com"] + default = [] +} +variable "shared_bindings_roles" { + description = "List of roles for additional shared project bindings." + # example: ["roles/storage.objectViewer", "roles/storage.admin"] + default = [] +} + +variable "terraform_owners" { + description = "Terraform project owners, in IAM format." + default = [] +} + +variable "project_services" { + description = "Service APIs enabled by default in new projects." + default = [ + "bigquery-json.googleapis.com", + "bigquerystorage.googleapis.com", + "cloudbilling.googleapis.com", + "cloudresourcemanager.googleapis.com", + "compute.googleapis.com", + "container.googleapis.com", + "containerregistry.googleapis.com", + "deploymentmanager.googleapis.com", + "iam.googleapis.com", + "iamcredentials.googleapis.com", + "logging.googleapis.com", + "oslogin.googleapis.com", + "pubsub.googleapis.com", + "replicapool.googleapis.com", + "replicapoolupdater.googleapis.com", + "resourceviews.googleapis.com", + "serviceusage.googleapis.com", + "storage-api.googleapis.com", + ] +} diff --git a/organization-bootstrap/environments/versions.tf b/organization-bootstrap/environments/versions.tf new file mode 100644 index 000000000..ac97c6ac8 --- /dev/null +++ b/organization-bootstrap/environments/versions.tf @@ -0,0 +1,4 @@ + +terraform { + required_version = ">= 0.12" +} diff --git a/organization-bootstrap/teams/README.md b/organization-bootstrap/teams/README.md new file mode 100644 index 000000000..e69de29bb