
{"id":8405,"date":"2024-08-28T12:27:52","date_gmt":"2024-08-28T12:27:52","guid":{"rendered":"https:\/\/rax-stg-wp-aws.com\/blogs\/building-a-google-cloud-landing-zone-in-a-scalable-repeatable-and-secure-way-part-2\/"},"modified":"2026-11-03T19:29:36","modified_gmt":"2026-11-03T19:29:36","slug":"building-a-google-cloud-landing-zone-in-a-scalable-repeatable-and-secure-way-part-2","status":"publish","type":"blogs","link":"https:\/\/www.rackspace.com\/en-gb\/blogs\/building-a-google-cloud-landing-zone-in-a-scalable-repeatable-and-secure-way-part-2\/","title":{"rendered":"Building a Google Cloud Landing Zone in a Scalable, Repeatable and Secure Way (Part 2)"},"content":{"rendered":"<p><strong>Introduction<\/strong><\/p>\n<p>This is part two of the two-part series on building a Google Cloud landing zone in a scalable, repeatable and secure fashion. In this post, I share step-by-step guidance for setting up a new landing zone on Google Cloud, using Google\u2019s open-source <a href=\"https:\/\/github.com\/GoogleCloudPlatform\/cloud-foundation-fabric\/tree\/master\/fast\">Fabric FAST<\/a>, which is part of its <a href=\"https:\/\/github.com\/GoogleCloudPlatform\/cloud-foundation-fabric\">Cloud Foundation Fabric<\/a>.&nbsp;<a>In part one<\/a>, I shared several manual setup tasks, following the initial steps from the&nbsp;<a href=\"https:\/\/cloud.google.com\/docs\/enterprise\/setup-checklist#checklist-section-1\">Google Cloud setup checklist<\/a><u>,&nbsp;<\/u>using the <a href=\"https:\/\/console.cloud.google.com\/cloud-setup\/overview?pli=1&amp;authuser=2&amp;organizationId=289855051445\">Google Cloud foundation guided steps<\/a>. In part one, we completed steps one and two from the checklist.<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/27038-body-1.jpg\" alt=\"GCPLZ Pic 1\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>From here onwards, we\u2019ll be using Fabric FAST to complete all the remaining activities using infrastructure-as-code.<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/27038-body-2.jpg\" alt=\"GCPLZ2\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>In this part of the series, we will complete the following steps:<\/p>\n<ul>\n<li><strong>Run FAST stages\/0-bootstrap<\/strong>: Configure automation, billing and log export projects, custom roles, service accounts, organization-level logging and workload identity federation support.<\/li>\n<li><strong>Migrate Terraform state to a GCS bucket<\/strong>.<\/li>\n<li><strong>Run FAST stages\/1-resman<\/strong>: Provide shared capability folders, like networking and security, and apply a set of top-down organization-level security policies.<\/li>\n<li><strong>Optionally run FAST stages-multitenant\/0-bootstrap-tenant<\/strong>: Provide optional top-level tenant folders that can be treated like separate organizations.<\/li>\n<\/ul>\n<p><strong>Fabric FAST stages<\/strong><\/p>\n<p>Fabric FAST is split into multiple stages. The stages are layered, meaning that a given stage is dependent on having run the preceding stages.<\/p>\n<p><strong>Summary of different stages:<\/strong><\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/27038-body-3.jpg\" alt=\"GCPLZ3\" \/><\/p>\n<ul>\n<li><strong>Bootstrap<\/strong>: Provides a foundational organization-level configuration to enable steps that depend on broad administrative permissions, preparing the prerequisites needed to enable automation in this and future stages.<\/li>\n<li><strong>Resource management:<\/strong> Creates the base resource hierarchy (folders) and the automation resources required later to delegate deployment of each part of the hierarchy to separate stages.&nbsp;And set organization policies on the organization, and any exception required on specific folders.<\/li>\n<li><strong>Networking<\/strong>: Provides centralized networking resources, using a hub-and-spoke design.<\/li>\n<li><strong>Security<\/strong>: Implements security configuration, adhering to best practices.<\/li>\n<li><strong>Google Cloud Project Factory<\/strong>: Creates a YAML-based factory that allows projects to be created for any given tenant (e.g., an application or team). This should be run once per environment (e.g., for dev, QA, staging, production).<\/li>\n<li><strong>Data platform<\/strong>: An optional stage intended for the deployment of components that would be needed to build a data platform, such as BigQuery, Pub\/Sub, Dataflow and Cloud Composer.<\/li>\n<li><strong>GKE multi-tenant<\/strong>: An optional stage for building a shared GKE environment that can host multiple tenant applications.<\/li>\n<\/ul>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/27038-body-4.jpg\" alt=\"GCPLZ 4\" \/><\/p>\n<p>Each FAST stage has its own folder in the repo. Each of these folders represents a Terraform root module, a folder where we can run terraform commands to execute a given stage in the overall process.<\/p>\n<p><strong>Multi-tenant top level :&nbsp;<\/strong>One useful feature of FAST is to be able to bootstrap such that the top level of the FAST resource hierarchy is a folder under the organization, rather than in the organization itself. This is useful if you potentially want more than one FAST hierarchy deployed in your organization.<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/27038-body-5.jpg\" alt=\"GCPLZ 5\" \/><\/p>\n<p><strong>Prerequisite<\/strong><\/p>\n<p>Most of the prerequisites have been completed in part one. However, you will need an environment running all three \u2014 Google Cloud CLI, Terraform and git.<\/p>\n<p><strong>Stage 0: Bootstrap<\/strong><\/p>\n<p>FAST starts with the 0-bootstrap stage. Open this folder in your cloned repo. You\u2019ll see a detailed description of this stage. In your development environment, make sure you are in the fast\/stages\/0-bootstrap folder.<\/p>\n<p><strong>Overview<\/strong><\/p>\n<p>Here is a quick overview of what this stage achieves:<\/p>\n<ul>\n<li>Creates custom roles that allow you to set IAM policies at the organization level, allowing the resource management service account to grant a specific set of roles.<\/li>\n<li>Creates a service account for the next stage.<\/li>\n<li>Creates an automation project for running subsequent FAST tasks.<\/li>\n<li>Creates GCS buckets to act as the remote backend for the Terraform state and to store FAST stage output files.<\/li>\n<li>Creates a billing export project.<\/li>\n<li>Creates a log export project.<\/li>\n<li>Sets up organization-level logging. Org-level log sinks are created to ensure a proper audit trail right from the start. By default, FAST provides log filters to capture <a href=\"https:\/\/cloud.google.com\/logging\/docs\/audit\">Cloud Audit Logs<\/a> and <a href=\"https:\/\/cloud.google.com\/vpc-service-controls\/docs\/troubleshooting#vpc-sc-errors\">VPC Service Controls violations<\/a> and<strong> <a href=\"https:\/\/cloud.google.com\/logging\/docs\/audit\/configure-gsuite-audit-logs\">Workspace Logs<\/a><\/strong> into a BigQuery dataset in a newly created top-level audit project.<\/li>\n<li>Enables Workload Identity Federation support with external providers. This allows non-Google external identities (such as Active Directory or OIDC identity providers, like Ping Identity or Okta) to be used to access Google Cloud resources without having to obtain and share a service account key.<\/li>\n<\/ul>\n<p><strong>Steps<\/strong><\/p>\n<p><strong>1. Login: <\/strong>Launch a <a href=\"https:\/\/console.cloud.google.com\/\">Google Cloud console<\/a> browser session, using your Org Admin user. If you want to use the Cloud Shell, simply launch it from the console.<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/27038-body-6.jpg\" alt=\"GCPLZ pic 6\" \/><\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/27038-body-7.png\" alt=\"GCPLZ7\" \/><\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/27038-body-8.jpg\" alt=\"GCPLZ Pic 8\" \/><\/p>\n<p>You will be given a link to open in your browser. Paste in the link, and when prompted to choose an account, make sure you select your Org Admin account. Google will give you a verification code, which you can now paste back into your gcloud CLI command.<\/p>\n<p><strong>2.&nbsp;<\/strong><strong>Grant roles: <\/strong>Now we will self-grant the required roles to our Org Admin account:<\/p>\n<ul>\n<li>Billing account administrator (roles\/billing.admin) either on the organization or the billing account logging admin (roles\/logging.admin)<\/li>\n<li>Organization role administrator (roles\/iam.organizationRoleAdmin)<\/li>\n<li>Organization administrator (roles\/resourcemanager.organizationAdmin)<\/li>\n<li>Project creator (roles\/resourcemanager.projectCreator)<\/li>\n<\/ul>\n<p class=\"MsoNormal\"><em># set variable for current logged-in user<\/em><\/p>\n<p class=\"MsoNormal\"><em>export FAST_BU=$(gcloud config list &#8211;format &#8216;value(core.account)&#8217;)<\/em><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\"><em># find and set your org id<\/em><\/p>\n<p class=\"MsoNormal\"><em>gcloud organizations list<\/em><\/p>\n<p class=\"MsoNormal\"><em>export FAST_ORG_ID=&lt;your org ID&gt;<\/em><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\"><em># set needed roles<\/em><\/p>\n<p class=\"MsoNormal\"><em>export FAST_ROLES=&#8221;roles\/billing.admin roles\/logging.admin \\<\/em><\/p>\n<p class=\"MsoNormal\"><em>&nbsp;roles\/iam.organizationRoleAdmin \\<\/em><\/p>\n<p class=\"MsoNormal\"><em>&nbsp;roles\/resourcemanager.projectCreator&#8221;<\/em><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\"><em>for role in $FAST_ROLES; do<\/em><\/p>\n<p class=\"MsoNormal\"><em>&nbsp;gcloud organizations add-iam-policy-binding $FAST_ORG_ID \\<\/em><\/p>\n<p class=\"MsoNormal\"><em>&nbsp;&nbsp; &#8211;member user:$FAST_BU &#8211;role $role<\/em><\/p>\n<p class=\"MsoNormal\"><em>done<\/em><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p class=\"MsoNormal\"><em># find your billing account ID<\/em><\/p>\n<p class=\"MsoNormal\"><em>gcloud alpha billing accounts list<\/em><\/p>\n<p class=\"MsoNormal\"><em>export FAST_BILLING_ACCOUNT_ID=&lt;your billing account id&gt;<\/em><\/p>\n<p class=\"MsoNormal\"><em>gcloud beta billing accounts add-iam-policy-binding $FAST_BILLING_ACCOUNT_ID \\<\/em><\/p>\n<p class=\"MsoNormal\"><em>&nbsp;&#8211;member user:$FAST_BU &#8211;role roles\/billing.admin<\/em><\/p>\n<p><strong>3. Create Terraform variables: <\/strong>Create a terraform.tfvars file, in the 0-boostrap folder. This will be used to supply the stage with the necessary variables for your environment. Note that by default, this terraform.tfvars file will not be under git source control, since it\u2019s excluded in the .gitignore file. This is to prevent you from checking potentially sensitive environment-specific information.<\/p>\n<p><strong><em>Note: Project IDs in Google Cloud need to be globally unique. So, think carefully about the prefix you want to use.<\/em><\/strong><\/p>\n<p class=\"MsoNormal\"><em># use `gcloud beta billing accounts list`<\/em><\/p>\n<p class=\"MsoNormal\"><em># if you have too many accounts, check the Cloud Console \ud83d\ude42<\/em><\/p>\n<p class=\"MsoNormal\"><em>billing_account = {<\/em><\/p>\n<p class=\"MsoNormal\"><em>id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &#8220;012345-67890A-BCDEF0&#8221;<\/em><\/p>\n<p class=\"MsoNormal\"><em>}<\/em><\/p>\n<p class=\"MsoNormal\"><em># use `gcloud organizations list`<\/em><\/p>\n<p class=\"MsoNormal\"><em>organization = {<\/em><\/p>\n<p class=\"MsoNormal\"><em>domain&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &#8220;gcpnerdy.org&#8221;<\/em><\/p>\n<p class=\"MsoNormal\"><em>id&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = 1234567890<\/em><\/p>\n<p class=\"MsoNormal\"><em>customer_id = &#8220;C000001&#8221;<\/em><\/p>\n<p class=\"MsoNormal\"><em>}<\/em><\/p>\n<p class=\"MsoNormal\"><em>outputs_location = &#8220;~\/fast-config&#8221;<\/em><\/p>\n<p class=\"MsoNormal\"><em># use something unique and no longer than 9 characters<\/em><\/p>\n<p class=\"MsoNormal\"><em>prefix = &#8220;ccoe&#8221;<\/em><\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p><strong>4. Run the Terraform<\/strong><\/p>\n<p><em># Setup application default credentials (ADC)<\/em><\/p>\n<p><em>gcloud auth application-default login<\/em><\/p>\n<p><em>terraform init<\/em><\/p>\n<p><em># optional &#8211; if you want to see what the apply command will do<\/em><\/p>\n<p><em>terraform plan<\/em><\/p>\n<p><em># apply the configuration<\/em><\/p>\n<p><em>terraform apply -var bootstrap_user=$(gcloud config list &#8211;format &#8216;value(core.account)&#8217;)<\/em><\/p>\n<p>It will take a couple of minutes to run. Afterwards, you\u2019ll see three new projects were created and new log sinks will be visible:<\/p>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/27038-body-9.jpg\" alt=\"GCPLZ pic 9\" \/><\/p>\n<p>In the billing project, we can see a BigQuery billing export dataset has been created. In the iac project, three new GCS buckets have been created.<\/p>\n<p><strong>Output variables<\/strong><\/p>\n<p>The 0-bootstrap stage creates several output variables. By default, it writes them to the folder ~\/fast-config. This can be changed in the .tfvars file we supplied earlier.<\/p>\n<p><strong>Switching state to remote backend<\/strong><\/p>\n<p>When we first run Terraform init, Terraform stores its state in a local file. However, it\u2019s a good idea to move this state into a so-called remote backend, i.e., a storage location that is accessible over a network and can be used collaboratively. <a href=\"https:\/\/cloud.google.com\/docs\/terraform\/resource-management\/store-state\">This page<\/a> describes the general process of migrating Terraform state to a Google Cloud Storage bucket. However, FAST facilitates this process for us. The 0-bootstrap guidance tells us the steps we need to take to migrate the TF state, including:<\/p>\n<p><em># to copy the FAST output files from the local fast-config directory:<\/em><\/p>\n<p><em>..\/..\/stage-links.sh ~\/fast-config<\/em><\/p>\n<p><em># alternatively, we can copy the FAST output files from the GCS bucket:<\/em><\/p>\n<p><em>export PREFIX=&lt;your prefix&gt;<\/em><\/p>\n<p><em>..\/..\/stage-links.sh gs:\/\/$PREFIX-prod-iac-core-outputs-0<\/em><\/p>\n<p><em># If you have any &#8220;bad interpreter&#8221; errors, you may have issues with your end-of-line chars<\/em><\/p>\n<p><em># If so, fix with this line, then try again<\/em><\/p>\n<p><em>sed -i -e &#8216;s\/\\r$\/\/&#8217; ..\/..\/stage-links.sh<\/em><\/p>\n<p>The command will return a subsequent ln command, which is specific for this stage. Running this line creates a symbolic link from the newly created 0-boostrap-providers.tf filed to the current working directory. Again, this file will not be checked-in to source control, as it\u2019s excluded in .gitignore.<\/p>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/27038-body-Picture23.png\" alt=\"GCPLZ Pic 22\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>Now we can migrate the state to the GCS bucket:<\/p>\n<p><em>terraform init -migrate-state<\/em><\/p>\n<p><em>terraform apply<\/em><\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/27038-body-10.jpg\" alt=\"GCPLZ Part 9\" \/><\/p>\n<p>&nbsp;<strong>Collaborative working<\/strong><\/p>\n<p>Having now migrated the state, if you want to continue the FAST process from another machine, you can. To resume TF steps on another machine, you will need to:<\/p>\n<p><em># Ensure pre-reqs: we have installed gcloud CLI, terraform, git<\/em><\/p>\n<p><em># Ensure terraform.tfvars matches what was set on the other machine<\/em><\/p>\n<p><em># Login with gcloud CLI, and set ADC<\/em><\/p>\n<p><em>gcloud auth login<\/em><\/p>\n<p><em>gcloud auth application-default login<\/em><\/p>\n<p><em># Change to: fast\/stages\/0-bootstrap folder<\/em><\/p>\n<p><em># Copy the external backend state providers.tf file to the local directory<\/em><\/p>\n<p><em>gsutil cp gs:\/\/ccoe-prod-iac-core-outputs-0\/providers\/0-bootstrap-providers.tf .\/<\/em><\/p>\n<p><em># Initialize Terraform; the state will be pulled from the GCS bucket<\/em><\/p>\n<p><em>terraform init<\/em><\/p>\n<p><em>terraform apply<\/em><\/p>\n<p><strong>Stage 1 \u2014 Resource hierarchy<\/strong><\/p>\n<p class=\"MsoNormal\"><strong>FAST<\/strong> continues with the <strong>1-resman<\/strong> stage. Open this folder in your cloned repo. You\u2019ll see a detailed description of this stage. In your development environment, make sure you are in the fast\/stages\/1-resman folder.<\/p>\n<p><strong>Overview<\/strong><\/p>\n<p>Here is a quick overview of what this stage achieves:<\/p>\n<ul>\n<li>Creates the top-level hierarchy of folders and associated resources.<\/li>\n<li>Sets organization policies and any exceptions required on specific folders.<\/li>\n<\/ul>\n<p>The diagram below shows the resource hierarchy that\u2019s created.<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/27038-body-11.jpg\" alt=\"GCPLZ Pic 11\" \/><\/p>\n<p class=\"MsoNormal\">Notes:<\/p>\n<ul>\n<li>Separate folders are created for shared capabilities, like networking and security.<\/li>\n<li>A separate sandbox folder is created. The intent of this folder is for experimentation with resources that are not subject to the same levels of IaC-enforced control as the rest of the hierarchy.<\/li>\n<li>A top-level Teams folder, which contains separate folders for each application\/team tenant.<\/li>\n<li>Subsequent shared capabilities (e.g., a multi-tenant GKE cluster) could be added without compromising this design.<\/li>\n<li>This stage is a prerequisite for provisioning top-level tenants. (See below.)<\/li>\n<\/ul>\n<p><strong>Which organization policies?<\/strong><\/p>\n<p>If you like, in the folder stages\/1-resman\/data\/org-policies, you can view the various policies that are set by FAST. These include, but are not limited to:<\/p>\n<ul>\n<li>Enforce compute.requireOsLogin<\/li>\n<li>Enforce compute.skipDefaultNetworkCreation<\/li>\n<li>Deny compute.vmExternalIpAccess<\/li>\n<li>Enforce iam.disableServiceAccountKeyCreation<\/li>\n<li>Enforce sql.restrictPublicIp<\/li>\n<li>Enforce storage.uniformBucketLevelAccess<\/li>\n<\/ul>\n<p>&nbsp;Of course, you are free to edit these files, to configure the org policies you want to apply.<\/p>\n<p><strong>Steps: <\/strong>Add a terraform.tfvars file. e.g.:<\/p>\n<p><em>team_folders = {<\/em><\/p>\n<p><em>&nbsp;team-ct = {<\/em><\/p>\n<p><em>&nbsp;&nbsp; descriptive_name = &#8220;Team CT&#8221;<\/em><\/p>\n<p><em>&nbsp;&nbsp; group_iam = {<\/em><\/p>\n<p><em>&nbsp;&nbsp;&nbsp;&nbsp; &#8220;team-ct@gcpnerdy.org&#8221; = [<\/em><\/p>\n<p><em>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;roles\/viewer&#8221;<\/em><\/p>\n<p><em>&nbsp;&nbsp;&nbsp;&nbsp; ]<\/em><\/p>\n<p><em>&nbsp;&nbsp; }<\/em><\/p>\n<p><em>&nbsp;&nbsp; impersonation_groups = [&#8220;team-ct-admins@gcpnerdy.org&#8221;]<\/em><\/p>\n<p><em>&nbsp;}<\/em><\/p>\n<p><em>}<\/em><\/p>\n<p><em>outputs_location = &#8220;~\/fast-config&#8221;<\/em><\/p>\n<p><em>We run the stage-links.sh script to obtain the commands to copy output from the previous stage.<\/em><\/p>\n<p><em># either<\/em><\/p>\n<p><em>..\/..\/stage-links.sh ~\/fast-config<\/em><\/p>\n<p><em># or<\/em><\/p>\n<p><em>..\/..\/stage-links.sh gs:\/\/$PREFIX-prod-iac-core-outputs-0<\/em><\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/27038-body-Picture25.png\" alt=\"GCPLZ Pic 12\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>As per the instructions, copy the commands and run them. Now run the Terraform:<\/p>\n<p><em># Initialize Terraform; the state will be pulled from the GCS bucket<\/em><\/p>\n<p><em>terraform init<\/em><\/p>\n<p><em>terraform apply<\/em><\/p>\n<p>For me, this creates 63 new resources and takes a couple of minutes to run. You\u2019ll see that several new projects have been created.<\/p>\n<p><strong>Configuring a tenant top level folder: 0-bootstrap-tenant<\/strong><\/p>\n<p>Now, we can optionally proceed to the 0-boostrap-tenant stage. Open the stages-multitenant\/0-bootstrap-tenant folder in your cloned repo and look at the guidance. In your development environment, make sure you are in the fast\/stages-multitenant\/0-bootstrap-tenant folder. Remember that we need to have run both the 0-bootstrap and 1-resman stages before running this stage.<\/p>\n<p><strong>Overview<\/strong><\/p>\n<p>Here we create a top-level tenant folder under the organization node. This stage creates service accounts for all tenant stages, such that billing and Organization Policy Administration bindings can be set, leveraging permissions of the org-level resman service account, which is used to run this stage. This avoids the need to grant broad scoped permissions on the organization to tenant-level service accounts, thus decoupling the tenant from the organization.<\/p>\n<p><strong>Steps<\/strong><\/p>\n<p><em># either<\/em><\/p>\n<p><em>..\/..\/stage-links.sh ~\/fast-config<\/em><\/p>\n<p><em># or<\/em><\/p>\n<p><em>..\/..\/stage-links.sh gs:\/\/$PREFIX-prod-iac-core-outputs-0<\/em><\/p>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/27038-body-12_0.jpg\" alt=\"GCPLZ Pic 13\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>As per the guidance:<\/p>\n<ul>\n<li>Copy all the commands, paste them and run them.<\/li>\n<li>Edit the 0-bootstrap-tenant-providers.tf file, and supply the name of your top-level tenant, as the variable \u201cprefix.\u201d<\/li>\n<\/ul>\n<p><em>terraform {<\/em><\/p>\n<p><em>&nbsp;backend &#8220;gcs&#8221; {<\/em><\/p>\n<p><em>&nbsp;&nbsp; bucket&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &#8220;ccoe-prod-iac-core-resman-0&#8221;<\/em><\/p>\n<p><em>&nbsp;&nbsp; impersonate_service_account = &#8220;ccoe-prod-resman-0@ccoe-prod-iac-core-0.iam.gserviceaccount.com&#8221;<\/em><\/p>\n<p><em>&nbsp;&nbsp; # remove the newline between quotes and set the tenant name as prefix<\/em><\/p>\n<p><em>&nbsp;&nbsp; prefix = &#8220;dazbo-lz&#8221;<\/em><\/p>\n<p><em>&nbsp;}<\/em><\/p>\n<p><em>}<\/em><\/p>\n<p><em>provider &#8220;google&#8221; {<\/em><\/p>\n<p><em>&nbsp;impersonate_service_account = &#8220;ccoe-prod-resman-0@ccoe-prod-iac-core-0.iam.gserviceaccount.com&#8221;<\/em><\/p>\n<p><em>}<\/em><\/p>\n<p><em>provider &#8220;google-beta&#8221; {<\/em><\/p>\n<p><em>&nbsp;impersonate_service_account = &#8220;ccoe-prod-resman-0@ccoe-prod-iac-core-0.iam.gserviceaccount.com&#8221;<\/em><\/p>\n<p><em>}<\/em><\/p>\n<p><em># end provider.tf for bootstrap-tenant<\/em><\/p>\n<p><strong>Now provide a terraform.tfvars file, and the required config:<\/strong><\/p>\n<p><em>tenant_config = {<\/em><\/p>\n<p><em>&nbsp;# used for the top-level folder name<\/em><\/p>\n<p><em>&nbsp;descriptive_name = &#8220;CCOE Tenant A&#8221;<\/em><\/p>\n<p><em>&nbsp;# tenant-specific groups, only the admin group is required<\/em><\/p>\n<p><em>&nbsp;# the organization domain is automatically added after the group name<\/em><\/p>\n<p><em>&nbsp;groups = {<\/em><\/p>\n<p><em>&nbsp;&nbsp; gcp-admins&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &#8220;tnta-admins&#8221;<\/em><\/p>\n<p><em>&nbsp;&nbsp; # gcp-devops&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &#8220;tnta-devops&#8221;<\/em><\/p>\n<p><em>&nbsp;&nbsp; # gcp-network-admins&nbsp; = &#8220;tnta-networking&#8221;<\/em><\/p>\n<p><em>&nbsp;&nbsp; # gcp-security-admins = &#8220;tnta-security&#8221;<\/em><\/p>\n<p><em>&nbsp;}<\/em><\/p>\n<p><em>&nbsp;# the 3 or 4 letter acronym or abbreviation used in resource names<\/em><\/p>\n<p><em>&nbsp;short_name = &#8220;tnta&#8221;<\/em><\/p>\n<p><em>&nbsp;# optional CI\/CD configuration, refer to the org-level stages for information<\/em><\/p>\n<p><em>&nbsp;# cicd = {<\/em><\/p>\n<p><em>&nbsp;#&nbsp;&nbsp; branch&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = null<\/em><\/p>\n<p><em>&nbsp;#&nbsp;&nbsp; identity_provider = &#8220;foo-provider&#8221;<\/em><\/p>\n<p><em>&nbsp;#&nbsp;&nbsp; name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &#8220;myorg\/tnta-bootstrap&#8221;<\/em><\/p>\n<p><em>&nbsp;#&nbsp;&nbsp; type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = &#8220;github&#8221;<\/em><\/p>\n<p><em>&nbsp;# }<\/em><\/p>\n<p><em>&nbsp;# optional group-level IAM bindings to add to the top-level folder<\/em><\/p>\n<p><em>&nbsp;# group_iam = {<\/em><\/p>\n<p><em>&nbsp;#&nbsp;&nbsp; tnta-support = [&#8220;roles\/viewer&#8221;]<\/em><\/p>\n<p><em>&nbsp;# }<\/em><\/p>\n<p><em>&nbsp;# optional IAM bindings to add to the top-level folder<\/em><\/p>\n<p><em>&nbsp;# iam&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = {<\/em><\/p>\n<p><em>&nbsp;#&nbsp;&nbsp; &#8220;roles\/logging.admin&#8221; = [<\/em><\/p>\n<p><em>&nbsp;#&nbsp;&nbsp;&nbsp;&nbsp; &#8220;serviceAccount:foo@myprj.iam.gserviceaccount.com&#8221;<\/em><\/p>\n<p><em>&nbsp;#&nbsp;&nbsp; ]<\/em><\/p>\n<p><em>&nbsp;# }<\/em><\/p>\n<p><em>&nbsp;# optional location overrides to global locations<\/em><\/p>\n<p><em>&nbsp;# locations = {<\/em><\/p>\n<p><em>&nbsp;#&nbsp;&nbsp; bq&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = null<\/em><\/p>\n<p><em>&nbsp;#&nbsp;&nbsp; gcs&nbsp;&nbsp;&nbsp;&nbsp; = null<\/em><\/p>\n<p><em>&nbsp;#&nbsp;&nbsp; logging = null<\/em><\/p>\n<p><em>&nbsp;#&nbsp;&nbsp; pubsub&nbsp; = null<\/em><\/p>\n<p><em>&nbsp;# }<\/em><\/p>\n<p><em>&nbsp;# optional folder ids for automation and logging project folders, typically<\/em><\/p>\n<p><em>&nbsp;# added in later stages and entered here once created<\/em><\/p>\n<p><em>&nbsp;# project_parent_ids = {<\/em><\/p>\n<p><em>&nbsp;#&nbsp;&nbsp; automation = &#8220;folders\/012345678&#8221;<\/em><\/p>\n<p><em>&nbsp;#&nbsp;&nbsp; logging&nbsp;&nbsp;&nbsp; = &#8220;folders\/0123456789&#8221;<\/em><\/p>\n<p><em>&nbsp;# }<\/em><\/p>\n<p><em>}<\/em><\/p>\n<p><em># tftest skip<\/em><\/p>\n<p><em>outputs_location = &#8220;~\/fast-config&#8221;<\/em><\/p>\n<p>One important thing to note is that we\u2019ve defined a new admin Google group called tnta-admins. This group needs to exist before we can apply the Terraform. So, in the <a href=\"https:\/\/admin.google.com\/\">Admin Console<\/a>, add this new group.<\/p>\n<p>Now run Terraform, as usual:<\/p>\n<p><em># Initialize Terraform; the state will be pulled from the GCS bucket<\/em><\/p>\n<p><em>terraform init<\/em><\/p>\n<p><em>terraform apply<\/em><\/p>\n<p>Finally, we can see that our top-level tenant folder has been created:<\/p>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/blog_article_images\/27038-body-13.jpg\" alt=\"GCPLZ Pic 13\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>Note that this stage also creates staging buckets that are tenant-specific:<\/p>\n<p><strong>In summary<\/strong><\/p>\n<p>In this second part of the process of building a Google Cloud landing zone, we have completed these steps:<\/p>\n<ul>\n<li><strong>Executed FAST stages\/0-bootstrap<\/strong>: To configure automation, billing and log export projects, custom roles, service accounts, organization-level logging and workload identity federation support.<\/li>\n<li><strong>Migrated Terraform state to a GCS bucket<\/strong>.<\/li>\n<li><strong>Executed FAST stages\/1-resman<\/strong>: Provide shared capability folders, like networking and security, and applied a set of top-down organization-level security policies to ensure we\u2019re secure from the start.<\/li>\n<li><strong>Executed FAST stages-multitenant\/0-bootstrap-tenant<\/strong>: To provide optional top-level tenant folders.<\/li>\n<li><strong>Executed FAST stages-multitenant\/1-resman-tenant<\/strong>: To create networking and security shared folders under the top-level tenancy.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>Building a Google Cloud Landing Zone in a Scalable, Repeatable and Secure Way (Part 2)<\/p>\n","protected":false},"author":2,"featured_media":8407,"menu_order":0,"comment_status":"open","ping_status":"open","template":"","format":"standard","meta":{"content-type":"","nid":"27038","content_type":"blog","created_by":"10130","authored_on":"2024-07-22T12:27:51+00:00","field_article_industries":"","tag_category":"Technical","field_blog_author_text":"By Jasbir Singh, Staff Consulting Architect, Rackspace Technology","seo_description":"Explore Part 2 of our guide on building a Google Cloud Landing Zone. Learn scalable, repeatable, and secure methods to optimize your cloud environment.","field_featured_image":"","insights_image":"\/wp-content\/uploads\/2026\/blog_technical_images\/27038-insights_image-google-cloud-technical-blog-1-insights.jpg","field_partners":"Google Cloud","rxt_platforms":"Google Cloud","product":"","publisheddate":"2024-08-28T12:27:52","rxt_solutions":"Cloud Management & Operations, Public Cloud","opengraph_tag":"","x_tag":"","teaser_flag":"Technical Blog","seo_titile":"Building Google Cloud Landing Zone in Scalable, Repeatable & Secure fashion - Part 2| Rackspace Technology","field_topics":"Public Cloud","field_slug":"building-google-cloud-landing-zones-part-2","footnotes":""},"categories":[178],"tags":[187,183,204],"class_list":["post-8405","blogs","type-blogs","status-publish","format-standard","has-post-thumbnail","hentry","category-blog","tag-google-cloud","tag-public-cloud","tag-technical"],"_links":{"self":[{"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/blogs\/8405","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/blogs"}],"about":[{"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/types\/blogs"}],"author":[{"embeddable":true,"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/comments?post=8405"}],"version-history":[{"count":3,"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/blogs\/8405\/revisions"}],"predecessor-version":[{"id":10078,"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/blogs\/8405\/revisions\/10078"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/media\/8407"}],"wp:attachment":[{"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/media?parent=8405"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/categories?post=8405"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.rackspace.com\/en-gb\/wp-json\/wp\/v2\/tags?post=8405"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}