3
0

More than 3 years have passed since last update.

Amazon SNS で SMS を送信出来ないときに確認するところ

Last updated at Posted at 2020-12-15

はじめに

DX 技術本部の yu-yama@sra です。

Amazon SNS を使用して VPC エンドポイント越しに SMS を送信しようとしたところ、
ややハマりしたので備忘メモを残します。

構成図

SMS.png

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 が届かない事象に遭遇。

修正前Javaコード
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に修正

修正後Javaコード
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"));

すると、めでたく無事に送信されました...

まとめ

  • サンプルコードを無思考で使用するのはやめましょう

    • サンプルコードはあくまでサンプルなので確実に動くことを保証するものではありません。使用する際は何を行っているか理解した上で使用しましょう。
  • ログをちゃんと読みましょう

    • まずはログを読むこと。

ごくごく基本的なことが出来ていないためのハマりでした。基本は大切。

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0