feat(ppal-aws): add Terraform configuration for Discord Bot
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>
This commit is contained in:
parent
50bb418fe7
commit
abed5cb5cb
1
workers/ppal-aws/terraform/.gitignore
vendored
Normal file
1
workers/ppal-aws/terraform/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
.terraform/
|
||||||
25
workers/ppal-aws/terraform/.terraform.lock.hcl
generated
Normal file
25
workers/ppal-aws/terraform/.terraform.lock.hcl
generated
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
# This file is maintained automatically by "terraform init".
|
||||||
|
# Manual edits may be lost in future updates.
|
||||||
|
|
||||||
|
provider "registry.terraform.io/hashicorp/aws" {
|
||||||
|
version = "5.100.0"
|
||||||
|
constraints = "~> 5.0"
|
||||||
|
hashes = [
|
||||||
|
"h1:Ijt7pOlB7Tr7maGQIqtsLFbl7pSMIj06TVdkoSBcYOw=",
|
||||||
|
"zh:054b8dd49f0549c9a7cc27d159e45327b7b65cf404da5e5a20da154b90b8a644",
|
||||||
|
"zh:0b97bf8d5e03d15d83cc40b0530a1f84b459354939ba6f135a0086c20ebbe6b2",
|
||||||
|
"zh:1589a2266af699cbd5d80737a0fe02e54ec9cf2ca54e7e00ac51c7359056f274",
|
||||||
|
"zh:6330766f1d85f01ae6ea90d1b214b8b74cc8c1badc4696b165b36ddd4cc15f7b",
|
||||||
|
"zh:7c8c2e30d8e55291b86fcb64bdf6c25489d538688545eb48fd74ad622e5d3862",
|
||||||
|
"zh:99b1003bd9bd32ee323544da897148f46a527f622dc3971af63ea3e251596342",
|
||||||
|
"zh:9b12af85486a96aedd8d7984b0ff811a4b42e3d88dad1a3fb4c0b580d04fa425",
|
||||||
|
"zh:9f8b909d3ec50ade83c8062290378b1ec553edef6a447c56dadc01a99f4eaa93",
|
||||||
|
"zh:aaef921ff9aabaf8b1869a86d692ebd24fbd4e12c21205034bb679b9caf883a2",
|
||||||
|
"zh:ac882313207aba00dd5a76dbd572a0ddc818bb9cbf5c9d61b28fe30efaec951e",
|
||||||
|
"zh:bb64e8aff37becab373a1a0cc1080990785304141af42ed6aa3dd4913b000421",
|
||||||
|
"zh:dfe495f6621df5540d9c92ad40b8067376350b005c637ea6efac5dc15028add4",
|
||||||
|
"zh:f0ddf0eaf052766cfe09dea8200a946519f653c384ab4336e2a4a64fdd6310e9",
|
||||||
|
"zh:f1b7e684f4c7ae1eed272b6de7d2049bb87a0275cb04dbb7cda6636f600699c9",
|
||||||
|
"zh:ff461571e3f233699bf690db319dfe46aec75e58726636a0d97dd9ac6e32fb70",
|
||||||
|
]
|
||||||
|
}
|
||||||
73
workers/ppal-aws/terraform/api_gateway.tf
Normal file
73
workers/ppal-aws/terraform/api_gateway.tf
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
resource "aws_apigatewayv2_api" "discord_interactions" {
|
||||||
|
name = "${var.project_name}-discord-interactions"
|
||||||
|
protocol_type = "HTTP"
|
||||||
|
description = "HTTP API for PPAL Discord Bot Interactions Endpoint"
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "${var.project_name}-discord-interactions"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_apigatewayv2_stage" "default" {
|
||||||
|
api_id = aws_apigatewayv2_api.discord_interactions.id
|
||||||
|
name = "$default"
|
||||||
|
auto_deploy = true
|
||||||
|
|
||||||
|
access_log_settings {
|
||||||
|
destination_arn = aws_cloudwatch_log_group.api_gateway.arn
|
||||||
|
format = jsonencode({
|
||||||
|
requestId = "$context.requestId"
|
||||||
|
ip = "$context.identity.sourceIp"
|
||||||
|
caller = "$context.identity.caller"
|
||||||
|
user = "$context.identity.user"
|
||||||
|
requestTime = "$context.requestTime"
|
||||||
|
httpMethod = "$context.httpMethod"
|
||||||
|
resourcePath = "$context.resourcePath"
|
||||||
|
status = "$context.status"
|
||||||
|
protocol = "$context.protocol"
|
||||||
|
responseLength = "$context.responseLength"
|
||||||
|
integrationErrorMessage = "$context.integrationErrorMessage"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "${var.project_name}-default-stage"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_cloudwatch_log_group" "api_gateway" {
|
||||||
|
name = "/aws/apigateway/${var.project_name}-discord-interactions"
|
||||||
|
retention_in_days = 7
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "${var.project_name}-api-gateway-logs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_apigatewayv2_integration" "lambda" {
|
||||||
|
api_id = aws_apigatewayv2_api.discord_interactions.id
|
||||||
|
integration_type = "AWS_PROXY"
|
||||||
|
|
||||||
|
connection_type = "INTERNET"
|
||||||
|
description = "Lambda integration for Discord interactions"
|
||||||
|
integration_method = "POST"
|
||||||
|
integration_uri = aws_lambda_function.discord_handler.invoke_arn
|
||||||
|
payload_format_version = "2.0"
|
||||||
|
timeout_milliseconds = var.lambda_timeout * 1000
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_apigatewayv2_route" "discord_interactions" {
|
||||||
|
api_id = aws_apigatewayv2_api.discord_interactions.id
|
||||||
|
route_key = "POST /interactions"
|
||||||
|
|
||||||
|
target = "integrations/${aws_apigatewayv2_integration.lambda.id}"
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_lambda_permission" "apigateway" {
|
||||||
|
statement_id = "AllowAPIGatewayInvoke"
|
||||||
|
action = "lambda:InvokeFunction"
|
||||||
|
function_name = aws_lambda_function.discord_handler.function_name
|
||||||
|
principal = "apigateway.amazonaws.com"
|
||||||
|
|
||||||
|
source_arn = "${aws_apigatewayv2_api.discord_interactions.execution_arn}/*/*"
|
||||||
|
}
|
||||||
73
workers/ppal-aws/terraform/dynamodb.tf
Normal file
73
workers/ppal-aws/terraform/dynamodb.tf
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
resource "aws_dynamodb_table" "users" {
|
||||||
|
name = "${var.project_name}-users"
|
||||||
|
billing_mode = "PAY_PER_REQUEST"
|
||||||
|
hash_key = "user_id"
|
||||||
|
|
||||||
|
attribute {
|
||||||
|
name = "user_id"
|
||||||
|
type = "S"
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute {
|
||||||
|
name = "guild_id"
|
||||||
|
type = "S"
|
||||||
|
}
|
||||||
|
|
||||||
|
global_secondary_index {
|
||||||
|
name = "GuildIndex"
|
||||||
|
hash_key = "guild_id"
|
||||||
|
projection_type = "ALL"
|
||||||
|
}
|
||||||
|
|
||||||
|
point_in_time_recovery {
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
server_side_encryption {
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "${var.project_name}-users"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_dynamodb_table" "conversations" {
|
||||||
|
name = "${var.project_name}-conversations"
|
||||||
|
billing_mode = "PAY_PER_REQUEST"
|
||||||
|
hash_key = "conversation_id"
|
||||||
|
|
||||||
|
attribute {
|
||||||
|
name = "conversation_id"
|
||||||
|
type = "S"
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute {
|
||||||
|
name = "user_id"
|
||||||
|
type = "S"
|
||||||
|
}
|
||||||
|
|
||||||
|
attribute {
|
||||||
|
name = "created_at"
|
||||||
|
type = "S"
|
||||||
|
}
|
||||||
|
|
||||||
|
global_secondary_index {
|
||||||
|
name = "UserIndex"
|
||||||
|
hash_key = "user_id"
|
||||||
|
range_key = "created_at"
|
||||||
|
projection_type = "ALL"
|
||||||
|
}
|
||||||
|
|
||||||
|
point_in_time_recovery {
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
server_side_encryption {
|
||||||
|
enabled = true
|
||||||
|
}
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "${var.project_name}-conversations"
|
||||||
|
}
|
||||||
|
}
|
||||||
131
workers/ppal-aws/terraform/iam.tf
Normal file
131
workers/ppal-aws/terraform/iam.tf
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
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 = "*"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
})
|
||||||
|
}
|
||||||
70
workers/ppal-aws/terraform/lambda.tf
Normal file
70
workers/ppal-aws/terraform/lambda.tf
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
data "aws_ecr_repository" "lambda" {
|
||||||
|
name = "${var.project_name}-lambda"
|
||||||
|
}
|
||||||
|
|
||||||
|
data "aws_ecr_image" "lambda" {
|
||||||
|
repository_name = data.aws_ecr_repository.lambda.name
|
||||||
|
image_tag = var.environment
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_lambda_function" "discord_handler" {
|
||||||
|
function_name = "${var.project_name}-discord-handler"
|
||||||
|
description = "PPAL Discord Bot command handler"
|
||||||
|
role = aws_iam_role.lambda_role.arn
|
||||||
|
package_type = "Image"
|
||||||
|
|
||||||
|
image_uri = "${data.aws_ecr_repository.lambda.repository_url}@${data.aws_ecr_image.lambda.image_digest}"
|
||||||
|
|
||||||
|
timeout = var.lambda_timeout
|
||||||
|
memory_size = var.lambda_memory_size
|
||||||
|
|
||||||
|
environment {
|
||||||
|
variables = {
|
||||||
|
ENVIRONMENT = var.environment
|
||||||
|
DISCORD_BOT_TOKEN_SECRET_ARN = aws_secretsmanager_secret.discord_bot_token.arn
|
||||||
|
DISCORD_PUBLIC_KEY_SECRET_ARN = aws_secretsmanager_secret.discord_public_key.arn
|
||||||
|
GITHUB_TOKEN_SECRET_ARN = aws_secretsmanager_secret.github_token.arn
|
||||||
|
OPENAI_API_KEY_SECRET_ARN = aws_secretsmanager_secret.openai_api_key.arn
|
||||||
|
USERS_TABLE_NAME = aws_dynamodb_table.users.name
|
||||||
|
CONVERSATIONS_TABLE_NAME = aws_dynamodb_table.conversations.name
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
logging_config {
|
||||||
|
log_format = "Text"
|
||||||
|
log_group = aws_cloudwatch_log_group.lambda_logs.name
|
||||||
|
}
|
||||||
|
|
||||||
|
depends_on = [
|
||||||
|
aws_cloudwatch_log_group.lambda_logs,
|
||||||
|
aws_iam_role_policy_attachment.lambda_basic,
|
||||||
|
aws_iam_role_policy.lambda_dynamodb,
|
||||||
|
aws_iam_role_policy.lambda_secrets,
|
||||||
|
]
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "${var.project_name}-discord-handler"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_cloudwatch_log_group" "lambda_logs" {
|
||||||
|
name = "/aws/lambda/${var.project_name}-discord-handler"
|
||||||
|
retention_in_days = 7
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "${var.project_name}-lambda-logs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_lambda_function_url" "discord_handler" {
|
||||||
|
function_name = aws_lambda_function.discord_handler.function_name
|
||||||
|
authorization_type = "NONE"
|
||||||
|
invoke_mode = "RESPONSE_STREAM"
|
||||||
|
|
||||||
|
cors {
|
||||||
|
allow_credentials = true
|
||||||
|
allow_origins = ["https://discord.com"]
|
||||||
|
allow_methods = ["POST"]
|
||||||
|
allow_headers = ["Content-Type", "X-Discord-Timestamp", "X-Signature-Ed25519", "X-Signature-Timestamp"]
|
||||||
|
}
|
||||||
|
}
|
||||||
78
workers/ppal-aws/terraform/outputs.tf
Normal file
78
workers/ppal-aws/terraform/outputs.tf
Normal file
@ -0,0 +1,78 @@
|
|||||||
|
output "api_gateway_url" {
|
||||||
|
description = "HTTP API Gateway endpoint URL for Discord Interactions"
|
||||||
|
value = aws_apigatewayv2_api.discord_interactions.api_endpoint
|
||||||
|
}
|
||||||
|
|
||||||
|
output "api_gateway_stage_url" {
|
||||||
|
description = "Full stage URL for Discord Interactions endpoint"
|
||||||
|
value = "${aws_apigatewayv2_api.discord_interactions.api_endpoint}/${aws_apigatewayv2_stage.default.name}"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "discord_interactions_endpoint" {
|
||||||
|
description = "Discord Interactions endpoint URL (POST /interactions)"
|
||||||
|
value = "${aws_apigatewayv2_api.discord_interactions.api_endpoint}/interactions"
|
||||||
|
}
|
||||||
|
|
||||||
|
output "lambda_function_name" {
|
||||||
|
description = "Lambda function name"
|
||||||
|
value = aws_lambda_function.discord_handler.function_name
|
||||||
|
}
|
||||||
|
|
||||||
|
output "lambda_function_arn" {
|
||||||
|
description = "Lambda function ARN"
|
||||||
|
value = aws_lambda_function.discord_handler.arn
|
||||||
|
}
|
||||||
|
|
||||||
|
output "lambda_function_url" {
|
||||||
|
description = "Lambda function URL"
|
||||||
|
value = aws_lambda_function_url.discord_handler.function_url
|
||||||
|
}
|
||||||
|
|
||||||
|
output "dynamodb_users_table_name" {
|
||||||
|
description = "DynamoDB users table name"
|
||||||
|
value = aws_dynamodb_table.users.name
|
||||||
|
}
|
||||||
|
|
||||||
|
output "dynamodb_users_table_arn" {
|
||||||
|
description = "DynamoDB users table ARN"
|
||||||
|
value = aws_dynamodb_table.users.arn
|
||||||
|
}
|
||||||
|
|
||||||
|
output "dynamodb_conversations_table_name" {
|
||||||
|
description = "DynamoDB conversations table name"
|
||||||
|
value = aws_dynamodb_table.conversations.name
|
||||||
|
}
|
||||||
|
|
||||||
|
output "dynamodb_conversations_table_arn" {
|
||||||
|
description = "DynamoDB conversations table ARN"
|
||||||
|
value = aws_dynamodb_table.conversations.arn
|
||||||
|
}
|
||||||
|
|
||||||
|
output "secrets_discord_bot_token_arn" {
|
||||||
|
description = "Secrets Manager ARN for Discord bot token"
|
||||||
|
value = aws_secretsmanager_secret.discord_bot_token.arn
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
output "secrets_discord_public_key_arn" {
|
||||||
|
description = "Secrets Manager ARN for Discord public key"
|
||||||
|
value = aws_secretsmanager_secret.discord_public_key.arn
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
output "secrets_github_token_arn" {
|
||||||
|
description = "Secrets Manager ARN for GitHub token"
|
||||||
|
value = aws_secretsmanager_secret.github_token.arn
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
output "secrets_openai_api_key_arn" {
|
||||||
|
description = "Secrets Manager ARN for OpenAI API key"
|
||||||
|
value = aws_secretsmanager_secret.openai_api_key.arn
|
||||||
|
sensitive = true
|
||||||
|
}
|
||||||
|
|
||||||
|
output "lambda_role_arn" {
|
||||||
|
description = "Lambda execution role ARN"
|
||||||
|
value = aws_iam_role.lambda_role.arn
|
||||||
|
}
|
||||||
84
workers/ppal-aws/terraform/secrets.tf
Normal file
84
workers/ppal-aws/terraform/secrets.tf
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
resource "aws_secretsmanager_secret" "discord_bot_token" {
|
||||||
|
name = var.discord_bot_token_secret_name
|
||||||
|
description = "Discord bot token for PPAL Discord Bot"
|
||||||
|
recovery_window_in_days = 7
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "${var.project_name}-discord-bot-token"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_secretsmanager_secret" "discord_public_key" {
|
||||||
|
name = var.discord_public_key_secret_name
|
||||||
|
description = "Discord public key for verifying interactions"
|
||||||
|
recovery_window_in_days = 7
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "${var.project_name}-discord-public-key"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_secretsmanager_secret" "github_token" {
|
||||||
|
name = var.github_token_secret_name
|
||||||
|
description = "GitHub token for PPAL Discord Bot"
|
||||||
|
recovery_window_in_days = 7
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "${var.project_name}-github-token"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_secretsmanager_secret" "openai_api_key" {
|
||||||
|
name = var.openai_api_key_secret_name
|
||||||
|
description = "OpenAI API key for PPAL Discord Bot"
|
||||||
|
recovery_window_in_days = 7
|
||||||
|
|
||||||
|
tags = {
|
||||||
|
Name = "${var.project_name}-openai-api-key"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Secret versions (placeholder values - must be updated manually or via CI/CD)
|
||||||
|
resource "aws_secretsmanager_secret_version" "discord_bot_token" {
|
||||||
|
secret_id = aws_secretsmanager_secret.discord_bot_token.id
|
||||||
|
secret_string = jsonencode({
|
||||||
|
token = "PLACEHOLDER_DISCORD_BOT_TOKEN"
|
||||||
|
})
|
||||||
|
|
||||||
|
lifecycle {
|
||||||
|
ignore_changes = [secret_string]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_secretsmanager_secret_version" "discord_public_key" {
|
||||||
|
secret_id = aws_secretsmanager_secret.discord_public_key.id
|
||||||
|
secret_string = jsonencode({
|
||||||
|
public_key = "PLACEHOLDER_DISCORD_PUBLIC_KEY"
|
||||||
|
})
|
||||||
|
|
||||||
|
lifecycle {
|
||||||
|
ignore_changes = [secret_string]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_secretsmanager_secret_version" "github_token" {
|
||||||
|
secret_id = aws_secretsmanager_secret.github_token.id
|
||||||
|
secret_string = jsonencode({
|
||||||
|
token = "PLACEHOLDER_GITHUB_TOKEN"
|
||||||
|
})
|
||||||
|
|
||||||
|
lifecycle {
|
||||||
|
ignore_changes = [secret_string]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resource "aws_secretsmanager_secret_version" "openai_api_key" {
|
||||||
|
secret_id = aws_secretsmanager_secret.openai_api_key.id
|
||||||
|
secret_string = jsonencode({
|
||||||
|
api_key = "PLACEHOLDER_OPENAI_API_KEY"
|
||||||
|
})
|
||||||
|
|
||||||
|
lifecycle {
|
||||||
|
ignore_changes = [secret_string]
|
||||||
|
}
|
||||||
|
}
|
||||||
59
workers/ppal-aws/terraform/variables.tf
Normal file
59
workers/ppal-aws/terraform/variables.tf
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
variable "aws_region" {
|
||||||
|
description = "AWS region for resources"
|
||||||
|
type = string
|
||||||
|
default = "ap-northeast-1"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "environment" {
|
||||||
|
description = "Environment name (e.g., production, staging)"
|
||||||
|
type = string
|
||||||
|
default = "production"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "project_name" {
|
||||||
|
description = "Project name used for resource naming"
|
||||||
|
type = string
|
||||||
|
default = "ppal"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "lambda_handler" {
|
||||||
|
description = "Lambda handler function name"
|
||||||
|
type = string
|
||||||
|
default = "index.handler"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "lambda_timeout" {
|
||||||
|
description = "Lambda function timeout in seconds"
|
||||||
|
type = number
|
||||||
|
default = 30
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "lambda_memory_size" {
|
||||||
|
description = "Lambda function memory size in MB"
|
||||||
|
type = number
|
||||||
|
default = 256
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "discord_bot_token_secret_name" {
|
||||||
|
description = "Secrets Manager secret name for Discord bot token"
|
||||||
|
type = string
|
||||||
|
default = "ppal/discord/bot-token"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "discord_public_key_secret_name" {
|
||||||
|
description = "Secrets Manager secret name for Discord public key"
|
||||||
|
type = string
|
||||||
|
default = "ppal/discord/public-key"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "github_token_secret_name" {
|
||||||
|
description = "Secrets Manager secret name for GitHub token"
|
||||||
|
type = string
|
||||||
|
default = "ppal/github/token"
|
||||||
|
}
|
||||||
|
|
||||||
|
variable "openai_api_key_secret_name" {
|
||||||
|
description = "Secrets Manager secret name for OpenAI API key"
|
||||||
|
type = string
|
||||||
|
default = "ppal/openai/api-key"
|
||||||
|
}
|
||||||
22
workers/ppal-aws/terraform/versions.tf
Normal file
22
workers/ppal-aws/terraform/versions.tf
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
terraform {
|
||||||
|
required_version = ">= 1.0"
|
||||||
|
|
||||||
|
required_providers {
|
||||||
|
aws = {
|
||||||
|
source = "hashicorp/aws"
|
||||||
|
version = "~> 5.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
provider "aws" {
|
||||||
|
region = var.aws_region
|
||||||
|
|
||||||
|
default_tags {
|
||||||
|
tags = {
|
||||||
|
Project = var.project_name
|
||||||
|
Environment = var.environment
|
||||||
|
ManagedBy = "Terraform"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user