Build the AWS side of the HNCB demo end to end (region ap-southeast-1): - T1 /tokenize + T2 /restore: Lambdas behind a public API Gateway (shared-secret auth), Presidio detection, random per-request tokens, DynamoDB vault; overlap resolution so a ROC ID stays TW_ROC_ID. - T3: Presidio made private (SG-locked to the tokenize Lambda in-VPC; DynamoDB gateway endpoint); only /tokenize + /restore are public. - T4: RAG Lambda registered as an MCP tool on an AgentCore Gateway (AWS_IAM/SigV4); agentcore_setup.sh + a SigV4 MCP invoke test. - T5: Strands agent deployed to AgentCore Runtime; SigV4 gateway auth, apac inference profile, pinned deps. - T6: advisor UI on S3+CloudFront with a Fusion-less demo orchestrator (/demo) chaining tokenize -> runtime -> restore. - T7: README runbook + trace check; teardown deletes gateway/runtime/memory/ECR. Verified live: the cloud AgentCore/Bedrock trace shows only tokens, never the real name. Secrets stay in gitignored local.auto.tfvars. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
142 lines
4.6 KiB
HCL
142 lines
4.6 KiB
HCL
# ---------------------------------------------------------------------------
|
|
# 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
|
|
}
|