So I’m sharing the final solution as a way of paying it forward, I wouldn’t have gotten this far without several blog- and forum posts, stack overflow and the ExAwsAmazonSES documentation (Read carefully, Everything is in there. I’m not sure why the AmazonSES documentation refers to using ExAwsAmazonSES if you have ex_aws already configured. I may be missing something, but ExAwsAmazonSES seems to be the better option).
I ended up with ex_aws in the end, so I don’t have to generate the security token by hand. It uses AWS_PROFILE, and loads the associatd key and secret as well. It will use aws sts and do the key rotation. No credentials in the production code or configuration code.
Dependencies used
{:ex_aws, "~> 2.1"},
{:ex_aws_sts, "~> 2.1"},
{:configparser_ex, "~> 4.0"},
{:hackney, "~> 1.9"},
{:swoosh, "~> 1.14.1"},
{:gen_smtp, "~> 1.2.0"},
Config for ex_aws and ExAwsAmazonSES in runtime.exs
I Found the idea to do this in runtime.exs in a suggestion. I might put the code in ~dev.exs~ again. I probably need to find an explanation of what to put where (dev.exs, config.exs, runtime.exs etc) I was following someone elses’ example and it seems to work for me. For production I’d probably use environment variables for the key and the secret, after creating a narrow IAM user that only has the permissions the app needs. So this will need some more factoring out.
if config_env() == :prod or config_env() == :dev do
IO.puts("Configuring AWS credentials")
config :ex_aws,
# Below works if you export AWS_PROFILE (specified by :awscli)
access_key_id: [{:system, "AWS_ACCESS_KEY_ID"}, {:awscli, :system, 30}, :instance_role],
secret_access_key: [{:system, "AWS_SECRET_ACCESS_KEY"}, {:awscli, :system, 30}, :instance_role],
region: "eu-west-2" # London. fill in your own region here.
IO.puts("Configuring ExAwsAmazonSEs Mailer. config_env: #{config_env()}")
config :pento, Pento.Mailer,
adapter: Swoosh.Adapters.ExAwsAmazonSES
config :swoosh, :api_client, Swoosh.ApiClient.Hackney
else
IO.puts("Not Configuring AWS credentials and mailer. config_env: #{config_env()}")
end
Feedback most welcome. I’m glad it finally works and hope I can save someone some time in the future.






















