#!/usr/bin/env bash

# GCP Network Sensor Terraform Bundle
# This script scaffolds a Terraform project for deploying the network sensor on GCP
# Usage: ./gcp-network-sensor.sh /path/to/target/root

set -euo pipefail

TARGET_ROOT="${1:-.}"
INSTALL_PATH="${TARGET_ROOT}/deploy/gcp-network-sensor"
BLACKSHIELD_API_URL="${BLACKSHIELD_API_URL:-https://api.blackshield.chaplau.com}"
BLACKSHIELD_NETWORK_SENSOR_IMAGE="${BLACKSHIELD_NETWORK_SENSOR_IMAGE:-public.ecr.aws/blackshield-security/network-sensor:1.0.0}"

replace_literal() {
  local file_path="$1"
  local placeholder="$2"
  local replacement="$3"
  local tmp_file="${file_path}.tmp.$$"

  sed "s|${placeholder}|${replacement}|g" "$file_path" > "$tmp_file"
  mv "$tmp_file" "$file_path"
}

echo "Creating GCP Network Sensor Terraform project at: ${INSTALL_PATH}"

mkdir -p "${INSTALL_PATH}"

# Write main.tf
cat > "${INSTALL_PATH}/main.tf" << 'EOF'
terraform {
  required_version = ">= 1.0"
  required_providers {
    google = {
      source  = "hashicorp/google"
      version = "~> 5.0"
    }
  }
}

provider "google" {
  project = var.gcp_project_id
  region  = var.gcp_region
}

# Service account for sensor
resource "google_service_account" "network_sensor" {
  account_id   = "blackshield-network-sensor"
  display_name = "BlackShield Network Sensor"
  project      = var.gcp_project_id
}

# IAM bindings for logging and secrets access
resource "google_project_iam_member" "sensor_logging" {
  project = var.gcp_project_id
  role    = "roles/logging.logWriter"
  member  = "serviceAccount:${google_service_account.network_sensor.email}"
}

resource "google_project_iam_member" "sensor_secrets" {
  project = var.gcp_project_id
  role    = "roles/secretmanager.secretAccessor"
  member  = "serviceAccount:${google_service_account.network_sensor.email}"
}

# Firewall rule for packet mirroring (VXLAN UDP 4789)
resource "google_compute_firewall" "allow_packet_mirror" {
  name    = "allow-packet-mirror-${var.environment}"
  network = var.vpc_network_name
  project = var.gcp_project_id

  allow {
    protocol = "udp"
    ports    = ["4789"]
  }

  source_ranges = ["10.0.0.0/8"]
  target_tags   = ["network-sensor"]
}

# Firewall rule for HTTPS egress
resource "google_compute_firewall" "allow_https_egress" {
  name              = "allow-https-egress-${var.environment}"
  network           = var.vpc_network_name
  direction         = "EGRESS"
  priority          = 1000
  destination_ranges = ["0.0.0.0/0"]
  project           = var.gcp_project_id

  allow {
    protocol = "tcp"
    ports    = ["443"]
  }

  target_tags = ["network-sensor"]
}

# Health check for internal load balancer
resource "google_compute_health_check" "network_sensor" {
  name    = "network-sensor-health-${var.environment}"
  project = var.gcp_project_id

  timeout_sec = 5

  http_health_check {
    port         = 8080
    request_path = "/health"
  }

  check_interval_sec  = 10
  unhealthy_threshold = 3
}

# Backend service for packet mirroring sink
resource "google_compute_backend_service" "network_sensor" {
  name                  = "network-sensor-backend-${var.environment}"
  project               = var.gcp_project_id
  protocol              = "TCP"
  health_checks         = [google_compute_health_check.network_sensor.id]
  load_balancing_scheme = "INTERNAL"
}

# Forwarding rule (internal load balancer for mirror collection)
resource "google_compute_forwarding_rule" "network_sensor" {
  name                  = "network-sensor-mirror-sink-${var.environment}"
  project               = var.gcp_project_id
  load_balancing_scheme = "INTERNAL"
  backend_service       = google_compute_backend_service.network_sensor.id
  network               = var.vpc_network_name
  subnetwork            = var.monitoring_subnet_name
}

# Compute instance for sensor
resource "google_compute_instance" "network_sensor" {
  name         = "network-sensor-${var.environment}"
  machine_type = var.machine_type
  zone         = var.gcp_zone
  tags         = ["network-sensor"]
  project      = var.gcp_project_id

  boot_disk {
    initialize_params {
      image = var.image_family
      size  = var.boot_disk_size
      type  = "pd-ssd"
    }
  }

  network_interface {
    network    = var.vpc_network_name
    subnetwork = var.monitoring_subnet_name
  }

  service_account {
    email  = google_service_account.network_sensor.email
    scopes = ["cloud-platform"]
  }

  metadata = {
    startup-script = templatefile("${path.module}/startup.sh.tftpl", {
      api_url      = var.api_url
      sensor_type  = var.sensor_type
      min_severity = var.min_severity
    })
  }

  depends_on = [
    google_secret_manager_secret_version.network_sensor_key
  ]
}

# Backend service backend binding
resource "google_compute_backend_service_backend" "network_sensor" {
  backend_service = google_compute_backend_service.network_sensor.id
  instance        = google_compute_instance.network_sensor.self_link
  project         = var.gcp_project_id
}

# Secret Manager for API key
resource "google_secret_manager_secret" "network_sensor_key" {
  secret_id = "blackshield-network-sensor-key"
  project   = var.gcp_project_id

  replication {
    automatic = true
  }
}

# Secret version (populated via variable)
resource "google_secret_manager_secret_version" "network_sensor_key" {
  secret      = google_secret_manager_secret.network_sensor_key.id
  secret_data = var.api_key
}

# Packet mirroring policy
resource "google_compute_packet_mirroring" "prod_to_sensor" {
  name    = "prod-to-sensor-${var.environment}"
  project = var.gcp_project_id

  network {
    url = "projects/${var.gcp_project_id}/global/networks/${var.vpc_network_name}"
  }

  mirrored_resources {
    subnets = [
      "projects/${var.gcp_project_id}/regions/${var.gcp_region}/subnetworks/${var.production_subnet_name}"
    ]
  }

  collector_ilb {
    url = google_compute_forwarding_rule.network_sensor.self_link
  }
}

# Outputs
output "sensor_instance_name" {
  value       = google_compute_instance.network_sensor.name
  description = "Network Sensor Instance Name"
}

output "sensor_instance_ip" {
  value       = google_compute_instance.network_sensor.network_interface[0].network_ip
  description = "Network Sensor Instance Private IP"
}
EOF

# Write variables.tf
cat > "${INSTALL_PATH}/variables.tf" << 'EOF'
variable "gcp_project_id" {
  type        = string
  description = "GCP Project ID"
}

variable "gcp_region" {
  type        = string
  description = "GCP Region"
  default     = "us-central1"
}

variable "gcp_zone" {
  type        = string
  description = "GCP Zone"
  default     = "us-central1-a"
}

variable "environment" {
  type        = string
  description = "Environment (dev, staging, prod)"
  default     = "prod"
}

variable "vpc_network_name" {
  type        = string
  description = "VPC Network name"
}

variable "monitoring_subnet_name" {
  type        = string
  description = "Monitoring subnet name (where sensor runs)"
}

variable "production_subnet_name" {
  type        = string
  description = "Production subnet name (traffic source)"
}

variable "machine_type" {
  type        = string
  description = "GCE instance machine type"
  default     = "e2-medium"
}

variable "boot_disk_size" {
  type        = number
  description = "Boot disk size in GB"
  default     = 50
}

variable "image_family" {
  type        = string
  description = "GCE image family"
  default     = "ubuntu-os-cloud/ubuntu-2204-lts"
}

variable "api_url" {
  type        = string
  description = "BlackShield API URL"
  default     = "https://api.blackshield.chaplau.com"
}

variable "sensor_type" {
  type        = string
  description = "Sensor type: suricata, zeek, or ebpf"
  default     = "suricata"
}

variable "min_severity" {
  type        = string
  description = "Minimum alert severity: low, medium, high, or critical"
  default     = "high"
}

variable "api_key" {
  type        = string
  description = "BlackShield API Key (sp_...)"
  sensitive   = true
}
EOF

replace_literal "${INSTALL_PATH}/variables.tf" "https://api.blackshield.chaplau.com" "$BLACKSHIELD_API_URL"

# Write startup script template
cat > "${INSTALL_PATH}/startup.sh.tftpl" << 'EOF'
#!/usr/bin/env bash
set -euo pipefail

# GCP Network Sensor Startup Script

PROJECT_ID=$(curl -s "http://metadata.google.internal/computeMetadata/v1/project/project-id" -H "Metadata-Flavor: Google")
ACCESS_TOKEN=$(curl -s "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token" -H "Metadata-Flavor: Google" | jq -r '.access_token')
API_KEY=$(curl -s "https://secretmanager.googleapis.com/v1/projects/$${PROJECT_ID}/secrets/blackshield-network-sensor-key/versions/latest:access" -H "Authorization: Bearer $${ACCESS_TOKEN}" | jq -r '.payload.data' | base64 --decode)

# Update system
apt-get update
apt-get install -y docker.io jq
systemctl enable --now docker

# Start sensor container
docker pull public.ecr.aws/blackshield-security/network-sensor:latest
docker rm -f network-sensor || true
docker run -d \
  --name network-sensor \
  --network host \
  --cap-add NET_ADMIN \
  --cap-add NET_RAW \
  --restart unless-stopped \
  -e BLACKSHIELD_API_KEY="$${API_KEY}" \
  -e BLACKSHIELD_API_URL="${api_url}" \
  -e SENSOR_TYPE="${sensor_type}" \
  -e MIN_SEVERITY="${min_severity}" \
  --log-driver=gcplogs \
  public.ecr.aws/blackshield-security/network-sensor:latest
EOF

replace_literal \
  "${INSTALL_PATH}/startup.sh.tftpl" \
  "public.ecr.aws/blackshield-security/network-sensor:latest" \
  "$BLACKSHIELD_NETWORK_SENSOR_IMAGE"

chmod +x "${INSTALL_PATH}/startup.sh.tftpl"

# Write terraform.tfvars.example
cat > "${INSTALL_PATH}/terraform.tfvars.example" << 'EOF'
gcp_project_id         = "your-gcp-project-id"
gcp_region             = "us-central1"
gcp_zone               = "us-central1-a"
vpc_network_name       = "default"
monitoring_subnet_name = "default"
production_subnet_name = "default"
api_key                = "sp_your_ingestion_key"
EOF

# Write README.md
cat > "${INSTALL_PATH}/README.md" << 'EOF'
# GCP Network Sensor Terraform

This Terraform configuration deploys a network sensor to GCP that captures traffic via Packet Mirroring.

## Prerequisites

- GCP project with compute creation permissions
- `terraform` CLI installed (>= 1.0)
- `gcloud` CLI configured
- An ingestion API key from BlackShield platform

## Quick Start

1. Copy `terraform.tfvars.example` to `terraform.tfvars`:
   ```bash
   cp terraform.tfvars.example terraform.tfvars
   ```

2. Edit `terraform.tfvars` and set:
   - `gcp_project_id`
   - `vpc_network_name` and subnet names
   - `api_key` (your ingestion API key)
   - `api_url` only if you need to override the BlackShield API endpoint that was prefilled by this guide

3. Initialize and apply:
   ```bash
   terraform init
   terraform apply
   ```

4. Monitor deployment:
   ```bash
   gcloud compute instances describe network-sensor-prod
   ```

## Configuration

See `variables.tf` for all available options (machine type, region, severity level, etc.).

## Outputs

After `terraform apply`, you'll see:
- `sensor_instance_name` — The compute instance name
- `sensor_instance_ip` — Private IP address for SSH access

## Cleanup

```bash
terraform destroy
```
EOF

echo "✓ GCP Network Sensor Terraform project created at: ${INSTALL_PATH}"
echo "  Files written:"
echo "    - main.tf"
echo "    - variables.tf"
echo "    - startup.sh.tftpl"
echo "    - terraform.tfvars.example"
echo "    - README.md"
