Implement reversible PII de-identification round trip (T1–T7)
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>
This commit is contained in:
@@ -1,9 +1,10 @@
|
||||
# ---------------------------------------------------------------------------
|
||||
# Hosting for the Presidio detector only. Fusion is a shared SaaS instance and is
|
||||
# NOT deployed here. Because Fusion SaaS calls the detector over the internet, the
|
||||
# analyzer port is public in this demo (lock it down / add auth for anything real;
|
||||
# better: fold detection behind the /tokenize endpoint so only that is public --
|
||||
# see CLAUDE.md task T3).
|
||||
# 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.
|
||||
# ---------------------------------------------------------------------------
|
||||
@@ -17,21 +18,42 @@ data "aws_subnets" "default" {
|
||||
}
|
||||
}
|
||||
|
||||
# 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 (public for SaaS Fusion demo - restrict for real use)"
|
||||
from_port = 5001
|
||||
to_port = 5001
|
||||
protocol = "tcp"
|
||||
cidr_blocks = ["0.0.0.0/0"]
|
||||
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
|
||||
@@ -42,6 +64,15 @@ resource "aws_security_group" "svc" {
|
||||
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({
|
||||
@@ -64,17 +95,37 @@ resource "aws_ecs_task_definition" "presidio" {
|
||||
requires_compatibilities = ["FARGATE"]
|
||||
network_mode = "awsvpc"
|
||||
cpu = 512
|
||||
memory = 1024
|
||||
execution_role_arn = aws_iam_role.ecs_exec.arn
|
||||
# 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
|
||||
|
||||
Reference in New Issue
Block a user