1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

LambdaとSNSでTypetalkに通知する仕組みを作る

Last updated at Posted at 2021-09-02

8月上旬に WAF Managed rule への変更が SNS トピック( aws-managed-waf-rule-notifications )に対して通知される機能がリリースされた。
今回は、 Lambda を使って Typetalk にそれを通知する仕組みを作ってみる。

#使用するサービス
##Amazon SNS
アプリケーション間のメッセージ、HTTP、Eメール、スマホのプッシュ通知を行うことができる。
ユーザーアクションをトリガーにできる。
今回は aws-managed-waf-rule-notifications という SNS トピックを使用し、 Lambda 関数に通知する。

##AWS Lambda
サーバレスでプラグラムを実行できるサービス。
今回は SNS からの通知を受け Typetalk api を叩く。

##Typetalk bot
Type talk 上のボット、 Typetalk api を叩くことで動かすことができる。

#システム構成
Untitled.png

#作成手順
###Typetalk bot の作成
Typetalk の通知したいトピックで bot を作成する。
ボットの設定画面から Typetalk Token と 「メッセージの取得と投稿の URL」をメモする。

###関数ファイルの作成
pip を使用するので必要であればインストール。

Lambda にアップロードする関数を作成する。

~ % mkdir lambda
~ % cd lambda
lambda % pip install requests -t./
lambda % vim lambda_function.py
lambda_function.py
import requests
import json

token = '{Typetalk Token}'
url = '{メッセージの取得と投稿の URL}'

def lambda_handler(event, lambda_context):
    data = {'message':json.dumps(event, indent=2)}
    headers = {'X-TYPETALK-TOKEN': token}
    r = requests.post(url, json = data, headers = headers)
    print(r.status_code)
    print(r.json())
    None
lambda % zip -r lambda.zip ./

###Lambda 関数を作成
関数名を適当に設定し、ランタイムを Python に設定。
実行ロールはデフォルトを使用。
スクリーンショット 2021-09-02 17.34.06.png

SNS トピックに arn:aws:sns:us-east-1:248400274283:aws-managed-waf-rule-notifications を設定しトリガーを追加。
スクリーンショット 2021-09-02 17.39.01.png

lambda.zip ファイルをアップロードする。
スクリーンショット 2021-09-02 17.43.36.png

テストイベントを作成する。
テンプレートのsns-notificationを設定し、名前を適当に決めたらテストをクリック。
スクリーンショット 2021-09-02 17.47.28.png

以下の表示がでて、 Typetalk に Bot が投稿していれば成功。
スクリーンショット 2021-09-02 17.53.07.png

#補足
AWS document などを探したが SNS 通知の具体的な内容、テンプレートは見つけられなかった。
aws-managed-waf-rule-notifications がリリースされてから managed rule が変更されておらず、一度も SNS 通知は飛んでいない。
AWS サポートいわく提供可能なものはないとのこと。
そのため、通知をそのまま Typetalk に丸投げする仕組みにしてある。

###感想
Lambda をまともに触るのは初めてで、かなり不安があったがなんとか完成できた。
Lambda の使い方や、 api との連携方法などなど多くの学びがあった。
今回は上長からの指示で仕事として Lambda 関数を作成したが、私用でも( Discord api など )チャレンジしたくなった。

#追記 : 通知分の整形
先日aws-managed-waf-rule-notificationsが通知され、テンプレートを把握できたので整形してtypetalkに通知するようにlambda関数を変更する。

通知されたaws-managed-waf-rule-notificationsの平文。

{
  "Records": [
    {
      "EventSource": "aws:sns",
      "EventVersion": "1.0",
      "EventSubscriptionArn": "arn:aws:sns:us-east-1:248400274283:aws-managed-waf-rule-notifications:b228a2dd-d3c4-4100-b66d-605c15c67f73",
      "Sns": {
        "Type": "Notification",
        "MessageId": "e2c454b9-3391-5c55-b6ef-0d76464587f6",
        "TopicArn": "arn:aws:sns:us-east-1:248400274283:aws-managed-waf-rule-notifications",
        "Subject": "Notification of upcoming version release for AWSManagedRulesWordPressRuleSet",
        "Message": "We will be releasing a new version of the AWS Managed Rules (AMR) for AWS WAF. The new version will add label support for all AWS Managed Rules rule groups that don't already have labeling. This release doesn't include any rule signature changes.\n\nStarting next week, October 6, 2021, we will begin rolling out this new version. The rollout will be completed over a period of two weeks, with changes deployed incrementally across each Region. You will receive a final notification when this new version is available globally. If you use the default version of an AMR rule group, AWS WAF will automatically update you to the latest version. If you use a static version of a rule group, you can update the version to adopt these changes.\n",
        "Timestamp": "2021-09-30T08:21:40.082Z",
        "SignatureVersion": "1",
        "Signature": "NjZzvXRQZnsv0FfDUONU8NhxcxZPDxuI9t5nUeWbgEH8VDlFzMzrQ+F2y/PK3M2d3wP0+T8tFLrwc8b8zeTxlyGBCll/68daiRnFpyjU+5D9AkpUzcAPheDH+ZiIJa4xfjPx+tzXSERT6AhchpXLbW63VRP//+eDVk3tAyCs+QINHHLtUHOe5kMxv25YQRG15XSc8z3E09ouiYkzjlS6DLzUHws9gA/F0gDnfxzogWD5U9HyVGNrqhgbLiMsFkUB8CHpYdQ1XvhF8ufDGb8LSli9uuONGg/Jmg1M/2K14a6hN3Q36VCejOHo5HqJvHyiB7oIyp7VIWxaOY/0GT8Bdw==",
        "SigningCertUrl": "https://sns.us-east-1.amazonaws.com/SimpleNotificationService-7ff5318490ec183fbaddaa2a969abfda.pem",
        "UnsubscribeUrl": "https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:248400274283:aws-managed-waf-rule-notifications:b228a2dd-d3c4-4100-b66d-605c15c67f73",
        "MessageAttributes": {
          "major_version": {
            "Type": "String",
            "Value": "v1"
          },
          "managed_rule_group": {
            "Type": "String",
            "Value": "AWSManagedRulesWordPressRuleSet"
          }
        }
      }
    }
  ]
}

###整形方法
通知分に以下の処理を行う。

  1. 必要箇所の抽出
  2. 翻訳

必要なのはSubjectとMessageの部分なので、以下のように抽出する。

subject = event['Records'][0]['Sns']['Subject']
message = event['Records'][0]['Sns']['Message']

また、翻訳にはDeepL apiを使用した。

全ての機能を含めた最終的なlambda関数は以下のような感じになった。

lambda_function.py
import requests
import json
import os

#環境変数からtypetalkのアクセス情報を読み込む
token = os.environ.get('TOKEN')
url = os.environ.get('URL')

#通知の英語部分、日本語部分をグローバル変数で定義
text_en = ""
text_jp = ""

#環境変数からdeeplのアクセス情報を読み込む
deepl_token = os.environ.get('DEEPL_TOKEN')
deepl_url = os.environ.get('DEEPL_URL')

def lambda_handler(event, lambda_context):
    #SNS通知から必要箇所を抽出
    subject = event['Records'][0]['Sns']['Subject']
    message = event['Records'][0]['Sns']['Message']

    #通知の英語部を整形
    text_en = subject + '\n\n' + '> ' + message.replace('\n', '\n>')
    print(text_en)
    
    #deeplの設定
    params = {
            "auth_key": deepl_token,
            "text": message,
            "source_lang": 'EN',
            "target_lang": 'JA'
        }
    
    #deeplにリクエスト
    request = requests.post(deepl_url, data=params)
    result = request.json()
    
    #deeplの結果から通知の日本語部を整形
    text_jp = result["translations"][0]["text"]
    text_jp = '> ' + text_jp.replace('\n', '\n>')
    print(text_jp)
    
    #英語部、日本語部を連結し通知文を整形
    text_full = '[aws-managed-waf-rule-notifications]' + '\n' + text_en + '\n\n' + text_jp
    data = {'message':text_full}
    headers = {'X-TYPETALK-TOKEN': token}
    print(data)
    
    #typetalkにリクエスト
    r = requests.post(url, json = data, headers = headers)
    print(r.status_code)
    print(r.json())
    None

###課題
DeepL api からエラーが返ってきた場合の動作を追加する必要がある。

#参考資料
https://business.ntt-east.co.jp/content/cloudsolution/column-134.html

1
0
3

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
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?