From 3df16bb315480b001a5e76b51e0e347c00870157 Mon Sep 17 00:00:00 2001 From: Ian Keane Date: Mon, 24 Aug 2026 09:38:51 -0400 Subject: [PATCH] SES setup for kan --- charts/kan/templates/external-secret.yaml | 17 +++++ terraform/ses.tf | 76 +++++++++++++++++++++++ 2 files changed, 93 insertions(+) create mode 100644 terraform/ses.tf diff --git a/charts/kan/templates/external-secret.yaml b/charts/kan/templates/external-secret.yaml index 0457be7..cd969b9 100644 --- a/charts/kan/templates/external-secret.yaml +++ b/charts/kan/templates/external-secret.yaml @@ -16,6 +16,11 @@ spec: data: BETTER_AUTH_SECRET: "{{ `{{ .better_auth_secret }}` }}" POSTGRES_URL: "postgresql://postgres:{{ `{{ .postgres_password }}` }}@postgres.postgres.svc.cluster.local:5432/kan?sslmode=disable" + EMAIL_SERVER_HOST: "{{ `{{ .ses_smtp_endpoint }}` }}" + EMAIL_SERVER_PORT: "587" + EMAIL_SERVER_USER: "{{ `{{ .ses_smtp_user }}` }}" + EMAIL_SERVER_PASSWORD: "{{ `{{ .ses_smtp_password }}` }}" + EMAIL_FROM: "noreply@{{ .Values.domain }}" data: - secretKey: better_auth_secret remoteRef: @@ -25,3 +30,15 @@ spec: remoteRef: key: dumpnet property: postgres.password + - secretKey: ses_smtp_endpoint + remoteRef: + key: dumpnet + property: ses.smtp_endpoint + - secretKey: ses_smtp_user + remoteRef: + key: dumpnet + property: ses.smtp_user + - secretKey: ses_smtp_password + remoteRef: + key: dumpnet + property: ses.smtp_password diff --git a/terraform/ses.tf b/terraform/ses.tf new file mode 100644 index 0000000..0c3d881 --- /dev/null +++ b/terraform/ses.tf @@ -0,0 +1,76 @@ +# SES domain verification and SMTP setup for dumpnet.chat + +resource "aws_ses_domain_identity" "dumpnet" { + domain = var.domain +} + +resource "aws_ses_domain_dkim" "dumpnet" { + domain = aws_ses_domain_identity.dumpnet.domain +} + +# DKIM DNS records (3 required) +resource "aws_route53_record" "ses_dkim" { + count = 3 + zone_id = data.aws_route53_zone.dumpnet.zone_id + name = "${aws_ses_domain_dkim.dumpnet.dkim_tokens[count.index]}._domainkey.${var.domain}" + type = "CNAME" + ttl = 300 + records = ["${aws_ses_domain_dkim.dumpnet.dkim_tokens[count.index]}.dkim.amazonses.com"] +} + +# Domain verification TXT record +resource "aws_route53_record" "ses_verification" { + zone_id = data.aws_route53_zone.dumpnet.zone_id + name = "_amazonses.${var.domain}" + type = "TXT" + ttl = 300 + records = [aws_ses_domain_identity.dumpnet.verification_token] +} + +resource "aws_ses_domain_identity_verification" "dumpnet" { + domain = aws_ses_domain_identity.dumpnet.id + depends_on = [aws_route53_record.ses_verification] +} + +# SMTP credentials via IAM user +resource "aws_iam_user" "ses_smtp" { + name = "${var.cluster_name}-ses-smtp" +} + +resource "aws_iam_user_policy" "ses_smtp" { + name = "ses-send" + user = aws_iam_user.ses_smtp.name + + policy = jsonencode({ + Version = "2012-10-17" + Statement = [{ + Effect = "Allow" + Action = "ses:SendRawEmail" + Resource = "*" + }] + }) +} + +resource "aws_iam_access_key" "ses_smtp" { + user = aws_iam_user.ses_smtp.name +} + +# Store SMTP credentials in Secrets Manager +# Note: SES SMTP password is derived from the IAM secret key, not the key itself +# The password must be calculated using the SES SMTP password algorithm +locals { + ses_smtp_endpoint = "email-smtp.${var.aws_region}.amazonaws.com" +} + +output "ses_smtp_endpoint" { + value = local.ses_smtp_endpoint +} + +output "ses_smtp_username" { + value = aws_iam_access_key.ses_smtp.id +} + +output "ses_smtp_password" { + value = aws_iam_access_key.ses_smtp.ses_smtp_password_v4 + sensitive = true +}