308 lines
7.4 KiB
HCL
308 lines
7.4 KiB
HCL
terraform {
|
|
required_version = ">= 1.0"
|
|
required_providers {
|
|
aws = {
|
|
source = "hashicorp/aws"
|
|
version = "~> 5.0"
|
|
}
|
|
random = {
|
|
source = "hashicorp/random"
|
|
version = "~> 3.0"
|
|
}
|
|
}
|
|
|
|
backend "s3" {
|
|
bucket = "calculator-127local-net-terraform-state"
|
|
key = "email/infrastructure/terraform.tfstate"
|
|
region = "us-west-2"
|
|
}
|
|
}
|
|
|
|
provider "aws" {
|
|
region = var.aws_region
|
|
|
|
default_tags {
|
|
tags = local.common_tags
|
|
}
|
|
}
|
|
|
|
# Common tags for all resources
|
|
locals {
|
|
common_tags = {
|
|
Project = "calculator-127local-net"
|
|
Environment = "production"
|
|
ManagedBy = "terraform"
|
|
Owner = "will@aerenserve.net"
|
|
Purpose = "email-forwarding"
|
|
CostCenter = "calculator-services"
|
|
}
|
|
}
|
|
|
|
# S3 bucket for email storage
|
|
resource "aws_s3_bucket" "email_storage" {
|
|
bucket = "calculator-127local-net-emails-${random_string.bucket_suffix.result}"
|
|
|
|
tags = merge(local.common_tags, {
|
|
Name = "Calculator Email Storage"
|
|
})
|
|
}
|
|
|
|
resource "random_string" "bucket_suffix" {
|
|
length = 8
|
|
special = false
|
|
upper = false
|
|
}
|
|
|
|
# S3 bucket versioning
|
|
resource "aws_s3_bucket_versioning" "email_storage" {
|
|
bucket = aws_s3_bucket.email_storage.id
|
|
versioning_configuration {
|
|
status = "Enabled"
|
|
}
|
|
}
|
|
|
|
# S3 bucket server-side encryption
|
|
resource "aws_s3_bucket_server_side_encryption_configuration" "email_storage" {
|
|
bucket = aws_s3_bucket.email_storage.id
|
|
|
|
rule {
|
|
apply_server_side_encryption_by_default {
|
|
sse_algorithm = "AES256"
|
|
}
|
|
}
|
|
}
|
|
|
|
# S3 bucket public access block
|
|
resource "aws_s3_bucket_public_access_block" "email_storage" {
|
|
bucket = aws_s3_bucket.email_storage.id
|
|
|
|
block_public_acls = true
|
|
block_public_policy = true
|
|
ignore_public_acls = true
|
|
restrict_public_buckets = true
|
|
}
|
|
|
|
# S3 bucket policy to allow SES to write emails
|
|
resource "aws_s3_bucket_policy" "email_storage" {
|
|
bucket = aws_s3_bucket.email_storage.id
|
|
|
|
policy = jsonencode({
|
|
Version = "2012-10-17"
|
|
Statement = [
|
|
{
|
|
Sid = "AllowSESToWriteEmails"
|
|
Effect = "Allow"
|
|
Principal = {
|
|
Service = "ses.amazonaws.com"
|
|
}
|
|
Action = [
|
|
"s3:PutObject"
|
|
]
|
|
Resource = "${aws_s3_bucket.email_storage.arn}/*"
|
|
Condition = {
|
|
StringEquals = {
|
|
"aws:Referer" = var.aws_account_id
|
|
}
|
|
}
|
|
}
|
|
]
|
|
})
|
|
}
|
|
|
|
# SES Domain identity for 127local.net
|
|
resource "aws_ses_domain_identity" "calculator" {
|
|
domain = var.domain_name
|
|
}
|
|
|
|
# SES Domain DKIM for 127local.net
|
|
resource "aws_ses_domain_dkim" "calculator" {
|
|
domain = aws_ses_domain_identity.calculator.domain
|
|
}
|
|
|
|
# Route53 records for SES DKIM validation
|
|
resource "aws_route53_record" "ses_dkim" {
|
|
count = 3
|
|
zone_id = var.route53_zone_id
|
|
name = "${element(aws_ses_domain_dkim.calculator.dkim_tokens, count.index)}._domainkey.${var.domain_name}"
|
|
type = "CNAME"
|
|
ttl = "600"
|
|
records = ["${element(aws_ses_domain_dkim.calculator.dkim_tokens, count.index)}.dkim.amazonses.com"]
|
|
}
|
|
|
|
# MX record for email receiving
|
|
resource "aws_route53_record" "ses_mx" {
|
|
zone_id = var.route53_zone_id
|
|
name = var.domain_name
|
|
type = "MX"
|
|
ttl = "300"
|
|
records = ["10 inbound-smtp.us-west-2.amazonaws.com"]
|
|
}
|
|
|
|
# SES Email receiving rule set
|
|
resource "aws_ses_receipt_rule_set" "calculator" {
|
|
rule_set_name = "calculator-main-rule-set"
|
|
}
|
|
|
|
# SES Receipt rule for calculator@127local.net
|
|
resource "aws_ses_receipt_rule" "calculator_forward" {
|
|
name = "calculator-forward"
|
|
rule_set_name = aws_ses_receipt_rule_set.calculator.rule_set_name
|
|
recipients = ["calculator@${var.domain_name}"]
|
|
enabled = true
|
|
scan_enabled = true
|
|
tls_policy = "Optional"
|
|
|
|
add_header_action {
|
|
header_name = "X-Forwarded-To"
|
|
header_value = var.forward_email
|
|
position = 1
|
|
}
|
|
|
|
s3_action {
|
|
bucket_name = aws_s3_bucket.email_storage.bucket
|
|
object_key_prefix = "calculator/"
|
|
position = 2
|
|
}
|
|
}
|
|
|
|
# Set this rule set as active
|
|
resource "aws_ses_active_receipt_rule_set" "calculator" {
|
|
rule_set_name = aws_ses_receipt_rule_set.calculator.rule_set_name
|
|
}
|
|
|
|
# Lambda function for email processing
|
|
resource "aws_lambda_function" "email_processor" {
|
|
filename = "email_processor.zip"
|
|
function_name = "calculator-email-processor"
|
|
role = aws_iam_role.lambda_role.arn
|
|
handler = "email_processor.handler"
|
|
source_code_hash = data.archive_file.email_processor_zip.output_base64sha256
|
|
runtime = "nodejs18.x"
|
|
timeout = 30
|
|
|
|
environment {
|
|
variables = {
|
|
FORWARD_EMAIL = var.forward_email
|
|
DOMAIN_NAME = var.domain_name
|
|
ENVIRONMENT = "production"
|
|
}
|
|
}
|
|
|
|
tags = merge(local.common_tags, {
|
|
Name = "Calculator Email Processor"
|
|
})
|
|
}
|
|
|
|
# Create zip file for Lambda function with dependencies
|
|
data "archive_file" "email_processor_zip" {
|
|
type = "zip"
|
|
source_dir = "."
|
|
output_path = "email_processor.zip"
|
|
excludes = ["email_processor.zip", "*.tf", "*.tfvars", "README.md", ".terraform", ".terraform.lock.hcl"]
|
|
}
|
|
|
|
# IAM role for Lambda function
|
|
resource "aws_iam_role" "lambda_role" {
|
|
name = "calculator-email-processor-role"
|
|
|
|
assume_role_policy = jsonencode({
|
|
Version = "2012-10-17"
|
|
Statement = [
|
|
{
|
|
Action = "sts:AssumeRole"
|
|
Effect = "Allow"
|
|
Principal = {
|
|
Service = "lambda.amazonaws.com"
|
|
}
|
|
}
|
|
]
|
|
})
|
|
|
|
tags = local.common_tags
|
|
}
|
|
|
|
# IAM policy for Lambda function
|
|
resource "aws_iam_role_policy" "lambda_policy" {
|
|
name = "calculator-email-processor-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:*:*:*"
|
|
},
|
|
{
|
|
Effect = "Allow"
|
|
Action = [
|
|
"s3:GetObject",
|
|
"s3:PutObject"
|
|
]
|
|
Resource = "${aws_s3_bucket.email_storage.arn}/*"
|
|
},
|
|
{
|
|
Effect = "Allow"
|
|
Action = [
|
|
"s3:ListBucket"
|
|
]
|
|
Resource = aws_s3_bucket.email_storage.arn
|
|
},
|
|
{
|
|
Effect = "Allow"
|
|
Action = [
|
|
"ses:SendEmail",
|
|
"ses:SendRawEmail"
|
|
]
|
|
Resource = "*"
|
|
}
|
|
]
|
|
})
|
|
}
|
|
|
|
# S3 bucket notification to trigger Lambda
|
|
resource "aws_s3_bucket_notification" "email_processor" {
|
|
bucket = aws_s3_bucket.email_storage.id
|
|
|
|
lambda_function {
|
|
lambda_function_arn = aws_lambda_function.email_processor.arn
|
|
events = ["s3:ObjectCreated:*"]
|
|
filter_prefix = "calculator/"
|
|
filter_suffix = ""
|
|
}
|
|
}
|
|
|
|
# Lambda permission for S3 to invoke the function
|
|
resource "aws_lambda_permission" "allow_s3" {
|
|
statement_id = "AllowExecutionFromS3Bucket"
|
|
action = "lambda:InvokeFunction"
|
|
function_name = aws_lambda_function.email_processor.function_name
|
|
principal = "s3.amazonaws.com"
|
|
source_arn = aws_s3_bucket.email_storage.arn
|
|
}
|
|
|
|
# Outputs
|
|
output "email_storage_bucket_name" {
|
|
value = aws_s3_bucket.email_storage.bucket
|
|
}
|
|
|
|
output "ses_domain_identity" {
|
|
value = aws_ses_domain_identity.calculator.domain
|
|
}
|
|
|
|
output "ses_receipt_rule_set_name" {
|
|
value = aws_ses_receipt_rule_set.calculator.rule_set_name
|
|
}
|
|
|
|
output "lambda_function_name" {
|
|
value = aws_lambda_function.email_processor.function_name
|
|
}
|
|
|
|
output "dkim_tokens" {
|
|
value = aws_ses_domain_dkim.calculator.dkim_tokens
|
|
}
|