LoginSignup
1
1

More than 3 years have passed since last update.

API GatewayからSNSトピックにメッセージ発行してメール通知

Last updated at Posted at 2020-05-24

Webhookで呼び出されたAPI Gatewayから、SNSにトピックを発行してメール通知する仕組みを作ってみました。本記事では簡単のため、Webhook役をcurlコマンドが演じています。

image.png

図中の四角数字は、以下手順の番号と対応しています。

【手順1】ロールの作成(IAM)

API GatewayのAPIにアタッチする用のロールを作成していきます。ユースケースから「API Gateway」を選択します。

image.png

ここでは、ロール名は「APIGatewayAWSProxyExecRole」とします。

ロール作成後はデフォルトで「AmazonAPIGatewayPushToCloudWatchLogs」がアタッチ済みとなっています。「AmazonSNSFullAccess」もアタッチしておきます。

image.png

【手順2】トピックの作成(SNS)

まず、トピックを作成します。トピック名は「MyTopic」とします。

image.png

つぎに、「サブスクリプションの作成」をクリックして、作成したトピックの購読設定を行います。

  • Eメールに通知する場合

    • プロトコルは「Eメール」を選択
    • エンドポイントにはSNSからの通知を受信するメールアドレスを入力
  • SMSに通知する場合

    • プロトコルは「SMS」を選択
    • エンドポイントにはSNSからの通知を受信する電話番号を入力(電話番号が日本の場合、「+81」の後に、電話番号先頭の0を除外した番号を入力する(例「08012345678」の場合「+818012345678」を入力))

最後に「サブスクリプションの作成」をクリックします。

image.png

「サブスクリプションの作成」をクリックしたタイミングで、Amazon SNSから「AWS Notification - Subscription Confirmation」という件名のメールが(上で入力したメールアドレス宛に)送信されますので、メールを開いてConfirmします。

【手順3】REST APIの作成(API Gateway)

API Gatewayで、REST APIを作成します。APIタイプは「REST API」を選択します。
image.png
API名は「MyAPI」としておきます。
image.png

APIのリソースとメソッドを作成します。
ここでは「/mail」リソースに対するPOSTメソッド、というインタフェースとしています。

image.png

  • 実行ロールには、【手順1】で作成したロールのARNを入力します。ARNは、IAMコンソールのロールから確認できます。
# 項目
1 統合タイプ AWSサービス
2 AWSリージョン (SNSトピックを作成したリージョン)
3 AWSサービス Simple Notification Service (SNS)
4 HTTPメソッド POST
5 アクション Publish
6 実行ロール arn:aws:iam::************:role/APIGatewayAWSProxyExecRole

次に、リクエストデータをバックエンド向け(SNS向け)に加工するため、統合リクエストの設定を行います。
「統合リクエスト」のリンクをクリックすると、設定画面が開きます。

image.png

統合リクエストの設定画面で、SNS向けにクエリ文字列を追加します。

image.png

# キー
1 Message method.request.body
2 TopicArn 'arn:aws:sns:ap-northeast-1:************:MyTopic'

TopicArnの値には、【手順2】で作成したSNSトピックのARNを指定します。ARNは、SNSのコンソール画面から確認できます。

設定保存後、「アクション」メニューの「デプロイ」をクリックして、デプロイを行います。
image.png

デプロイ後にURLが表示されますので、メモしておきます。
URLはhttps://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/test/mailの形式になります。

(補足)リソースポリシーの設定(API Gateway)

作成したAPIをデプロイ後はインターネットに公開されるため、誰でもアクセスできてしまいます。リクエスト元のIPアドレスを制限したい場合、リソースポリシーを定義することでアクセス元を制限することができます。

今回は、ホワイトリスト形式で登録します。以下をベースにして作成します。

  • Resourceは、本APIのARNを指定してください。
  • aws:SourceIPに、APIへのアクセスを許可するIPアドレスを指定してください。
リソースポリシー(ホワイトリスト形式)
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:ap-northeast-1:xxxxxxxxxxxx:xxxxxxxxxx/*/*/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "xxx.xxx.xxx.xxx"
                }
            }
        }
    ]
}

作成したリソースポリシーを、以下のテキストエリアにペーストして保存します。

image.png

リソースポリシーを保存し、APIをデプロイした後は、許可された送信元(IPアドレス)からのアクセスのみリクエストを受け付けます。
許可されない送信元からのアクセスに対しては、403 Forbiddenで以下のエラーメッセージが返されます。

403_Forbidden
{
  "Message": "User: anonymous is not authorized to perform: execute-api:Invoke on resource: arn:aws:execute-api:ap-northeast-1:************:**********/test/POST/mail"
}

リソースポリシーをテストする際、固定のグローバルIPをもつホストからリクエストを投げる必要がありますが、パブリックサブネットにEC2インスタンスを立てればいいですかね。

【手順4】REST API呼出しのテスト(curlコマンド)

今回作成したAPIを、curlコマンドで呼出してみます。

$ curl -X POST -H "Content-Type: application/json" -d '{"id":"1024", "name":"yz2cm"}' https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/test/mail

【手順2】で購読設定したメールアドレスに、メールが送信されているはずです。

  • 送信元はMyTopic <no-reply@sns.amazonaws.com>
  • 件名はAWS Notification Message固定。
SNSからの受信メール

{"id":"1024","name":"yz2cm"}

--
If you wish to stop receiving notifications from this topic, please click or visit the link below to unsubscribe:
https://sns.ap-northeast-1.amazonaws.com/unsubscribe.html?SubscriptionArn=arn:aws:sns:ap-northeast-1:xxxxxxxxxxxx:MyTopic:e9709da9-e2fc-4098-9b1b-89bcd50af664&Endpoint=foo@gmail.com

Please do not reply directly to this email. If you have any questions or comments regarding this email, please contact us at https://aws.amazon.com/support

コマンドの標準出力
{
    "PublishResponse": {
        "PublishResult": {
            "MessageId":"dbb7488c-6c45-5c31-8038-1fc87bc2f28d",
            "SequenceNumber":null
        },
        "ResponseMetadata": {
            "RequestId":"347548a3-f894-552f-a8ef-1fe7ef138b93"
        }
    }
}

参考ページ

本記事を書くにあたり、参考にさせていただいたページです。

1
1
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
1
1