「AWS LambdaからSMSを送りたい」と思い、こちらの記事「【AWS】Lambda+Amazon SNSでSMSを送信する - Qiita」を参考に実装していました。Lambdaへの権限を絞る時に少しつまづいたのでメモに残します。
結論を先に載せますと、こちらのStackOverflowの記事「Authorization when sending a text message using AmazonSNSClient - StackOverflow」を参考に解決しました。
つまづいたところ
SMSの送信にはAmazon SNSサービスのsns:Publish
権限を利用します。
しかし、この権限にはリソースの指定が必要です。
以下のような「全てのリソースへのアクセスを許可する」ポリシーを作れば解決しますが、これではアカウント・リージョンを絞らないまま、今回使わないSNSトピックに手が届いてしまいます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sns:Publish"
],
"Resource": "*"
}
]
}
では、「SMS用のトピックを作ればいい」、という話になります。これが可能な場合はもちろんそうすれば良いですが、今回はサブスクライブ先の電話番号を管理したくありませんでしたのでその方法は取りませんでした。
解決方法
以下のように、まず
・「全てのアカウント・リージョンのトピック」に対するPublish権限を拒否
した後、
・全てのリソースへのPublish権限を許可
することで解決しました。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": [
"sns:Publish"
],
"Resource": "arn:aws:sns:*:*:*"
},
{
"Effect": "Allow",
"Action": [
"sns:Publish"
],
"Resource": "*"
}
]
}
おまけ:電話番号が固定の場合(未検証)
「特定の電話番号に対し許可」する場合は、エラーメッセージから推測するに、以下の方法でできるのではないかな、と思います(未検証です)。
以下では、日本国内電話番号のみ許可しています。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sns:Publish"
],
"Resource": "+81*"
}
]
}
おまけ:CDK
CDK(TypeScript)ではこんな風に書きました。
- Node.js: 14.15.4
- CDK: 1.50.0
// 関数
public static createSMSPublishRoleStatement(): PolicyStatement[] {
// SNSトピックリソースへのPublishを全面禁止
const denyPolicy: PolicyStatement = new PolicyStatement({
effect: Effect.DENY,
actions: ["sns:Publish"],
resources: ["arn:aws:sns:*:*:*"],
});
// 電話番号でPublishできるよう許可
const allowPolicy: PolicyStatement = new PolicyStatement({
effect: Effect.ALLOW,
actions: ["sns:Publish"],
resources: ["*"],
});
return [denyPolicy, allowPolicy];
}
public static addPolicyStatementsToLambda(
lambdaFunc: LambdaFunction /*(Function as LambdaFunction)*/,
policyStatements: PolicyStatement[]
): void {
policyStatements.forEach((policyStatement: PolicyStatement) => {
lambdaFunc.addToRolePolicy(policyStatement);
});
}
// 実行
const smsPublishPolicyStatements: PolicyStatement[] = createSMSPublishRoleStatement();
addPolicyStatementsToLambda(
${"ポリシーを紐付けたいLambda"},
smsPublishPolicyStatements.concat([
${"他のポリシーステートメント"},
])
);