# --------------------------------------------------------------------------- # Hosting for the Presidio detector only. Fusion is a shared SaaS instance and is # NOT deployed here. The detector is PRIVATE (task T3): its port 5001 is reachable # only from the /tokenize Lambda's security group, not the internet. The only # public surface is the API Gateway (/tokenize + /restore). The task keeps a public # IP purely so Fargate can pull the image from ECR (there's no NAT); inbound is # still SG-locked, so nothing is reachable from outside the VPC. # # For a laptop-only rehearsal you can skip this file and run Presidio via docker. # --------------------------------------------------------------------------- data "aws_vpc" "default" { default = true } data "aws_subnets" "default" { filter { name = "vpc-id" values = [data.aws_vpc.default.id] } } # Route tables of the default VPC -- needed to attach the DynamoDB gateway endpoint # so the (now VPC-attached) tokenize Lambda can still reach the vault/customers tables. data "aws_route_tables" "default" { vpc_id = data.aws_vpc.default.id } resource "aws_ecs_cluster" "this" { name = "${local.name}-cluster" tags = local.onprem_tag } # SG the tokenize Lambda runs in. No ingress; egress open so it can reach Presidio # (5001) and the DynamoDB endpoint. Presidio trusts this SG (below). resource "aws_security_group" "tokenize_lambda" { name = "${local.name}-tokenize-lambda-sg" description = "tokenize Lambda ENIs" vpc_id = data.aws_vpc.default.id egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = local.onprem_tag } resource "aws_security_group" "svc" { name = "${local.name}-svc-sg" description = "Demo services SG" vpc_id = data.aws_vpc.default.id ingress { description = "Presidio analyzer -- only the tokenize Lambda may call it" from_port = 5001 to_port = 5001 protocol = "tcp" security_groups = [aws_security_group.tokenize_lambda.id] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = local.onprem_tag } # Gateway endpoint so VPC-attached Lambdas reach DynamoDB without a NAT / public route. resource "aws_vpc_endpoint" "dynamodb" { vpc_id = data.aws_vpc.default.id service_name = "com.amazonaws.${var.region}.dynamodb" vpc_endpoint_type = "Gateway" route_table_ids = data.aws_route_tables.default.ids tags = merge(local.onprem_tag, { Name = "${local.name}-dynamodb" }) } resource "aws_iam_role" "ecs_exec" { name = "${local.name}-ecs-exec" assume_role_policy = jsonencode({ Version = "2012-10-17" Statement = [{ Effect = "Allow" Principal = { Service = "ecs-tasks.amazonaws.com" } Action = "sts:AssumeRole" }] }) } resource "aws_iam_role_policy_attachment" "ecs_exec" { role = aws_iam_role.ecs_exec.name policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" } resource "aws_ecs_task_definition" "presidio" { family = "${local.name}-presidio" requires_compatibilities = ["FARGATE"] network_mode = "awsvpc" cpu = 512 # zh_core_web_lg (~600MB) plus presidio/spacy needs headroom; 1GB OOMs on load. memory = 2048 execution_role_arn = aws_iam_role.ecs_exec.arn # Built natively on Apple Silicon (podman) -> run on Fargate Graviton. runtime_platform { cpu_architecture = "ARM64" operating_system_family = "LINUX" } container_definitions = jsonencode([{ name = "presidio" image = var.presidio_image_uri essential = true portMappings = [{ containerPort = 5001 }] logConfiguration = { logDriver = "awslogs" options = { "awslogs-group" = aws_cloudwatch_log_group.presidio.name "awslogs-region" = var.region "awslogs-stream-prefix" = "presidio" } } }]) tags = local.onprem_tag } resource "aws_cloudwatch_log_group" "presidio" { name = "/ecs/${local.name}-presidio" retention_in_days = 7 tags = local.onprem_tag } resource "aws_ecs_service" "presidio" { name = "${local.name}-presidio" cluster = aws_ecs_cluster.this.id task_definition = aws_ecs_task_definition.presidio.arn desired_count = 1 launch_type = "FARGATE" network_configuration { subnets = data.aws_subnets.default.ids security_groups = [aws_security_group.svc.id] assign_public_ip = true } tags = local.onprem_tag }