Last active
November 24, 2020 16:35
-
-
Save mikesparr/42adb3b463d867f0dca4865362c213ac to your computer and use it in GitHub Desktop.
Example Terraform GCP org with Memcache in service project
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| terraform { | |
| required_providers { | |
| google = { | |
| source = "hashicorp/google" | |
| version = ">= 3.37" | |
| } | |
| google-beta = { | |
| source = "hashicorp/google-beta" | |
| version = ">= 3.37" | |
| } | |
| } | |
| } | |
| provider "google" { | |
| version = "3.37.0" | |
| region = var.region | |
| zone = var.zone | |
| } | |
| provider "google-beta" { | |
| version = "3.37.0" | |
| region = var.region | |
| zone = var.zone | |
| } | |
| data "google_billing_account" "account" { | |
| provider = google-beta | |
| billing_account = var.billing_account_id | |
| } | |
| # folders | |
| resource "google_folder" "demo_org" { | |
| display_name = "demo-org" | |
| parent = var.root_folder | |
| } | |
| resource "google_folder" "shared_services" { | |
| display_name = "shared-services" | |
| parent = google_folder.demo_org.name | |
| } | |
| resource "google_folder" "engineering" { | |
| display_name = "engineering" | |
| parent = google_folder.demo_org.name | |
| } | |
| resource "google_folder" "product_x" { | |
| display_name = "product-x" | |
| parent = google_folder.engineering.name | |
| } | |
| resource "google_folder" "non_production" { | |
| display_name = "non-production" | |
| parent = google_folder.product_x.name | |
| } | |
| resource "google_folder" "production" { | |
| display_name = "production" | |
| parent = google_folder.product_x.name | |
| } | |
| # audit config | |
| resource "google_folder_iam_audit_config" "audit_root_folder" { | |
| folder = google_folder.demo_org.folder_id | |
| service = "allServices" | |
| audit_log_config { | |
| log_type = "ADMIN_READ" | |
| } | |
| audit_log_config { | |
| log_type = "DATA_READ" | |
| } | |
| # audit_log_config { | |
| # log_type = "DATA_WRITE" | |
| # } | |
| } | |
| # policies | |
| resource "google_folder_organization_policy" "default_network_policy" { | |
| folder = google_folder.demo_org.id | |
| constraint = "compute.skipDefaultNetworkCreation" | |
| boolean_policy { | |
| enforced = true | |
| } | |
| } | |
| resource "google_folder_organization_policy" "service_acct_key_policy" { | |
| folder = google_folder.demo_org.id | |
| constraint = "iam.disableServiceAccountKeyCreation" | |
| boolean_policy { | |
| enforced = true | |
| } | |
| } | |
| resource "google_folder_organization_policy" "shielded_vm_policy" { | |
| folder = google_folder.demo_org.id | |
| constraint = "compute.requireShieldedVm" | |
| boolean_policy { | |
| enforced = true | |
| } | |
| } | |
| # finding GSuite ID: https://www.youtube.com/watch?v=AeadQfJT5kw | |
| resource "google_folder_organization_policy" "allow_only_policy_member_domains" { | |
| folder = google_folder.demo_org.id | |
| constraint = "constraints/iam.allowedPolicyMemberDomains" | |
| list_policy { | |
| allow { | |
| values = var.allowed_domain_ids | |
| } | |
| } | |
| } | |
| resource "google_folder_organization_policy" "restrict_vm_external_ip_policy" { | |
| folder = google_folder.demo_org.id | |
| constraint = "compute.vmExternalIpAccess" | |
| list_policy { | |
| deny { | |
| all = true | |
| } | |
| } | |
| } | |
| resource "google_folder_organization_policy" "disable_appengine_code_download_policy" { | |
| folder = google_folder.demo_org.id | |
| constraint = "appengine.disableCodeDownload" | |
| boolean_policy { | |
| enforced = true | |
| } | |
| } | |
| # shared projects | |
| resource "random_id" "shared_random_id" { | |
| byte_length = 4 | |
| } | |
| # security | |
| resource "google_project" "shared_security" { | |
| name = "security" | |
| project_id = "security2-${random_id.shared_random_id.hex}" | |
| folder_id = google_folder.shared_services.name | |
| billing_account = var.billing_account_id | |
| labels = { "dept" : "infosec" } | |
| } | |
| # bucket for audit-logs, with log sink and dynamic sa role | |
| resource "google_storage_bucket" "bucket_audit_logs" { | |
| name = var.audit_logs_bucket_name | |
| location = "US" | |
| project = google_project.shared_security.project_id | |
| labels = { "dept": "infosec", "role": "storage" } | |
| } | |
| resource "google_logging_folder_sink" "log_sink_audit" { | |
| name = "demo-org-audit-logs" | |
| folder = google_folder.demo_org.name | |
| include_children = true | |
| destination = "storage.googleapis.com/${google_storage_bucket.bucket_audit_logs.name}" | |
| filter = "protoPayload.@type:\"type.googleapis.com/google.cloud.audit.AuditLog\"" | |
| } | |
| resource "google_project_iam_binding" "audit_log_writer" { | |
| project = google_project.shared_security.project_id | |
| role = "roles/storage.objectCreator" | |
| members = [ | |
| google_logging_folder_sink.log_sink_audit.writer_identity, | |
| ] | |
| } | |
| # monitoring | |
| resource "google_project" "shared_monitoring" { | |
| name = "monitoring" | |
| project_id = "monitoring2-${random_id.shared_random_id.hex}" | |
| folder_id = google_folder.shared_services.name | |
| billing_account = var.billing_account_id | |
| labels = { "dept" : "engineering" } | |
| } | |
| resource "google_project_service" "bq_service_monitoring" { | |
| project = google_project.shared_monitoring.project_id | |
| service = "monitoring.googleapis.com" | |
| } | |
| resource "google_monitoring_notification_channel" "notification_channel_security" { | |
| provider = google-beta | |
| project = google_project.shared_monitoring.project_id # var.monitoring_project_id | |
| display_name = "Security Notification Channel" | |
| type = "email" | |
| labels = { | |
| email_address = var.group_security_admins | |
| } | |
| } | |
| resource "google_monitoring_notification_channel" "notification_channel_devops" { | |
| provider = google-beta | |
| project = google_project.shared_monitoring.project_id # var.monitoring_project_id | |
| display_name = "Devops Notification Channel" | |
| type = "email" | |
| labels = { | |
| email_address = var.group_devops | |
| } | |
| } | |
| resource "google_monitoring_notification_channel" "notification_channel_billing" { | |
| provider = google-beta | |
| project = google_project.shared_monitoring.project_id # var.monitoring_project_id | |
| display_name = "Billing Notification Channel" | |
| type = "email" | |
| labels = { | |
| email_address = var.group_billing_admins | |
| } | |
| } | |
| resource "google_monitoring_notification_channel" "notification_channel_developers" { | |
| provider = google-beta | |
| project = google_project.shared_monitoring.project_id # var.monitoring_project_id | |
| display_name = "Developers Notification Channel" | |
| type = "email" | |
| labels = { | |
| email_address = var.group_developers | |
| } | |
| } | |
| # TODO: workspace for monitoring (not avail in Terraform it seems so manual) | |
| # billing | |
| resource "google_project" "shared_billing" { | |
| name = "billing" | |
| project_id = "billing2-${random_id.shared_random_id.hex}" | |
| folder_id = google_folder.shared_services.name | |
| billing_account = var.billing_account_id | |
| labels = { "dept" : "finance" } | |
| } | |
| # enable billingbudgets.googleapis.com | |
| resource "google_project_service" "bq_service_billing_budgets" { | |
| project = google_project.shared_billing.project_id | |
| service = "billingbudgets.googleapis.com" | |
| } | |
| # BigQuery dataset for billing export | |
| # NOTE: must enable 'Logs Configuration Writer' for tf-sa on billing acct | |
| resource "google_project_service" "bq_service_billing" { | |
| project = google_project.shared_billing.project_id | |
| service = "bigquery.googleapis.com" | |
| } | |
| resource "google_project_service" "bq_data_transfer_service_billing" { | |
| project = google_project.shared_billing.project_id | |
| service = "bigquerydatatransfer.googleapis.com" | |
| } | |
| resource "google_bigquery_dataset" "billing_dataset" { | |
| project = google_project.shared_billing.project_id | |
| dataset_id = "billing_export_${random_id.shared_random_id.hex}" | |
| friendly_name = "Billing Export" | |
| description = "Exported billing data" | |
| location = "US" | |
| delete_contents_on_destroy = true # destroying resource will fail otherwise | |
| labels = { "dept" = "finance", "role" = "analytics" } | |
| } | |
| resource "google_logging_billing_account_sink" "billing_bq_export" { | |
| name = "billing-export" | |
| billing_account = var.billing_account_id | |
| destination = "bigquery.googleapis.com/projects/${google_project.shared_billing.project_id}/datasets/${google_bigquery_dataset.billing_dataset.dataset_id}" | |
| } | |
| resource "google_project_iam_binding" "billing_export_writer" { | |
| project = google_project.shared_billing.project_id | |
| role = "roles/bigquery.dataOwner" | |
| members = [ | |
| google_logging_billing_account_sink.billing_bq_export.writer_identity, | |
| ] | |
| } | |
| # host projects | |
| # nonprod | |
| resource "google_project" "shared_nw_nonprod" { | |
| name = "shared-nw-nonprod" | |
| project_id = "shared-nw-nonprod-${random_id.shared_random_id.hex}" | |
| folder_id = google_folder.shared_services.name | |
| billing_account = var.billing_account_id | |
| labels = { "dept" : "network", "env" : "non-production" } | |
| } | |
| resource "google_project_service" "compute_shared_nw_nonprod" { | |
| project = google_project.shared_nw_nonprod.project_id | |
| service = "compute.googleapis.com" | |
| } | |
| resource "google_project_service" "container_shared_nw_nonprod" { | |
| project = google_project.shared_nw_nonprod.project_id | |
| service = "container.googleapis.com" | |
| } | |
| resource "google_project_service" "servicenetworking_shared_nw_nonprod" { | |
| project = google_project.shared_nw_nonprod.project_id | |
| service = "servicenetworking.googleapis.com" | |
| } | |
| resource "google_compute_shared_vpc_host_project" "host_nonprod" { | |
| project = google_project.shared_nw_nonprod.project_id | |
| depends_on = [google_project_service.compute_shared_nw_nonprod] | |
| } | |
| resource "google_compute_network" "vpc_devops" { | |
| name = "devops-10-19-0-0" | |
| routing_mode = "REGIONAL" | |
| auto_create_subnetworks = false | |
| project = google_project.shared_nw_nonprod.project_id | |
| depends_on = [google_project_service.compute_shared_nw_nonprod] | |
| } | |
| resource "google_compute_subnetwork" "subnet_devops_k8s" { | |
| name = "k8s-nodes-devops" | |
| ip_cidr_range = "10.19.0.0/22" | |
| region = var.region | |
| private_ip_google_access = true | |
| project = google_project.shared_nw_nonprod.project_id | |
| network = google_compute_network.vpc_devops.id | |
| secondary_ip_range { | |
| range_name = "k8s-pods-devops" | |
| ip_cidr_range = "10.89.0.0/18" | |
| } | |
| secondary_ip_range { | |
| range_name = "k8s-svcs-devops" | |
| ip_cidr_range = "10.89.64.0/22" | |
| } | |
| } | |
| resource "google_compute_subnetwork" "subnet_devops_bastion" { | |
| name = "bastion-devops" | |
| ip_cidr_range = "10.19.64.0/29" | |
| region = var.region | |
| private_ip_google_access = true | |
| project = google_project.shared_nw_nonprod.project_id | |
| network = google_compute_network.vpc_devops.id | |
| } | |
| resource "google_compute_subnetwork" "subnet_devops_vms" { | |
| name = "vms-devops" | |
| ip_cidr_range = "10.19.65.0/24" | |
| region = var.region | |
| private_ip_google_access = true | |
| project = google_project.shared_nw_nonprod.project_id | |
| network = google_compute_network.vpc_devops.id | |
| } | |
| resource "google_compute_subnetwork" "subnet_devops_dbs" { | |
| name = "databases-devops" | |
| ip_cidr_range = "10.19.70.0/24" | |
| region = var.region | |
| private_ip_google_access = true | |
| project = google_project.shared_nw_nonprod.project_id | |
| network = google_compute_network.vpc_devops.id | |
| } | |
| # TODO: firewall rule port 22 for bastion | |
| resource "google_compute_network" "vpc_development" { | |
| name = "dev-10-12-0-0" | |
| routing_mode = "REGIONAL" | |
| auto_create_subnetworks = false | |
| project = google_project.shared_nw_nonprod.project_id | |
| depends_on = [google_project_service.compute_shared_nw_nonprod] | |
| } | |
| resource "google_compute_subnetwork" "subnet_dev_k8s" { | |
| name = "k8s-nodes-dev" | |
| ip_cidr_range = "10.12.0.0/22" | |
| region = var.region | |
| project = google_project.shared_nw_nonprod.project_id | |
| private_ip_google_access = true | |
| network = google_compute_network.vpc_development.id | |
| secondary_ip_range { | |
| range_name = "k8s-pods-dev" | |
| ip_cidr_range = "10.82.0.0/18" | |
| } | |
| secondary_ip_range { | |
| range_name = "k8s-svcs-dev" | |
| ip_cidr_range = "10.82.64.0/22" | |
| } | |
| } | |
| resource "google_compute_global_address" "service_range" { | |
| provider = google-beta | |
| name = "devrange-${random_id.shared_random_id.hex}" | |
| project = google_project.shared_nw_nonprod.project_id | |
| purpose = "VPC_PEERING" | |
| address_type = "INTERNAL" | |
| prefix_length = 16 | |
| network = google_compute_network.vpc_development.id | |
| } | |
| resource "google_service_networking_connection" "private_service_connection" { | |
| provider = google-beta | |
| network = google_compute_network.vpc_development.id | |
| service = "servicenetworking.googleapis.com" | |
| reserved_peering_ranges = [google_compute_global_address.service_range.name] | |
| } | |
| resource "google_compute_subnetwork" "subnet_dev_bastion" { | |
| name = "bastion-dev" | |
| ip_cidr_range = "10.12.64.0/29" | |
| region = var.region | |
| private_ip_google_access = true | |
| project = google_project.shared_nw_nonprod.project_id | |
| network = google_compute_network.vpc_development.id | |
| } | |
| resource "google_compute_subnetwork" "subnet_dev_vms" { | |
| name = "vms-dev" | |
| ip_cidr_range = "10.12.65.0/24" | |
| region = var.region | |
| private_ip_google_access = true | |
| project = google_project.shared_nw_nonprod.project_id | |
| network = google_compute_network.vpc_development.id | |
| } | |
| resource "google_compute_subnetwork" "subnet_dev_dbs" { | |
| name = "databases-dev" | |
| ip_cidr_range = "10.12.70.0/24" | |
| region = var.region | |
| private_ip_google_access = true | |
| project = google_project.shared_nw_nonprod.project_id | |
| network = google_compute_network.vpc_development.id | |
| } | |
| # TODO: firewall rule port 22 for bastion | |
| # prod | |
| resource "google_project" "shared_nw_prod" { | |
| name = "shared-nw-prod" | |
| project_id = "shared-nw-prod-${random_id.shared_random_id.hex}" | |
| folder_id = google_folder.shared_services.name | |
| billing_account = var.billing_account_id | |
| labels = { "dept" : "network", "env" : "production" } | |
| } | |
| resource "google_project_service" "compute_shared_nw_prod" { | |
| project = google_project.shared_nw_prod.project_id | |
| service = "compute.googleapis.com" | |
| } | |
| resource "google_project_service" "container_shared_nw_prod" { | |
| project = google_project.shared_nw_prod.project_id | |
| service = "container.googleapis.com" | |
| } | |
| resource "google_compute_shared_vpc_host_project" "host_prod" { | |
| project = google_project.shared_nw_prod.project_id | |
| depends_on = [google_project_service.compute_shared_nw_prod] | |
| } | |
| # network stage | |
| resource "google_compute_network" "vpc_stage" { | |
| name = "stage-10-11-0-0" | |
| routing_mode = "REGIONAL" | |
| auto_create_subnetworks = false | |
| project = google_project.shared_nw_prod.project_id | |
| depends_on = [google_project_service.compute_shared_nw_prod] | |
| } | |
| resource "google_compute_subnetwork" "subnet_stage_k8s" { | |
| name = "k8s-nodes-stage" | |
| ip_cidr_range = "10.11.0.0/22" | |
| region = var.region | |
| project = google_project.shared_nw_prod.project_id | |
| private_ip_google_access = true | |
| network = google_compute_network.vpc_stage.id | |
| secondary_ip_range { | |
| range_name = "k8s-pods-stage" | |
| ip_cidr_range = "10.81.0.0/18" | |
| } | |
| secondary_ip_range { | |
| range_name = "k8s-svcs-stage" | |
| ip_cidr_range = "10.81.64.0/22" | |
| } | |
| } | |
| resource "google_compute_subnetwork" "subnet_stage_bastion" { | |
| name = "bastion-stage" | |
| ip_cidr_range = "10.11.64.0/29" | |
| region = var.region | |
| private_ip_google_access = true | |
| project = google_project.shared_nw_prod.project_id | |
| network = google_compute_network.vpc_stage.id | |
| } | |
| resource "google_compute_subnetwork" "subnet_stage_vms" { | |
| name = "vms-stage" | |
| ip_cidr_range = "10.11.65.0/24" | |
| region = var.region | |
| private_ip_google_access = true | |
| project = google_project.shared_nw_prod.project_id | |
| network = google_compute_network.vpc_stage.id | |
| } | |
| resource "google_compute_subnetwork" "subnet_stage_dbs" { | |
| name = "databases-stage" | |
| ip_cidr_range = "10.11.70.0/24" | |
| region = var.region | |
| private_ip_google_access = true | |
| project = google_project.shared_nw_prod.project_id | |
| network = google_compute_network.vpc_stage.id | |
| } | |
| # network prod | |
| resource "google_compute_network" "vpc_production" { | |
| name = "production-10-10-0-0" | |
| routing_mode = "REGIONAL" | |
| auto_create_subnetworks = false | |
| project = google_project.shared_nw_prod.project_id | |
| depends_on = [google_project_service.compute_shared_nw_prod] | |
| } | |
| resource "google_compute_subnetwork" "subnet_prod_k8s" { | |
| name = "k8s-nodes-prod" | |
| ip_cidr_range = "10.10.0.0/22" | |
| region = var.region | |
| project = google_project.shared_nw_prod.project_id | |
| private_ip_google_access = true | |
| network = google_compute_network.vpc_production.id | |
| secondary_ip_range { | |
| range_name = "k8s-pods-prod" | |
| ip_cidr_range = "10.80.0.0/18" | |
| } | |
| secondary_ip_range { | |
| range_name = "k8s-svcs-prod" | |
| ip_cidr_range = "10.80.64.0/22" | |
| } | |
| } | |
| resource "google_compute_subnetwork" "subnet_prod_bastion" { | |
| name = "bastion-prod" | |
| ip_cidr_range = "10.12.64.0/29" | |
| region = var.region | |
| private_ip_google_access = true | |
| project = google_project.shared_nw_prod.project_id | |
| network = google_compute_network.vpc_production.id | |
| } | |
| resource "google_compute_subnetwork" "subnet_prod_vms" { | |
| name = "vms-prod" | |
| ip_cidr_range = "10.11.65.0/24" | |
| region = var.region | |
| private_ip_google_access = true | |
| project = google_project.shared_nw_prod.project_id | |
| network = google_compute_network.vpc_production.id | |
| } | |
| resource "google_compute_subnetwork" "subnet_prod_dbs" { | |
| name = "databases-prod" | |
| ip_cidr_range = "10.11.70.0/24" | |
| region = var.region | |
| private_ip_google_access = true | |
| project = google_project.shared_nw_prod.project_id | |
| network = google_compute_network.vpc_production.id | |
| } | |
| # service projects | |
| # dev | |
| resource "google_project" "development" { | |
| name = "development" | |
| project_id = "development-${random_id.shared_random_id.hex}" | |
| folder_id = google_folder.non_production.name | |
| billing_account = var.billing_account_id | |
| labels = { "dept" : "engineering", "env" : "non-production", "product" : "x" } | |
| } | |
| resource "google_project_service" "compute_development" { | |
| project = google_project.development.project_id | |
| service = "compute.googleapis.com" | |
| } | |
| resource "google_project_service" "container_development" { | |
| project = google_project.development.project_id | |
| service = "container.googleapis.com" | |
| } | |
| resource "google_project_service" "servicenetworking_development" { | |
| project = google_project.development.project_id | |
| service = "servicenetworking.googleapis.com" | |
| } | |
| resource "google_project_service" "memcache_development" { | |
| project = google_project.development.project_id | |
| service = "memcache.googleapis.com" | |
| } | |
| resource "google_compute_shared_vpc_service_project" "service_dev" { | |
| host_project = google_compute_shared_vpc_host_project.host_nonprod.project | |
| service_project = google_project.development.project_id | |
| } | |
| # add IAM role to link project to shared subnet | |
| data "google_project" "project_development" { | |
| project_id = google_project.development.project_id | |
| } | |
| resource "google_compute_subnetwork_iam_member" "member_development" { | |
| project = google_project.shared_nw_nonprod.project_id | |
| region = google_compute_subnetwork.subnet_dev_k8s.region | |
| subnetwork = google_compute_subnetwork.subnet_dev_k8s.name | |
| role = "roles/compute.networkUser" | |
| member = format("serviceAccount:service-%[email protected]", data.google_project.project_development.number) | |
| } | |
| # add memcache (Memorystore) example to development | |
| resource "google_memcache_instance" "cache_dev" { | |
| provider = google-beta | |
| project = google_project.development.project_id | |
| name = "cache-dev" | |
| region = var.region | |
| authorized_network = google_service_networking_connection.private_service_connection.network | |
| node_config { | |
| cpu_count = 1 | |
| memory_size_mb = 1024 | |
| } | |
| node_count = 1 | |
| memcache_version = "MEMCACHE_1_5" | |
| depends_on = [ | |
| google_service_networking_connection.private_service_connection, | |
| google_project_service.memcache_development | |
| ] | |
| } | |
| # stage | |
| resource "google_project" "stage" { | |
| name = "stage" | |
| project_id = "stage-${random_id.shared_random_id.hex}" | |
| folder_id = google_folder.production.name | |
| billing_account = var.billing_account_id | |
| labels = { "dept" : "engineering", "env" : "non-production", "product" : "x" } | |
| } | |
| resource "google_project_service" "compute_stage" { | |
| project = google_project.stage.project_id | |
| service = "compute.googleapis.com" | |
| } | |
| resource "google_project_service" "container_stage" { | |
| project = google_project.stage.project_id | |
| service = "container.googleapis.com" | |
| } | |
| resource "google_compute_shared_vpc_service_project" "service_stage" { | |
| host_project = google_compute_shared_vpc_host_project.host_prod.project | |
| service_project = google_project.stage.project_id | |
| } | |
| # add IAM role to link project to shared subnet | |
| data "google_project" "project_stage" { | |
| project_id = google_project.stage.project_id | |
| } | |
| resource "google_compute_subnetwork_iam_member" "member_stage" { | |
| project = google_project.shared_nw_prod.project_id | |
| region = google_compute_subnetwork.subnet_stage_k8s.region | |
| subnetwork = google_compute_subnetwork.subnet_stage_k8s.name | |
| role = "roles/compute.networkUser" | |
| member = format("serviceAccount:service-%[email protected]", data.google_project.project_stage.number) | |
| } | |
| # prod | |
| resource "google_project" "production" { | |
| name = "production" | |
| project_id = "production-${random_id.shared_random_id.hex}" | |
| folder_id = google_folder.production.name | |
| billing_account = var.billing_account_id | |
| labels = { "dept" : "engineering", "env" : "production", "product" : "x" } | |
| } | |
| resource "google_project_service" "compute_production" { | |
| project = google_project.production.project_id | |
| service = "compute.googleapis.com" | |
| } | |
| resource "google_project_service" "container_production" { | |
| project = google_project.production.project_id | |
| service = "container.googleapis.com" | |
| } | |
| resource "google_compute_shared_vpc_service_project" "service_prod" { | |
| host_project = google_compute_shared_vpc_host_project.host_prod.project | |
| service_project = google_project.production.project_id | |
| } | |
| # add IAM role to link project to shared subnet | |
| data "google_project" "project_production" { | |
| project_id = google_project.production.project_id | |
| } | |
| resource "google_compute_subnetwork_iam_member" "member_production" { | |
| project = google_project.shared_nw_prod.project_id | |
| region = google_compute_subnetwork.subnet_prod_k8s.region | |
| subnetwork = google_compute_subnetwork.subnet_prod_k8s.name | |
| role = "roles/compute.networkUser" | |
| member = format("serviceAccount:service-%[email protected]", data.google_project.project_production.number) | |
| } | |
| # BUDGET | |
| # budget notifications | |
| resource "google_billing_budget" "budget_sandbox" { | |
| provider = google-beta | |
| billing_account = data.google_billing_account.account.id | |
| display_name = "Sandbox Billing Budget" | |
| budget_filter { | |
| projects = [ | |
| "projects/mike-stage" | |
| ] | |
| } | |
| amount { | |
| specified_amount { | |
| currency_code = "USD" | |
| units = "100" | |
| } | |
| } | |
| threshold_rules { | |
| threshold_percent = 0.75 | |
| } | |
| all_updates_rule { | |
| monitoring_notification_channels = [ | |
| google_monitoring_notification_channel.notification_channel_billing.id, | |
| ] | |
| } | |
| } | |
| # LOG MONITORING / ALERTS (production) | |
| resource "google_logging_metric" "log_metric_route" { | |
| project = google_project.production.project_id | |
| name = "route_monitoring/metric" | |
| filter = "resource.type=\"gce_route\" AND jsonPayload.event_subtype=\"compute.routes.delete\" OR jsonPayload.event_subtype=\"compute.routes.insert\"" | |
| metric_descriptor { | |
| metric_kind = "DELTA" | |
| value_type = "INT64" | |
| unit = "1" | |
| display_name = "Route Monitoring" | |
| } | |
| } | |
| resource "google_monitoring_alert_policy" "alert_policy_route" { | |
| project = google_project.shared_monitoring.project_id | |
| display_name = "Route Monitoring" | |
| combiner = "OR" | |
| notification_channels = [google_monitoring_notification_channel.notification_channel_security.name] | |
| conditions { | |
| display_name = "logging/user/ROUTE_MONITORING" | |
| condition_threshold { | |
| filter = "metric.type=\"logging.googleapis.com/user/route_monitoring/metric\" AND resource.type=\"global\"" | |
| duration = "60s" | |
| comparison = "COMPARISON_GT" | |
| aggregations { | |
| alignment_period = "60s" | |
| per_series_aligner = "ALIGN_RATE" | |
| cross_series_reducer = "REDUCE_COUNT" | |
| } | |
| trigger { | |
| count = 1 | |
| percent = 0 | |
| } | |
| } | |
| } | |
| } | |
| resource "google_logging_metric" "log_metric_sql_instance" { | |
| project = google_project.production.project_id | |
| name = "sql_instance_monitoring/metric" | |
| filter = "protoPayload.methodName=\"cloudsql.instances.update\"" | |
| metric_descriptor { | |
| metric_kind = "DELTA" | |
| value_type = "INT64" | |
| unit = "1" | |
| display_name = "SQL Instance Monitoring" | |
| } | |
| } | |
| resource "google_monitoring_alert_policy" "alert_policy_sql_instance" { | |
| project = google_project.shared_monitoring.project_id | |
| display_name = "SQL Instance Monitoring" | |
| combiner = "OR" | |
| notification_channels = [google_monitoring_notification_channel.notification_channel_security.name] | |
| conditions { | |
| display_name = "logging/user/SQL_INSTANCE_MONITORING" | |
| condition_threshold { | |
| filter = "metric.type=\"logging.googleapis.com/user/sql_instance_monitoring/metric\" AND resource.type=\"global\"" | |
| duration = "60s" | |
| comparison = "COMPARISON_GT" | |
| aggregations { | |
| alignment_period = "60s" | |
| per_series_aligner = "ALIGN_RATE" | |
| cross_series_reducer = "REDUCE_COUNT" | |
| } | |
| trigger { | |
| count = 1 | |
| percent = 0 | |
| } | |
| } | |
| } | |
| } | |
| resource "google_logging_metric" "log_metric_network" { | |
| project = google_project.shared_nw_prod.project_id | |
| name = "network_monitoring/metric" | |
| filter = "resource.type=gce_network AND jsonPayload.event_subtype=\"compute.networks.insert\" OR jsonPayload.event_subtype=\"compute.networks.patch\" OR jsonPayload.event_subtype=\"compute.networks.delete\" OR jsonPayload.event_subtype=\"compute.networks.removePeering\" OR jsonPayload.event_subtype=\"compute.networks.addPeering\"" | |
| metric_descriptor { | |
| metric_kind = "DELTA" | |
| value_type = "INT64" | |
| unit = "1" | |
| display_name = "Network Monitoring" | |
| } | |
| } | |
| resource "google_monitoring_alert_policy" "alert_policy_network" { | |
| project = google_project.shared_monitoring.project_id | |
| display_name = "Network Monitoring" | |
| combiner = "OR" | |
| notification_channels = [google_monitoring_notification_channel.notification_channel_security.name] | |
| conditions { | |
| display_name = "logging/user/NETWORK_MONITORING" | |
| condition_threshold { | |
| filter = "metric.type=\"logging.googleapis.com/user/network_monitoring/metric\" AND resource.type=\"global\"" | |
| duration = "60s" | |
| comparison = "COMPARISON_GT" | |
| aggregations { | |
| alignment_period = "60s" | |
| per_series_aligner = "ALIGN_RATE" | |
| cross_series_reducer = "REDUCE_COUNT" | |
| } | |
| trigger { | |
| count = 1 | |
| percent = 0 | |
| } | |
| } | |
| } | |
| } | |
| resource "google_logging_metric" "log_metric_firewall" { | |
| project = google_project.shared_nw_prod.project_id | |
| name = "firewall_monitoring/metric" | |
| filter = "resource.type=\"gce_firewall_rule\" AND jsonPayload.event_subtype=\"compute.firewalls.patch\" OR jsonPayload.event_subtype=\"compute.firewalls.insert\"" | |
| metric_descriptor { | |
| metric_kind = "DELTA" | |
| value_type = "INT64" | |
| unit = "1" | |
| display_name = "Firewall Monitoring" | |
| } | |
| } | |
| resource "google_monitoring_alert_policy" "alert_policy_firewall" { | |
| project = google_project.shared_monitoring.project_id | |
| display_name = "Firewall Monitoring" | |
| combiner = "OR" | |
| notification_channels = [google_monitoring_notification_channel.notification_channel_security.name] | |
| conditions { | |
| display_name = "logging/user/FIREWALL_MONITORING" | |
| condition_threshold { | |
| filter = "metric.type=\"logging.googleapis.com/user/firewall_monitoring/metric\" AND resource.type=\"global\"" | |
| duration = "60s" | |
| comparison = "COMPARISON_GT" | |
| aggregations { | |
| alignment_period = "60s" | |
| per_series_aligner = "ALIGN_RATE" | |
| cross_series_reducer = "REDUCE_COUNT" | |
| } | |
| trigger { | |
| count = 1 | |
| percent = 0 | |
| } | |
| } | |
| } | |
| } | |
| resource "google_logging_metric" "log_metric_project_ownership" { | |
| project = google_project.production.project_id | |
| name = "project_ownership_monitoring/metric" | |
| filter = "(protoPayload.serviceName=\"cloudresourcemanager.googleapis.com\") AND (ProjectOwnership OR projectOwnerInvitee) OR (protoPayload.serviceData.policyDelta.bindingDeltas.action=\"REMOVE\" AND protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\") OR (protoPayload.serviceData.policyDelta.bindingDeltas.action=\"ADD\" AND protoPayload.serviceData.policyDelta.bindingDeltas.role=\"roles/owner\")" | |
| metric_descriptor { | |
| metric_kind = "DELTA" | |
| value_type = "INT64" | |
| unit = "1" | |
| display_name = "Project Ownership Monitoring" | |
| } | |
| } | |
| resource "google_monitoring_alert_policy" "alert_policy_project_ownership" { | |
| project = google_project.shared_monitoring.project_id | |
| display_name = "Project Ownership Monitoring" | |
| combiner = "OR" | |
| notification_channels = [google_monitoring_notification_channel.notification_channel_security.name] | |
| conditions { | |
| display_name = "logging/user/PROJECT_OWNERSHIP_MONITORING" | |
| condition_threshold { | |
| filter = "metric.type=\"logging.googleapis.com/user/project_ownership_monitoring/metric\" AND resource.type=\"global\"" | |
| duration = "60s" | |
| comparison = "COMPARISON_GT" | |
| aggregations { | |
| alignment_period = "60s" | |
| per_series_aligner = "ALIGN_RATE" | |
| cross_series_reducer = "REDUCE_COUNT" | |
| } | |
| trigger { | |
| count = 1 | |
| percent = 0 | |
| } | |
| } | |
| } | |
| } | |
| resource "google_logging_metric" "log_metric_bucket_iam" { | |
| project = google_project.production.project_id | |
| name = "bucket_iam_monitoring/metric" | |
| filter = "resource.type=gcs_bucket AND protoPayload.methodName=\"storage.setIamPermissions\"" | |
| metric_descriptor { | |
| metric_kind = "DELTA" | |
| value_type = "INT64" | |
| unit = "1" | |
| display_name = "Bucket IAM Monitoring" | |
| } | |
| } | |
| resource "google_monitoring_alert_policy" "alert_policy_bucket_iam" { | |
| project = google_project.shared_monitoring.project_id | |
| display_name = "Bucket IAM Monitoring" | |
| combiner = "OR" | |
| notification_channels = [google_monitoring_notification_channel.notification_channel_security.name] | |
| conditions { | |
| display_name = "logging/user/BUCKET_IAM_MONITORING" | |
| condition_threshold { | |
| filter = "metric.type=\"logging.googleapis.com/user/bucket_iam_monitoring/metric\" AND resource.type=\"global\"" | |
| duration = "60s" | |
| comparison = "COMPARISON_GT" | |
| aggregations { | |
| alignment_period = "60s" | |
| per_series_aligner = "ALIGN_RATE" | |
| cross_series_reducer = "REDUCE_COUNT" | |
| } | |
| trigger { | |
| count = 1 | |
| percent = 0 | |
| } | |
| } | |
| } | |
| } | |
| resource "google_logging_metric" "log_metric_audit_config" { | |
| project = google_project.production.project_id | |
| name = "audit_config_monitoring/metric" | |
| filter = "protoPayload.methodName=\"SetIamPolicy\" AND protoPayload.serviceData.policyDelta.auditConfigDeltas:*" | |
| metric_descriptor { | |
| metric_kind = "DELTA" | |
| value_type = "INT64" | |
| unit = "1" | |
| display_name = "Audit Config Monitoring" | |
| } | |
| } | |
| resource "google_monitoring_alert_policy" "alert_policy_audit_config" { | |
| project = google_project.shared_monitoring.project_id | |
| display_name = "Audit Config Monitoring" | |
| combiner = "OR" | |
| notification_channels = [google_monitoring_notification_channel.notification_channel_security.name] | |
| conditions { | |
| display_name = "logging/user/AUDIT_CONFIG_MONITORING" | |
| condition_threshold { | |
| filter = "metric.type=\"logging.googleapis.com/user/audit_config_monitoring/metric\" AND resource.type=\"global\"" | |
| duration = "60s" | |
| comparison = "COMPARISON_GT" | |
| aggregations { | |
| alignment_period = "60s" | |
| per_series_aligner = "ALIGN_RATE" | |
| cross_series_reducer = "REDUCE_COUNT" | |
| } | |
| trigger { | |
| count = 1 | |
| percent = 0 | |
| } | |
| } | |
| } | |
| } | |
| resource "google_logging_metric" "log_metric_custom_role" { | |
| project = google_project.production.project_id | |
| name = "custom_role_monitoring/metric" | |
| filter = "resource.type=\"iam_role\" AND protoPayload.methodName=\"google.iam.admin.v1.CreateRole\" OR protoPayload.methodName=\"google.iam.admin.v1.DeleteRole\" OR protoPayload.methodName=\"google.iam.admin.v1.UpdateRole\"" | |
| metric_descriptor { | |
| metric_kind = "DELTA" | |
| value_type = "INT64" | |
| unit = "1" | |
| display_name = "Custom Role Monitoring" | |
| } | |
| } | |
| resource "google_monitoring_alert_policy" "alert_policy_custom_role" { | |
| project = google_project.shared_monitoring.project_id | |
| display_name = "Custom Role Monitoring" | |
| combiner = "OR" | |
| notification_channels = [google_monitoring_notification_channel.notification_channel_security.name] | |
| conditions { | |
| display_name = "logging/user/CUSTOM_ROLE_MONITORING" | |
| condition_threshold { | |
| filter = "metric.type=\"logging.googleapis.com/user/custom_role_monitoring/metric\" AND resource.type=\"global\"" | |
| duration = "60s" | |
| comparison = "COMPARISON_GT" | |
| aggregations { | |
| alignment_period = "60s" | |
| per_series_aligner = "ALIGN_RATE" | |
| cross_series_reducer = "REDUCE_COUNT" | |
| } | |
| trigger { | |
| count = 1 | |
| percent = 0 | |
| } | |
| } | |
| } | |
| } | |
| # IAM roles | |
| # org | |
| # resource "google_organization_iam_binding" "org_iam_org_admin" { | |
| # org = var.org_id | |
| # role = "roles/iam.organizationAdmin" | |
| # | |
| # members = [ | |
| # var.group_org_admins | |
| # ] | |
| # } | |
| # | |
| # resource "google_organization_iam_binding" "org_iam_billing_admin" { | |
| # org = var.org_id | |
| # role = "roles/billing.admin" | |
| # | |
| # members = [ | |
| # var.group_billing_admins | |
| # ] | |
| # } | |
| # | |
| # Billing Account User (tf-sa: org) | |
| # resource "google_organization_iam_binding" "org_iam_billing_user" { | |
| # org = var.org_id | |
| # role = "roles/billing.user" | |
| # | |
| # members = [ | |
| # var.sa_terraform_admin | |
| # ] | |
| # } | |
| # | |
| # Organization Policy Admin (tf-sa: org) | |
| # resource "google_organization_iam_binding" "org_iam_org_policy_admin" { | |
| # org = var.org_id | |
| # role = "roles/orgpolicy.policyAdmin" | |
| # | |
| # members = [ | |
| # var.sa_terraform_admin | |
| # ] | |
| # } | |
| # | |
| # Cloud Security Scanner Editor (security: org) | |
| # resource "google_organization_iam_binding" "org_iam_security_scanner_editor" { | |
| # org = var.org_id | |
| # role = "roles/cloudsecurityscanner.editor" | |
| # | |
| # members = [ | |
| # var.group_security_admins | |
| # ] | |
| # } | |
| # TODO: change (org) scoped bindings to google_organization_iam_binding (non-playground-org) | |
| # Viewer (security, network, devops: org) | |
| resource "google_folder_iam_binding" "folder_iam_viewer" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/viewer" | |
| members = [ | |
| var.group_security_admins, | |
| var.group_network_admins, | |
| var.group_devops | |
| ] | |
| } | |
| # Security Admin (security: org) | |
| resource "google_folder_iam_binding" "folder_iam_security_admin" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/iam.securityAdmin" | |
| members = [ | |
| var.group_security_admins | |
| ] | |
| } | |
| # Compute Network Admin (network: org) roles/compute.networkAdmin | |
| resource "google_folder_iam_binding" "folder_iam_compute_network_admin" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/compute.networkAdmin" | |
| members = [ | |
| var.group_network_admins | |
| ] | |
| } | |
| # Service Networking Admin (network: org) roles/servicenetworking.networksAdmin | |
| resource "google_folder_iam_binding" "folder_iam_service_networking_admin" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/servicenetworking.networksAdmin" | |
| members = [ | |
| var.group_network_admins | |
| ] | |
| } | |
| # Compute Shared VPC Admin (network, tf-sa: org) | |
| resource "google_folder_iam_binding" "folder_iam_xpn_admin" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/compute.xpnAdmin" | |
| members = [ | |
| var.group_network_admins | |
| ] | |
| } | |
| # Logs Viewer (network: org) | |
| resource "google_folder_iam_binding" "folder_iam_log_viewer" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/compute.xpnAdmin" | |
| members = [ | |
| var.group_network_admins | |
| ] | |
| } | |
| # Private Logs Viewer (security: org) | |
| resource "google_folder_iam_binding" "folder_iam_private_log_viewer" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/logging.viewer" | |
| members = [ | |
| var.group_network_admins | |
| ] | |
| } | |
| # Compute Security Admin (security: org) | |
| resource "google_folder_iam_binding" "folder_iam_compute_security_admin" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/compute.securityAdmin" | |
| members = [ | |
| var.group_network_admins | |
| ] | |
| } | |
| # Compute Organization Security Policy Admin (security: org) | |
| resource "google_folder_iam_binding" "folder_iam_compute_org_security_policy_admin" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/compute.orgSecurityPolicyAdmin" | |
| members = [ | |
| var.group_network_admins | |
| ] | |
| } | |
| # Compute Instance Admin (tf-sa: org) | |
| resource "google_folder_iam_binding" "folder_iam_compute_instance_admin" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/compute.instanceAdmin" | |
| members = [ | |
| var.sa_terraform_admin | |
| ] | |
| } | |
| # Create Service Accounts (tf-sa: org) | |
| resource "google_folder_iam_binding" "folder_iam_sa_creator" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/iam.serviceAccountCreator" | |
| members = [ | |
| var.sa_terraform_admin | |
| ] | |
| } | |
| # Delete Service Accounts (tf-sa: org) | |
| resource "google_folder_iam_binding" "folder_iam_sa_deleter" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/iam.serviceAccountDeleter" | |
| members = [ | |
| var.sa_terraform_admin | |
| ] | |
| } | |
| # Service Account User (tf-sa: org) | |
| resource "google_folder_iam_binding" "folder_iam_sa_user" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/iam.serviceAccountUser" | |
| members = [ | |
| var.sa_terraform_admin | |
| ] | |
| } | |
| # Service Account Token Creator (tf-sa: org) | |
| resource "google_folder_iam_binding" "folder_iam_sa_token_creator" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/iam.serviceAccountTokenCreator" | |
| members = [ | |
| var.sa_terraform_admin | |
| ] | |
| } | |
| # Logs Configuration Writer (tf-sa: org) | |
| resource "google_folder_iam_binding" "folder_iam_log_config_writer" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/logging.configWriter" | |
| members = [ | |
| var.sa_terraform_admin | |
| ] | |
| } | |
| # Folder Creator (tf-sa: org) | |
| resource "google_folder_iam_binding" "folder_iam_folder_creator" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/resourcemanager.folderCreator" | |
| members = [ | |
| var.sa_terraform_admin | |
| ] | |
| } | |
| # Folder Editor (tf-sa: org) | |
| resource "google_folder_iam_binding" "folder_iam_folder_editor" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/resourcemanager.folderEditor" | |
| members = [ | |
| var.sa_terraform_admin | |
| ] | |
| } | |
| # projects | |
| # Project Creator (tf-sa: org) | |
| resource "google_folder_iam_binding" "folder_iam_project_creator" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/resourcemanager.projectCreator" | |
| members = [ | |
| var.sa_terraform_admin | |
| ] | |
| } | |
| # Project Deleter (tf-sa: org) | |
| resource "google_folder_iam_binding" "folder_iam_product_deleter" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/resourcemanager.projectDeleter" | |
| members = [ | |
| var.sa_terraform_admin | |
| ] | |
| } | |
| # Access Context Manager Editor (tf-sa: org) | |
| resource "google_folder_iam_binding" "folder_iam_access_context_editor" { | |
| folder = google_folder.demo_org.id | |
| role = "roles/accesscontextmanager.policyEditor" | |
| members = [ | |
| var.sa_terraform_admin | |
| ] | |
| } | |
| # BigQuery Data Viewer (billing: billing project) | |
| resource "google_project_iam_binding" "project_iam_bq_data_viewer" { | |
| project = google_project.shared_billing.project_id | |
| role = "roles/bigquery.dataViewer" | |
| members = [ | |
| var.group_billing_admins | |
| ] | |
| } | |
| # Editor (security: security project) | |
| resource "google_project_iam_binding" "project_iam_security_editor" { | |
| project = google_project.shared_security.project_id | |
| role = "roles/editor" | |
| members = [ | |
| var.group_security_admins | |
| ] | |
| } | |
| # Monitoring Admin (devops: monitoring project) | |
| resource "google_project_iam_binding" "project_iam_monitoring_admin" { | |
| project = google_project.shared_monitoring.project_id | |
| role = "roles/monitoring.admin" | |
| members = [ | |
| var.group_devops | |
| ] | |
| } | |
| # Monitoring Viewer (dev: monitoring project) | |
| resource "google_project_iam_binding" "project_iam_monitoring_viewer" { | |
| project = google_project.shared_monitoring.project_id | |
| role = "roles/monitoring.viewer" | |
| members = [ | |
| var.group_developers | |
| ] | |
| } | |
| # Kubernetes Engine Developer (dev: development project) | |
| resource "google_project_iam_binding" "project_iam_container_developer" { | |
| project = google_project.development.project_id | |
| role = "roles/container.developer" | |
| members = [ | |
| var.group_developers | |
| ] | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| variable "org_id" { | |
| default = "YOUR_ORG_ID" | |
| } | |
| variable "billing_account_id" { | |
| default = "CHANGEME" # DoiT Playground | |
| } | |
| # wherever you set up your workspace for monitoring | |
| variable "monitoring_project_id" { | |
| default = "mike-stage" | |
| } | |
| # finding GSuite ID: https://www.youtube.com/watch?v=AeadQfJT5kw | |
| variable "allowed_domain_ids" { | |
| default = ["CHANGEME"] | |
| } | |
| variable "region" { | |
| default = "us-west4" | |
| } | |
| variable "zone" { | |
| default = "us-west4-a" | |
| } | |
| variable "root_folder" { | |
| default = "folders/CHANGEME" # CHANGE: folder in playground | |
| } | |
| variable "audit_logs_bucket_name" { | |
| default = "demo-org-audit-logs" | |
| } | |
| # IAM groups (set up in Cloud Identity or GSuite) | |
| # CHANGE: using personal domain for testing / demo | |
| variable "group_org_admins" { | |
| default = "group:[email protected]" | |
| } | |
| variable "group_billing_admins" { | |
| default = "group:[email protected]" | |
| } | |
| variable "group_security_admins" { | |
| default = "group:[email protected]" | |
| } | |
| variable "group_network_admins" { | |
| default = "group:[email protected]" | |
| } | |
| variable "group_devops" { | |
| default = "group:[email protected]" | |
| } | |
| variable "group_developers" { | |
| default = "group:[email protected]" | |
| } | |
| variable "sa_terraform_admin" { | |
| default = "serviceAccount:[email protected]" | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment