From 653b3f6a23f90e55f823bab3b1e47d3aa0939954 Mon Sep 17 00:00:00 2001 From: Conan Scott Date: Wed, 1 Jul 2026 04:52:20 +0000 Subject: [PATCH] Add core Terraform: DynamoDB vault + customers, RAG Lambda, IAM, outputs --- terraform/main.tf | 116 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 terraform/main.tf diff --git a/terraform/main.tf b/terraform/main.tf new file mode 100644 index 0000000..92b7ff2 --- /dev/null +++ b/terraform/main.tf @@ -0,0 +1,116 @@ +terraform { + required_version = ">= 1.5" + required_providers { + aws = { source = "hashicorp/aws", version = "~> 5.0" } + archive = { source = "hashicorp/archive", version = "~> 2.0" } + } +} + +provider "aws" { + region = var.region +} + +locals { + name = var.project + # Logical trust zones are represented by tags for the demo (everything is one account). + onprem_tag = { Zone = "on-prem-VPC-A" } + cloud_tag = { Zone = "cloud-VPC-B" } +} + +######################################## +# Token vault + seeded customer data (both live in the "on-prem" zone) +######################################## +resource "aws_dynamodb_table" "vault" { + name = "${local.name}-vault" + billing_mode = "PAY_PER_REQUEST" + hash_key = "token" + attribute { + name = "token" + type = "S" + } + ttl { + attribute_name = "expires_at" + enabled = true + } + tags = local.onprem_tag +} + +resource "aws_dynamodb_table" "customers" { + name = "${local.name}-customers" + billing_mode = "PAY_PER_REQUEST" + hash_key = "customer_id" + attribute { + name = "customer_id" + type = "S" + } + tags = local.onprem_tag +} + +######################################## +# RAG tool Lambda (step 4-6): resolves the token, reads customer data, +# returns a de-identified evidence package. Never returns raw PII. +######################################## +data "archive_file" "rag" { + type = "zip" + source_dir = "${path.module}/../lambda_rag" + output_path = "${path.module}/rag_lambda.zip" +} + +resource "aws_iam_role" "rag" { + name = "${local.name}-rag-role" + assume_role_policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Effect = "Allow" + Principal = { Service = "lambda.amazonaws.com" } + Action = "sts:AssumeRole" + }] + }) +} + +resource "aws_iam_role_policy" "rag" { + name = "${local.name}-rag-policy" + role = aws_iam_role.rag.id + policy = jsonencode({ + Version = "2012-10-17" + Statement = [ + { + Effect = "Allow" + Action = ["dynamodb:GetItem", "dynamodb:Query"] + Resource = [aws_dynamodb_table.vault.arn, aws_dynamodb_table.customers.arn] + }, + { + Effect = "Allow" + Action = ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"] + Resource = "arn:aws:logs:*:*:*" + } + ] + }) +} + +resource "aws_lambda_function" "rag" { + function_name = "${local.name}-rag-tool" + role = aws_iam_role.rag.arn + runtime = "python3.12" + handler = "handler.lambda_handler" + filename = data.archive_file.rag.output_path + source_code_hash = data.archive_file.rag.output_base64sha256 + timeout = 15 + environment { + variables = { + VAULT_TABLE = aws_dynamodb_table.vault.name + CUSTOMERS_TABLE = aws_dynamodb_table.customers.name + } + } + tags = local.onprem_tag +} + +######################################## +# Outputs +######################################## +output "region" { value = var.region } +output "vault_table" { value = aws_dynamodb_table.vault.name } +output "customers_table" { value = aws_dynamodb_table.customers.name } +output "rag_lambda_name" { value = aws_lambda_function.rag.function_name } +output "rag_lambda_arn" { value = aws_lambda_function.rag.arn } +output "bedrock_model_id" { value = var.bedrock_model_id }