Add AWS infrastructure as code for PPAL Discord Bot: - API Gateway (HTTP API) for Discord Interactions endpoint - Lambda function (Node.js 20.x container image) - DynamoDB tables (users, conversations) with PAY_PER_REQUEST - Secrets Manager for tokens (Discord, GitHub, OpenAI) - IAM role with inline policies for Lambda execution Files: - versions.tf: Terraform 1.0+ with AWS provider 5.x - variables.tf: environment, project_name, lambda config - api_gateway.tf: HTTP API with CloudWatch logging - lambda.tf: ECR-based Lambda with function URL - dynamodb.tf: GSI-enabled tables with PITR & encryption - secrets.tf: 4 secrets with placeholder values - iam.tf: Inline policies for DynamoDB, Secrets, Logs, ECR - outputs.tf: Endpoint URLs, ARNs (sensitive) Co-Authored-By: Claude <noreply@anthropic.com>
132 lines
3.1 KiB
HCL
132 lines
3.1 KiB
HCL
resource "aws_iam_role" "lambda_role" {
|
|
name = "${var.project_name}-lambda-role"
|
|
|
|
assume_role_policy = jsonencode({
|
|
Version = "2012-10-17"
|
|
Statement = [
|
|
{
|
|
Action = "sts:AssumeRole"
|
|
Effect = "Allow"
|
|
Principal = {
|
|
Service = "lambda.amazonaws.com"
|
|
}
|
|
}
|
|
]
|
|
})
|
|
|
|
tags = {
|
|
Name = "${var.project_name}-lambda-role"
|
|
}
|
|
}
|
|
|
|
# Basic Lambda execution permissions
|
|
resource "aws_iam_role_policy_attachment" "lambda_basic" {
|
|
role = aws_iam_role.lambda_role.name
|
|
policy_arn = "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
|
|
}
|
|
|
|
# DynamoDB permissions
|
|
resource "aws_iam_role_policy" "lambda_dynamodb" {
|
|
name = "${var.project_name}-dynamodb-policy"
|
|
role = aws_iam_role.lambda_role.id
|
|
|
|
policy = jsonencode({
|
|
Version = "2012-10-17"
|
|
Statement = [
|
|
{
|
|
Effect = "Allow"
|
|
Action = [
|
|
"dynamodb:GetItem",
|
|
"dynamodb:PutItem",
|
|
"dynamodb:UpdateItem",
|
|
"dynamodb:DeleteItem",
|
|
"dynamodb:Query",
|
|
"dynamodb:Scan",
|
|
"dynamodb:BatchGetItem",
|
|
"dynamodb:BatchWriteItem"
|
|
]
|
|
Resource = [
|
|
aws_dynamodb_table.users.arn,
|
|
aws_dynamodb_table.conversations.arn,
|
|
"${aws_dynamodb_table.users.arn}/index/*",
|
|
"${aws_dynamodb_table.conversations.arn}/index/*"
|
|
]
|
|
}
|
|
]
|
|
})
|
|
}
|
|
|
|
# Secrets Manager permissions
|
|
resource "aws_iam_role_policy" "lambda_secrets" {
|
|
name = "${var.project_name}-secrets-policy"
|
|
role = aws_iam_role.lambda_role.id
|
|
|
|
policy = jsonencode({
|
|
Version = "2012-10-17"
|
|
Statement = [
|
|
{
|
|
Effect = "Allow"
|
|
Action = [
|
|
"secretsmanager:GetSecretValue",
|
|
"secretsmanager:DescribeSecret"
|
|
]
|
|
Resource = [
|
|
aws_secretsmanager_secret.discord_bot_token.arn,
|
|
aws_secretsmanager_secret.discord_public_key.arn,
|
|
aws_secretsmanager_secret.github_token.arn,
|
|
aws_secretsmanager_secret.openai_api_key.arn
|
|
]
|
|
}
|
|
]
|
|
})
|
|
}
|
|
|
|
# CloudWatch Logs permissions
|
|
resource "aws_iam_role_policy" "lambda_logs" {
|
|
name = "${var.project_name}-logs-policy"
|
|
role = aws_iam_role.lambda_role.id
|
|
|
|
policy = jsonencode({
|
|
Version = "2012-10-17"
|
|
Statement = [
|
|
{
|
|
Effect = "Allow"
|
|
Action = [
|
|
"logs:CreateLogGroup",
|
|
"logs:CreateLogStream",
|
|
"logs:PutLogEvents"
|
|
]
|
|
Resource = "arn:aws:logs:${var.aws_region}:*:log-group:/aws/lambda/${var.project_name}*"
|
|
}
|
|
]
|
|
})
|
|
}
|
|
|
|
# ECR permissions for pulling Lambda image
|
|
resource "aws_iam_role_policy" "lambda_ecr" {
|
|
name = "${var.project_name}-ecr-policy"
|
|
role = aws_iam_role.lambda_role.id
|
|
|
|
policy = jsonencode({
|
|
Version = "2012-10-17"
|
|
Statement = [
|
|
{
|
|
Effect = "Allow"
|
|
Action = [
|
|
"ecr:GetDownloadUrlForLayer",
|
|
"ecr:BatchGetImage",
|
|
"ecr:BatchCheckLayerAvailability"
|
|
]
|
|
Resource = "${data.aws_ecr_repository.lambda.arn}"
|
|
},
|
|
{
|
|
Effect = "Allow"
|
|
Action = [
|
|
"ecr:GetAuthorizationToken"
|
|
]
|
|
Resource = "*"
|
|
}
|
|
]
|
|
})
|
|
}
|