Files
hncb-fusion-deid-demo/terraform/ui.tf
Conan Scott 78d67a2469 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>
2026-07-01 17:10:58 +10:00

86 lines
2.7 KiB
HCL

# ---------------------------------------------------------------------------
# T6: host the advisor UI on S3 + CloudFront. The bucket is private; CloudFront
# reaches it via Origin Access Control. index.html is static and committed; the
# live endpoint is injected via a generated config.js so we never bake an
# ephemeral URL into the repo.
# ---------------------------------------------------------------------------
resource "aws_s3_bucket" "ui" {
bucket_prefix = "${local.name}-ui-"
force_destroy = true
tags = local.onprem_tag
}
resource "aws_cloudfront_origin_access_control" "ui" {
name = "${local.name}-ui-oac"
origin_access_control_origin_type = "s3"
signing_behavior = "always"
signing_protocol = "sigv4"
}
resource "aws_cloudfront_distribution" "ui" {
enabled = true
default_root_object = "index.html"
comment = "${local.name} advisor UI"
origin {
domain_name = aws_s3_bucket.ui.bucket_regional_domain_name
origin_id = "ui-s3"
origin_access_control_id = aws_cloudfront_origin_access_control.ui.id
}
default_cache_behavior {
allowed_methods = ["GET", "HEAD"]
cached_methods = ["GET", "HEAD"]
target_origin_id = "ui-s3"
viewer_protocol_policy = "redirect-to-https"
forwarded_values {
query_string = false
cookies { forward = "none" }
}
}
restrictions {
geo_restriction { restriction_type = "none" }
}
viewer_certificate {
cloudfront_default_certificate = true
}
tags = local.cloud_tag
}
resource "aws_s3_bucket_policy" "ui" {
bucket = aws_s3_bucket.ui.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Effect = "Allow"
Principal = { Service = "cloudfront.amazonaws.com" }
Action = "s3:GetObject"
Resource = "${aws_s3_bucket.ui.arn}/*"
Condition = { StringEquals = { "AWS:SourceArn" = aws_cloudfront_distribution.ui.arn } }
}]
})
}
resource "aws_s3_object" "index" {
bucket = aws_s3_bucket.ui.id
key = "index.html"
source = "${path.module}/../ui/index.html"
etag = filemd5("${path.module}/../ui/index.html")
content_type = "text/html"
}
# Injected config: the demo orchestrator endpoint the UI calls.
resource "aws_s3_object" "config" {
bucket = aws_s3_bucket.ui.id
key = "config.js"
content = "window.DEMO_ENDPOINT = \"${trimsuffix(aws_apigatewayv2_stage.default.invoke_url, "/")}/demo\";\n"
content_type = "application/javascript"
etag = md5("${trimsuffix(aws_apigatewayv2_stage.default.invoke_url, "/")}/demo")
}
output "ui_url" { value = "https://${aws_cloudfront_distribution.ui.domain_name}" }