From 911e0fc68d176e725b31c9f9a59acf3db0f2804c Mon Sep 17 00:00:00 2001 From: Erik Stambaugh Date: Mon, 22 Jan 2024 19:27:29 -0800 Subject: [PATCH] Add first pass SES stuff --- Makefile | 3 + ansible/Makefile | 6 +- ansible/inventory.tmpl.yaml | 2 + .../roles/mastodon/templates/env.production | 11 +- terraform/main.tf | 2 +- terraform/outputs.tf | 2 +- terraform/ses.tf | 136 ++++++++++++++++++ 7 files changed, 155 insertions(+), 7 deletions(-) create mode 100644 terraform/ses.tf diff --git a/Makefile b/Makefile index 12ecce5..6ed77ed 100644 --- a/Makefile +++ b/Makefile @@ -34,6 +34,9 @@ config.mk: config.mk.in .s3_iam_credentials: terraform/.s3_id terraform/.s3_secret cat $^ > $@ +.ses_iam_credentials: terraform/.ses_id terraform/.ses_secret + cat $^ > $@ + terraform/.s3_id terraform/.s3_secret: terraform diff --git a/ansible/Makefile b/ansible/Makefile index 9b31deb..cd804c9 100644 --- a/ansible/Makefile +++ b/ansible/Makefile @@ -27,7 +27,7 @@ inventory.yaml: inventory.tmpl.yaml sedline SEDLINE = -sedline: terraform_sedline config_sedline s3_sedline +sedline: terraform_sedline config_sedline secret_sedline config_sedline: $(addprefix __sed_,$(shell grep '^[0-9A-Z_]' ../config.mk | awk '{print $$1}')) @@ -37,9 +37,11 @@ __sed_%: $(eval SEDLINE := $$(SEDLINE) -e 's/{{$*}}/$($*)/') # FIXME: this is awful because it's all in the clear -s3_sedline: +secret_sedline: $(eval SEDLINE := $$(SEDLINE) -e 's/{{S3_IAM_ID}}/$(shell head -1 ../.s3_iam_credentials)/') $(eval SEDLINE := $$(SEDLINE) -e 's/{{S3_IAM_SECRET}}/$(shell tail -1 ../.s3_iam_credentials)/') + $(eval SEDLINE := $$(SEDLINE) -e 's/{{SES_IAM_ID}}/$(shell head -1 ../.ses_iam_credentials)/') + $(eval SEDLINE := $$(SEDLINE) -e 's/{{SES_IAM_SECRET}}/$(shell tail -1 ../.ses_iam_credentials)/') # FIXME: DRY this target diff --git a/ansible/inventory.tmpl.yaml b/ansible/inventory.tmpl.yaml index 4b90fc5..2d20898 100644 --- a/ansible/inventory.tmpl.yaml +++ b/ansible/inventory.tmpl.yaml @@ -20,6 +20,8 @@ social: s3_hostname: "s3.{{AWS_REGION}}.amazonaws.com" s3_iam_id: {{S3_IAM_ID}} s3_iam_secret: {{S3_IAM_SECRET}} + ses_iam_id: {{SES_IAM_ID}} + ses_iam_secret: {{SES_IAM_SECRET}} #smtp_server: otp_secret: diff --git a/ansible/roles/mastodon/templates/env.production b/ansible/roles/mastodon/templates/env.production index eba929e..ca29d0f 100644 --- a/ansible/roles/mastodon/templates/env.production +++ b/ansible/roles/mastodon/templates/env.production @@ -48,11 +48,16 @@ OTP_SECRET={{otp_secret}} # Sending mail # ------------ -#SMTP_SERVER=#{#{smtp_server#}#} -SMTP_PORT=25 +SMTP_SERVER=email-smtp.{{aws_region}}.amazonaws.com +SMTP_PORT=465 SMTP_FROM_ADDRESS=Mastodon -SMTP_AUTH_METHOD=none +SMTP_LOGIN={{ses_iam_id}} +SMTP_PASSWORD={{ses_iam_secret}} +SMTP_ENABLE_STARTTLS_AUTO=false +SMTP_TLS=true +SMTP_AUTH_METHOD=plain SMTP_OPENSSL_VERIFY_MODE=none +SMTP_ENABLE_STARTTLS=never ## File storage (optional) ## ----------------------- diff --git a/terraform/main.tf b/terraform/main.tf index a2fc8dd..1ee8eeb 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -67,7 +67,7 @@ module "sg" { }, { rule = "https-443-tcp" - cidr_blocks = "${chomp(data.http.myip.body)}/32" + cidr_blocks = "${chomp(data.http.myip.response_body)}/32" } ] } diff --git a/terraform/outputs.tf b/terraform/outputs.tf index 1ad0221..f11c9c8 100644 --- a/terraform/outputs.tf +++ b/terraform/outputs.tf @@ -13,7 +13,7 @@ output "s3_bucket_name" { value = module.s3_bucket.s3_bucket_id } output "my_ip" { - value = "${chomp(data.http.myip.body)}" + value = "${chomp(data.http.myip.response_body)}" } #output "aws_route53_zone" { diff --git a/terraform/ses.tf b/terraform/ses.tf new file mode 100644 index 0000000..fc420d5 --- /dev/null +++ b/terraform/ses.tf @@ -0,0 +1,136 @@ + +## - verification + +resource "aws_ses_domain_identity" "social" { + domain = local.domain_name +} + +module "ses_zone_records" { + # count = local.route53_zone == "" ? 0 : 1 + + source = "terraform-aws-modules/route53/aws//modules/records" + version = "~> 2.0" + zone_name = keys(module.zone.route53_zone_zone_id)[0] + + records = [ + { + name = "_amazonses.${aws_ses_domain_identity.social.id}" + type = "TXT" + ttl = "600" + records = [ aws_ses_domain_identity.social.verification_token ] + }, + { + name = local.domain_name + type = "MX" + ttl = "600" + records = ["10 feedback-smtp.${local.aws_region}.amazonses.com"] + }, + + # SPF + { + name = aws_ses_domain_mail_from.social.mail_from_domain + type = "TXT" + ttl = "600" + records = [ "v=spf1 include:amazonses.com -all" ] + }, + { + name = local.domain_name + type = "TXT" + ttl = "600" + records = [ "v=spf1 include:amazonses.com -all" ] + }, + + # DKIM + { + name = "${aws_ses_domain_dkim.social.dkim_tokens[0]}._domainkey" + type = "CNAME" + ttl = "600" + records = ["${aws_ses_domain_dkim.social.dkim_tokens[0]}.dkim.amazonses.com"] + }, + { + name = "${aws_ses_domain_dkim.social.dkim_tokens[1]}._domainkey" + type = "CNAME" + ttl = "600" + records = ["${aws_ses_domain_dkim.social.dkim_tokens[1]}.dkim.amazonses.com"] + }, + { + name = "${aws_ses_domain_dkim.social.dkim_tokens[2]}._domainkey" + type = "CNAME" + ttl = "600" + records = ["${aws_ses_domain_dkim.social.dkim_tokens[2]}.dkim.amazonses.com"] + }, + + + ] + + depends_on = [module.zone] +} + +resource "aws_ses_domain_identity_verification" "social" { + domain = aws_ses_domain_identity.social.id + + depends_on = [ module.ses_zone_records ] +} + +resource "aws_ses_domain_dkim" "social" { + domain = aws_ses_domain_identity.social.domain +} + +## - mx record + +resource "aws_ses_domain_mail_from" "social" { + domain = aws_ses_domain_identity.social.domain + mail_from_domain = "bounce.${aws_ses_domain_identity.social.domain}" +} + + +#resource "aws_route53_record" "mx_receive" { +# count = var.enable_incoming_email_record ? 1 : 0 +# +# name = data.aws_route53_zone.domain.name +# zone_id = var.zone_id +# type = "MX" +# ttl = "600" +# records = concat(["10 inbound-smtp.${data.aws_region.current.name}.amazonaws.com"], var.additional_incoming_email_records) +#} + +## SMTP credentials + +resource "random_pet" "smtp" {} + +resource "aws_iam_user" "ses" { + name = "smtp-${random_pet.smtp.id}" +} + +resource "aws_iam_user_policy_attachment" "send_mail" { + policy_arn = aws_iam_policy.send_mail.arn + user = aws_iam_user.ses.name +} + +resource "aws_iam_policy" "send_mail" { + name = "social-send-mail" + policy = data.aws_iam_policy_document.send_mail.json +} + +data "aws_iam_policy_document" "send_mail" { + statement { + actions = ["ses:SendRawEmail"] + resources = ["*"] + } +} + +resource "aws_iam_access_key" "ses" { + user = aws_iam_user.ses.name +} + +resource "local_file" "ses_secret" { + filename = ".ses_secret" + content = "${aws_iam_access_key.ses.secret}\n" +} +resource "local_file" "ses_id" { + filename = ".ses_id" + content = "${aws_iam_access_key.ses.id}\n" +} + + +