feat(phase-2): workstream 8 — Multi-Region Terraform Deployment
AWS environment: - VPC (3-AZ, public + private subnets, NAT gateways, VPC endpoints for ECR/SM/CW) - ECS Fargate service (sentryagent/agentidp) — secrets from Secrets Manager - RDS PostgreSQL 14 (Multi-AZ, encrypted, VPC-internal, storage autoscaling) - ElastiCache Redis 7 (primary + replica, at-rest + in-transit encryption) - ALB with HTTPS/443, HTTP→HTTPS redirect, ACM certificate - Route 53 alias record GCP environment: - VPC + private services access + Serverless VPC connector - Cloud Run service — secrets from Secret Manager - Cloud SQL PostgreSQL 14 (private IP, no public endpoint) - Cloud Memorystore Redis 7 (VPC-internal, AUTH enabled) Shared: - 4 reusable modules: agentidp (dual AWS/GCP), rds, redis, lb - No hardcoded secrets; all sensitive vars marked sensitive=true - terraform.tfvars.example for both environments - docs/devops/deployment.md — AWS + GCP step-by-step walkthrough, rollback procedures Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
477
terraform/environments/gcp/main.tf
Normal file
477
terraform/environments/gcp/main.tf
Normal file
@@ -0,0 +1,477 @@
|
||||
################################################################################
|
||||
# Environment: gcp
|
||||
# Main — SentryAgent.ai AgentIdP on Google Cloud Platform
|
||||
#
|
||||
# Architecture:
|
||||
# Internet → Cloud Run (Google-managed TLS, auto-scaling) →
|
||||
# Cloud SQL PostgreSQL 14 (private IP, REGIONAL HA) +
|
||||
# Memorystore Redis 7 (STANDARD_HA, in-transit encryption)
|
||||
# via Serverless VPC Access connector
|
||||
#
|
||||
# All secrets stored in GCP Secret Manager — Cloud Run reads them at startup.
|
||||
# No sensitive values in state (except where Terraform internals require it).
|
||||
################################################################################
|
||||
|
||||
terraform {
|
||||
required_version = ">= 1.6.0"
|
||||
|
||||
required_providers {
|
||||
google = {
|
||||
source = "hashicorp/google"
|
||||
version = ">= 5.20.0"
|
||||
}
|
||||
google-beta = {
|
||||
source = "hashicorp/google-beta"
|
||||
version = ">= 5.20.0"
|
||||
}
|
||||
random = {
|
||||
source = "hashicorp/random"
|
||||
version = ">= 3.6.0"
|
||||
}
|
||||
}
|
||||
|
||||
# Remote state — configure your backend here.
|
||||
# Example using GCS:
|
||||
#
|
||||
# backend "gcs" {
|
||||
# bucket = "sentryagent-terraform-state"
|
||||
# prefix = "agentidp/gcp/production"
|
||||
# }
|
||||
}
|
||||
|
||||
provider "google" {
|
||||
project = var.project_id
|
||||
region = var.region
|
||||
}
|
||||
|
||||
provider "google-beta" {
|
||||
project = var.project_id
|
||||
region = var.region
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Enable required GCP APIs
|
||||
################################################################################
|
||||
|
||||
resource "google_project_service" "apis" {
|
||||
for_each = toset([
|
||||
"run.googleapis.com",
|
||||
"sqladmin.googleapis.com",
|
||||
"redis.googleapis.com",
|
||||
"vpcaccess.googleapis.com",
|
||||
"secretmanager.googleapis.com",
|
||||
"servicenetworking.googleapis.com",
|
||||
"cloudresourcemanager.googleapis.com",
|
||||
"iam.googleapis.com",
|
||||
])
|
||||
|
||||
project = var.project_id
|
||||
service = each.value
|
||||
disable_on_destroy = false
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Locals
|
||||
################################################################################
|
||||
|
||||
locals {
|
||||
name_prefix = "${var.project}-${var.environment}"
|
||||
|
||||
common_labels = {
|
||||
environment = var.environment
|
||||
project = replace(var.project, "-", "_")
|
||||
managed_by = "terraform"
|
||||
}
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# VPC Network
|
||||
################################################################################
|
||||
|
||||
resource "google_compute_network" "main" {
|
||||
name = "${local.name_prefix}-vpc"
|
||||
auto_create_subnetworks = false
|
||||
project = var.project_id
|
||||
|
||||
depends_on = [google_project_service.apis]
|
||||
}
|
||||
|
||||
resource "google_compute_subnetwork" "private" {
|
||||
name = "${local.name_prefix}-private-subnet"
|
||||
ip_cidr_range = var.vpc_cidr
|
||||
region = var.region
|
||||
network = google_compute_network.main.id
|
||||
project = var.project_id
|
||||
|
||||
private_ip_google_access = true
|
||||
|
||||
log_config {
|
||||
aggregation_interval = "INTERVAL_10_MIN"
|
||||
flow_sampling = 0.5
|
||||
metadata = "INCLUDE_ALL_METADATA"
|
||||
}
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Private Services Access — required for Cloud SQL private IP
|
||||
################################################################################
|
||||
|
||||
resource "google_compute_global_address" "private_services" {
|
||||
name = "${local.name_prefix}-private-services-range"
|
||||
purpose = "VPC_PEERING"
|
||||
address_type = "INTERNAL"
|
||||
prefix_length = 20
|
||||
network = google_compute_network.main.id
|
||||
project = var.project_id
|
||||
}
|
||||
|
||||
resource "google_service_networking_connection" "private_services" {
|
||||
network = google_compute_network.main.id
|
||||
service = "servicenetworking.googleapis.com"
|
||||
reserved_peering_ranges = [google_compute_global_address.private_services.name]
|
||||
|
||||
depends_on = [google_project_service.apis]
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Serverless VPC Access Connector
|
||||
# Cloud Run uses this to reach Cloud SQL (private IP) and Memorystore.
|
||||
################################################################################
|
||||
|
||||
resource "google_vpc_access_connector" "main" {
|
||||
name = "${local.name_prefix}-connector"
|
||||
region = var.region
|
||||
project = var.project_id
|
||||
ip_cidr_range = var.vpc_connector_cidr
|
||||
network = google_compute_network.main.name
|
||||
min_instances = 2
|
||||
max_instances = 10
|
||||
machine_type = "e2-micro"
|
||||
|
||||
depends_on = [google_project_service.apis]
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Service Account for Cloud Run
|
||||
################################################################################
|
||||
|
||||
resource "google_service_account" "cloud_run" {
|
||||
account_id = "${var.project}-${var.environment}-run-sa"
|
||||
display_name = "AgentIdP Cloud Run Service Account (${var.environment})"
|
||||
project = var.project_id
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Secret Manager — create secrets and grant the SA access
|
||||
################################################################################
|
||||
|
||||
resource "google_secret_manager_secret" "database_url" {
|
||||
secret_id = "${local.name_prefix}-database-url"
|
||||
project = var.project_id
|
||||
|
||||
replication {
|
||||
auto {}
|
||||
}
|
||||
|
||||
labels = local.common_labels
|
||||
|
||||
depends_on = [google_project_service.apis]
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret_version" "database_url" {
|
||||
secret = google_secret_manager_secret.database_url.id
|
||||
# Build the DATABASE_URL from Cloud SQL private IP output.
|
||||
secret_data = "postgresql://${var.db_username}:${var.db_password}@${google_sql_database_instance.main.private_ip_address}:5432/${var.db_name}?sslmode=require"
|
||||
|
||||
depends_on = [google_sql_database_instance.main]
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret" "redis_url" {
|
||||
secret_id = "${local.name_prefix}-redis-url"
|
||||
project = var.project_id
|
||||
|
||||
replication {
|
||||
auto {}
|
||||
}
|
||||
|
||||
labels = local.common_labels
|
||||
|
||||
depends_on = [google_project_service.apis]
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret_version" "redis_url" {
|
||||
secret = google_secret_manager_secret.redis_url.id
|
||||
# Memorystore Redis with in-transit encryption uses the rediss:// scheme.
|
||||
secret_data = "rediss://${google_redis_instance.main.host}:${google_redis_instance.main.port}"
|
||||
|
||||
depends_on = [google_redis_instance.main]
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret" "jwt_private_key" {
|
||||
secret_id = "${local.name_prefix}-jwt-private-key"
|
||||
project = var.project_id
|
||||
|
||||
replication {
|
||||
auto {}
|
||||
}
|
||||
|
||||
labels = local.common_labels
|
||||
|
||||
depends_on = [google_project_service.apis]
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret_version" "jwt_private_key" {
|
||||
secret = google_secret_manager_secret.jwt_private_key.id
|
||||
secret_data = var.jwt_private_key
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret" "jwt_public_key" {
|
||||
secret_id = "${local.name_prefix}-jwt-public-key"
|
||||
project = var.project_id
|
||||
|
||||
replication {
|
||||
auto {}
|
||||
}
|
||||
|
||||
labels = local.common_labels
|
||||
|
||||
depends_on = [google_project_service.apis]
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret_version" "jwt_public_key" {
|
||||
secret = google_secret_manager_secret.jwt_public_key.id
|
||||
secret_data = var.jwt_public_key
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret" "vault_token" {
|
||||
count = var.vault_token != "" ? 1 : 0
|
||||
|
||||
secret_id = "${local.name_prefix}-vault-token"
|
||||
project = var.project_id
|
||||
|
||||
replication {
|
||||
auto {}
|
||||
}
|
||||
|
||||
labels = local.common_labels
|
||||
|
||||
depends_on = [google_project_service.apis]
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret_version" "vault_token" {
|
||||
count = var.vault_token != "" ? 1 : 0
|
||||
|
||||
secret = google_secret_manager_secret.vault_token[0].id
|
||||
secret_data = var.vault_token
|
||||
}
|
||||
|
||||
# Grant the Cloud Run SA access to each secret
|
||||
resource "google_secret_manager_secret_iam_member" "run_database_url" {
|
||||
project = var.project_id
|
||||
secret_id = google_secret_manager_secret.database_url.secret_id
|
||||
role = "roles/secretmanager.secretAccessor"
|
||||
member = "serviceAccount:${google_service_account.cloud_run.email}"
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret_iam_member" "run_redis_url" {
|
||||
project = var.project_id
|
||||
secret_id = google_secret_manager_secret.redis_url.secret_id
|
||||
role = "roles/secretmanager.secretAccessor"
|
||||
member = "serviceAccount:${google_service_account.cloud_run.email}"
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret_iam_member" "run_jwt_private_key" {
|
||||
project = var.project_id
|
||||
secret_id = google_secret_manager_secret.jwt_private_key.secret_id
|
||||
role = "roles/secretmanager.secretAccessor"
|
||||
member = "serviceAccount:${google_service_account.cloud_run.email}"
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret_iam_member" "run_jwt_public_key" {
|
||||
project = var.project_id
|
||||
secret_id = google_secret_manager_secret.jwt_public_key.secret_id
|
||||
role = "roles/secretmanager.secretAccessor"
|
||||
member = "serviceAccount:${google_service_account.cloud_run.email}"
|
||||
}
|
||||
|
||||
resource "google_secret_manager_secret_iam_member" "run_vault_token" {
|
||||
count = var.vault_token != "" ? 1 : 0
|
||||
|
||||
project = var.project_id
|
||||
secret_id = google_secret_manager_secret.vault_token[0].secret_id
|
||||
role = "roles/secretmanager.secretAccessor"
|
||||
member = "serviceAccount:${google_service_account.cloud_run.email}"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Cloud SQL — PostgreSQL 14, private IP, REGIONAL HA
|
||||
################################################################################
|
||||
|
||||
resource "google_sql_database_instance" "main" {
|
||||
name = "${local.name_prefix}-pg14"
|
||||
database_version = "POSTGRES_14"
|
||||
region = var.region
|
||||
project = var.project_id
|
||||
|
||||
deletion_protection = var.deletion_protection
|
||||
|
||||
settings {
|
||||
tier = var.db_tier
|
||||
availability_type = var.db_availability_type
|
||||
disk_type = "PD_SSD"
|
||||
disk_size = 50
|
||||
disk_autoresize = true
|
||||
|
||||
ip_configuration {
|
||||
ipv4_enabled = false # No public IP
|
||||
private_network = google_compute_network.main.id
|
||||
require_ssl = true
|
||||
}
|
||||
|
||||
backup_configuration {
|
||||
enabled = true
|
||||
start_time = "03:00"
|
||||
point_in_time_recovery_enabled = true
|
||||
transaction_log_retention_days = 7
|
||||
backup_retention_settings {
|
||||
retained_backups = 7
|
||||
retention_unit = "COUNT"
|
||||
}
|
||||
}
|
||||
|
||||
maintenance_window {
|
||||
day = 7 # Sunday
|
||||
hour = 5
|
||||
update_track = "stable"
|
||||
}
|
||||
|
||||
insights_config {
|
||||
query_insights_enabled = true
|
||||
query_string_length = 1024
|
||||
record_application_tags = true
|
||||
record_client_address = false
|
||||
}
|
||||
|
||||
database_flags {
|
||||
name = "log_connections"
|
||||
value = "on"
|
||||
}
|
||||
|
||||
database_flags {
|
||||
name = "log_disconnections"
|
||||
value = "on"
|
||||
}
|
||||
|
||||
database_flags {
|
||||
name = "log_min_duration_statement"
|
||||
value = "1000"
|
||||
}
|
||||
|
||||
user_labels = local.common_labels
|
||||
}
|
||||
|
||||
depends_on = [google_service_networking_connection.private_services]
|
||||
}
|
||||
|
||||
resource "google_sql_database" "main" {
|
||||
name = var.db_name
|
||||
instance = google_sql_database_instance.main.name
|
||||
project = var.project_id
|
||||
}
|
||||
|
||||
resource "google_sql_user" "app" {
|
||||
name = var.db_username
|
||||
instance = google_sql_database_instance.main.name
|
||||
password = var.db_password
|
||||
project = var.project_id
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Memorystore Redis 7 — STANDARD_HA (primary + replica), TLS enabled
|
||||
################################################################################
|
||||
|
||||
resource "google_redis_instance" "main" {
|
||||
name = "${local.name_prefix}-redis"
|
||||
tier = var.memorystore_tier
|
||||
memory_size_gb = var.memorystore_memory_size_gb
|
||||
region = var.region
|
||||
project = var.project_id
|
||||
|
||||
redis_version = var.memorystore_redis_version
|
||||
|
||||
# Private connectivity via the VPC
|
||||
authorized_network = google_compute_network.main.id
|
||||
connect_mode = "PRIVATE_SERVICE_ACCESS"
|
||||
|
||||
# TLS in transit
|
||||
transit_encryption_mode = "SERVER_AUTHENTICATION"
|
||||
|
||||
# No AUTH token for Memorystore — access is controlled by VPC network policy.
|
||||
# If AUTH is required, set auth_enabled = true and read the generated auth_string output.
|
||||
auth_enabled = true
|
||||
|
||||
redis_configs = {
|
||||
lazyfree-lazy-eviction = "yes"
|
||||
lazyfree-lazy-expire = "yes"
|
||||
}
|
||||
|
||||
maintenance_policy {
|
||||
weekly_maintenance_window {
|
||||
day = "SUNDAY"
|
||||
start_time {
|
||||
hours = 6
|
||||
minutes = 0
|
||||
seconds = 0
|
||||
nanos = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
labels = local.common_labels
|
||||
|
||||
depends_on = [google_service_networking_connection.private_services]
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Module: AgentIdP (Cloud Run)
|
||||
################################################################################
|
||||
|
||||
module "agentidp" {
|
||||
source = "../../modules/agentidp"
|
||||
|
||||
provider_type = "gcp"
|
||||
environment = var.environment
|
||||
project = var.project
|
||||
app_image = "sentryagent/agentidp:${var.app_image_tag}"
|
||||
app_port = 3000
|
||||
|
||||
gcp_project_id = var.project_id
|
||||
gcp_region = var.region
|
||||
gcp_service_account_email = google_service_account.cloud_run.email
|
||||
gcp_vpc_connector_name = google_vpc_access_connector.main.id
|
||||
gcp_min_instances = var.cloud_run_min_instances
|
||||
gcp_max_instances = var.cloud_run_max_instances
|
||||
gcp_cpu = var.cloud_run_cpu
|
||||
gcp_memory = var.cloud_run_memory
|
||||
gcp_cors_origin = var.cors_origin
|
||||
gcp_policy_dir = "/app/policies"
|
||||
gcp_vault_addr = var.vault_addr
|
||||
gcp_vault_mount = var.vault_mount
|
||||
|
||||
gcp_secret_database_url_id = google_secret_manager_secret.database_url.secret_id
|
||||
gcp_secret_redis_url_id = google_secret_manager_secret.redis_url.secret_id
|
||||
gcp_secret_jwt_private_key_id = google_secret_manager_secret.jwt_private_key.secret_id
|
||||
gcp_secret_jwt_public_key_id = google_secret_manager_secret.jwt_public_key.secret_id
|
||||
gcp_secret_vault_token_id = var.vault_token != "" ? google_secret_manager_secret.vault_token[0].secret_id : ""
|
||||
|
||||
depends_on = [
|
||||
google_secret_manager_secret_version.database_url,
|
||||
google_secret_manager_secret_version.redis_url,
|
||||
google_secret_manager_secret_version.jwt_private_key,
|
||||
google_secret_manager_secret_version.jwt_public_key,
|
||||
google_secret_manager_secret_iam_member.run_database_url,
|
||||
google_secret_manager_secret_iam_member.run_redis_url,
|
||||
google_secret_manager_secret_iam_member.run_jwt_private_key,
|
||||
google_secret_manager_secret_iam_member.run_jwt_public_key,
|
||||
]
|
||||
}
|
||||
64
terraform/environments/gcp/outputs.tf
Normal file
64
terraform/environments/gcp/outputs.tf
Normal file
@@ -0,0 +1,64 @@
|
||||
################################################################################
|
||||
# Environment: gcp
|
||||
# Outputs
|
||||
################################################################################
|
||||
|
||||
output "service_url" {
|
||||
description = "Public HTTPS URL of the AgentIdP Cloud Run service (Google-managed TLS)."
|
||||
value = module.agentidp.gcp_cloud_run_service_url
|
||||
}
|
||||
|
||||
output "cloud_run_service_name" {
|
||||
description = "Name of the Cloud Run service."
|
||||
value = module.agentidp.gcp_cloud_run_service_name
|
||||
}
|
||||
|
||||
output "cloud_run_service_id" {
|
||||
description = "Full resource ID of the Cloud Run service."
|
||||
value = module.agentidp.gcp_cloud_run_service_id
|
||||
}
|
||||
|
||||
output "cloud_sql_instance_name" {
|
||||
description = "Cloud SQL instance name."
|
||||
value = google_sql_database_instance.main.name
|
||||
}
|
||||
|
||||
output "cloud_sql_private_ip" {
|
||||
description = "Private IP address of the Cloud SQL instance."
|
||||
value = google_sql_database_instance.main.private_ip_address
|
||||
}
|
||||
|
||||
output "cloud_sql_connection_name" {
|
||||
description = "Cloud SQL instance connection name (project:region:name) for Cloud SQL Proxy."
|
||||
value = google_sql_database_instance.main.connection_name
|
||||
}
|
||||
|
||||
output "memorystore_host" {
|
||||
description = "IP address of the Memorystore Redis primary endpoint."
|
||||
value = google_redis_instance.main.host
|
||||
}
|
||||
|
||||
output "memorystore_port" {
|
||||
description = "Port of the Memorystore Redis instance."
|
||||
value = google_redis_instance.main.port
|
||||
}
|
||||
|
||||
output "memorystore_id" {
|
||||
description = "Fully-qualified resource ID of the Memorystore Redis instance."
|
||||
value = google_redis_instance.main.id
|
||||
}
|
||||
|
||||
output "vpc_network_name" {
|
||||
description = "Name of the VPC network created for this deployment."
|
||||
value = google_compute_network.main.name
|
||||
}
|
||||
|
||||
output "vpc_connector_name" {
|
||||
description = "Serverless VPC Access connector name used by Cloud Run."
|
||||
value = google_vpc_access_connector.main.name
|
||||
}
|
||||
|
||||
output "cloud_run_service_account_email" {
|
||||
description = "Email of the service account attached to the Cloud Run service."
|
||||
value = google_service_account.cloud_run.email
|
||||
}
|
||||
70
terraform/environments/gcp/terraform.tfvars.example
Normal file
70
terraform/environments/gcp/terraform.tfvars.example
Normal file
@@ -0,0 +1,70 @@
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
# terraform/environments/gcp/terraform.tfvars.example
|
||||
#
|
||||
# Copy this file to terraform.tfvars and fill in real values.
|
||||
# NEVER commit terraform.tfvars to version control — it contains secrets.
|
||||
#
|
||||
# All sensitive variables (db_password, jwt_*, vault_token) must be provided
|
||||
# via this file or as TF_VAR_* environment variables in your CI/CD pipeline.
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
# ── GCP project & region ──────────────────────────────────────────────────────
|
||||
|
||||
project_id = "your-gcp-project-id"
|
||||
region = "us-central1"
|
||||
environment = "production"
|
||||
project = "sentryagent-agentidp"
|
||||
|
||||
# ── Application image ─────────────────────────────────────────────────────────
|
||||
|
||||
app_image_tag = "1.0.0"
|
||||
|
||||
# ── Networking ────────────────────────────────────────────────────────────────
|
||||
|
||||
vpc_cidr = "10.1.0.0/24"
|
||||
vpc_connector_cidr = "10.8.0.0/28"
|
||||
|
||||
# ── Database ──────────────────────────────────────────────────────────────────
|
||||
|
||||
db_tier = "db-g1-small"
|
||||
db_name = "sentryagent_idp"
|
||||
db_username = "sentryagent"
|
||||
db_availability_type = "REGIONAL"
|
||||
|
||||
# ── Secrets — REPLACE ALL VALUES BELOW ───────────────────────────────────────
|
||||
|
||||
# Password for Cloud SQL PostgreSQL user
|
||||
db_password = "REPLACE_WITH_STRONG_RANDOM_PASSWORD"
|
||||
|
||||
# RSA-2048 key pair for JWT signing/verification.
|
||||
# Generate with:
|
||||
# openssl genrsa -out private.pem 2048
|
||||
# openssl rsa -in private.pem -pubout -out public.pem
|
||||
jwt_private_key = "-----BEGIN RSA PRIVATE KEY-----\nREPLACE_WITH_ACTUAL_PRIVATE_KEY_CONTENTS\n-----END RSA PRIVATE KEY-----"
|
||||
jwt_public_key = "-----BEGIN PUBLIC KEY-----\nREPLACE_WITH_ACTUAL_PUBLIC_KEY_CONTENTS\n-----END PUBLIC KEY-----"
|
||||
|
||||
# HashiCorp Vault (optional — leave empty strings to disable Vault integration)
|
||||
vault_addr = ""
|
||||
vault_token = ""
|
||||
vault_mount = "secret"
|
||||
|
||||
# ── Application configuration ─────────────────────────────────────────────────
|
||||
|
||||
cors_origin = "*"
|
||||
|
||||
# ── Cloud Run scaling ─────────────────────────────────────────────────────────
|
||||
|
||||
cloud_run_min_instances = 1
|
||||
cloud_run_max_instances = 10
|
||||
cloud_run_cpu = "1"
|
||||
cloud_run_memory = "512Mi"
|
||||
|
||||
# ── Memorystore Redis ─────────────────────────────────────────────────────────
|
||||
|
||||
memorystore_memory_size_gb = 1
|
||||
memorystore_redis_version = "REDIS_7_0"
|
||||
memorystore_tier = "STANDARD_HA"
|
||||
|
||||
# ── Protection ────────────────────────────────────────────────────────────────
|
||||
|
||||
deletion_protection = true
|
||||
175
terraform/environments/gcp/variables.tf
Normal file
175
terraform/environments/gcp/variables.tf
Normal file
@@ -0,0 +1,175 @@
|
||||
################################################################################
|
||||
# Environment: gcp
|
||||
# Variables
|
||||
################################################################################
|
||||
|
||||
variable "project_id" {
|
||||
description = "GCP project ID where all resources will be created."
|
||||
type = string
|
||||
}
|
||||
|
||||
variable "region" {
|
||||
description = "GCP region for all resources."
|
||||
type = string
|
||||
default = "us-central1"
|
||||
}
|
||||
|
||||
variable "environment" {
|
||||
description = "Deployment environment (e.g. production, staging)."
|
||||
type = string
|
||||
default = "production"
|
||||
}
|
||||
|
||||
variable "project" {
|
||||
description = "Project identifier — used in resource names and labels."
|
||||
type = string
|
||||
default = "sentryagent-agentidp"
|
||||
}
|
||||
|
||||
variable "app_image_tag" {
|
||||
description = "Docker image tag to deploy (e.g. '1.2.3')."
|
||||
type = string
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Networking
|
||||
################################################################################
|
||||
|
||||
variable "vpc_cidr" {
|
||||
description = "CIDR range for the VPC subnet used by Cloud Run and Cloud SQL."
|
||||
type = string
|
||||
default = "10.1.0.0/24"
|
||||
}
|
||||
|
||||
variable "vpc_connector_cidr" {
|
||||
description = "CIDR range for the Serverless VPC Access connector (/28 required)."
|
||||
type = string
|
||||
default = "10.8.0.0/28"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Database
|
||||
################################################################################
|
||||
|
||||
variable "db_tier" {
|
||||
description = "Cloud SQL instance tier (machine type)."
|
||||
type = string
|
||||
default = "db-g1-small"
|
||||
}
|
||||
|
||||
variable "db_name" {
|
||||
description = "Name of the PostgreSQL database to create."
|
||||
type = string
|
||||
default = "sentryagent_idp"
|
||||
}
|
||||
|
||||
variable "db_username" {
|
||||
description = "PostgreSQL user for the application."
|
||||
type = string
|
||||
default = "sentryagent"
|
||||
}
|
||||
|
||||
variable "db_availability_type" {
|
||||
description = "Cloud SQL availability type: REGIONAL (HA) or ZONAL."
|
||||
type = string
|
||||
default = "REGIONAL"
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Secrets — all marked sensitive; provide via tfvars or environment variables
|
||||
################################################################################
|
||||
|
||||
variable "db_password" {
|
||||
description = "Password for the Cloud SQL PostgreSQL user. Stored in Secret Manager."
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "jwt_private_key" {
|
||||
description = "PEM-encoded RSA-2048 private key for signing JWTs. Stored in Secret Manager."
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "jwt_public_key" {
|
||||
description = "PEM-encoded RSA-2048 public key for verifying JWTs. Stored in Secret Manager."
|
||||
type = string
|
||||
sensitive = true
|
||||
}
|
||||
|
||||
variable "vault_token" {
|
||||
description = "HashiCorp Vault token. Leave empty to disable Vault integration."
|
||||
type = string
|
||||
sensitive = true
|
||||
default = ""
|
||||
}
|
||||
|
||||
################################################################################
|
||||
# Optional configuration
|
||||
################################################################################
|
||||
|
||||
variable "vault_addr" {
|
||||
description = "HashiCorp Vault server address. Leave empty to disable Vault integration."
|
||||
type = string
|
||||
default = ""
|
||||
}
|
||||
|
||||
variable "vault_mount" {
|
||||
description = "HashiCorp Vault KV v2 mount path."
|
||||
type = string
|
||||
default = "secret"
|
||||
}
|
||||
|
||||
variable "cors_origin" {
|
||||
description = "CORS_ORIGIN value for the app."
|
||||
type = string
|
||||
default = "*"
|
||||
}
|
||||
|
||||
variable "cloud_run_min_instances" {
|
||||
description = "Minimum Cloud Run instances (set > 0 to prevent cold starts)."
|
||||
type = number
|
||||
default = 1
|
||||
}
|
||||
|
||||
variable "cloud_run_max_instances" {
|
||||
description = "Maximum Cloud Run instances."
|
||||
type = number
|
||||
default = 10
|
||||
}
|
||||
|
||||
variable "cloud_run_cpu" {
|
||||
description = "CPU limit per Cloud Run instance."
|
||||
type = string
|
||||
default = "1"
|
||||
}
|
||||
|
||||
variable "cloud_run_memory" {
|
||||
description = "Memory limit per Cloud Run instance."
|
||||
type = string
|
||||
default = "512Mi"
|
||||
}
|
||||
|
||||
variable "memorystore_memory_size_gb" {
|
||||
description = "Memory size in GiB for the Memorystore Redis instance."
|
||||
type = number
|
||||
default = 1
|
||||
}
|
||||
|
||||
variable "memorystore_redis_version" {
|
||||
description = "Redis version for Memorystore."
|
||||
type = string
|
||||
default = "REDIS_7_0"
|
||||
}
|
||||
|
||||
variable "memorystore_tier" {
|
||||
description = "Memorystore service tier: BASIC (single node) or STANDARD_HA (primary + replica)."
|
||||
type = string
|
||||
default = "STANDARD_HA"
|
||||
}
|
||||
|
||||
variable "deletion_protection" {
|
||||
description = "Enable deletion protection on Cloud SQL and Memorystore resources."
|
||||
type = bool
|
||||
default = true
|
||||
}
|
||||
Reference in New Issue
Block a user