cloud-foundation-fabric/fast/stages-multitenant/0-bootstrap-tenant
Ludovico Magnocavallo 5453c585e0
FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052)
* rename stages

* remove support for external org billing, rename output files

* resman: make groups optional, align on new billing account variable

* bootstrap: multitenant outputs

* tenant bootstrap stage, untested

* fix folder name

* fix stage 0 output names

* optional creation for tag keys in organization module

* single tenant bootstrap minus tag

* rename output files, add tenant tag key

* fix organization module tag values output

* test skipping creation for tags in organization module

* single tenant bootstrap plan working

* multitenant bootstrap

* tfdoc

* fix check links error messages

* fix links

* tfdoc

* fix links

* rename fast tests, fix bootstrap tests

* multitenant stages have their own folder, simplify stage numbering

* stage renumbering

* wip

* rename tests

* exclude fast providers in fixture

* stage 0 tests

* stage 1 tests

* network stages tests

* stage tests

* tfdoc

* fix links

* tfdoc

* multitenant tests

* remove local files

* stage links command

* fix links script, TODO

* wip

* wip single tenant bootstrap

* working tenant bootstrap

* update gitignore

* remove local files

* tfdoc

* remove local files

* allow tests for tenant bootstrap stage

* tenant bootstrap proxies stage 1 tfvars

* stage 2 and 3 service accounts and IAM in tenant bootstrap

* wip

* wip

* wip

* drop multitenant bootstrap

* tfdoc

* add missing stage 2 SAs, fix org-level IAM condition

* wip

* wip

* optional tag value creation in organization module

* stage 1 working

* linting

* linting

* READMEs

* wip

* Make stage-links script work in old macos bash

* stage links command help

* fix output file names

* diagrams

* fix svg

* stage 0 skeleton and diagram

* test svg

* test svg

* test diagram

* diagram

* readme

* fix stage links script

* stage 0 readme

* README changes

* stage readmes

* fix outputs order

* fix link

* fix tests

* stage 1 test

* skip stage example

* boilerplate

* fix tftest skip

* default bootstrap stage log sinks to log buckets

* add logging to tenant bootstrap

* move iam variables out of tenant config

* fix cicd, reintroduce missing variable

* use optional in stage 1 cicd variable

* rename extras stage

* rename and move identity providers local, use optional for cicd variable

* tfdoc

* add support for wif pool and providers, ci/cd

* tfdoc

* fix links

* better handling of modules repository

* add missing role on logging project

* fix cicd pools in locals, test cicd

* fix workflow extension

* fix module source replacement

* allow tenant bootstrap cicd sa to impersonate resman sa

* tenant workflow templates fix for no providers file

* fix output files, push github workflow template to new repository

* remove try from outpout files

* align stage 1 cicd internals to stage 0

* tfdoc

* tests

* fix tests

* tests

* improve variable descriptions

* use optional in fast features

* actually create tenant log sinks, and allow the resman sa to do it

* test

* tests

* aaaand tests again

* fast features tenant override

* fast features tenant override

* fix wording

* add missing comment

* configure pf service accounts

* add missing comment

* tfdoc

* tests

* IAM docs

* update copyright

---------

Co-authored-by: Julio Castillo <jccb@google.com>
2023-02-04 15:00:45 +01:00
..
templates FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052) 2023-02-04 15:00:45 +01:00
IAM.md FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052) 2023-02-04 15:00:45 +01:00
README.md FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052) 2023-02-04 15:00:45 +01:00
automation-sas.tf FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052) 2023-02-04 15:00:45 +01:00
automation.tf FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052) 2023-02-04 15:00:45 +01:00
billing.tf FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052) 2023-02-04 15:00:45 +01:00
cicd.tf FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052) 2023-02-04 15:00:45 +01:00
diagram.svg FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052) 2023-02-04 15:00:45 +01:00
identity-providers.tf FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052) 2023-02-04 15:00:45 +01:00
log-export.tf FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052) 2023-02-04 15:00:45 +01:00
main.tf FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052) 2023-02-04 15:00:45 +01:00
organization.tf FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052) 2023-02-04 15:00:45 +01:00
outputs-files.tf FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052) 2023-02-04 15:00:45 +01:00
outputs-gcs.tf FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052) 2023-02-04 15:00:45 +01:00
outputs.tf FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052) 2023-02-04 15:00:45 +01:00
variables.tf FAST multitenant bootstrap and resource management, rename org-level FAST stages (#1052) 2023-02-04 15:00:45 +01:00

README.md

Tenant bootstrap

The primary purpose of this stage is to decouple a single tenant from centrally managed resources in the organization, so that subsequent management of the tenant's own hierarchy and resources can be implemented with a high degree of autonomy.

It is logically equivalent to organization-level bootstrap as it's concerned with setting up IAM bindings on a root node and creating supporting projects attached to it, but it depends on the organization-level resource management stage and uses the same service account and permissions since it operates at the hierarchy level (folders, tags, organization policies).

The resources and policies managed here are:

  • the tag value in the tenant key used in IAM conditions
  • the billing IAM bindings for the tenant-specific automation service accounts
  • the organization-level IAM binding that allows conditional managing of org policies on the tenant folder
  • the top-level tenant folder which acts as the root of the tenant's hierarchy
  • any organization policy that needs to be set for the tenant on its root folder
  • the tenant automation and logging projects
  • service accounts for all tenant stages
  • GCS buckets for bootstrap and resource management state
  • optional CI/CD setup for this and the resource management tenant stages
  • tenant-specific Workload Identity Federation pool and providers (planned)

One notable difference compared to organization-level bootstrap is the creation of service accounts for all tenant stages: this is done here so that Billing and Organization Policy Admin bindings can be set, leveraging permissions of the org-level resman service account which is used to run this stage. Doing this here avoids the need to grant broad scoped permissions on the organization to tenant-level service accounts, and effectively decouples the tenant from the organization.

The following diagram is a high level reference of what this stage manages, showing one hypothetical tenant (additional tenants require additional instances of this stage being deployed):

%%{init: {'theme':'base'}}%%
classDiagram
    Organization~🏢~ -- Tenant 0~📁~
    Tenant 0~📁~ -- tn0_automation
    Tenant 0~📁~ -- tn0_logging
    class Organization~🏢~ {
        - tag value
        - IAM bindings()
        - org policies()
    }
    class Tenant 0~📁~ {
        - log sinks
        - IAM bindings()
        - tag bindings()
    }
    class tn0_automation {
        - GCS buckets
        - service accounts
        - optional CI/CD
        - IAM bindings()
    }
    class tn0_logging {
        - log sink destinations
    }

As most of the features of this stage follow the same design and configurations of the organization-level bootstrap stage, we will only focus on the tenant-specific configuration in this document.

Naming

This stage sets the prefix used to name tenant resources, and passes it downstream to the other tenant stages together with the other globals needed by the tenant. The default is to append the tenant short name (a 3 or 4 letter acronym or abbreviation) to the organization-level prefix, if that is not desired this can be changed by editing local definitions in the main.tf file. Just be aware that some resources have name length constraints.

How to run this stage

The tenant bootstrap stage is the effective boundary between organization and tenant-level resources: it uses the same inputs as the organization-level resource management stage, and produces outputs which provide the needed context to all other tenant stages.

Output files and cross-stage variables

As mentioned above, the organization-level set of output files are used here with one exception: the provider file is different since state is specific to this stage. The stage-links.sh script can be used to get the commands needed for the provider and output files, just pass a single argument with your FAST output files folder path, or GCS bucket URI:

../../stage-links.sh ~/fast-config

The script output can be copy/pasted to a terminal:

# copy and paste the following commands for '0-bootstrap-tenant'

cp ~/fast-config/providers/0-bootstrap-tenant-providers.tf ./
ln -s ~/fast-config/tfvars/globals.auto.tfvars.json ./
ln -s ~/fast-config/tfvars/0-bootstrap.auto.tfvars.json ./
ln -s ~/fast-config/tfvars/1-resman.auto.tfvars.json ./

# ---> remember to set the prefix in the provider file <---

As shown in the script output above, the provider file is a template used as a source for potentially multiple tenant installations, so it needs to be specifically configured for this tenant by setting the backend prefix to a unique string so that the Terraform state file will not overlap with other tenants. Open it in an editor and perform the change before proceeding.

Global overrides

The globals variable file linekd above contains definition which were set for the organization, for example the locations used for log sink destinations. These might not be correct for each tenant, so this stage allows overriding them via the tenant configuration variable described in the next section.

Tenant-level configuration

The tenant configuration resides in the tenant_config variable, this is an example configuration for a tenant with comments explaining the different choices that need to be made:

tenant_config = {
  # used for the top-level folder name
  descriptive_name = "My First Tenant"
  # tenant-specific groups, only the admin group is required
  # the organization domain is automatically added after the group name
  groups = {
    gcp-admins          = "tn01-admins"
    # gcp-devops          = "tn01-devops"
    # gcp-network-admins  = "tn01-networking"
    # gcp-security-admins = "tn01-security"
  }
  # the 3 or 4 letter acronym or abbreviation used in resource names
  short_name = "tn01"
  # optional CI/CD configuration, refer to the org-level stages for information 
  # cicd = {
  #   branch            = null
  #   identity_provider = "foo-provider"
  #   name              = "myorg/tn01-bootstrap"
  #   type              = "github"
  # }
  # optional group-level IAM bindings to add to the top-level folder
  # group_iam = {
  #   tn01-support = ["roles/viewer"]
  # }
  # optional IAM bindings to add to the top-level folder
  # iam       = {
  #   "roles/logging.admin" = [
  #     "serviceAccount:foo@myprj.iam.gserviceaccount.com"
  #   ]
  # }
  # optional location overrides to global locations
  # locations = {
  #   bq      = null
  #   gcs     = null
  #   logging = null
  #   pubsub  = null
  # }
  # optional folder ids for automation and logging project folders, typically
  # added in later stages and entered here once created
  # project_parent_ids = {
  #   automation = "folders/012345678"
  #   logging    = "folders/0123456789"
  # }
}
# tftest skip

Configure the tenant variable in a tfvars file for this stage. A few minor points worth noting:

  • the administrator group is the only one required here, specifying other groups only has the effect of populating the output file with group names for reuse in later stages
  • the iam variable is merged with the IAM bindings for service accounts in the main.tf file, which take precedence; if a role specified in the variable is ignored, that's probably the case
  • locations can be overridden at the attribute level, there's no need to specify those that are equal to the ones in the organization globals file

Running the stage

Once the configuration is done just go through the usual init/apply cycle. On successful apply, a tfvars file specific for this tenant and a set of provider files will be created.

TODO

  • tenant-level Workload Identity Federation pool and providers configuration
  • tenant-level logging project and sinks

Files

name description modules resources
automation-sas.tf Tenant automation stage 2 and 3 service accounts. iam-service-account google_organization_iam_member
automation.tf Tenant automation project and resources. gcs · iam-service-account · project
billing.tf Billing roles for standalone billing accounts. google_billing_account_iam_member
cicd.tf Workload Identity Federation configurations for CI/CD. iam-service-account · source-repository
identity-providers.tf Workload Identity Federation provider definitions. google_iam_workload_identity_pool · google_iam_workload_identity_pool_provider
log-export.tf Audit log project and sink. bigquery-dataset · gcs · logging-bucket · project · pubsub
main.tf Module-level locals and resources. folder
organization.tf Organization tag and conditional IAM grant. organization google_organization_iam_member · google_tags_tag_value_iam_member
outputs-files.tf Output files persistence to local filesystem. local_file
outputs-gcs.tf Output files persistence to automation GCS bucket. google_storage_bucket_object
outputs.tf Module outputs.
variables.tf Module variables.

Variables

name description type required default producer
automation Automation resources created by the organization-level bootstrap stage. object({…}) 0-bootstrap
billing_account Billing account id. If billing account is not part of the same org set is_org_level to false. object({…}) 0-bootstrap
organization Organization details. object({…}) 0-bootstrap
prefix Prefix used for resources that need unique names. Use 9 characters or less. string 0-bootstrap
tag_keys Organization tag keys. object({…}) 1-resman
tag_names Customized names for resource management tags. object({…}) 1-resman
tag_values Organization resource management tag values. map(string) 1-resman
tenant_config Tenant configuration. Short name must be 4 characters or less. object({…})
cicd_repositories CI/CD repository configuration. Identity providers reference keys in the federated_identity_providers variable. Set to null to disable, or set individual repositories to null if not needed. object({…}) null
custom_roles Custom roles defined at the organization level, in key => id format. object({…}) null 0-bootstrap
fast_features Selective control for top-level FAST features. object({…}) {} 0-bootstrap
federated_identity_providers Workload Identity Federation pools. The cicd_repositories variable references keys here. map(object({…})) {}
group_iam Tenant-level custom group IAM settings in group => [roles] format. map(list(string)) {}
iam Tenant-level custom IAM settings in role => [principal] format. map(list(string)) {}
iam_additive Tenant-level custom IAM settings in role => [principal] format for non-authoritative bindings. map(list(string)) {}
locations Optional locations for GCS, BigQuery, and logging buckets created here. These are the defaults set at the organization level, and can be overridden via the tenant config variable. object({…}) {…} 0-bootstrap
log_sinks Tenant-level log sinks, in name => {type, filter} format. map(object({…})) {…}
outputs_location Enable writing provider, tfvars and CI/CD workflow files to local filesystem. Leave null to disable. string null
project_parent_ids Optional parents for projects created here in folders/nnnnnnn format. Null values will use the tenant folder as parent. object({…}) {…}
test_principal Used when testing to bypass the data source returning the current identity. string null

Outputs

name description sensitive consumers
cicd_workflows CI/CD workflows for tenant bootstrap and resource management stages.
federated_identity Workload Identity Federation pool and providers.
provider Terraform provider file for tenant resource management stage. stage-01
tenant_resources Tenant-level resources.
tfvars Terraform variable files for the following tenant stages.