18
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

posted at

updated at

Organization

ないのなら作ってしまおう、Microsoft Teams 向け AWS Chatbot っぽいもの

AWS Chatbot とは

ざっくりと言ってしまうと、AWS上で起きた事象を Slack や Amazon Chime に通知したり、スラッシュコマンドなどで操作できたりするものです。

本稿執筆時点では、ベータ版のため、この資料1.10 Beta Service Participation に則り、これ以上の言及は致しません。

背景

現時点では、Slack と Amazon Chime のみの対応のため、Microsoft Teams 用として AWS Chatbot っぽいものを作ろうということです。

ベータが外れたころに採用されてるといいなぁと願いながら...

レシピ

登場人物

  • Microsoft Teams
  • AWS Lambda
  • Amazon SNS
  • Amazon CloudWatch

Slackでいうところのスラッシュコマンドのようなものを実装するなら Amazon API Gateway も使います。

Microsoft Teams の設定

AWS からの通知を受け付ける設定をします。
通知を受け付けたいチームのチャネル右側の[...]をクリックします。
image.png

すると、以下のようなメニューが表示されるので[コネクタ]をクリックします。
image.png

コネクタの一覧が表示されたら[Incoming Webhook] の構成ボタンをクリックします
image.png

次に任意の名称を付けます。
image.png

最後にお好みに応じてイメージをアップロードして、「作成」ボタンをクリックします
image.png

作成が完了すると、AWS からの通知を受け付けるURLが生成されるので、コピーして控えておきます。作業が終わったら[完了]ボタンで閉じます。
このURLは後続の AWS Lambda上のコードに使用します。
image.png

URL を控えるのを忘れても、再度、コネクタの画面を表示し、左側の「構成済み」からたどることができます。
image.png

コネクタが作られたチャネルには、以下のような記事がポストされます。
image.png

AWS Lambda 上のコード

※今回は、CloudWatch メトリクスのアラームを受けて、それを Microsoft Teamsに送付するサンプルです。
※Lambdaに入っていないモジュールとして、PIL(pillow) と requests を使用しています。
※適宜配置してください。
※Python3.8 で動作確認しています。

lambda_function.py
import boto3
import json
import io
import base64
from PIL import Image
from io import BytesIO
import requests

teams_endpoint = 'Microsoft Teamsの設定で控えておいたURLを指定する'
# URLは必用に応じてKMSなどを利用して暗号化したり、環境変数機能をご利用ください。

def lambda_handler(event, context):
    subjet = event['Records'][0]['Sns']['Subject']

    # SNS が送信するJson内のMessage要素以下はStringなのでJsonとして読み込む
    message = json.loads(event['Records'][0]['Sns']['Message'])

    newStateReason = message['NewStateReason']
    newStateValue = message['NewStateValue']
    nameSpace = message['Trigger']['Namespace']
    metricName = message['Trigger']['MetricName']
    topicName =  event['Records'][0]['Sns']['TopicArn'].split(':')[5]
    resourceId = message['Trigger']['Dimensions'][0]['value']
    resourceType = message['Trigger']['Dimensions'][0]['name']

    # Microsoft Teams にポストする内容をつくる
    text = []
    text.append(newStateReason)
    text.append("\r\n\r\n")
    text.append("**Alarm State:** {0}          **Name Space:**: {1}".format(newStateValue, nameSpace))
    text.append("**Metric:** {0}          **Topic Name:** {1}".format(metricName, topicName))
    text.append("\r\n\r\n")

    # 対象のメトリック画像を取得する
    cw = boto3.client('cloudwatch')
    widget = '{\
            "view": "timeSeries",\
            "stacked": false,\
            "metrics": [\
                [ "'+ nameSpace +'", "'+ metricName +'", "'+ resourceType + '", "' + resourceId +'" ]\
            ], \
            "width": 480,\
            "height": 180,\
            "start": "-PT2H",\
            "end": "P0D",\
            "timezone": "+0900"\
        }'

    response = cw.get_metric_widget_image(MetricWidget = widget)
    img = Image.open(BytesIO(response["MetricWidgetImage"]))

    # メモリ上に画像を格納するおまじない
    buffer = io.BytesIO()
    img.save(buffer,"PNG")

    # メモリ上に保存した画像をBASE64エンコードする
    imgBase64 = base64.b64encode(buffer.getvalue()).decode().replace("'", "")

    # BASE64エンコードした文字列を Microsoft Teams へ送信する内容に追加
    text.append("![Chart](data:image/png;base64,{0})".format(imgBase64))

    # Microsoft Teams へ送信する下ごしらえ
    request = {
        'title': subjet,
        'text': '\r\n\r\n'.join(text)
        }

    # Microsoft Teams へ送信する
    response = requests.post(teams_endpoint, json.dumps(request))

Amazon SNS の設定

トピックの作成

Amazon SNS の画面を表示させ、[トピックの作成]ボタンをクリックします。
image.png
名前や表示名を指定します。その他必要な設定があれば実施し、[トピックの作成]ボタンをクリックします。
image.png

サブスクリプションの作成

トピックの作成が完了すると、以下の画面が表示されるので、[サブスクリプションの作成]ボタンをクリックします。
image.png
プロトコルに「AWS Lambda」を選択します。
そして、エンドポイントで先ほど作成した AWS Lambda の Lambda関数を指定し、その他必要に応じて設定を行い、[サブスクリプションの作成]ボタンをクリックします。
image.png

Amazon CloudWatch アラームの設定

Amazon CloudWatch の画面を表示し、左側にある「アラーム」をクリックします。
アラームの一覧が表示されたら、[アラームの作成]ボタンをクリックします。
image.png

[メトリクスの選択]ボタンをクリックします。
image.png

フィルタ条件を指定するフィールドに、通知したいEC2インスタンスのインスタンスIDを指定し、Enterキーを押します。
すると、以下のように EC2>インスタンス別メトリクス のみになるのでクリックします。
image.png

通知したいメトリクスを選択します。この例では、CPUUtilization (CPU使用率)を選択しています。
選択したら、画面下部の[メトリクスの選択]ボタンをクリックします
image.png

メトリクスの条件設定を行います。
通知したい条件を設定します。この例では、CPU 使用率が 80 を超えたら通知が出るようにしています。
[次へ]ボタンをクリックして進めます。
image.png

SNS トピックは先ほど作成したものを利用するので、
[既存の SNS トピックを選択]を選択します。
そして、[通知の送信先]に作成したものを指定します。
[次へ]ボタンをクリックして進めます。
image.png

アラームの名称を指定します。任意のもので構いません。
[次へ]ボタンをクリックします。
image.png

プレビューと作成画面が表示されるので、設定内容を確認して、
image.png
画面をスクロースして、[アラームの作成]ボタンをクリックします。
image.png

テスト

色々と設定が終わったら、Cloudwatch アラームを発火させます。
アラームを設定した EC2 インスタンスが Linux であれば、以下のコマンドを実行することで、簡単にCPU使用率をあげることができます。

sudo yes >> /dev/null &
[1] 10968

少し待つと、 Microsoft Teams 以下のような記事が追加されます。
image.png

テストが終わったら、プロセスを kill してください。

まとめ

コミュニケーション基盤が Slack や Amazon Chime ではなく Microsoft Teams のため、すぐに AWS Chatbot の恩恵にあずかれない!と悲しんでいる方も、この作例をもとに、ニッコリ笑顔になっていただけたら幸いです。

参考資料

https://hacknote.jp/archives/51333/
https://qiita.com/m_hama123/items/c40c8f5271ca03fc57e9

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
18
Help us understand the problem. What are the problem?