Edited at

API Gateway + Lambda で SNS にメッセージ投稿する

More than 3 years have passed since last update.

以前からかなり欲しかった機能だった API Gateway が us-east-1 等いくつかの region で利用可能になったので、早速使ってみました。

Amazon SNS にメッセージ投稿を行うと、

までは作ってあるので、後は NewRelic 等の監視サービスや独自監視ツールから Amazon SNS にメッセージを投げられれば、Amazon SNS をハブにしていろいろ連携できるようになります。

これまでは、


  • 自前で SNS の API を叩く


    • Webhook しか対応していないサービスは連携不可



  • Zapier 等のハブサービスを利用


    • 品質や応答速度がやや心配(見えない)



  • サーバを立てて HTTP ラッパーを実装する


    • サーバの維持、メンテナンスコストが問題



ぐらいしか選択肢がなかったのですが、API Gateway の登場で、自前でサーバを作らずに HTTP から Lambda を呼び出せるようになったので、AWS のサービスだけで完結できます。

今回は、試しに NewRelic の channel 設定で Webhook を追加し、Alert を Amazon SNS に投げてみます。


Lambda から SNS へ投稿するための Role を作成する

Lambda から Amazon SNS へ Publish するため、Role を新たに作成しておきます。


lambda_basic_execution を作成しているのであれば、既存のものに追加しても OK ですが、分けておいたほうがいいと思います。


自分は lambda_sns_execution として作成しました。

通常の権限に加えて、sns:Publish を有効にしておきます。

resource も特定の Topic を指定してしまったほうが安全でしょう。


Lambda function を作成する

まずは Lambda function の作成です。

package.json や gulpfile.coffee は、これまでのものとほぼ同じなので省略します。


必要な package が aws-sdk になるだけです。



src/index.coffee

topicArn = 'YOUR_TOPIC_ARN'

snsRegion = 'ap-northeast-1'

AWS = require 'aws-sdk'
AWS.config.update region: snsRegion
sns = new AWS.SNS()

exports.handler = (event, context) ->
params =
Message: JSON.stringify(default: JSON.stringify(event))
MessageStructure: 'json'
Subject: event.condition_name
TopicArn: topicArn

sns.publish params, (err, data) ->
if err
context.done null, err
return

context.done null, 'Post succeeded.'
return


gulp build でさくっと zip を作成、以下のコマンドで function を作成します。

aws --region us-east-1 lambda create-function \

--function-name lambda-newrelic-sns \
--runtime nodejs \
--role arn:aws:iam::xxxxxxxx:role/lambda_sns_execution \
--handler index.handler \
--description 'Send message to Amazon SNS' \
--timeout 3 \
--memory-size 128 \
--zip-file fileb://dist/lambda.zip


Amazon API Gateway から Lambda を呼び出す際、まだ東京リージョンの function は呼び出せませんので、us-east-1 で作成しておきます。



API Gateway を作成する

まずは、API Gateway に行き、必要であればリージョンを N.Virginia に変更しておきます。


API の作成

新規に API を作成します。

API が作成されたので、「Create Resource」を押してリソースを作成します。

/newrelic という endpoint が作成されたので、「Create Method」を押して、POST を選択。

すると、POST メソッドの設定画面になります。

Lambda Function を選択し、region を us-east-1 に、作成した Lambda function 名を入力します。


自動的に function の候補が表示されます。


最後に、以下の様な画面が表示されれば作成完了です。


API のデプロイ

作成した API はデプロイしないと有効になりません。「Deploy API」をクリックし、

適当に stage を作成します。

ここで作成した stage は、API のパスに含まれることになります。


「prod」と入力すると、ttps://xxxxxxxx.us-east-1.execute-api.com/prod/newrelic のようなパスになります。


これで API の利用準備が整いました。

Stages をたどると、API の URL が確認できます。


Lambda function 側の管理画面でも、「API endpoints」を選択すれば確認できます。



NewRelic の設定を行う

NewRelic にログインし、Alerts(beta) から、Notification Channels に行きます。

「New notification channel」から新規の通知チャネルを作成し、Webhook を選択、チャネルの名称及び、API の URL を入力します。

これで、NewRelic からの Alert 情報が POST で API に送信され、それが Amazon SNS に流れるようになります。


補足

現状のままだと、SNS の Message 形式を JSON データにしているため、メールや Slack への投稿時にそのまま JSON データがベタで表示されます。

また、きちんと運用するには Basic 認証等の機構を追加すべきですね。API Gatewayにもその設定がありますので。

NewRelic から投稿されるデータのフォーマットに合わせて、メッセージ内容をうまくカスタマイズすることで、より柔軟な通知が実現できます。

NewRelic から投稿されるデータのフォーマットは、こちらになります。

Customize your webhook payload