main.tf (364 lines of code) (raw):

/** * Copyright 2022 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ terraform { backend "gcs" { bucket = "pi-delivery-tf-state" prefix = "terraform/state" } required_providers { google = { source = "hashicorp/google" version = "~> 4.47.0" } google-beta = { source = "hashicorp/google-beta" version = "~> 4.47.0" } } } provider "google" { project = var.project } provider "google-beta" { project = var.project } locals { managed_domains = [ "api.staging.pi.delivery" ] regions = toset(var.regions) } data "google_cloudfunctions2_function" "api_pi" { for_each = local.regions name = "api-pi" location = each.value } data "google_cloudfunctions2_function" "api_not_found" { name = "api-not-found" location = "us-central1" } data "google_cloudfunctions2_function" "api_pi_staging" { name = "api-pi-staging" location = "us-central1" } resource "google_storage_bucket" "functions_staging" { name = "piaas-gcp-gcf-staging" location = "US" uniform_bucket_level_access = true } resource "google_service_account" "functions_api" { account_id = "sa-functions-api" display_name = "Service Account for API on Cloud Functions" } resource "google_project_iam_binding" "storage_object_viewer" { project = var.project role = "roles/storage.objectViewer" members = [ "serviceAccount:${google_service_account.functions_api.email}" ] } resource "google_project_iam_binding" "logging_log_writer" { project = var.project role = "roles/logging.logWriter" members = [ "serviceAccount:${google_service_account.functions_api.email}" ] } resource "google_project_iam_binding" "monitoring_metric_writer" { project = var.project role = "roles/monitoring.metricWriter" members = [ "serviceAccount:${google_service_account.functions_api.email}" ] } resource "google_compute_global_address" "api" { name = "global-api-ip" } resource "google_compute_global_address" "api_v6" { name = "global-api-ip-v6" ip_version = "IPV6" } resource "random_id" "certificate" { byte_length = 4 prefix = "cert-" keepers = { managed_domains = join(",", local.managed_domains) } } resource "google_compute_managed_ssl_certificate" "certificate" { name = random_id.certificate.hex managed { domains = local.managed_domains } lifecycle { create_before_destroy = true } } resource "random_id" "neg" { byte_length = 4 keepers = { v = 7 } } resource "google_compute_region_network_endpoint_group" "api_func_pi_prod" { for_each = data.google_cloudfunctions2_function.api_pi name = "api-neg-func-pi-prod-${each.value.location}-${random_id.neg.hex}" network_endpoint_type = "SERVERLESS" region = each.value.location description = "API network endpoint for /v1/pi ${each.value.location}" cloud_run { service = each.value.name } } resource "google_compute_region_network_endpoint_group" "api_func_pi_staging" { name = "api-neg-func-pi-staging-${random_id.neg.hex}" network_endpoint_type = "SERVERLESS" region = data.google_cloudfunctions2_function.api_pi_staging.location description = "API network endpoint for /v1/pi staging" cloud_run { service = data.google_cloudfunctions2_function.api_pi_staging.name } } resource "google_compute_region_network_endpoint_group" "api_not_found" { name = "api-neg-not-found" network_endpoint_type = "SERVERLESS" region = data.google_cloudfunctions2_function.api_not_found.location description = "Endpoint for 404" cloud_run { service = data.google_cloudfunctions2_function.api_not_found.name } } resource "random_id" "backend" { byte_length = 4 } resource "google_compute_backend_service" "api_func_pi_prod" { name = "api-func-pi-prod-backend-${random_id.backend.hex}" load_balancing_scheme = "EXTERNAL_MANAGED" security_policy = "api-prod" dynamic "backend" { for_each = google_compute_region_network_endpoint_group.api_func_pi_prod content { group = backend.value.id } } log_config { enable = true sample_rate = 0.2 } lifecycle { create_before_destroy = true } } resource "google_compute_backend_service" "api_func_pi_staging" { name = "api-func-pi-staging-backend-${random_id.backend.hex}" load_balancing_scheme = "EXTERNAL_MANAGED" security_policy = "api-staging" backend { group = google_compute_region_network_endpoint_group.api_func_pi_staging.id } log_config { enable = true sample_rate = 1.0 } lifecycle { create_before_destroy = true } } resource "google_compute_backend_service" "api_not_found" { name = "api-not-found-backend" load_balancing_scheme = "EXTERNAL_MANAGED" security_policy = "api-prod" backend { group = google_compute_region_network_endpoint_group.api_not_found.id } log_config { enable = true sample_rate = 1.0 } lifecycle { create_before_destroy = true } } resource "google_compute_url_map" "api" { name = "api-url-map" default_service = google_compute_backend_service.api_not_found.id default_route_action { cors_policy { allow_origins = ["*"] disabled = false } } header_action { response_headers_to_add { header_name = "Strict-Transport-Security" header_value = "max-age=63072000" replace = true } response_headers_to_add { header_name = "Access-Control-Allow-Origin" header_value = "*" replace = true } } host_rule { hosts = ["api.pi.delivery"] path_matcher = "api-func-prod" } host_rule { hosts = ["api.staging.pi.delivery"] path_matcher = "api-func-staging" } path_matcher { name = "api-func-prod" default_service = google_compute_backend_service.api_not_found.id path_rule { paths = ["/v1/pi"] service = google_compute_backend_service.api_func_pi_prod.id route_action { cors_policy { allow_origins = ["*"] disabled = false } } } default_route_action { cors_policy { allow_origins = ["*"] disabled = false } } } path_matcher { name = "api-func-staging" default_service = google_compute_backend_service.api_not_found.id path_rule { paths = ["/v1/pi"] service = google_compute_backend_service.api_func_pi_staging.id route_action { cors_policy { allow_origins = ["*"] disabled = false } } } default_route_action { cors_policy { allow_origins = ["*"] disabled = false } } } } resource "google_compute_managed_ssl_certificate" "api" { name = "cert-api-pi-delivery" managed { domains = ["api.staging.pi.delivery", "api.pi.delivery"] } lifecycle { prevent_destroy = true } } data "google_compute_ssl_certificate" "k8s" { name = "mcrt-4dd17c3e-570e-4db8-9ec5-45803b394fd0" } resource "google_compute_ssl_policy" "ssl_policy" { name = "ssl-policy" profile = "MODERN" min_tls_version = "TLS_1_2" } resource "google_compute_target_https_proxy" "api" { name = "api-https-proxy" url_map = google_compute_url_map.api.id ssl_certificates = [google_compute_managed_ssl_certificate.certificate.id, google_compute_managed_ssl_certificate.api.id, data.google_compute_ssl_certificate.k8s.id] ssl_policy = google_compute_ssl_policy.ssl_policy.id } resource "google_compute_global_forwarding_rule" "api" { name = "api-forwarding-rule" port_range = "443" load_balancing_scheme = "EXTERNAL_MANAGED" ip_address = google_compute_global_address.api.id target = google_compute_target_https_proxy.api.id } resource "google_compute_global_forwarding_rule" "api_v6" { name = "api-forwarding-rule-v6" port_range = "443" load_balancing_scheme = "EXTERNAL_MANAGED" ip_address = google_compute_global_address.api_v6.id target = google_compute_target_https_proxy.api.id } resource "google_dns_managed_zone" "pi_delivery" { name = "pi-delivery" dns_name = "pi.delivery." description = "pi.delivery" dnssec_config { state = "on" } } resource "google_dns_record_set" "txt" { name = google_dns_managed_zone.pi_delivery.dns_name managed_zone = google_dns_managed_zone.pi_delivery.name type = "TXT" ttl = 21600 rrdatas = [ "\"google-site-verification=0z8eYQsVmHdhVIQLltoNwaimDS9IBevwwGV4klEUPKs\"" ] } resource "google_dns_record_set" "web" { name = google_dns_managed_zone.pi_delivery.dns_name managed_zone = google_dns_managed_zone.pi_delivery.name type = "A" ttl = 21600 // https://firebase.google.com/docs/hosting/custom-domain rrdatas = ["199.36.158.100"] } resource "google_dns_record_set" "api_a" { name = "api.${google_dns_managed_zone.pi_delivery.dns_name}" type = "A" ttl = 21600 managed_zone = google_dns_managed_zone.pi_delivery.name rrdatas = [ google_compute_global_address.api.address ] } resource "google_dns_record_set" "api_aaaa" { name = "api.${google_dns_managed_zone.pi_delivery.dns_name}" type = "AAAA" ttl = 21600 managed_zone = google_dns_managed_zone.pi_delivery.name rrdatas = [ google_compute_global_address.api_v6.address ] } resource "google_dns_record_set" "api_staging_a" { name = "api.staging.${google_dns_managed_zone.pi_delivery.dns_name}" type = "A" ttl = 60 managed_zone = google_dns_managed_zone.pi_delivery.name rrdatas = [ google_compute_global_address.api.address ] } resource "google_dns_record_set" "api_staging_aaaa" { name = "api.staging.${google_dns_managed_zone.pi_delivery.dns_name}" type = "AAAA" ttl = 60 managed_zone = google_dns_managed_zone.pi_delivery.name rrdatas = [ google_compute_global_address.api_v6.address ] }