Search code examples
amazon-web-servicesauthorizationamazon-ses

How do I create a Deny From All Except List SES Authorization Policy?


I'm using AWS SES to send emails from several different platforms. I need to lock down our domain's verified identity to only allow sends from a list of specific from addresses.

I hit two main problems when trying to make this work:

  1. If I combine a Deny policy with an Allow policy then only the first address in the FromAddress condition is permitted to send. All others return an error.
  2. If I do not include a Deny policy then all addresses are allowed to send, even addresses not in the list of permitted email addresses.

Below is an example of a combined Deny + Allow policy that I tried. I went through AWS documentation a ton to determine what's permitted. From what I can tell the FromAddress condition supports arrays (AWS lists), and using ForAnyValue:StringEquals should work like an OR operator. I'm probably missing something simple.

{
"Version": "2012-10-17",
"Statement": [
    {
        "Sid": "stid",
        "Effect": "Deny",
        "Principal": {
            "AWS": "*"
        },
        "Action": [
            "ses:SendEmail",
            "ses:SendRawEmail",
            "ses:SendTemplatedEmail",
            "ses:SendBulkTemplatedEmail"
        ],
        "Resource": "arn:this-is-too-secret",
        "Condition": {}
    },
    {
        "Sid": "stid2",
        "Effect": "Allow",
        "Principal": {
            "AWS": "*"
        },
        "Action": [
            "ses:SendEmail",
            "ses:SendRawEmail",
            "ses:SendTemplatedEmail",
            "ses:SendBulkTemplatedEmail"
        ],
        "Resource": "arn:this-is-too-secret",
        "Condition": {
            "ForAnyValue:StringEquals": {
                "ses:FromAddress": [
                    "example1@domain.com",
                    "example2@domain.com",
                    "example3@domain.com",
                    "example4@domain.com",
                    "example5@domain.com"
                ]
            }
        }
    }
]
}

Solution

  • Looking back, I should have seen this sooner. You can accomplish this using Deny, ForAllValues, and StringNotEquals. Essentially, if the provided FromAddress equals any in the list it will fail the StringNotEquals condition, which will invert the Deny, and allow the email to go through.

    {
    "Version": "2012-10-17",
    "Statement": [
    {
      "Sid": "stid",
      "Effect": "Deny",
      "Principal": {
        "AWS": "*"
      },
      "Action": [
        "ses:SendEmail",
        "ses:SendRawEmail",
        "ses:SendTemplatedEmail",
        "ses:SendBulkTemplatedEmail"
      ],
      "Resource": "arn:this-is-too-secret",
      "Condition": {
        "ForAllValues:StringNotEqualsIgnoreCase": {
          "ses:FromAddress": [
                "example1@domain.com",
                "example2@domain.com",
                "example3@domain.com",
                "example4@domain.com",
                "example5@domain.com"
            ]
        }
      }
    }
    ]
    }