Skip to content

janik6n/gcp-landing-zone

Repository files navigation

GCP Landing Zone module

This repository contains an example Google Cloud Platform Project Landing Zone OpenTofu module. The Landing Zone module manages following resources:

  • GitHub Actions OIDC configuration & Service account
  • Log & metric alerts and alert policies
  • Artifact Registry Repository for container images
  • Secret Manager secrets (not secret versions)

The LZ module itself uses few modules to promote reusability.

This configuration is used with OpenTofu, but can easily be adjusted to be used with Terraform. No OpenTofu specific features are used.

Requirements

Name Version
terraform ~> 1.9
google ~> 6.18

Providers

Name Version
google ~> 6.18

Modules

Name Source Version
mod_docker_repository ./modules/docker-repository/v1.0.0 n/a
mod_github_oidc ./modules/github-oidc/v1.0.0 n/a
mod_monitoring ./modules/monitoring/v1.0.0 n/a
mod_secrets ./modules/secret/v1.0.0 n/a

Resources

Name Type
google_project_service.this resource
google_project.this data source

Inputs

Name Description Type Default Required
alert_notification_channels Map of notification channels
map(object({
type = string # email
address = string
}))
{} no
app_name App Name. Resource names are derived from this and environment. string n/a yes
docker_repository Artifact Registry Docker repository configuration settings
object({
create_docker_repository = bool
versions_to_keep = number
delete_older_than = string
cleanup_dryrun = bool
vulnerability_scanning = bool
})
n/a yes
enable_monitoring Enable monitoring bool true no
environment The environment where the Cloud Run service will be deployed string n/a yes
github_oidc GitHub OIDC configuration settings
object({
create_github_oidc_configuration = bool
workload_identity_pool_disabled = bool
workload_identity_pool_provider_disabled = bool
github_org = string
allowed_repositories = set(string)
allowed_roles = set(string)
})
n/a yes
log_alerts Map of log alert configurations
map(object({
severity = string # ERROR, CRITICAL
additional_filters = optional(list(string))
link_display_name = string
link_url = string
auto_close = string
documentation = string
notification_rate_limit = string
}))
{} no
metric_alerts Map of metric alert configurations
map(object({
severity = string # ERROR, CRITICAL
link_display_name = string
link_url = string
auto_close = string
documentation = string
filter = string # "resource.type = "pubsub_subscription" AND metric.type = "pubsub.googleapis.com/subscription/num_undelivered_messages" AND metadata.system_labels.topic_id = "pubsub-app-test-dl-topic""
duration = string # "300s"
comparison = string # "COMPARISON_GT"
alignment_period = string # "300s"
per_series_aligner = string # "ALIGN_MAX"
}))
{} no
project The GCP project name string n/a yes
region The GCP region where resources will be created string "europe-north1" no
secrets List of secrets to create. This DOES NOT create secret versions. set(string) n/a yes

Outputs

Name Description
docker_repository Artifact Registry Docker repository (only shown if repository was created)
environment Environment name
github_oidc_details GitHub OIDC configuration details (only shown if OIDC was configured)
monitoring_log_alerts Monitoring configuration details for log alerts (only shown if alerts were configured)
monitoring_metric_alerts Monitoring configuration details for metric alerts (only shown if alerts were configured)
monitoring_notification_channels Monitoring notification channels (only shown if channels were configured)
project_name Project name
secret_ids List of secret IDs created (only shown if secrets were created)

Prerequisites

Initial setup is done on laptop, further iterations can be run with GitHub Actions after setting those up. Make sure these prerequisites are met before continuing:

  1. Install OpenTofu. Version 1.9.* is required. Note: None of OpenTofu specific features are used, so you can use Terraform instead. In this case check all version constraints! (look for all occurances of required_version on repo-scope).
  2. Install gcloud CLI. Version 509.* is expected.
  3. Make sure you have the required permissions to:
  1. Login to Google Cloud on the CLI.
  2. OpenTofu (and Terraform) will use local authentication credentials, so create them with:
    gcloud auth application-default login
  3. You are now ready to proceed.

How to use this module

A working example is found in ./example directory. Following commands are expected to be run in this directory.

This module expects, that a clean GCP Project exists with billing project association, and a Storage bucket for TF backend. If you need to create a new GCP Project, see Bonus: Create new GCP Project for LZ below.

  1. Edit TF configuration in environment.auto.tfvars and providers.tf.
  2. Step-by-step:
    # format source code
    tofu fmt -recursive
    # init
    tofu init
    # validate
    tofu validate
    # plan
    tofu plan -out=env.tfplan
    # apply
    tofu apply env.tfplan

If you need to completely delete the Landing Zone, run

tofu destroy

About GitHub Actions OIDC

This LZ module creates OIDC configuration for GitHub Actions, assuming you will use https://github.com/google-github-actions/setup-gcloud for authentication in your workflow.

Actions workflow authenticate to GCP using project-specific OIDC configuration and Service account.

Project / environment specific Actions secrets must be created, for example:

  • GCP_SA_EMAIL_DEV
  • GCP_WORKLOAD_IDENTITY_PROVIDER_DEV

DEV in the above corresponds to the environment you set in environment.auto.tfvars, but this is not "hard mapping" so feel free to use what ever secret names you want.

Bonus: Create new GCP Project for LZ

To create a new Project, and some other things:

  • Create new Project
  • Associate it with existing Billing Project (assuming there is only one of them)
  • Enable following Cloud APIs:
    • artifactregistry.googleapis.com
    • clouderrorreporting.googleapis.com
    • cloudresourcemanager.googleapis.com
    • cloudscheduler.googleapis.com
    • dns.googleapis.com
    • iam.googleapis.com
    • iamcredentials.googleapis.com
    • pubsub.googleapis.com
    • run.googleapis.com
    • secretmanager.googleapis.com
  • Create Cloud Storage bucket for TF state backend
# run
./scripts/setup-new-gcp-project.sh [project-name] [GCP-region]

Save the printed Storage Bucket name for further use in Landing Zone configuration.

Note: This was created and used with zsh shell. Adjust as needed for your shell of choice.

Changelog

CHANGELOG

License

MIT License. Copyright janik6n.