はじめに
DX 技術本部の yu-yama@sra です。
Amazon SNS を使用して VPC エンドポイント越しに SMS を送信しようとしたところ、
ややハマりしたので備忘メモを残します。
構成図
TL;DR
- SMS を送信する AWS リソースに設定している IAM ロールのポリシーに aws:SourceIp を使用していないか確認しましょう
- SMS メッセージの送信に支払うことのできる上限額 (USD)を超えていないか確認しましょう
ハマりその1 - 権限
AWS リソースに IAM ロールをアタッチして VPC エンドポイント越しに SMS の送信を試みていたが、権限エラーが発生しており、修正前ポリシーの設定は以下のようになっていた。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sns:ListPhoneNumbersOptedOut",
"sns:Publish",
"sns:SetSMSAttributes",
"sns:GetSMSAttributes",
"sns:OptInPhoneNumber",
"sns:CheckIfPhoneNumberIsOptedOut"
],
"Resource": "*",
"Condition": {
"IpAddress": {
"aws:SourceIp": "{AWSリソースの存在するサブネットのIPアドレスレンジ}"
}
}
}
]
}
調べたところ、
リクエスト実行元が Amazon VPC エンドポイントを使用するホストである場合、aws:SourceIp キーは使用できません。
引用:AWS グローバル条件コンテキストキー - AWS Identity and Access Management
とのことで aws:SourceIp キーが使えないらしいので、以下のように修正
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sns:ListPhoneNumbersOptedOut",
"sns:Publish",
"sns:SetSMSAttributes",
"sns:GetSMSAttributes",
"sns:OptInPhoneNumber",
"sns:CheckIfPhoneNumberIsOptedOut"
],
"Resource": "*"
}
]
}
すると、権限エラーが返却されなくなった
ハマりその2 - メッセージ送信上限額
上記権限問題修正後、メッセージ送信で 200 status
が返却されているのに SMS が届かない事象に遭遇。
Map<String, MessageAttributeValue> smsAttributes =
new HashMap<String, MessageAttributeValue>();
smsAttributes.put("AWS.SNS.SMS.SenderID", new MessageAttributeValue()
.withStringValue("mySenderID") //The sender ID shown on the device.
.withDataType("String"));
smsAttributes.put("AWS.SNS.SMS.MaxPrice", new MessageAttributeValue()
.withStringValue("0.50") //Sets the max price to 0.50 USD.
.withDataType("Number"));
smsAttributes.put("AWS.SNS.SMS.SMSType", new MessageAttributeValue()
.withStringValue("Promotional") //Sets the type to promotional.
.withDataType("String"));
AWSの提供しているAWS SDK for Java で、メッセージ属性値(上限価格を 0.50 USD、SMS 型をプロモーション)を設定しSMS メッセージを送信するサンプルコードまんまなのだが届かない。
ログを出力し確認したところ、
{
"notification": {
"messageId": "12345-6789-0123-456789012345",
"timestamp": "2020-12-25 00:00:00.000"
},
"delivery": {
"numberOfMessageParts": 10,
"destination": "+819012345678",
"priceInUSD": 0.7451,
"smsType": "Promotional",
"providerResponse": "This delivery would exceed max price",
"dwellTimeMs": 317,
"dwellTimeMsUntilDeviceAck": 862
},
"status": "FAILURE"
}
"This delivery would exceed max price"
と最大価格を超えている旨のメッセージが出力されていた...
現在0.5なので1に修正
Map<String, MessageAttributeValue> smsAttributes =
new HashMap<String, MessageAttributeValue>();
smsAttributes.put("AWS.SNS.SMS.SenderID", new MessageAttributeValue()
.withStringValue("mySenderID") //The sender ID shown on the device.
.withDataType("String"));
smsAttributes.put("AWS.SNS.SMS.MaxPrice", new MessageAttributeValue()
.withStringValue("1.00") //Sets the max price to 1.00 USD.
.withDataType("Number"));
smsAttributes.put("AWS.SNS.SMS.SMSType", new MessageAttributeValue()
.withStringValue("Promotional") //Sets the type to promotional.
.withDataType("String"));
すると、めでたく無事に送信されました...
まとめ
-
サンプルコードを無思考で使用するのはやめましょう
- サンプルコードはあくまでサンプルなので確実に動くことを保証するものではありません。使用する際は何を行っているか理解した上で使用しましょう。
-
ログをちゃんと読みましょう
- まずはログを読むこと。
ごくごく基本的なことが出来ていないためのハマりでした。基本は大切。