Use ExAws SES adapter with ECS task-role credentials#613
Conversation
There was a problem hiding this comment.
Pull request overview
This PR updates production email delivery to use Swoosh’s ExAws-backed SES adapter so AWS credentials are resolved at runtime from the ECS task role (instead of relying on static AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY env vars).
Changes:
- Switch prod runtime mailer configuration to
Swoosh.Adapters.ExAwsAmazonSESand configure ExAws to use the:instance_rolecredential provider. - Add ExAws-related dependencies (
:ex_aws,:sweet_xml) and updatemix.lock. - Pass
AWS_REGIONinto the ECS task environment so the runtime config can enable SES in production.
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
mix.exs |
Adds ExAws/SweetXml dependencies needed for the ExAws SES adapter. |
mix.lock |
Locks newly added ExAws/SweetXml (and transitive) dependencies. |
config/runtime.exs |
Updates production runtime config to use ExAwsAmazonSES with instance-role credentials and preserves configuration set passthrough. |
infra/modules/service/task.tf |
Adds AWS_REGION to ECS task env so prod runtime config can select SES adapter. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| {:gen_smtp, "~> 1.0"}, | ||
| {:phoenix_swoosh, "~> 1.2"}, | ||
| {:ex_aws, "~> 2.1"}, | ||
| {:sweet_xml, "~> 0.6"}, |
There was a problem hiding this comment.
False positive — ~> 0.6 in Hex means >= 0.6.0 and < 1.0.0 (see Version docs), so 0.7.5 is in range and satisfies both our constraint and ex_aws's transitive ~> 0.7 requirement. mix.exs and mix.lock agree, and mix deps.get resolves cleanly. Leaving as-is to match the constraint published in the Swoosh.Adapters.ExAwsAmazonSES docs.
| config :ex_aws, | ||
| access_key_id: [:instance_role], | ||
| secret_access_key: [:instance_role], | ||
| region: ses_region |
There was a problem hiding this comment.
Fixed in 50d6ad4 — added http_client: ExAws.Request.Req to the :ex_aws config. We already depend on :req, and ex_aws ships ExAws.Request.Req as a built-in alternative to the default Hackney client. Confirmed via deps/ex_aws/lib/ex_aws/instance_meta.ex:18 that instance-role credential resolution goes through config.http_client.request/5, so this is required for the credential lookup to work in ECS.
|
@ryan-mahoney needs a rebase |
Without this, ExAws falls back to its default ExAws.Request.Hackney, which is not in our deps. Instance-role credential resolution makes HTTP calls to the ECS metadata endpoint via the configured http_client, so SES sends would fail at runtime.
50d6ad4 to
d77d1f0
Compare
Summary
Swoosh.Adapters.AmazonSES(staticAWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY) toSwoosh.Adapters.ExAwsAmazonSES, which resolves credentials via ExAws's:instance_roleprovider — picking up ECS task-role credentials at runtime.:ex_awsand:sweet_xmldeps required by the ExAws-backed adapter.AWS_REGIONinto the ECS task container so the runtime config can select the ExAws adapter (otherwise it falls back toSwoosh.Adapters.Logger).AWS_SES_CONFIGURATION_SETpassthrough.Closes #582.
Test plan
mix compile --warnings-as-errorspasses locally.mix format --check-formatted config/runtime.exspasses.terraform fmt -check infra/modules/service/task.tfpasses.AWS_REGIONand that the first SES send succeeds (noAccessDeniedin CloudWatch).ses:SendEmailcalls.