📉

Step FunctionsのHTTPSエンドポイントを活用してSendGridのレピュテーションを閾値監視する

2024/02/05に公開

はじめに

AWS re:Invent 2023で発表されたStep FunctionsのHTTPSエンドポイントを使うと、Step Functionsから外部のAPIにリクエストを行うに際し、Lambdaを利用する必要がありません

本記事はこの機能の活用例を紹介します。

やったこととその構成図

メール配信サービスであるSendGridでは、管理画面やAPIでレピュテーションを確認することができます。

このレピュテーションを閾値監視したかったのですが、レピュテーションが一定の値を下回った場合にアラートする(メールやSlackで通知する)ような機能はSendGrid上には見当たりませんでした。

そこで、以下の仕組みを構築することにしました。

  1. 定期的にSendGridのAPIからレピュテーションを取得する(Step FunctionsのHTTPSエンドポイントを利用)
  2. 上記のレピュテーションの値をAWSのCloudWatchメトリクス化する(Step Functionsを利用)
  3. 上記メトリクスをClouWatch Alarmで閾値監視し、閾値を下回ったらSNS & AWS Chatbot経由でSlack通知する

構成図としては以下になります。

Step FunctionsのHTTPSエンドポイントとは

EventBridgeには、2021年からAPI destinationという機能があります。AWS外の任意のWeb APIにリクエストを行える機能です。そして、EventBridge API destinationを使うには、EventBridge connectionというものを作成する必要があり、これは接続先APIの認証情報を設定、管理するものとなります。認証情報の実体はSecrets Managerに格納されます。

Step FunctionsのHTTPSエンドポイントというものは、このEventBridge connectionを活用した機能です。

この辺りの概念は、マネジメントコンソールのStep Functionsの画面で、HTTPSエンドポイントを設定する際に表示される説明が最もわかりやすく、そちらを使って解説します。以下の画面の「その理由をご覧ください」を押してみてください。

すると、以下の図と解説が表示されます。

Step FunctionsのHTTP(S)エンドポイントは、EventBridge connectionを使って外部のAPIにリクエストを行う流れであることや、EventBridge connectionの裏側にはSecrets Managerが存在し、これがAPIの認証に利用されることがわかります。

HTTPタスクは、APIプロバイダへの認証クレデンシャルを安全に管理するために、EventBridge connectionリソースを必要とします。connectionを使用すると、API キーなどの秘密をステートマシン定義にハードコードするのを避けることができます。代わりに、connectionを作成するときに認証の詳細を提供し、connection ARNをステートマシン定義に含めます。
同じconnection ARNを、APIプロバイダーを呼び出すすべてのHTTPタスクで再利用できます。EventBridge connectionは、Basic、OAuth、およびAPI Keyの認証スキームをサポートします。EventBridgeは裏でAWS Secrets Managerを使用してシークレットを管理します。

SendGridのレピュテーションとは

管理画面では以下にパーセンテージ表示されている値です。

公式のドキュメントでは以下の通り説明されています(日本語は機械翻訳したもの)。

The reputation score is based on your bounces, blocks, spam, invalid emails, and successfully delivered emails.
レピュテーションスコアは、バウンス、ブロック、スパム、無効メール、正常に配信されたメールに基づいています。
https://docs.sendgrid.com/glossary/account-reputation-dashboard

APIでは以下のように取得することができます。その際、どのサブユーザーのレピュテーションなのかをusernamesに指定する必要があります。

curl -X GET "https://api.sendgrid.com/v3/subusers/reputations?usernames={usernames}" \
--header "Authorization: Bearer <<YOUR_API_KEY_HERE>>"

以下はレスポンスの例です。

[
  {"reputation":99.88289382373353,"username":"example"}
]

APIの仕様の詳細は以下を参照ください。

サブユーザーの概念は以下を参照ください。

SendGridのAPIキーを発行する

ここから先は、閾値監視の仕組み作成について解説していきます。

まず、ブラウザでhttps://app.sendgrid.com/settings/api_keysにアクセスし、APIキーを作成します。

APIキーの権限は、Subusersの読み取り権限のみあれば充分です。

キーを作成したら、表示されたキーの値を控えてください。後でEventBridge connectionを作成する際に必要となります。

EventBridge connectionを作成する

AWSのマネジメントコンソールで、

  1. EventBridge
  2. APIの送信先
  3. 「接続」タブ

と画面遷移することでEventBridge connectionの画面が表示されるので、「接続を作成」ボタンを押します。

次に表示された画面では、

  • 送信先タイプ: その他
  • 認証タイプ: APIキー

を選択し、

  • APIキー名: Authorization
  • 値: Bearer 先ほどSendGridの画面に表示されていたキーの値

を入力して、作成ボタンを押します。

Secrets Managerが自動作成される

EventBridge connectionを作成したことで、認証情報を格納したSecrets Managerが自動作成されます。

Secrets Managerの値を見ると、以下の通り、先ほど入力したAPIキー名(ヘッダー名)と値が格納されていることがわかります。

{
  "api_key_name":"Authorization",
  "api_key_value":"Bearer SG.xxx...",
  "invocation_http_parameters":{}
}

なお、Secrets ManagerのTerraform管理に関してですが、EventBrdige connectionによって自動作成されることもあり、管理対象外としました。

Step Functionsの作成

Step Functionsの構成は非常にシンプルで、

  1. HTTP(S) Endpoint
  2. CloudWatchのPut Metric Data

を順に実行する流れとなります。

HTTP(S) Endpointの作成

HTTP(S) Endpoint作成のポイントは以下です。

  • APIエンドポイント: https://api.sendgrid.com/v3/subusers/reputations
  • Authentication: 作成済みのEventBridge connectionをプルダウンから選択

また、任意でクエリパラメータを設定できますが、どのサブユーザーのレピュテーションを取得するのかをusernamesに指定する必要があるので、以下の通り入力します。

{
  "usernames": "<< subuser name >>"
}

<< subuser name >>には実際のサブユーザー名を入力してください。

CloudWatchメトリクスの作成

CloudWatchメトリクスの作成にあたっては、CloudWatchのPutMetricDataを選択し、以下を入力します。

Namespace, Dimensions, MeticNameはあくまで一例なので参考にしてください。

{
  "MetricData": [
    {
      "Dimensions": [
        {
          "Name": "Username",
          "Value.$": "$[0].username"
        }
      ],
      "MetricName": "Reputation",
      "Unit": "Percent",
      "Value.$": "$[0].reputation"
    }
  ],
  "Namespace": "SendGrid"
}

ASL

Step Functionsのステートマシンを表現するASL(Amazon States Language)全体は以下になります。

{
  "Comment": "SendGridのreputationを取得し、CloudWatchのカスタムメトリクスとして記録する",
  "StartAt": "Call third-party API",
  "States": {
    "Call third-party API": {
      "Next": "PutMetricData",
      "Parameters": {
        "ApiEndpoint": "https://api.sendgrid.com/v3/subusers/reputations",
        "Authentication": {
          "ConnectionArn": "arn:aws:events:ap-northeast-1:123456789012:connection/example/uuid"
        },
        "Method": "GET",
        "QueryParameters": {
          "usernames": "<< subuser name >>"
        }
      },
      "Resource": "arn:aws:states:::http:invoke",
      "Retry": [
        {
          "BackoffRate": 2,
          "ErrorEquals": [
            "States.ALL"
          ],
          "IntervalSeconds": 1,
          "JitterStrategy": "FULL",
          "MaxAttempts": 3
        }
      ],
      "Type": "Task"
    },
    "PutMetricData": {
      "End": true,
      "InputPath": "$.ResponseBody",
      "Parameters": {
        "MetricData": [
          {
            "Dimensions": [
              {
                "Name": "Username",
                "Value.$": "$[0].username"
              }
            ],
            "MetricName": "Reputation",
            "Unit": "Percent",
            "Value.$": "$[0].reputation"
          }
        ],
        "Namespace": "SendGrid"
      },
      "Resource": "arn:aws:states:::aws-sdk:cloudwatch:putMetricData",
      "Type": "Task"
    }
  }
}

その他のAWSリソースの作成

以下のAWSリソースの作成については詳細な説明を割愛します。

  • Step Functionsを定期起動するためのリソース
    • EventBridge Rule
  • 監視と通知のためのリソース
    • CloudWatch Alarm, SNS, AWS Chatbot

定期起動のタイミングとしては、レピュテーションはそう短いサイクルで変化しないようなので、1時間ごととしています。

Slack通知

以上を行うことで、レピュテーションが設定した閾値以下になった場合、Slackに通知がされます。

以下は検証のために一時的に閾値を変更して通知させたものです。

終わりに

HTTPSエンドポイントを使うことで、AWS外のAPIを叩くようなStep Functionsを構築する場合でも、Lambdaを作成する必要が無くなりました。ちょっとした処理を実現するのにLambda関数のコードを書かなくて済むのは嬉しいですね。

また、これはEventBridge connectionに対する感想ですが、作成時にSecrets Managerも自動作成されるのも便利に感じました。

本記事が参考になれば幸いです。

スマートラウンド テックブログ

Discussion