サービスクォータ監視通知にクォータのリージョンを通知内容に入れてみる

サービスクォータ監視通知にクォータのリージョンを通知内容に入れてみる

2025.11.04

以下の方法でAWSサービスクォータ監視を実装しました。

https://dev.classmethod.jp/articles/aws-service-quotas-slack-notification-stepfunctions-slack-webhook/

今回はクォータの対象リージョンを素早く把握するために、通知メッセージにリージョン情報を入れてみました。

追加の方法をブログにしてみました。

イメージは以下です。


リージョン情報追加前

random__Channel__-_test_-_Slack.png
リージョン情報追加後

Trusted Advisorサービスの制限 イベント の内容確認

クォータ監視の仕組みでは、Trusted Advisorのサービスの制限のチェックを利用しています。

チェック発生時にイベントが発生して、EventBridgeルールで検出します。

イベントの内容を確認して、リージョン情報が含まれているか確認してみました。(公式ドキュメントからイベント構造の記載箇所を見つけられなかったため、実際のイベントで確認しました。)

以下は実際に検出したイベントです。

VPC
{
    "version": "0",
    "id": "9cbec8aa-461b-f452-a6e6-848aed225f30",
    "detail-type": "Trusted Advisor Check Item Refresh Notification",
    "source": "aws.trustedadvisor",
    "account": "123456789012",
    "time": "2025-11-04T01:53:17Z",
    "region": "us-east-1",
    "resources": [],
    "detail": {
        "check-name": "VPC",
        "check-item-detail": {
            "Status": "Green",
            "Current Usage": "1",
            "Limit Name": "VPCs",
            "Region": "us-west-1",
            "Service": "VPC",
            "Limit Amount": "5"
        },
        "status": "OK",
        "resource_id": "",
        "uuid": "e21d6506-5ff4-4bde-bb87-5ce55e09f194"
    }
}
EC2-VPC Elastic IP Address
{
    "version": "0",
    "id": "5e473685-ef1c-9581-e9e9-3255563d189e",
    "detail-type": "Trusted Advisor Check Item Refresh Notification",
    "source": "aws.trustedadvisor",
    "account": "123456789012",
    "time": "2025-11-04T02:00:50Z",
    "region": "us-east-1",
    "resources": [],
    "detail": {
        "check-name": "EC2-VPC Elastic IP Address",
        "check-item-detail": {
            "Status": "Green",
            "Current Usage": "0",
            "Limit Name": "EC2-VPC Elastic IP addresses (EIPs)",
            "Region": "eu-west-3",
            "Service": "VPC",
            "Limit Amount": "5"
        },
        "status": "OK",
        "resource_id": "",
        "uuid": "79050973-a7c4-4fbf-bf50-0573a6243b61"
    }
}
Auto Scaling Groups
{
    "version": "0",
    "id": "28a759d7-6f08-3f45-f394-73f1884c87e9",
    "detail-type": "Trusted Advisor Check Item Refresh Notification",
    "source": "aws.trustedadvisor",
    "account": "123456789012",
    "time": "2025-11-04T01:53:23Z",
    "region": "us-east-1",
    "resources": [],
    "detail": {
        "check-name": "Auto Scaling Groups",
        "check-item-detail": {
            "Status": "Green",
            "Current Usage": "0",
            "Limit Name": "Auto Scaling groups",
            "Region": "us-east-2",
            "Service": "AutoScaling",
            "Limit Amount": "500"
        },
        "status": "OK",
        "resource_id": "",
        "uuid": "b3626017-512e-4e4d-9d26-7d377ed3d6c4"
    }
}

リージョン情報はregiondetail.check-item-detail.Regionの2箇所にあることが分かります。

それぞれの違いは以下です。

  • region: Trusted Advisor
    イベントが発行されるリージョン(常に us-east-1)
  • detail.check-item-detail.Region:
    実際のクォータが適用されているリージョン(例:us-west-1,
    eu-west-3, us-east-2 など)

Trusted Advisorのすべてのイベントはus-east-1のEventBridgeに送信されるためregionは常にus-east-1になります。

As Trusted Advisor is a Global service, all Events are emitted to EventBridge in the US East (N. Virginia) Region.

Monitoring AWS Trusted Advisor check results with Amazon EventBridge | AWS Document

今回やりたいことは、実際のクォータが適用されているリージョンを通知に含めることであるためdetail.check-item-detail.Regionを使います。

Tips: Globalリソースのdetail.check-item-detail.Regionの値

IAM関連等グローバルリソースの場合、detail.check-item-detail.Regionの値がどうなるか気になり確認してみました。

結果は以下のように、Regionの値は"-"になりました。

{
    "version": "0",
    "id": "91243803-eaee-5d1a-d988-24589fb66378",
    "detail-type": "Trusted Advisor Check Item Refresh Notification",
    "source": "aws.trustedadvisor",
    "account": "123456789012",
    "time": "2025-11-04T02:26:14Z",
    "region": "us-east-1",
    "resources": [],
    "detail": {
        "check-name": "IAM Group",
        "check-item-detail": {
            "Status": "Green",
            "Current Usage": "0",
            "Limit Name": "Groups",
            "Region": "-",
            "Service": "IAM",
            "Limit Amount": "300"
        },
        "status": "OK",
        "resource_id": "",
        "uuid": "59d176aa-6736-4a61-8e64-9f931fd4dff1"
    }
}

EventBridgeルール入力トランスフォーマー・Step Functionsステートマシンの更新

クォータのリージョン情報を通知するために、リソースを修正します。

修正後のCloudFormationテンプレートは以下です。

service-quota-monitoring.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: 'AWS Service Quota Monitoring with Trusted Advisor, EventBridge, Step Functions, and Slack webhook integration (with region information)'

Parameters:
  SlackWebhookUrl:
    Type: String
    Description: 'Slack webhook URL for notifications'
    NoEcho: true

Resources:
  # IAM Role for Step Functions
  # Reference: https://docs.aws.amazon.com/step-functions/latest/dg/cw-logs.html
  StepFunctionsServiceRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: ServiceQuotaMonitoring-StepFunctions-Role
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: states.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: ServiceQuotaMonitoring-StepFunctions-Policy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              # CloudWatch Logs permissions for Step Functions logging
              # Reference: https://docs.aws.amazon.com/step-functions/latest/dg/cw-logs.html
              # Note: Resource must be "*" as these API actions don't support specific resource ARNs
              - Effect: Allow
                Action:
                  - logs:CreateLogDelivery
                  - logs:CreateLogStream
                  - logs:GetLogDelivery
                  - logs:UpdateLogDelivery
                  - logs:DeleteLogDelivery
                  - logs:ListLogDeliveries
                  - logs:PutLogEvents
                  - logs:PutResourcePolicy
                  - logs:DescribeResourcePolicies
                  - logs:DescribeLogGroups
                Resource: '*'
              - Effect: Allow
                Action:
                  - states:InvokeHTTPEndpoint
                Resource: '*'
                Condition:
                  StringEquals:
                    'states:HTTPEndpoint': !Ref SlackWebhookUrl
              - Effect: Allow
                Action:
                  - events:RetrieveConnectionCredentials
                Resource: !GetAtt SlackWebhookConnection.Arn
              - Effect: Allow
                Action:
                  - secretsmanager:GetSecretValue
                  - secretsmanager:DescribeSecret
                Resource: !GetAtt SlackWebhookConnection.SecretArn

  # IAM Role for EventBridge
  EventBridgeServiceRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: ServiceQuotaMonitoring-EventBridge-Role
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: events.amazonaws.com
            Action: sts:AssumeRole
            Condition:
              StringEquals:
                aws:SourceArn: !Sub 'arn:aws:events:${AWS::Region}:${AWS::AccountId}:rule/ServiceQuotaMonitoring-Alert'
                aws:SourceAccount: !Ref AWS::AccountId
      Policies:
        - PolicyName: ServiceQuotaMonitoring-EventBridge-Policy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - states:StartExecution
                Resource: !Ref SlackNotificationStateMachine

  # EventBridge Connection for Slack webhook
  SlackWebhookConnection:
    Type: AWS::Events::Connection
    Properties:
      Name: ServiceQuotaMonitoring-SlackWebhook
      Description: 'Connection for Slack webhook'
      AuthorizationType: API_KEY
      AuthParameters:
        ApiKeyAuthParameters:
          ApiKeyName: 'Authorization'
          ApiKeyValue: 'Bearer dummy'

  # CloudWatch Log Group for Step Functions
  StepFunctionsLogGroup:
    Type: AWS::Logs::LogGroup
    Properties:
      LogGroupName: '/aws/stepfunctions/ServiceQuotaMonitoring-SlackNotification'
      RetentionInDays: 14

  # Step Functions State Machine
  SlackNotificationStateMachine:
    Type: AWS::StepFunctions::StateMachine
    Properties:
      StateMachineName: ServiceQuotaMonitoring-SlackNotification
      RoleArn: !GetAtt StepFunctionsServiceRole.Arn
      LoggingConfiguration:
        Level: ALL
        IncludeExecutionData: true
        Destinations:
          - CloudWatchLogsLogGroup:
              LogGroupArn: !GetAtt StepFunctionsLogGroup.Arn
      DefinitionString: !Sub |
        {
          "Comment": "Send service quota alerts to Slack",
          "StartAt": "SendSlackNotification",
          "States": {
            "SendSlackNotification": {
              "Type": "Task",
              "Resource": "arn:aws:states:::http:invoke",
              "Parameters": {
                "ApiEndpoint": "${SlackWebhookUrl}",
                "Method": "POST",
                "Headers": {
                  "Content-Type": "application/json"
                },
                "RequestBody": {
                  "text.$": "States.Format('*Trusted Advisor Service Quota*\n\n*Check*: {}\n*Status*: {}\n*Account*: {}\n*Region*: {}\n\n*Console Link*: https://{}.signin.aws.amazon.com/console/trustedadvisor?region={}', $.checkname, $.status, $.account, $.checkregion, $.account, $.region)"
                },
                "InvocationConfig": {
                  "ConnectionArn": "${SlackWebhookConnection.Arn}"
                }
              },
              "End": true,
              "Retry": [
                {
                  "ErrorEquals": ["States.Http.HttpRequestFailed"],
                  "IntervalSeconds": 5,
                  "MaxAttempts": 3,
                  "BackoffRate": 2.0
                }
              ],
              "Catch": [
                {
                  "ErrorEquals": ["States.ALL"],
                  "Next": "NotificationFailed"
                }
              ]
            },
            "NotificationFailed": {
              "Type": "Fail",
              "Cause": "Failed to send Slack notification"
            }
          }
        }

  # EventBridge Rule for Service Quota Monitoring
  ServiceQuotaMonitoringRule:
    Type: AWS::Events::Rule
    Properties:
      Name: ServiceQuotaMonitoring-Alert
      Description: 'Monitor AWS service quotas via Trusted Advisor alerts'
      EventPattern:
        source:
          - aws.trustedadvisor
          - custom.testing # テスト用 テスト時のみコメントイン
        detail-type:
          - Trusted Advisor Check Item Refresh Notification
        detail:
          status:
            - ERROR
            - WARN
          check-name:
            - VPC
            - VPC Internet Gateways
            - EC2-VPC Elastic IP Address
            - Auto Scaling Groups
      State: ENABLED
      Targets:
        - Arn: !Ref SlackNotificationStateMachine
          Id: ServiceQuotaMonitoringStepFunctionsTarget
          RoleArn: !GetAtt EventBridgeServiceRole.Arn
          InputTransformer:
            InputPathsMap:
              account: $.account
              checkname: $.detail.check-name
              status: $.detail.status
              region: $.region
              checkregion: $.detail.check-item-detail.Region
            InputTemplate: |
              {
                "account": "<account>",
                "checkname": "<checkname>",
                "status": "<status>",
                "region": "<region>",
                "checkregion": "<checkregion>"
              }

修正箇所を確認します。まずはEventBridgeルールです。

クォータが適用されているリージョンの情報をcheckregionとして、入力トランスフォーマーと入力テンプレートに追加しました。

これで、Slack通知用のStep Functionsステートマシンでcheckregionの値を使えます。

  # EventBridge Rule for Service Quota Monitoring
  ServiceQuotaMonitoringRule:
    Type: AWS::Events::Rule
    Properties:
    # 省略
      Targets:
        - Arn: !Ref SlackNotificationStateMachine
          Id: ServiceQuotaMonitoringStepFunctionsTarget
          RoleArn: !GetAtt EventBridgeServiceRole.Arn
          InputTransformer:
            InputPathsMap:
              account: $.account
              checkname: $.detail.check-name
              status: $.detail.status
              region: $.region
+              checkregion: $.detail.check-item-detail.Region
            InputTemplate: |
              {
                "account": "<account>",
                "checkname": "<checkname>",
                "status": "<status>",
                "region": "<region>",
+                "checkregion": "<checkregion>"
              }

checkregionの値を、Slackに通知するようにステートマシン定義を変更します。

  # Step Functions State Machine
  SlackNotificationStateMachine:
    Type: AWS::StepFunctions::StateMachine
    Properties:
    # 省略
      DefinitionString: !Sub |
        {
          "Comment": "Send service quota alerts to Slack",
          "StartAt": "SendSlackNotification",
          "States": {
            "SendSlackNotification": {
              "Type": "Task",
              "Resource": "arn:aws:states:::http:invoke",
              "Parameters": {
                "ApiEndpoint": "${SlackWebhookUrl}",
                "Method": "POST",
                "Headers": {
                  "Content-Type": "application/json"
                },
                "RequestBody": {
+                  "text.$": "States.Format('*Trusted Advisor Service Quota*\n\n*Check*: {}\n*Status*: {}\n*Account*: {}\n*Region*: {}\n\n*Console Link*: https://{}.signin.aws.amazon.com/console/trustedadvisor?region={}', $.checkname, $.status, $.account, $.checkregion, $.account, $.region)"
-                  "text.$": "States.Format('*Trusted Advisor Service Quota*\n\n*Check*: {}\n*Status*: {}\n*Account*: {}\n\n*Console Link*: https://{}.signin.aws.amazon.com/console/trustedadvisor?region={}', $.checkname, $.status, $.account, $.account, $.region)"
                },

CloudFormationテンプレートを更新したら完了です。

動作確認

サンプルイベントを作成して、テスト通知が行われることを確認します。

以下のファイルを用意します。

quota-events-put.json
[
  {
    "Source": "custom.testing",
    "DetailType": "Trusted Advisor Check Item Refresh Notification",
    "Detail": "{\"check-name\":\"Auto Scaling Groups\",\"check-item-detail\":{\"Status\":\"Green\",\"Current Usage\":\"0\",\"Limit Name\":\"Auto Scaling groups\",\"Region\":\"us-east-2\",\"Service\":\"AutoScaling\",\"Limit Amount\":\"500\"},\"status\":\"WARN\",\"resource_id\":\"\",\"uuid\":\"b3626017-512e-4e4d-9d26-7d377ed3d6c4\"}",
    "Time": "2025-11-04T01:53:23Z",
    "Resources": []
  },
  {
    "Source": "custom.testing",
    "DetailType": "Trusted Advisor Check Item Refresh Notification",
    "Detail": "{\"check-name\":\"EC2-VPC Elastic IP Address\",\"check-item-detail\":{\"Status\":\"Green\",\"Current Usage\":\"0\",\"Limit Name\":\"EC2-VPC Elastic IP addresses (EIPs)\",\"Region\":\"eu-west-3\",\"Service\":\"VPC\",\"Limit Amount\":\"5\"},\"status\":\"ERROR\",\"resource_id\":\"\",\"uuid\":\"79050973-a7c4-4fbf-bf50-0573a6243b61\"}",
    "Time": "2025-11-04T02:00:50Z",
    "Resources": []
  },
  {
    "Source": "custom.testing",
    "DetailType": "Trusted Advisor Check Item Refresh Notification",
    "Detail": "{\"check-name\":\"VPC\",\"check-item-detail\":{\"Status\":\"Yellow\",\"Current Usage\":\"3\",\"Limit Name\":\"VPCs\",\"Region\":\"us-west-1\",\"Service\":\"VPC\",\"Limit Amount\":\"5\"},\"status\":\"WARN\",\"resource_id\":\"\",\"uuid\":\"12345678-1234-5678-9012-123456789012\"}",
    "Time": "2025-11-04T03:15:30Z",
    "Resources": []
  },
  {
    "Source": "custom.testing",
    "DetailType": "Trusted Advisor Check Item Refresh Notification",
    "Detail": "{\"check-name\":\"VPC Internet Gateways\",\"check-item-detail\":{\"Status\":\"Red\",\"Current Usage\":\"4\",\"Limit Name\":\"Internet gateways\",\"Region\":\"ap-northeast-1\",\"Service\":\"VPC\",\"Limit Amount\":\"5\"},\"status\":\"ERROR\",\"resource_id\":\"\",\"uuid\":\"87654321-4321-8765-2109-876543210987\"}",
    "Time": "2025-11-04T04:22:45Z",
    "Resources": []
  }
]

以下のコマンドを実行して、サンプルイベントを作成します。

aws events put-events \
    --entries file://test/quota-events-put.json \
    --region us-east-1

Slackを確認すると、Region情報が含まれた通知を受信できました。

random__Channel__-_test_-_Slack.png

おわりに

Trusted Advisorイベントは、regionにはTrusted Advisorのリージョンであるus-east-1が入ります。

今回のようなリージョン個別の情報を使いたい場合は、detail内のリージョン情報を利用しましょう。

この記事をシェアする

FacebookHatena blogX

関連記事