Webhookで呼び出されたAPI Gatewayから、SNSにトピックを発行してメール通知する仕組みを作ってみました。本記事では簡単のため、Webhook役をcurl
コマンドが演じています。
図中の四角数字は、以下手順の番号と対応しています。
【手順1】ロールの作成(IAM)
API GatewayのAPIにアタッチする用のロールを作成していきます。ユースケースから「API Gateway」を選択します。
ここでは、ロール名は「APIGatewayAWSProxyExecRole
」とします。
ロール作成後はデフォルトで「AmazonAPIGatewayPushToCloudWatchLogs
」がアタッチ済みとなっています。「AmazonSNSFullAccess
」もアタッチしておきます。
【手順2】トピックの作成(SNS)
まず、トピックを作成します。トピック名は「MyTopic」とします。
つぎに、「サブスクリプションの作成」をクリックして、作成したトピックの購読設定を行います。
-
Eメールに通知する場合
- プロトコルは「Eメール」を選択
- エンドポイントにはSNSからの通知を受信するメールアドレスを入力
-
SMSに通知する場合
- プロトコルは「SMS」を選択
- エンドポイントにはSNSからの通知を受信する電話番号を入力(電話番号が日本の場合、「+81」の後に、電話番号先頭の0を除外した番号を入力する(例「08012345678」の場合「+818012345678」を入力))
最後に「サブスクリプションの作成」をクリックします。
「サブスクリプションの作成」をクリックしたタイミングで、Amazon SNSから「AWS Notification - Subscription Confirmation」という件名のメールが(上で入力したメールアドレス宛に)送信されますので、メールを開いてConfirmします。
【手順3】REST APIの作成(API Gateway)
API Gatewayで、REST APIを作成します。APIタイプは「REST API」を選択します。
API名は「MyAPI」としておきます。
APIのリソースとメソッドを作成します。
ここでは「/mail」リソースに対するPOSTメソッド、というインタフェースとしています。
- 実行ロールには、【手順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向け)に加工するため、統合リクエストの設定を行います。
「統合リクエスト」のリンクをクリックすると、設定画面が開きます。
統合リクエストの設定画面で、SNS向けにクエリ文字列を追加します。
# | キー | 値 |
---|---|---|
1 | Message | method.request.body |
2 | TopicArn | 'arn:aws:sns:ap-northeast-1:************:MyTopic' |
TopicArn
の値には、【手順2】で作成したSNSトピックのARNを指定します。ARNは、SNSのコンソール画面から確認できます。
設定保存後、「アクション」メニューの「デプロイ」をクリックして、デプロイを行います。
デプロイ後に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"
}
}
}
]
}
作成したリソースポリシーを、以下のテキストエリアにペーストして保存します。
リソースポリシーを保存し、APIをデプロイした後は、許可された送信元(IPアドレス)からのアクセスのみリクエストを受け付けます。
許可されない送信元からのアクセスに対しては、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
固定。
{"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"
}
}
}
参考ページ
本記事を書くにあたり、参考にさせていただいたページです。