terraform { required_version = ">= 1.5" required_providers { aws = { source = "hashicorp/aws" version = "~> 5.0" } } backend "s3" { bucket = "metaflow-access-core-terraform-state" key = "dev/terraform.tfstate" region = "us-east-1" dynamodb_table = "metaflow-access-core-terraform-locks" encrypt = true } } provider "aws" { region = var.region default_tags { tags = local.tags } } locals { name = "access-core-dev" project = "metaflow-access-core" tags = { Project = local.project Environment = "dev" ManagedBy = "terraform" } } # ------------------------------------------------------------------- secrets resource "random_password" "db" { length = 32 special = false } resource "aws_secretsmanager_secret" "db" { name = "${local.name}-rds-password" description = "RDS password for access-core-dev (synthetic data only)" } resource "aws_secretsmanager_secret_version" "db" { secret_id = aws_secretsmanager_secret.db.id secret_string = jsonencode({ password = random_password.db.result }) } resource "random_string" "django_secret_key" { length = 50 special = false } resource "aws_secretsmanager_secret" "app" { name = "${local.name}-app-secrets" description = "Application secrets for access-core-dev" } resource "aws_secretsmanager_secret_version" "app" { secret_id = aws_secretsmanager_secret.app.id secret_string = jsonencode({ django-secret-key = random_string.django_secret_key.result }) } # ---------------------------------------------------------------- vpc + net module "vpc" { source = "../../modules/vpc" name = local.name cidr_block = var.vpc_cidr az_count = 1 tags = local.tags } module "endpoints" { source = "../../modules/endpoints" name = local.name region = var.region vpc_id = module.vpc.vpc_id vpc_cidr = module.vpc.vpc_cidr private_subnet_ids = module.vpc.private_subnet_ids private_route_table_id = module.vpc.private_route_table_id services = ["s3", "secretsmanager"] # dev: no KMS/SQS traffic yet tags = local.tags } # ------------------------------------------------------------------- storage module "storage" { source = "../../modules/storage" bucket_name = "${local.project}-dev-artifacts" sse_kms = false # dev: SSE-S3 to keep costs minimal (AWS_Cost_Estimate.md) versioned = false force_destroy = true tags = local.tags } # ---------------------------------------------------------------------- queue # Note: dev private subnets have no SQS route (no sqs interface endpoint and no # NAT, by design). The task role still receives SQS IAM grants for when the # webhook consumer lands; until then those grants are inert. Add "sqs" to the # endpoints services list above before any dev task can reach the queue API. module "queue" { source = "../../modules/queue" name = local.name tags = local.tags } # --------------------------------------------------------------------- database module "database" { source = "../../modules/database" name = local.name vpc_id = module.vpc.vpc_id private_subnet_ids = module.vpc.private_subnet_ids vpc_cidr = module.vpc.vpc_cidr password = random_password.db.result instance_class = "db.t3.micro" storage_encrypted = false # dev: synthetic data only (AWS_Cost_Estimate.md) kms_key_id = "" backup_retention_days = 1 tags = local.tags } # ------------------------------------------------------------------------ ecs module "ecs" { source = "../../modules/ecs" name = local.name environment = "dev" region = var.region cluster_name = local.name vpc_id = module.vpc.vpc_id public_subnet_ids = module.vpc.public_subnet_ids private_subnet_ids = module.vpc.private_subnet_ids image_tag = var.image_tag # No NAT egress in dev (the compose cms-worker service + local mock cover CMS polling). enable_worker = false django_settings_module = "access_core.settings.dev" postgres_host = module.database.address db_secret_arn = aws_secretsmanager_secret.db.arn app_secrets_arn = aws_secretsmanager_secret.app.arn s3_bucket_arn = module.storage.bucket_arn queue_arn = module.queue.webhook_queue_arn extra_environment = { PHI_LOCAL_ENCRYPTION_KEY = var.phi_local_key AWS_S3_BUCKET = module.storage.bucket_name } tags = local.tags }