Skip to content

Google Cloud Organization Module#

This module provides a foundation for setting up a Google Cloud Organization with proper infrastructure-as-code (IaC) management, audit logging, and folder structure. It creates the necessary management projects, storage buckets for Terraform state, audit logging configuration, and service accounts with appropriate permissions.

Compatibility#

This module is compatible with Terraform version ~> 1.0 and has been tested with the following provider versions:

  • Google Provider: >= 6.28.0, < 7.0.0
  • Google Beta Provider: >= 6.28.0, < 7.0.0

Features#

Management Infrastructure#

  • Creates an IaC management project for Terraform state storage.
  • Sets up a versioned GCS bucket for Terraform state files (tfstate_bucket variable).
  • Creates a service account for Terraform operations.

Folder Structure#

  • Supports creation and management of a hierarchical folder structure (configured via root_folders and sub_folders variables).
  • Enables multi-level folder hierarchies (up to 4 levels).
  • Flexible parent-child folder relationships (see "Configurable Components" for details).

Audit & Logging#

  • Creates a dedicated audit project
  • Sets up organization or folder level audit logging. If explicitly specified it can be project based logging as well
  • Configures log export to a dedicated GCS bucket in audit project
  • Enables versioning for audit logs

Security & IAM#

  • Creates and configures service accounts with least privilege. The idea is when this module is used in deployment templates, any subsequent deployment to be done using this service account
  • Sets up folder-level IAM permissions
  • Configures organization-level roles
  • Manages billing account access
  • [EXPERIMENTAL] Supports predefined groups for common admin roles (optional)
  • [EXPERIMENTAL] Automatically adds Terraform service account to DevOps group if configured

Configurable Components#

The following components are optional and can be configured as needed:

Management Folder (create_mgmt_folder variable)#

  • Creates a dedicated folder for management resources
  • Can be disabled if using existing management folder

Sub-Folders (sub_folders variable)#

  • Supports up to 4 levels of folder hierarchy
  • Flexible parent-child relationships
  • Optional for each level

API Activation (activate_apis variable)#

  • Additional APIs to enable in projects
  • Supplements default APIs

Experimental Features#

DISCLAIMER: The following features are experimental and should be considered BETA functionality. They have not been thoroughly tested in production environments and may be subject to breaking changes in future versions. Use at your own risk and test thoroughly before implementing in production.

Group-based IAM Permissions (groups variable)

  • Assigns predefined roles to groups specified in a map.
  • The map keys must be one of the following predefined identifiers. Groups follow the GCP Enterprise Setup Checklist:
  • gcp-billing-admins: Billing account administration
    • roles/billing.admin: Full access to billing accounts
  • gcp-network-admins: Network administration and VPC management
    • roles/cloudasset.owner: Asset inventory management
    • roles/cloudsupport.techSupportEditor: Technical support access
    • roles/compute.orgFirewallPolicyAdmin: Organization firewall policy management
    • roles/compute.xpnAdmin: Shared VPC management
  • gcp-organization-admins: Full organization administration
    • roles/cloudasset.owner: Asset inventory management
    • roles/cloudsupport.admin: Full support access
    • roles/compute.osAdminLogin: OS login administration
    • roles/owner: Full organization ownership
    • roles/resourcemanager.folderAdmin: Folder management
    • roles/resourcemanager.organizationAdmin: Organization administration
    • roles/resourcemanager.projectCreator: Project creation
    • roles/billing.admin: Billing administration
    • roles/orgpolicy.policyAdmin: Organization policy management
  • gcp-security-admins: Security and compliance management
    • roles/cloudasset.owner: Asset inventory management
    • roles/cloudsupport.techSupportEditor: Technical support access
    • roles/iam.securityReviewer: IAM security review
    • roles/logging.admin: Logging administration
    • roles/securitycenter.admin: Security Center administration
    • roles/iam.organizationRoleAdmin: Organization role management
    • roles/orgpolicy.policyAdmin: Organization policy management
  • gcp-devops: DevOps and infrastructure management
    • roles/cloudsupport.techSupportEditor: Technical support access
    • roles/logging.viewer: Log viewing
    • roles/monitoring.viewer: Monitoring access
    • roles/resourcemanager.folderAdmin: Folder management
    • roles/compute.xpnAdmin: Shared VPC management
    • roles/resourcemanager.projectCreator: Project creation
    • roles/storage.admin: Storage administration
    • roles/resourcemanager.projectIamAdmin: Project IAM management
    • roles/compute.orgFirewallPolicyAdmin: Organization firewall policy management
    • roles/compute.orgSecurityResourceAdmin: Organization security resource management
    • roles/iam.securityAdmin: Security administration
    • roles/logging.configWriter: Logging configuration
    • roles/resourcemanager.organizationViewer: Organization viewing
    • roles/resourcemanager.folderViewer: Folder viewing
    • roles/iam.organizationRoleAdmin: Organization role management
    • roles/billing.user: Billing access
  • gcp-secops-admins: Security operations (optional)
    • No default roles assigned
  • gcp-support: Support team access (optional)

    • No default roles assigned (maps to gcp-devops by default)
  • Group values can be specified in three formats:

  • Simple group name (domain will be added automatically):
    gcp-organization-admins = "org-admins"   # Becomes "group:org-admins@yourdomain.com"
    
  • Full IAM-formatted principal:
    gcp-network-admins = "group:network-team@yourdomain.com"
    
  • Default name (based on the key):

    gcp-devops = "gcp-devops" # Becomes "group:gcp-devops@yourdomain.com"
    

  • If the groups map is empty or omitted, no group permissions are applied.

  • When groups = {} (default), the module will not create any IAM bindings at all.
  • Because of complexity using google cloud identity in terraform members of the groups should be added from Google Workspace
  • You don't need to specify all groups - only include what you need.

Usage#

module "organization" {
  source = "git:https:git@github.com:your-repo/terraform-google-organization.git"

  # Required variables
billing_account = "YOUR_BILLING_ACCOUNT_ID"
domain          = "labs.example.com"
parent_folder   = "123456789123"

# Optional variables with sensible defaults
prefix         = "gcp-blues-29"
tfstate_bucket = "iac-tfstate"
location       = "me-west1"

create_mgmt_folder  = true
mgmt_folder         = "management"
root_folders        = ["platform", "marketplace"]
deletion_protection = false
sub_folders = {
  level2 = [
    {
      name   = "nonprod"
      parent = "platform"
    },
    {
      name   = "prod"
      parent = "platform"
    }
  ],
  level3 = [
    {
      name   = "shared"
      parent = "platform/nonprod"
    },
    {
      name   = "dev"
      parent = "platform/nonprod"
    },
    {
      name   = "stage"
      parent = "platform/nonprod"
    },
    {
      name   = "shared"
      parent = "platform/prod"
    },
    {
      name   = "app1"
      parent = "platform/prod"
    },
    {
      name   = "app2"
      parent = "platform/prod"
    }
  ]
}

# Audit logging configuration
audit_project     = "audit"
log_sink_name     = "organization_sink"
bucket_name       = "audit-logs"
create_log_export = false

# Project configuration
random_project_id = false
deletion_policy = "DELETE"

# Safety settings
force_destroy_state_bucket = true

# EXPERIMENTAL: Groups for IAM permissions
# Provide a map of predefined keys to actual group names.
# Omit or set to {} for no group permissions.
groups = {}

}

Module Deletion#

When deleting this module, consider the following:

  1. State Bucket:
  2. If force_destroy_state_bucket = false, you'll need to manually empty the bucket first
  3. Contains Terraform state files - ensure proper backup before deletion

  4. Audit Logs:

  5. Audit logs bucket contains important audit trail
  6. Consider archiving logs before deletion
  7. Set force_destroy = true if needed

  8. Service Accounts:

  9. Check for dependencies before deletion
  10. Revoke any OAuth tokens if necessary

  11. Projects:

  12. Projects will be scheduled for deletion
  13. Can be restored within 30 days
  14. After 30 days, deletion is permanent

Software#

This module requires the following software dependencies:

Service Account#

The service account used to run this module must have the following IAM roles:

  • roles/resourcemanager.organizationAdmin - To manage organization resources
  • roles/resourcemanager.folderAdmin - To create and manage folders
  • roles/resourcemanager.projectCreator - To create projects
  • roles/billing.admin - To associate billing accounts with projects
  • roles/storage.admin - To create and manage storage buckets
  • roles/iam.serviceAccountAdmin - To create and manage service accounts
  • roles/logging.configWriter - To configure audit logging
  • roles/iam.organizationRoleAdmin - To manage organization-level IAM

APIs#

The following GCP APIs must be enabled in the target organization:

  • Cloud Resource Manager API (cloudresourcemanager.googleapis.com)
  • Identity and Access Management (IAM) API (iam.googleapis.com)
  • Cloud Storage API (storage.googleapis.com)
  • Cloud Logging API (logging.googleapis.com)
  • Cloud Billing API (cloudbilling.googleapis.com)
  • Service Usage API (serviceusage.googleapis.com)

License#

This module is covered by a commercial license. Please see LICENSE for details.

Support#

This module is developed and maintained by MyOps Limited. For any support inquiries, please contact us at info@myops.co.il.

Requirements#

Name Version
terraform ~> 1
google >= 6.28.0, < 7.0.0
google-beta >= 6.28.0, < 7.0.0

Providers#

Name Version
google >= 6.28.0, < 7.0.0

Modules#

Name Source Version
audit_project terraform-google-modules/project-factory/google ~> 18.0
iac_project terraform-google-modules/project-factory/google ~> 18.0
log_export terraform-google-modules/log-export/google ~> 10.0
log_export_destination_storage terraform-google-modules/log-export/google//modules/storage ~> 10.0
tf-service-account git::https://github.com/GoogleCloudPlatform/cloud-foundation-fabric.git//modules/iam-service-account v39.0.0

Resources#

Name Type
google_folder.level_2 resource
google_folder.level_3 resource
google_folder.level_4 resource
google_folder.mgmt_folder resource
google_folder.root_folders resource
google_organization_iam_member.organization_iam_additive resource
google_storage_bucket.tfstate_bucket resource
google_folder.mgmt_folder data source
google_folder.parent_folder data source
google_folder.root_folders data source
google_organization.org data source

Inputs#

Name Description Type Default Required
activate_apis List of API to activate on the project list(string) [] no
audit_project Audit project name string "audit" no
billing_account Billing Account string n/a yes
bucket_name The name of the bucket to be created and used for log entries matching the filter. string "audit_logs" no
create_mgmt_folder Wheather to create shared mgmt folder or not bool true no
deletion_policy Whether to enable deletion protection for the Projects string "PREVENT" no
deletion_protection Whether to enable deletion protection for the folders bool true no
domain Organization domain string n/a yes
force_destroy_state_bucket Whether to allow destroying the state bucket - WARNING: only set to true in testing and cleaning up bool false no
groups [EXPERIMENTAL] Map of predefined group identifiers (e.g., 'gcp-billing-admins') to actual group names (e.g., 'my-billing-admins'). If omitted or empty, no group-based permissions are applied. If names are provided without domain prefix, the 'group:' principal and organization domain are interpolated. map(string) {} no
iac_project IaC project name for tfstate bucket string "mgmt-iac" no
location Default Location of the tfstate bucket & audit logs if unspecified string "" no
log_location Audit logs bucket location string "" no
log_sink_name Log sink name string "folder_sink" no
log_sink_parent Entity name to sink logs from. Type is one of the following: 'project', 'folder', 'billing_account', or 'organization' string "" no
log_sink_parent_type The GCP resource in which you create the log sink. Must be one of the following: 'project', 'folder', 'billing_account', or 'organization' string "" no
mgmt_folder Name of the folder that will be created if admin_folder = true or admin_folder name string "management" no
parent_folder Name of the folder that will be created if create_parent_folder = true or parent_folder name string n/a yes
prefix Prefix used for naming string null no
random_project_id Flag to enable random suffix generation bool false no
root_folders Provide list of root folders to create list(string)
[
"nonprod",
"prod"
]
no
sub_folders Define a folder structure for your organization. You can define the struture up to 4 levels deep. Levels 2-4 map a child folder to a parent folder. Example {level1=[us, eu], level2 = [{name = tenant, parent = us}], level3 = [{name = dev, parent = us/tenant}]
object({
level2 = optional(list(object({
name = string
parent = string
})))
level3 = optional(list(object({
name = string
parent = string
})))
level4 = optional(list(object({
name = string
parent = string
})))
})
{} no
tfstate_bucket tfstate bucket name string "tfstate" no
tfstate_location Location of the tfstate bucket string "" no

Outputs#

Name Description
audit_project Audit Project ID
console_link Console link
destination_uri Destination URI
iac_project IaC Management Project ID
log_filter Log filter expression
log_sink_sa Service account name of the log sink
mgmt_folder Share mgmt Folder ID
org_id Organization ID
organization_group_iam [EXPERIMENTAL] Organization group IAM bindings
root_folders Root folders
sub_folders Sub folders object
tfstate_bucket Bucket where the state file for this module will be stored