11

I have an IAM role with the following policy attached:

{
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "*",
      "Resource": "*"
    }
  ]
}

As you can see, full access is granted.

I use the following python to get the convert the IAM credentials to SMTP credentials:

#!/usr/bin/env python

from __future__ import print_function

import base64
import hashlib
import hmac
import json
import struct
import urllib2

METADATA_BASE = 'http://169.254.169.254/2012-01-12/meta-data'


def main():
    access_key_id, secret_access_key = get_access_creds()
    username, password = get_smtp_creds(access_key_id, secret_access_key)

    print('SMTP Username: %s' % username)
    print('SMTP Password: %s' % password)


def get_access_creds():
    url_handle = urllib2.urlopen('%s/iam/security-credentials' %
                                 (METADATA_BASE,))
    role_name = url_handle.read()
    url_handle.close()

    url_handle = urllib2.urlopen('%s/iam/security-credentials/%s' %
                                 (METADATA_BASE, role_name))
    sec_cred_doc = url_handle.read()
    url_handle.close()

    sec_cred_data = json.loads(sec_cred_doc)
    access_key_id =  buffer(sec_cred_data['AccessKeyId'])
    secret_access_key = buffer(sec_cred_data['SecretAccessKey'])

    return access_key_id, secret_access_key


def get_smtp_creds(access_key_id, secret_access_key):
    message = 'SendRawEmail'
    version = 0x02

    sig= hmac.new(
        secret_access_key,
        msg=message,
        digestmod=hashlib.sha256)
    sig_bytes = sig.digest()
    sig_and_version_bytes = (struct.pack('B', version) + sig_bytes)
    smtp_password = base64.b64encode(sig_and_version_bytes)

    return access_key_id, smtp_password

if __name__ == '__main__':
    main()

When I run this code, some SMTP username and password are output. When I try to send a message with those with say swaks, for example, it fails. Here's an example command line:

swaks -s email-smtp.us-east-1.amazonaws.com --from wt@example.com --to wt@example.com --auth-user <smtp username from script above> --auth-password <smtp password from script above> --tls

Example.com is, of course, a placeholder. The real domain has been verified on my AWS SES account.

In fact, if I run the same code to convert from an IAM user instead of discovering the role credentials from the meta-data, I can use the username and password to send email just fine.

AFAICT, this just isn't allowed with IAM role credentials, which is lame if it's true. I was planning on generating a Postfix config to allow processes on the box to send mail to localhost and have that routed to the SES service. I was trying to avoid putting IAM user credentials on the servers. However, it looks like there may not be a way to avoid that now.

Any thoughts?

Wren T.
  • 327
  • 3
  • 5
  • 1
    I have tried the same thing and come to the same conclusion. It looks like it's currently not possible to use IAM Role Credentials for SES SMTP. – Christian Jun 07 '14 at 14:35
  • and while using IAM role, you don't even need SMTP creds. Just use SES client from boto3. – Hardeep Singh May 18 '20 at 06:38

3 Answers3

3

You can use this project to send SMTP without credentials using IAM role instead https://github.com/loopingz/aws-smtp-relay

1

You can try to give your user the following permission. It seems redundant since you have already use wildcards, but the following policy works here (also with postfix) and is generated by AWS.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "ses:SendRawEmail",
      "Resource": "*"
    }
  ]
}
Skiaddict
  • 116
  • 1
  • 10
-1

Why don't you start with the simplest one?

{
    "Version": "2012-10-17",
    "Statement":[{
       "Effect": "Allow",
       "Action": ["ses:*"],
       "Resource":"*"
       }
    ]
 }
Chris
  • 103
  • 4