AWS Step FunctionsとDynamoDBで、アカウントごとにTeamsでのメンション対象者を動的に変えてみた

AWS Step FunctionsとDynamoDBで、アカウントごとにTeamsでのメンション対象者を動的に変えてみた

Clock Icon2024.11.15

はじめに

以前、AWS Step Functionsを使ってMicrosoft Teamsに通知する方法について紹介しました。

https://dev.classmethod.jp/articles/aws-stepfunctions-notify-microsoft-teams/

今回は、ステートマシンにアカウントIDを渡すことで、通知先のメンション対象者を動的に変更する方法をご紹介します。

ステートマシンに加え、アカウントIDとメンション対象者をデータとして保存するため、Amazon DynamoDBを利用することで、実現可能です。

システム構成は以下の通りです。

cm-hirai-screenshot 2024-11-11 10.17.55

Step Functionsを使うことで、柔軟なワークフローを組み立てながら、Teams通知を組み込めるところが利点です。

利用ケースとしては、AWS Secuirty Hub管理アカウントでアラート時、Teamsでアカウント管理者にメンションを飛ばして通知する、などが考えられます。

通知画面は以下のイメージです。メンションを飛ばしています。

cm-hirai-screenshot 2024-11-11 10.14.23

TeamsのWebhookURL

Microsoft Teams内のOffice365コネクタが廃止されることが発表されたため、以下の記事を参考にワークフローからWebhookURLを発行しておく必要があります。

https://qiita.com/fukasawah/items/896c3638c203a973c2f0

以下のようなURLです。

EventBridge 接続を作成

以下の設定でEventBridge接続を作成します。

  1. 接続タイプ:「API KEY」を選択
  2. API キーの設定
    • キー名:Content-Type
    • キー値:application/json

cm-hirai-screenshot 2024-11-11 8.03.02

DynamoDB

DynamoDBテーブルを以下の設定で作成します。

  • テーブル名:TeamsWebhookSettings
  • パーティションキー:AccountId(文字列型)
    cm-hirai-screenshot 2024-11-08 9.08.31

項目は以下の通り作成します。

{
  "AccountId": {
    "S": "111111111111"
  },
  "MentionedEmail": {
    "S": "[email protected]"
  },
  "MentionedName": {
    "S": "テストユーザー1"
  }
}

cm-hirai-screenshot 2024-11-11 9.59.18

ステートマシンを作成

ステートマシンのフローには、以下の2つのステートを追加します。

  • DynamoDB GetItem:DynamoDBからデータを取得
  • Call third-party API:Teamsへの通知を実行
    cm-hirai-screenshot 2024-11-11 9.51.04

DynamoDB GetItemは、以下の通り設定します。

  • 状態名:Get DynamoDB Data
  • 統合タイプ:Optimized
  • API パラメータ:以下の通り
{
  "TableName": "TeamsWebhookSettings",
  "Key": {
    "AccountId": {
      "S.$": "$.accountId"
    }
  }
}

cm-hirai-screenshot 2024-11-11 9.51.15

取得したDynamoDBデータを次のフローに渡します。

  • ResultPath を使用して元の入力を出力に追加
    • Combine original input with result:$.dynamoData
      cm-hirai-screenshot 2024-11-11 9.51.20

続いてCall third-party APIを設定します。

  • メソッド:POST
  • 認証:先ほど作成したEventBridge接続
  • リクエスト本文
{
  "type": "message",
  "attachments": [
    {
      "contentType": "application/vnd.microsoft.card.adaptive",
      "content": {
        "type": "AdaptiveCard",
        "body": [
          {
            "type": "TextBlock",
            "text.$": "States.Format('<at>{}</at>', $.dynamoData.Item.MentionedName.S)",
            "weight": "bolder",
            "size": "medium"
          },
          {
            "type": "TextBlock",
            "text": "アラートを検知しました",
            "size": "Large",
            "weight": "Bolder"
          },
          {
            "type": "Table",
            "columns": [
              {
                "width": 1
              },
              {
                "width": 2
              }
            ],
            "rows": [
              {
                "type": "TableRow",
                "cells": [
                  {
                    "type": "TableCell",
                    "items": [
                      {
                        "type": "TextBlock",
                        "text": "項目",
                        "weight": "Bolder"
                      }
                    ]
                  },
                  {
                    "type": "TableCell",
                    "items": [
                      {
                        "type": "TextBlock",
                        "wrap": true,
                        "text": "内容"
                      }
                    ]
                  }
                ]
              },
              {
                "type": "TableRow",
                "cells": [
                  {
                    "type": "TableCell",
                    "items": [
                      {
                        "type": "TextBlock",
                        "text.$": "$.item",
                        "weight": "Bolder"
                      }
                    ]
                  },
                  {
                    "type": "TableCell",
                    "items": [
                      {
                        "type": "TextBlock",
                        "wrap": true,
                        "text.$": "$.content"
                      }
                    ]
                  }
                ]
              }
            ]
          }
        ],
        "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
        "version": "1.4",
        "msteams": {
          "width": "full",
          "entities": [
            {
              "type": "mention",
              "text.$": "States.Format('<at>{}</at>', $.dynamoData.Item.MentionedName.S)",
              "mentioned": {
                "id.$": "$.dynamoData.Item.MentionedEmail.S",
                "name.$": "$.dynamoData.Item.MentionedName.S"
              }
            }
          ]
        }
      }
    }
  ]
}

WebhookUrlの形式は以下のとおりです。

対してCall third-party APIでは以下の通り分割します。

cm-hirai-screenshot 2024-11-11 9.57.19
cm-hirai-screenshot 2024-11-11 9.57.10
補足:WebhookUrlを柔軟に変更したい場合は、DynamoDBテーブルに新しい項目として追加することをするとよいです。

ステートマシン全体のコードは以下の通りです。

(クリックで展開)
{
  "Comment": "Teams Webhook Notification State Machine",
  "StartAt": "Get DynamoDB Data",
  "States": {
    "Get DynamoDB Data": {
      "Type": "Task",
      "Resource": "arn:aws:states:::dynamodb:getItem",
      "Parameters": {
        "TableName": "TeamsWebhookSettings",
        "Key": {
          "AccountId": {
            "S.$": "$.accountId"
          }
        }
      },
      "ResultPath": "$.dynamoData",
      "Next": "Call Teams Webhook"
    },
    "Call Teams Webhook": {
      "Type": "Task",
      "Resource": "arn:aws:states:::http:invoke",
      "Parameters": {
        "Method": "POST",
        "Authentication": {
          "ConnectionArn": "arn:aws:events:ap-northeast-1:xxxxxxxxxxxx:connection/teams/95886171-4978-49f4-93b7-b89b427ed190"
        },
        "ApiEndpoint": "https://prod-xx.japaneast.logic.azure.com/workflows/xxxxxx/triggers/manual/paths/invoke",
        "QueryParameters": {
          "api-version": "2016-06-01",
          "sp": "/triggers/manual/run",
          "sv": "1.0",
          "sig": "xxxxxx-xxxxx"
        },
        "RequestBody": {
          "type": "message",
          "attachments": [
            {
              "contentType": "application/vnd.microsoft.card.adaptive",
              "content": {
                "type": "AdaptiveCard",
                "body": [
                  {
                    "type": "TextBlock",
                    "text.$": "States.Format('<at>{}</at>', $.dynamoData.Item.MentionedName.S)",
                    "weight": "bolder",
                    "size": "medium"
                  },
                  {
                    "type": "TextBlock",
                    "text": "アラートを検知しました",
                    "size": "Large",
                    "weight": "Bolder"
                  },
                  {
                    "type": "Table",
                    "columns": [
                      {
                        "width": 1
                      },
                      {
                        "width": 2
                      }
                    ],
                    "rows": [
                      {
                        "type": "TableRow",
                        "cells": [
                          {
                            "type": "TableCell",
                            "items": [
                              {
                                "type": "TextBlock",
                                "text": "項目",
                                "weight": "Bolder"
                              }
                            ]
                          },
                          {
                            "type": "TableCell",
                            "items": [
                              {
                                "type": "TextBlock",
                                "wrap": true,
                                "text": "内容"
                              }
                            ]
                          }
                        ]
                      },
                      {
                        "type": "TableRow",
                        "cells": [
                          {
                            "type": "TableCell",
                            "items": [
                              {
                                "type": "TextBlock",
                                "text.$": "$.item",
                                "weight": "Bolder"
                              }
                            ]
                          },
                          {
                            "type": "TableCell",
                            "items": [
                              {
                                "type": "TextBlock",
                                "wrap": true,
                                "text.$": "$.content"
                              }
                            ]
                          }
                        ]
                      }
                    ]
                  }
                ],
                "$schema": "http://adaptivecards.io/schemas/adaptive-card.json",
                "version": "1.4",
                "msteams": {
                  "width": "full",
                  "entities": [
                    {
                      "type": "mention",
                      "text.$": "States.Format('<at>{}</at>', $.dynamoData.Item.MentionedName.S)",
                      "mentioned": {
                        "id.$": "$.dynamoData.Item.MentionedEmail.S",
                        "name.$": "$.dynamoData.Item.MentionedName.S"
                      }
                    }
                  ]
                }
              }
            }
          ]
        }
      },
      "End": true
    }
  }
}

ステートマシン名を記載し、作成します。

cm-hirai-screenshot 2024-11-08 9.34.40
ステートマシン用のIAMロールは。IAMポリシーも含め自動で作成されます。
cm-hirai-screenshot 2024-11-08 9.36.11

試してみる

以下のJSONデータを使用してステートマシンを実行します。

{
  "item": "test",
  "content": "hoge",
  "accountId": "111111111111"
}

通知されました。
cm-hirai-screenshot 2024-11-11 10.11.28

以下のように、入力JSONのアカウントIDを変更するだけで、Teams上での通知先を動的に切り替えることができます。これにより、アカウントごとに適切な担当者への通知が可能になります。

{
  "item": "test2",
  "content": "hoge2",
  "accountId": "000000000000"
}

cm-hirai-screenshot 2024-11-11 10.17.55

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.