最近,我有机会设置 Amazon Simple Email Service(以下简称:SES)的认证策略,所以这次写下来作为备忘。
前言
Amazon Simple Email Service(SES)是一项通过 API 端点或 SMTP 接口进行邮件发送的服务。为了使用 SES,您需要创建一个经过验证的 ID,可以是电子邮件地址或域名。只要 ID 状态显示为"已验证",即可使用。
认证策略可以通过经过验证的 ID 详细页面上的"认证"标签进行设置。通过以 JSON 格式设置特定已验证 ID 的允许或拒绝的 API 操作及其条件,您可以定义和限制每个已验证 ID 的使用方式。
本文将介绍认证策略的使用案例和设置示例。
限制发件人地址
当您希望使用no-reply等无法实际接收邮件的发件人地址时,可以将域名注册为已验证ID。注册域名为已验证ID后,无需单独验证电子邮件地址,您可以从该已验证域名的任意子域名或电子邮件地址发送邮件。然而,这样会导致一些不打算在生产环境中使用的电子邮件地址(例如test-case123-20240730@example.net)也能作为发件人地址使用。为了防止这种情况,可以使用策略来限制发件人。
以下示例中,发件人被限制为no-reply@example.net。
策略示例
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "stmt1721805312724",
"Effect": "Deny",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": [
"ses:SendEmail",
"ses:SendRawEmail"
],
"Resource": "arn:aws:ses:us-west-2:123456789012:identity/example.net",
"Condition": {
"StringNotLike": {
"ses:FromAddress": "no-reply@example.net"
}
}
}
]
}
通过这种方式,可以防止使用意图之外的电子邮件地址进行邮件发送。
$ aws ses send-email --from test-case123-20240730@example.net --to mail-to@example.org --subject subject --text body
An error occurred (AccessDenied) when calling the SendEmail operation: User `arn:aws:sts::123456789012:assumed-role/role-for-ec2/i-085d53c347635f98a' is not authorized to perform `ses:SendEmail' on resource `arn:aws:ses:us-west-2:123456789012:identity/example.net'
限制邮件的发送目标域
所有新账户最初都会被放置在沙盒环境中,邮件的发送目标被限制为已验证的电子邮件地址或域名。因此,未验证的目标地址不会接收到邮件,所以通常情况下很少需要限制发送目标。不过,对于已经进行上限提升(从沙盒中删除账户)的账户来说,则不受此限制。通过向AWS申请上限提升,账户可以向未验证的电子邮件地址或域名发送邮件。
在沙盒环境中,发送配额为每24小时200封邮件,发送速率为每秒1封邮件。这些限制也可以通过申请上限提升来提高。在提高发送配额和发送速率的同时,如果还希望限制发送目标,可以使用认证策略来实现。
以下示例中,发送目标被限制为*@example.org。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "stmt1721805435092",
"Effect": "Deny",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": [
"ses:SendRawEmail",
"ses:SendEmail"
],
"Resource": "arn:aws:ses:us-west-2:123456789012:identity/example.net",
"Condition": {
"ForAllValues:StringNotLike": {
"ses:Recipients": "*@example.org"
}
}
}
]
}
限制发件人的IP地址
如果不允许与外部通信,并且希望在私有子网内进行邮件发送处理,则可以通过指定IP地址来限制发件人。
以下示例中,发件人被限制为仅允许来自172.31.0.0/16的IP地址。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "stmt1721803415601",
"Effect": "Deny",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
"Action": [
"ses:SendEmail",
"ses:SendRawEmail"
],
"Resource": "arn:aws:ses:us-west-2:123456789012:identity/example.net",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": "172.31.0.0/16"
}
}
}
]
}
实际上,我在创建了VPC端点的私有子网中设置了CIDR,并尝试了不通过互联网的邮件发送。
$ aws ses send-email --from mail-from@example.net --to mail-to@example.org --subject subject --text body
Connect timeout on endpoint URL: "https://email.us-west-2.amazonaws.com/"
结果是无法到达 API 端点并超时。官方文档中记录了使用 SMTP 接口连接 SES 的 VPC 端点的步骤。实际上,SES 的 VPC 端点只支持 SMTP 接口,不提供 API 的 VPC 端点。因此,如果不能允许外部通信并希望在私有子网内进行邮件发送处理,就需要使用 SMTP 实现。使用 SMTP 接口有与使用 API 不同的地方,下面简要总结了这些不同之处。
利用 | 通信要件 | 権限付与 | 実装 |
---|---|---|---|
API | 互联网 | 向附加到发送电子邮件的服务(例如 EC2 或 ECS)的 IAM 角色授予权限 | 直接发出 HTTPS 请求 使用 AWS 开发工具包 使用 AWS CLI |
SMTP | 互联网 VPC端点 | 发布并使用访问密钥/秘密密钥作为 SMTP 认证信息 | 使用支持 SMTP 的软件 使用 SMTP 兼容语言进行编程 |
总结
以上、SES 的批准策略尝试总结。个人认为,SES 在 AWS 服务中虽然相对容易导入和验证,但也更容易导致安全事件。希望这能成为大家思考批准策略以防止意外邮件发送的契机。