AWS Step FunctionsでMicrosoft Teamsに通知してみた

2024.06.27

はじめに

AWS Step Functionsを使ってMicrosoft Teamsに通知する方法について、構築手順をまとめました。

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

利用ケースとしては、以下が考えられます。

  • 障害検知時にTeamsに通知し、メンバーにメンションを飛ばす
  • バッチ処理の完了をTeamsに通知する

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

全体の構成は以下の通りです。HTTPタスクを利用してTeamsに通知します。

今回はStep Functionsを起点にMicrosoft Teamsに通知しますが、他のサービスからStep Functions経由で通知することも可能です。

Step Functionsを呼び出すことができるAWSサービスには、以下のようなものがあります。

  • AWS Lambda (StartExecution API を使用)
  • Amazon API Gateway
  • Amazon EventBridge
  • AWS CodePipeline
  • AWS IoT ルールエンジン
  • AWS Step Functions

Amazon EventBridge の一機能である Amazon EventBridge Pipes でも、ターゲットをStep Functionsに設定することが可能です。

ソースは以下が選択できます。

  • Amazon DynamoDB Streams
  • Amazon Kinesis Data Streams
  • Amazon MQ broker
  • Amazon MSK stream
  • Amazon SQS queue
  • Apache Kafka Streams

以上のように、様々なAWSサービスからStep Functionsを呼び出すことができます。

HTTPタスク

HTTPタスクは、Step Functionsの機能の1つで、Microsoft TeamsやSalesforceなどのサードパーティのAPIを直接呼び出すことができます。

HTTPタスクでは、API呼び出しの認証情報をEventBridge 接続で管理できるため、シークレットをステートマシン定義にハードコーディングすることを避けられます。

HTTPタスクを使用すると、以下のようなメリットがあります。

  • ステートマシン内から直接外部APIを呼び出せるため、Lambda関数を介さずにシンプルな構成にできる
  • API呼び出しの認証情報をEventBridge 接続で管理できるため、シークレットをステートマシン定義にハードコーディングすることを避けられる
  • リクエストとレスポンスのデータ変換や、リトライ、エラー処理などステートマシン内を柔軟に設定できる

HTTPタスクを使ったサードパーティAPI連携の全体の流れは以下のようになります。

  1. EventBridge 接続を作成し、API認証情報を設定する
  2. ステートマシン定義にHTTPタスクを追加し、APIエンドポイント、メソッド、ヘッダー、リクエスト本文などを設定する
  3. ステートマシンを実行すると、HTTPタスクがEventBridge 接続の認証情報を使ってAPIを呼び出す
  4. APIレスポンスはHTTPタスクの出力として後続のステートに渡される

このようにHTTPタスクを使うことで、Step FunctionsからサードパーティAPIを直接呼び出すことができます。

次節以降で、Microsoft TeamsへのWebhook通知を例に、具体的な実装方法を見ていきましょう。

TeamsのWebhookURLを取得

Teamsのチームの作成とWebhookURLの取得方法は以下の記事をご参考ください。

EventBridge 接続を作成

EventBridge 接続では、API キー名をContent-Type、キーの値をapplication/jsonと指定して作成します。

作成すると、EventBridge 接続の情報を保存するSecrets Managerのシークレットが自動作成されます。

Step Functions ステートマシンを作成

フローには、Call third-party APIのみを挿入します。

[設定]タブで以下の設定を行います。[入力]や[出力]、[エラー処理]タブはデフォルトのままです。

  • API エンドポイント:TeamsのWebhookURL
  • メソッド:POST
  • Authentication:EventBridge 接続

リクエスト本文は以下のとおりです。

{
  "type": "message",
  "attachments": [
    {
      "contentType": "application/vnd.microsoft.card.adaptive",
      "content": {
        "type": "AdaptiveCard",
        "body": [
          {
            "type": "TextBlock",
            "text": "<at>平井裕二</at>",
            "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.5",
        "msteams": {
          "width": "full",
          "entities": [
            {
              "type": "mention",
              "text": "<at>平井裕二</at>",
              "mentioned": {
                "id": "xxx@example.com",
                "name": "平井 裕二"
              }
            }
          ]
        }
      }
    }
  ]
}

Incoming WebhookでTeamsにメンション付きで通知するには、アダプティブカード形式で通知する必要がありますので、typeAdaptiveCardに設定します。

https://learn.microsoft.com/ja-jp/microsoftteams/platform/task-modules-and-cards/cards/cards-format?tabs=adaptive-md,desktop,connector-html

リクエスト本文のidnameは、メンション対象者に応じて変更してください。

  • id:ユーザーのメールアドレス(xxxx@example.com)を指定
  • name:ユーザー名(ユーザー名)を指定

メンションするには、ユーザー名を<at></at>で囲む必要があります

設定に遷移し、ステートマシン名を入力し、タイプは標準にします。また、実行ロールを[新しいロールを作成]にすると、先程選択したEventBridge 接続リソースに対するポリシーも自動作成されます。

ステートマシンの[作成]クリックすると、ステートマシン用のIAMロールのアクセス許可内容が確認できます。確認後、作成します。

ステートマシンのIAMロール

ステートマシンのIAMロールには以下の3つのポリシーが適用されていました。 3つのポリシーとも名前にランダムな文字列が含まれていますが、それぞれ異なる文字列です。

  • EventBridgeRetrieveConnectionCredentialsScopedAccessPolicy-[ランダム文字列]
    • EventBridge接続の認証情報を取得するためのポリシー
  • StepFunctionsInvokeHttpEndpointScopedAccessPolicy-[ランダム文字列]
    • HTTPタスクでTeamsのWebhookURLを呼び出すためのポリシー
  • XRayAccessPolicy-e012773e-dbcb-4a75-bee1-cbfc4e404683-[ランダム文字列]
    • X-Rayでトレースを行うためのポリシー

EventBridgeRetrieveConnectionCredentialsScopedAccessPolicy-[ランダム文字列]ポリシーの内容は以下の通りです。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Sid": "RetrieveConnectionCredentials1",
            "Action": [
                "events:RetrieveConnectionCredentials"
            ],
            "Resource": [
                "arn:aws:events:ap-northeast-1:xxxxxxxxxxxx:connection/stepfunctions-notify-teams/*"
            ]
        },
        {
            "Effect": "Allow",
            "Sid": "GetAndDescribeSecretValue1",
            "Action": [
                "secretsmanager:GetSecretValue",
                "secretsmanager:DescribeSecret"
            ],
            "Resource": [
                "arn:aws:secretsmanager:ap-northeast-1:xxxxxxxxxxxx:secret:events!connection/stepfunctions-notify-teams/*"
            ]
        }
    ]
}

StepFunctionsInvokeHttpEndpointScopedAccessPolicy-[ランダム文字列]ポリシーの内容は以下の通りです。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Sid": "InvokeHttpEndpoint1",
            "Action": [
                "states:InvokeHTTPEndpoint"
            ],
            "Resource": [
                "arn:aws:states:ap-northeast-1:xxxxxxxxxxxx:stateMachine:*"
            ],
            "Condition": {
                "StringEquals": {
                    "states:HTTPEndpoint": [
                        "WebhookURLの値"
                    ],
                    "states:HTTPMethod": [
                        "POST"
                    ]
                }
            }
        }
    ]
}

XRayAccessPolicy-e012773e-dbcb-4a75-bee1-cbfc4e404683-[ランダム文字列]

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "xray:PutTraceSegments",
                "xray:PutTelemetryRecords",
                "xray:GetSamplingRules",
                "xray:GetSamplingTargets"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

EventBridge接続、シークレット、WebhookURLがIAMポリシーに指定されているため、ステートマシン内のこれらの値を変更する場合は、IAMポリシーもあわせて修正する必要があります。

テスト

[実行を開始]をクリックします。実行の入力値は以下です。

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

以下のアクセス許可エラーが発生しました。

AWS Step Functions is not authorized to perform states:InvokeHTTPEndpoint on API Endpoint https://xxx.webhook.office.com/webhookb2/xxx. Ensure that the StateMachine role contains the states:InvokeHTTPEndpoint permission for the given API Endpoint

WebhookURLには@が含まれていましたが、エラーメッセージでは@%40にURLエンコードされていました。

そのため、ステートマシンのIAMポリシーで指定するWebhookURLの@%40に置き換えました。

置き換え後、再度実行すると、通知できていることが確認できました。

最後に

AWS Step FunctionsでMicrosoft Teamsに通知する構築方法を紹介しました。

柔軟なワークフローを組み立てながら、Teams通知を組み込めるのがStep Functionsの利点です。ぜひ活用してみてください。