diff --git a/.github/workflows/_terraform.yml b/.github/workflows/_terraform.yml index 15fbdb062..2cb5ce9d9 100644 --- a/.github/workflows/_terraform.yml +++ b/.github/workflows/_terraform.yml @@ -28,10 +28,9 @@ jobs: run: | sudo apt-get update sudo apt-get install -y cloud-init - sudo cloud-init schema --config-file terraform/modules/google-cloud/apps/relay/templates/cloud-init.yaml + cloud-init schema --config-file terraform/modules/google-cloud/apps/relay/templates/cloud-init.yaml # This doesn't work if the file contains interpolated variables - # sudo cloud-init schema --config-file terraform/modules/google-cloud/apps/elixir/templates/cloud-init.yaml - sudo cloud-init schema --config-file terraform/modules/google-cloud/apps/gateway-region-instance-group/templates/cloud-init.yaml + # cloud-init schema --config-file terraform/modules/google-cloud/apps/elixir/templates/cloud-init.yaml - name: Check Formatting working-directory: terraform run: | diff --git a/terraform/modules/google-cloud/apps/gateway-region-instance-group/README.md b/terraform/modules/google-cloud/apps/gateway-region-instance-group/README.md new file mode 100644 index 000000000..b0468dccc --- /dev/null +++ b/terraform/modules/google-cloud/apps/gateway-region-instance-group/README.md @@ -0,0 +1,3 @@ +# Terraform Google Gateway + +This module has been moved to a dedicated repisotry [here](https://github.com/firezone/terraform-google-gateway). diff --git a/terraform/modules/google-cloud/apps/gateway-region-instance-group/iam.tf b/terraform/modules/google-cloud/apps/gateway-region-instance-group/iam.tf deleted file mode 100644 index 5419f8884..000000000 --- a/terraform/modules/google-cloud/apps/gateway-region-instance-group/iam.tf +++ /dev/null @@ -1,63 +0,0 @@ - -# Create IAM role for the application instances -resource "google_service_account" "application" { - project = var.project_id - - account_id = "firezone-${var.name}" - display_name = "${var.name} instances" - description = "Service account for ${var.name} Firezone Gateway instances." -} - -## Allow application service account to pull images from the container registry -resource "google_project_iam_member" "artifacts" { - project = var.project_id - - role = "roles/artifactregistry.reader" - - member = "serviceAccount:${google_service_account.application.email}" -} - -## Allow fluentbit to injest logs -resource "google_project_iam_member" "logs" { - project = var.project_id - - role = "roles/logging.logWriter" - - member = "serviceAccount:${google_service_account.application.email}" -} - -## Allow reporting application errors -resource "google_project_iam_member" "errors" { - project = var.project_id - - role = "roles/errorreporting.writer" - - member = "serviceAccount:${google_service_account.application.email}" -} - -## Allow reporting metrics -resource "google_project_iam_member" "metrics" { - project = var.project_id - - role = "roles/monitoring.metricWriter" - - member = "serviceAccount:${google_service_account.application.email}" -} - -## Allow reporting metrics -resource "google_project_iam_member" "service_management" { - project = var.project_id - - role = "roles/servicemanagement.reporter" - - member = "serviceAccount:${google_service_account.application.email}" -} - -## Allow appending traces -resource "google_project_iam_member" "cloudtrace" { - project = var.project_id - - role = "roles/cloudtrace.agent" - - member = "serviceAccount:${google_service_account.application.email}" -} diff --git a/terraform/modules/google-cloud/apps/gateway-region-instance-group/main.tf b/terraform/modules/google-cloud/apps/gateway-region-instance-group/main.tf deleted file mode 100644 index 064adaeeb..000000000 --- a/terraform/modules/google-cloud/apps/gateway-region-instance-group/main.tf +++ /dev/null @@ -1,240 +0,0 @@ -data "google_compute_zones" "in_region" { - project = var.project_id - region = var.compute_region -} - -locals { - labels = merge({ - managed_by = "terraform" - application = "firezone-gateway" - }, var.labels) - - network_tags = [ - "firezone-gateways-${var.name}" - ] - - google_health_check_ip_ranges = [ - "130.211.0.0/22", - "35.191.0.0/16", - ] - - compute_region_zones = length(var.compute_instance_availability_zones) == 0 ? data.google_compute_zones.in_region.names : var.compute_instance_availability_zones -} - -# Fetch most recent COS image -data "google_compute_image" "ubuntu" { - family = "ubuntu-2204-lts" - project = "ubuntu-os-cloud" -} - -# Deploy app -resource "google_compute_instance_template" "application" { - project = var.project_id - - name_prefix = "${var.name}-" - - description = "This template is used to create ${var.name} Firezone Gateway instances." - - machine_type = var.compute_instance_type - - can_ip_forward = true - - tags = local.network_tags - - labels = merge({ - container-vm = data.google_compute_image.ubuntu.name - version = replace(var.vsn, ".", "-") - }, local.labels) - - scheduling { - automatic_restart = true - on_host_maintenance = "MIGRATE" - provisioning_model = "STANDARD" - } - - reservation_affinity { - type = "ANY_RESERVATION" - } - - disk { - source_image = data.google_compute_image.ubuntu.self_link - auto_delete = true - boot = true - } - - network_interface { - subnetwork = var.compute_subnetwork - - stack_type = "IPV4_IPV6" - - dynamic "ipv6_access_config" { - for_each = var.compute_provision_public_ipv6_address == true ? [true] : [] - - content { - network_tier = "PREMIUM" - # Ephemeral IP address - } - } - - dynamic "access_config" { - for_each = var.compute_provision_public_ipv4_address == true ? [true] : [] - - content { - network_tier = "PREMIUM" - # Ephemeral IP address - } - } - } - - service_account { - email = google_service_account.application.email - - scopes = [ - # Those are default scopes - "https://www.googleapis.com/auth/devstorage.read_only", - "https://www.googleapis.com/auth/logging.write", - "https://www.googleapis.com/auth/monitoring.write", - "https://www.googleapis.com/auth/service.management.readonly", - "https://www.googleapis.com/auth/servicecontrol", - "https://www.googleapis.com/auth/trace.append", - ] - } - - shielded_instance_config { - enable_integrity_monitoring = true - enable_secure_boot = false - enable_vtpm = true - } - - metadata = { - user-data = templatefile("${path.module}/templates/cloud-init.yaml", { - project_id = var.project_id - otlp_grpc_endpoint = "127.0.0.1:4317" - observability_log_level = var.observability_log_level - - firezone_token = var.token - firezone_api_url = var.api_url - firezone_version = var.vsn - firezone_artifact_url = "https://storage.googleapis.com/firezone-prod-artifacts/firezone-gateway" - }) - - google-logging-enabled = "true" - google-logging-use-fluentbit = "true" - - # Report health-related metrics to Cloud Monitoring - google-monitoring-enabled = "true" - } - - depends_on = [ - google_project_service.compute, - google_project_service.pubsub, - google_project_service.bigquery, - google_project_service.container, - google_project_service.stackdriver, - google_project_service.logging, - google_project_service.monitoring, - google_project_service.cloudprofiler, - google_project_service.cloudtrace, - google_project_service.servicenetworking, - google_project_iam_member.artifacts, - google_project_iam_member.logs, - google_project_iam_member.errors, - google_project_iam_member.metrics, - google_project_iam_member.service_management, - google_project_iam_member.cloudtrace, - ] - - lifecycle { - create_before_destroy = true - } -} - -# Create health check -resource "google_compute_health_check" "port" { - project = var.project_id - - name = "${var.name}-${var.health_check.name}" - - check_interval_sec = var.health_check.check_interval_sec != null ? var.health_check.check_interval_sec : 5 - timeout_sec = var.health_check.timeout_sec != null ? var.health_check.timeout_sec : 5 - healthy_threshold = var.health_check.healthy_threshold != null ? var.health_check.healthy_threshold : 2 - unhealthy_threshold = var.health_check.unhealthy_threshold != null ? var.health_check.unhealthy_threshold : 2 - - log_config { - enable = false - } - - http_health_check { - port = var.health_check.port - - host = var.health_check.http_health_check.host - request_path = var.health_check.http_health_check.request_path - response = var.health_check.http_health_check.response - } - - lifecycle { - create_before_destroy = true - } -} - -# Use template to deploy zonal instance group -resource "google_compute_region_instance_group_manager" "application" { - project = var.project_id - - name = "${var.name}-${var.compute_region}" - - base_instance_name = var.name - - region = var.compute_region - distribution_policy_zones = local.compute_region_zones - - target_size = var.compute_instance_replicas - - wait_for_instances = true - wait_for_instances_status = "STABLE" - - version { - name = var.vsn - instance_template = google_compute_instance_template.application.self_link - } - - auto_healing_policies { - initial_delay_sec = var.health_check.initial_delay_sec - - health_check = google_compute_health_check.port.self_link - } - - update_policy { - type = "PROACTIVE" - minimal_action = "REPLACE" - - max_unavailable_fixed = max(1, length(local.compute_region_zones)) - max_surge_fixed = max(1, var.compute_instance_replicas - 1) + length(local.compute_region_zones) - } - - timeouts { - create = "30m" - update = "30m" - delete = "20m" - } - - depends_on = [ - google_compute_instance_template.application - ] -} - -## Open HTTP port for the health checks -resource "google_compute_firewall" "http-health-checks" { - project = var.project_id - - name = "${var.name}-healthcheck" - network = var.compute_network - - source_ranges = local.google_health_check_ip_ranges - target_tags = local.network_tags - - allow { - protocol = var.health_check.protocol - ports = [var.health_check.port] - } -} diff --git a/terraform/modules/google-cloud/apps/gateway-region-instance-group/outputs.tf b/terraform/modules/google-cloud/apps/gateway-region-instance-group/outputs.tf deleted file mode 100644 index efed6b114..000000000 --- a/terraform/modules/google-cloud/apps/gateway-region-instance-group/outputs.tf +++ /dev/null @@ -1,15 +0,0 @@ -output "service_account" { - value = google_service_account.application -} - -output "target_tags" { - value = local.network_tags -} - -output "instance_template" { - value = google_compute_instance_template.application -} - -output "instance_group" { - value = google_compute_region_instance_group_manager.application -} diff --git a/terraform/modules/google-cloud/apps/gateway-region-instance-group/services.tf b/terraform/modules/google-cloud/apps/gateway-region-instance-group/services.tf deleted file mode 100644 index f8ac4715e..000000000 --- a/terraform/modules/google-cloud/apps/gateway-region-instance-group/services.tf +++ /dev/null @@ -1,83 +0,0 @@ -resource "google_project_service" "compute" { - project = var.project_id - service = "compute.googleapis.com" - - disable_on_destroy = false -} - -resource "google_project_service" "pubsub" { - project = var.project_id - service = "pubsub.googleapis.com" - - disable_on_destroy = false -} - -resource "google_project_service" "bigquery" { - project = var.project_id - service = "bigquery.googleapis.com" - - disable_on_destroy = false -} - -resource "google_project_service" "container" { - project = var.project_id - service = "container.googleapis.com" - - depends_on = [ - google_project_service.compute, - google_project_service.pubsub, - google_project_service.bigquery, - ] - - disable_on_destroy = false -} - -resource "google_project_service" "stackdriver" { - project = var.project_id - service = "stackdriver.googleapis.com" - - disable_on_destroy = false -} - -resource "google_project_service" "logging" { - project = var.project_id - service = "logging.googleapis.com" - - disable_on_destroy = false - - depends_on = [google_project_service.stackdriver] -} - -resource "google_project_service" "monitoring" { - project = var.project_id - service = "monitoring.googleapis.com" - - disable_on_destroy = false - - depends_on = [google_project_service.stackdriver] -} - -resource "google_project_service" "cloudprofiler" { - project = var.project_id - service = "cloudprofiler.googleapis.com" - - disable_on_destroy = false - - depends_on = [google_project_service.stackdriver] -} - -resource "google_project_service" "cloudtrace" { - project = var.project_id - service = "cloudtrace.googleapis.com" - - disable_on_destroy = false - - depends_on = [google_project_service.stackdriver] -} - -resource "google_project_service" "servicenetworking" { - project = var.project_id - service = "servicenetworking.googleapis.com" - - disable_on_destroy = false -} diff --git a/terraform/modules/google-cloud/apps/gateway-region-instance-group/templates/cloud-init.yaml b/terraform/modules/google-cloud/apps/gateway-region-instance-group/templates/cloud-init.yaml deleted file mode 100644 index 0f46a3802..000000000 --- a/terraform/modules/google-cloud/apps/gateway-region-instance-group/templates/cloud-init.yaml +++ /dev/null @@ -1,55 +0,0 @@ -#cloud-config - -package_update: true -package_upgrade: true -package_reboot_if_required: true - -packages: - - apt-transport-https - - ca-certificates - - software-properties-common - - curl - -write_files: - - path: /etc/apt/keyrings - permissions: "0755" - owner: root:root - content: "" - - - path: /etc/google-cloud-ops-agent/config.yaml - permissions: "0644" - owner: root - content: | - combined: - receivers: - otlp: - type: otlp - metrics_mode: googlecloudmonitoring - metrics: - service: - pipelines: - otlp: - receivers: [otlp] - traces: - service: - pipelines: - otlp: - receivers: [otlp] - -runcmd: - # Install Ops Agent - - curl -sSO https://dl.google.com/cloudagents/add-google-cloud-ops-agent-repo.sh - - sudo bash add-google-cloud-ops-agent-repo.sh --also-install - # Install Firezone Gateway - - | - export FIREZONE_TOKEN="${firezone_token}" - export FIREZONE_API_URL="${firezone_api_url}" - export FIREZONE_VERSION="${firezone_version}" - export FIREZONE_ARTIFACT_URL="${firezone_artifact_url}" - export FIREZONE_LOG_FORMAT="google-cloud" - export FIREZONE_GOOGLE_CLOUD_PROJECT_ID="${project_id}" - export FIREZONE_OTLP_GRPC_ENDPOINT="${otlp_grpc_endpoint}" - export RUST_LOG="${observability_log_level}" - curl -fsSL https://raw.githubusercontent.com/firezone/firezone/main/scripts/gateway-systemd-install.sh -o /tmp/gateway-install.sh - bash /tmp/gateway-install.sh - rm /tmp/gateway-install.sh diff --git a/terraform/modules/google-cloud/apps/gateway-region-instance-group/variables.tf b/terraform/modules/google-cloud/apps/gateway-region-instance-group/variables.tf deleted file mode 100644 index ffa80dcc7..000000000 --- a/terraform/modules/google-cloud/apps/gateway-region-instance-group/variables.tf +++ /dev/null @@ -1,148 +0,0 @@ -variable "project_id" { - type = string - description = "ID of a Google Cloud Project" -} - -################################################################################ -## Compute -################################################################################ - -variable "compute_network" { - type = string -} - -variable "compute_subnetwork" { - type = string -} - -variable "compute_region" { - type = string -} - -variable "compute_instance_availability_zones" { - type = list(string) - default = [] - description = "List of zones in the region defined in `compute_region` where replicas should be deployed. Empty list means that all available zones will be used." -} - -variable "compute_instance_replicas" { - type = string -} - -variable "compute_instance_type" { - type = string -} - -variable "compute_provision_public_ipv4_address" { - type = bool - default = true - description = "Whether to provision public IPv4 address for the instances." -} - -variable "compute_provision_public_ipv6_address" { - type = bool - default = true - description = "Whether to provision public IPv4 address for the instances." -} - -################################################################################ -## Observability -################################################################################ - -variable "observability_log_level" { - type = string - nullable = false - default = "info" - - description = "Sets RUST_LOG environment variable which applications should use to configure Rust Logger. Default: 'info'." -} - -################################################################################ -## Regional Instance Group -################################################################################ - -variable "name" { - type = string - nullable = true - default = "gateway" - - description = "Name of the application." -} - -variable "labels" { - type = map(string) - nullable = false - default = {} - - description = "Labels to add to all created by this module resources." -} - -################################################################################ -## Firezone Gateway -################################################################################ - -variable "token" { - type = string - description = "Portal token to use for authentication." - sensitive = true -} - -variable "api_url" { - type = string - default = "wss://api.firezone.dev" - description = "URL of the control plane endpoint." -} - -variable "artifact_url" { - type = string - default = "https://storage.googleapis.com/firezone-prod-artifacts/firezone-gateway" - description = "URL from which Firezone install script will download the gateway binary" -} - -variable "vsn" { - type = string - default = "latest" - description = "Version of the Firezone gateway that is downloaded from `artifact_url`." -} - -variable "health_check" { - type = object({ - name = string - protocol = string - port = number - - initial_delay_sec = number - check_interval_sec = optional(number) - timeout_sec = optional(number) - healthy_threshold = optional(number) - unhealthy_threshold = optional(number) - - http_health_check = optional(object({ - host = optional(string) - request_path = optional(string) - port = optional(string) - response = optional(string) - })) - }) - - nullable = false - - default = { - name = "health" - protocol = "TCP" - port = 8080 - - initial_delay_sec = 100 - - check_interval_sec = 15 - timeout_sec = 10 - healthy_threshold = 1 - unhealthy_threshold = 3 - - http_health_check = { - request_path = "/healthz" - } - } - - description = "Health check which will be used for auto healing policy." -}