main.tf (239 lines of code) (raw):
/**
* Copyright 2021 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.
*/
locals {
gcp_project_id = var.gcp_project
mirror_vpc_network_id = distinct([for subnet in var.subnets : subnet.mirror_vpc_network])
packet_mirroring_mirror_subnet_sources = var.mirror_vpc_subnets
packet_mirroring_mirror_tag_sources = var.mirror_vpc_tags
packet_mirroring_mirror_instance_sources = var.mirror_vpc_instances
collector_vpc_name = var.collector_vpc_name
collector_vpc_subnets = {
for subnet in var.subnets : "${element(split("/", subnet.mirror_vpc_network), 1)}--${element(split("/", subnet.mirror_vpc_network), 4)}--${subnet.collector_vpc_subnet_region}" => subnet
}
collector_vpc_subnets_cidrs = {
for subnet in var.subnets : "${element(split("/", subnet.mirror_vpc_network), 1)}--${element(split("/", subnet.mirror_vpc_network), 4)}--${subnet.collector_vpc_subnet_region}" => subnet.collector_vpc_subnet_cidr
}
subnet_key_count = [
for key in var.subnets : "${element(split("/", key.mirror_vpc_network), 1)}--${element(split("/", key.mirror_vpc_network), 4)}--${key.collector_vpc_subnet_region}"
]
same_project_mirror_networks = [for network in local.mirror_vpc_network_id : network if element(split("/", network), 1) == local.gcp_project_id]
}
# -------------------------------------------------------------- #
# VPC NETWORK
# -------------------------------------------------------------- #
resource "google_compute_network" "main" {
name = local.collector_vpc_name
project = local.gcp_project_id
routing_mode = var.vpc_routing_mode
description = var.vpc_description
auto_create_subnetworks = var.auto_create_subnetworks
delete_default_routes_on_create = var.delete_default_internet_gateway_routes
mtu = var.mtu
}
resource "google_compute_subnetwork" "main" {
for_each = local.collector_vpc_subnets
name = format("%s-%s-%02d", local.collector_vpc_name, "subnet", index(var.subnets, each.value) + 1)
project = local.gcp_project_id
ip_cidr_range = each.value.collector_vpc_subnet_cidr
region = each.value.collector_vpc_subnet_region
private_ip_google_access = var.private_ip_google_access
network = google_compute_network.main.self_link
depends_on = [google_compute_network.main]
}
# -------------------------------------------------------------- #
# FIREWALL-RULES
# -------------------------------------------------------------- #
resource "google_compute_firewall" "allow-health-check" {
name = "${local.collector_vpc_name}-rule-allow-health-check"
project = local.gcp_project_id
network = google_compute_network.main.name
direction = "INGRESS"
allow {
protocol = "tcp"
ports = ["80"]
}
source_ranges = ["35.191.0.0/16", "130.211.0.0/22"]
depends_on = [google_compute_subnetwork.main]
}
resource "google_compute_firewall" "allow_ingress" {
name = "${local.collector_vpc_name}-rule-allow-ingress"
project = local.gcp_project_id
network = google_compute_network.main.name
direction = "INGRESS"
allow {
protocol = "all"
}
source_ranges = ["0.0.0.0/0"]
depends_on = [google_compute_subnetwork.main]
}
resource "google_compute_firewall" "allow_egress" {
for_each = toset(local.same_project_mirror_networks)
name = "${element(split("/", each.value), 4)}-rule-allow-egress"
project = local.gcp_project_id
network = element(split("/", each.value), 4)
direction = "EGRESS"
allow {
protocol = "all"
}
destination_ranges = [for subnet in var.subnets : subnet.collector_vpc_subnet_cidr if subnet.mirror_vpc_network == each.value]
depends_on = [google_compute_subnetwork.main]
}
# -------------------------------------------------------------- #
# VPC-PEERING
# -------------------------------------------------------------- #
resource "google_compute_network_peering" "mirror_vpc_network_peering" {
for_each = toset(local.same_project_mirror_networks)
name = format("%s-%s-%02d", "mirror-to-", local.collector_vpc_name, index(local.same_project_mirror_networks, each.key) + 1)
network = each.value
peer_network = google_compute_network.main.id
export_custom_routes = var.export_local_custom_routes
import_custom_routes = var.export_peer_custom_routes
depends_on = [google_compute_subnetwork.main, google_compute_firewall.allow_egress]
}
resource "google_compute_network_peering" "collector_vpc_network_peering" {
for_each = toset(local.mirror_vpc_network_id)
name = format("%s-%s-%02d", local.collector_vpc_name, "to-mirror", index(local.mirror_vpc_network_id, each.key) + 1)
network = google_compute_network.main.id
peer_network = each.value
export_custom_routes = var.export_peer_custom_routes
import_custom_routes = var.export_local_custom_routes
depends_on = [google_compute_subnetwork.main, google_compute_firewall.allow_egress, google_compute_network_peering.mirror_vpc_network_peering]
}
# -------------------------------------------------------------- #
# INSTANCE-TEMPLATE
# -------------------------------------------------------------- #
resource "google_compute_instance_template" "main" {
for_each = local.collector_vpc_subnets
name = format("%s-%02d", local.collector_vpc_name, index(var.subnets, each.value) + 1)
project = local.gcp_project_id
description = var.template_description
metadata_startup_script = templatefile(
"${path.module}/files/startup_script.sh",
{
vpc_id = each.value.mirror_vpc_network
project_id = element(split("/", each.value.mirror_vpc_network), 1)
vpc_name = element(split("/", each.value.mirror_vpc_network), 4)
ip_cidrs = format("0.0.0.0/0\tAll-Traffic\n"),
collector_cidr = lookup(local.collector_vpc_subnets_cidrs, each.key)
})
machine_type = var.machine_type
can_ip_forward = false
disk {
source_image = var.golden_image
auto_delete = true
boot = true
}
# Google recommends custom service accounts that have cloud-platform scope and permissions granted via IAM Roles.
service_account {
email = var.service_account_email
scopes = ["cloud-platform", "logging-write", "monitoring"]
}
network_interface {
network = google_compute_network.main.self_link
subnetwork = google_compute_subnetwork.main[each.key].id
}
depends_on = [google_compute_subnetwork.main, google_compute_network_peering.collector_vpc_network_peering]
}
# -------------------------------------------------------------- #
# HEALTH-CHECK
# -------------------------------------------------------------- #
resource "google_compute_health_check" "main" {
name = "${local.collector_vpc_name}-http-health-check"
project = local.gcp_project_id
description = "Health check via http"
timeout_sec = 5
check_interval_sec = 10
healthy_threshold = 2
unhealthy_threshold = 3
http_health_check {
port = 80
}
depends_on = [google_compute_instance_template.main]
}
# -------------------------------------------------------------- #
# MANAGED-INSTANCE-GROUP
# -------------------------------------------------------------- #
resource "google_compute_region_instance_group_manager" "main" {
for_each = google_compute_instance_template.main
name = format("%s-%02d", local.collector_vpc_name, index(local.subnet_key_count, each.key) + 1)
region = format("%s", element(split("--", each.key), 2))
project = local.gcp_project_id
base_instance_name = "mig-instance"
version {
instance_template = each.value.id
}
auto_healing_policies {
health_check = google_compute_health_check.main.id
initial_delay_sec = 90
}
depends_on = [google_compute_instance_template.main, google_compute_health_check.main]
}
# -------------------------------------------------------------- #
# AUTO-SCALER
# -------------------------------------------------------------- #
resource "google_compute_region_autoscaler" "main" {
for_each = google_compute_region_instance_group_manager.main
name = format("%s-%02d", local.collector_vpc_name, index(local.subnet_key_count, each.key) + 1)
project = local.gcp_project_id
region = format("%s", element(split("/", each.value.id), 3))
target = each.value.id
autoscaling_policy {
max_replicas = 5
min_replicas = 1
cooldown_period = 240
cpu_utilization {
target = 0.75
}
}
depends_on = [google_compute_region_instance_group_manager.main]
}
# -------------------------------------------------------------- #
# INTERNAL-LOAD-BALANCER
# -------------------------------------------------------------- #
resource "google_compute_region_backend_service" "main" {
for_each = google_compute_region_instance_group_manager.main
name = format("%s-%02d", local.collector_vpc_name, index(local.subnet_key_count, each.key) + 1)
project = local.gcp_project_id
region = format("%s", element(split("/", each.value.instance_group), 8))
health_checks = [google_compute_health_check.main.id]
load_balancing_scheme = "INTERNAL"
backend {
group = each.value.instance_group
}
depends_on = [google_compute_region_instance_group_manager.main, google_compute_region_autoscaler.main]
}
# -------------------------------------------------------------- #
# FORWARDING-RULE
# -------------------------------------------------------------- #
resource "google_compute_forwarding_rule" "main" {
for_each = google_compute_region_backend_service.main
name = format("%s-%02d", local.collector_vpc_name, index(local.subnet_key_count, each.key) + 1)
project = local.gcp_project_id
region = format("%s", element(split("/", each.value.id), 3))
load_balancing_scheme = "INTERNAL"
backend_service = each.value.id
all_ports = true
allow_global_access = false
is_mirroring_collector = true
network = google_compute_network.main.self_link
subnetwork = google_compute_subnetwork.main[each.key].id
depends_on = [google_compute_region_backend_service.main]
}
# -------------------------------------------------------------- #
# PACKET-MIRRORING
# -------------------------------------------------------------- #
resource "google_compute_packet_mirroring" "main" {
for_each = local.collector_vpc_subnets
name = format("%s-%02d", local.collector_vpc_name, index(local.subnet_key_count, each.key) + 1)
project = local.gcp_project_id
region = each.value.collector_vpc_subnet_region
network {
url = each.value.mirror_vpc_network
}
collector_ilb {
url = google_compute_forwarding_rule.main[each.key].id
}
mirrored_resources {
dynamic "subnetworks" {
for_each = lookup(local.packet_mirroring_mirror_subnet_sources, each.key, [])
content {
url = subnetworks.value
}
}
tags = lookup(local.packet_mirroring_mirror_tag_sources, each.key, [])
dynamic "instances" {
for_each = lookup(local.packet_mirroring_mirror_instance_sources, each.key, [])
content {
url = instances.value
}
}
}
filter {
ip_protocols = var.ip_protocols
direction = var.direction
cidr_ranges = var.cidr_ranges
}
depends_on = [google_compute_forwarding_rule.main]
}