dshimizu/blog/alpha

とりとめのないITブログ

AWS Health のイベントを Slack へ通知する

はじめに

AWS Health の Dashboard に表示されるイベントをマネジメントコンソールから確認するのは手間なので、 Slack へ通知できるようにしたいと思い、やり方を調べていました。

EventBridge + SNS + Chatbotを使って自前で作成するやり方があるのは知っていたのですが、調べたところ、AWS Health Aware というものや、AWS User Notfication というサービスを使うやり方もあるようでした。

あまり調べてないですが AWS Health Aware は AWS Health API は使うようで、これはビジネスまたはエンタープライズサポートプランに加入している場合に利用可能なものであるようなので、個人で利用しているサポート未加入の自分のアカウントで使えませんでした。 AWS User Notfication は手動でやる必要がありそうでしたが、EventBridge + SNS + Chatbot に相当する設定を、結構簡単に作成できそうでした。

色々なやり方があることに気づきつつ、EventBridge + SNS + Chatbot を組み合わせて Slack へ通知するオーソドックスな CloudFormation テンプレートを作ってやってみました。 同じような記事はたくさんあるので N 番煎じです。

目次

設定

以下のようなものを作成します。 パブリックイベントは us-east-1 でしか配信されないようなので、このイベントを検知するために、 us-east-1 リージョンにもリソースを作成します。 同じチャンネルIDを指定したChatbotをCloudFormationで複数作成できなかったので、ここでは us-east-1 のイベントを通知するSlackチャンネルと、ap-northeast-1 リージョンのイベントを通知するSlackチャンネルを分ける形にしており、Chatbotの設定も2つになっています。

AWS Chatbot で Slack 連携設定する

AWS Chatbot での Slack 連携設定については割愛します。ドキュメントに記載があります。

CloudFormation テンプレートを利用してリソースを作成する (us-east-1 リージョン)

以下のテンプレートで、AWS Chatbotの定義のSlackのワークスペースとチャンネルIDを環境に合わせて設定し、 us-east-1 リージョンにデプロイします。 グローバルイベントus-east-1 リージョンでしか検知できないため、このリージョンに設定します。

  • Monitoring AWS Health events with Amazon EventBridge - AWS Health

    Some AWS Health events are not Region-specific. Events that aren't specific to a Region are called global events. These include events sent for AWS Identity and Access Management (IAM). To receive global events, you must create a rule for the US East (N. Virginia) Region for the primary Region and US West (Oregon) Region as the backup Region.

AWSTemplateFormatVersion: "2010-09-09"
Description: AWS Health Dashboard Event Notify

Parameters:
  SlackWorkspaceId:
    Type: String
  SlackChannelId:
    Type: String

Resources:
  ################################################################
  # SNS 関連のリソース定義
  ################################################################
  # SNS Topic に設定する IAM Role の定義
  # * SNS の配信ステータスログを CloudWatch へ配信するための権限を定義する
  SNSIAMRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - sns.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: '/'
      Policies:
        - PolicyName: !Sub ${AWS::StackName}-sns-policy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - 'logs:Describe*'
                  - 'logs:Get*'
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                  - 'logs:PutMetricFilter'
                  - 'logs:PutRetentionPolicy'
                Resource: '*'

  # SNS トピックの定義
  # * EventBridge からのメッセージを受けて Chatbot へ送るためのリソースを定義している
  SNSTopic:
    Type: AWS::SNS::Topic
    DependsOn:
      - SNSIAMRole
    Properties:
      TopicName: !Sub ${AWS::StackName}-sns-topic
      DeliveryStatusLogging:
       - Protocol: http/s
         SuccessFeedbackSampleRate: 100
         SuccessFeedbackRoleArn: !GetAtt SNSIAMRole.Arn
         FailureFeedbackRoleArn: !GetAtt SNSIAMRole.Arn

  # SNS トピックポリシーの定義
  # * EventBridge から SNS トピックへのアクセスを許可する
  SNSTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    DependsOn:
      - SNSTopic
      - EventsRule
    Properties:
      PolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service: events.amazonaws.com
            Action: sns:Publish
            Resource: !GetAtt EventsRule.Arn
      Topics:
        - !Ref SNSTopic

  ################################################################
  # EventBridge 関連のリソースの定義
  ################################################################
  # Event Rule の定義
  # * アカウント固有イベントと公開イベントの両方を受信して、SNSへ送信する
  EventsRule:
    Type: AWS::Events::Rule
    DependsOn:
      - SNSTopic
    Properties:
      EventPattern:
        source:
          - aws.health
      Targets:
        - Id: HealthEventSlackNotifyToSNSTopic
          Arn: !Ref SNSTopic

  ################################################################
  # Chatbot 関連のリソース定義
  ################################################################
  # Chatbot 用の IAM Role 定義
  # * Chatbot のログを CloudWatch Logs へ配信するための権限を定義する
  ChatbotIAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: chatbot.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: !Sub ${AWS::StackName}-chatbot-policy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                  - 'logs:PutMetricFilter'
                  - 'logs:PutRetentionPolicy'
                Resource: '*'

  # AWS ChatbotでのSlackチャンネルの定義
  # ※ 事前に Slack ワークススペースと AWS Chatbot の連携を行なっておく必要がある
  ChatbotSlackChannelConfiguration:
    Type: AWS::Chatbot::SlackChannelConfiguration
    DependsOn:
      - SNSTopic
      - ChatbotIAMRole
    Properties: 
      ConfigurationName: !Sub ${AWS::StackName}-chatbot-config
      IamRoleArn: !GetAtt ChatbotIAMRole.Arn
      LoggingLevel: ERROR
      SlackWorkspaceId: !Ref SlackWorkspaceId
      SlackChannelId: !Ref SlackChannelId
      SnsTopicArns: 
         - !Ref SNSTopic

Outputs:
  SNSIAMRole:
    Description: IAM Role For SNS
    Value: !GetAtt SNSIAMRole.Arn

  SNSTopicArn:
    Description: SNS Topic
    Value: !GetAtt SNSTopic.TopicArn

  SNSTopicPolicyArn:
    Description: SNS Topic Policy
    Value: !Ref SNSTopicPolicy

  EventsRuleArn:
    Description: Events Rule
    Value: !GetAtt EventsRule.Arn

  ChatbotIAMRoleArn:
    Description: IAM Role For Chatbot
    Value: !GetAtt ChatbotIAMRole.Arn

  ChatbotSlackChannelConfigurationArn:
    Description: Chatbot Slack Channel Configuration
    Value: !GetAtt ChatbotSlackChannelConfiguration.Arn

CloudFormation テンプレートを利用してリソースを作成する (ap-northeast-1 リージョン)

以下のような CloudForamtion テンプレートを利用して、リソースを作成します。 作成されるリソースの命名${AWS::StackName}-リソース名 のような形にしていますが、必要に応じて変更します。 入力パラメーターで Slack のワークスペースIDとチャンネルIDを設定するようにしています。

AWSTemplateFormatVersion: "2010-09-09"
Description: AWS Health Dashboard Event Notify

Parameters:
  SlackWorkspaceId:
    Type: String
  SlackChannelId:
    Type: String

Resources:
  ################################################################
  # SNS 関連のリソース定義
  ################################################################
  # SNS Topic に設定する IAM Role の定義
  # * SNS の配信ステータスログを CloudWatch へ配信するための権限を定義する
  SNSIAMRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - sns.amazonaws.com
            Action:
              - 'sts:AssumeRole'
      Path: '/'
      Policies:
        - PolicyName: !Sub ${AWS::StackName}-sns-policy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - 'logs:Describe*'
                  - 'logs:Get*'
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                  - 'logs:PutMetricFilter'
                  - 'logs:PutRetentionPolicy'
                Resource: '*'

  # SNS トピックの定義
  # * EventBridge からのメッセージを受けて Chatbot へ送るためのリソースを定義している
  SNSTopic:
    Type: AWS::SNS::Topic
    DependsOn:
      - SNSIAMRole
    Properties:
      TopicName: !Sub ${AWS::StackName}-sns-topic
      DeliveryStatusLogging:
       - Protocol: http/s
         SuccessFeedbackSampleRate: 100
         SuccessFeedbackRoleArn: !GetAtt SNSIAMRole.Arn
         FailureFeedbackRoleArn: !GetAtt SNSIAMRole.Arn

  # SNS トピックポリシーの定義
  # * EventBridge から SNS トピックへのアクセスを許可する
  SNSTopicPolicy:
    Type: AWS::SNS::TopicPolicy
    DependsOn:
      - SNSTopic
      - EventsRule
    Properties:
      PolicyDocument:
        Statement:
          - Effect: Allow
            Principal:
              Service: events.amazonaws.com
            Action: sns:Publish
            Resource: !GetAtt EventsRule.Arn
      Topics:
        - !Ref SNSTopic

  ################################################################
  # EventBridge 関連のリソースの定義
  ################################################################
  # Event Rule の定義
  # * アカウント固有イベントと公開イベントの両方を受信して、SNSへ送信する
  EventsRule:
    Type: AWS::Events::Rule
    DependsOn:
      - SNSTopic
    Properties:
      EventPattern:
        source:
          - aws.health
      Targets:
        - Id: HealthEventSlackNotifyToSNSTopic
          Arn: !Ref SNSTopic

  ################################################################
  # Chatbot 関連のリソース定義
  ################################################################
  # Chatbot 用の IAM Role 定義
  # * Chatbot のログを CloudWatch Logs へ配信するための権限を定義する
  ChatbotIAMRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service: chatbot.amazonaws.com
            Action: sts:AssumeRole
      Policies:
        - PolicyName: !Sub ${AWS::StackName}-chatbot-policy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                  - 'logs:PutMetricFilter'
                  - 'logs:PutRetentionPolicy'
                Resource: '*'

  # AWS ChatbotでのSlackチャンネルの定義
  # ※ 事前に Slack ワークススペースと AWS Chatbot の連携を行なっておく必要がある
  ChatbotSlackChannelConfiguration:
    Type: AWS::Chatbot::SlackChannelConfiguration
    DependsOn:
      - SNSTopic
      - ChatbotIAMRole
    Properties: 
      ConfigurationName: !Sub ${AWS::StackName}-chatbot-config
      IamRoleArn: !GetAtt ChatbotIAMRole.Arn
      LoggingLevel: ERROR
      SlackWorkspaceId: !Ref SlackWorkspaceId
      SlackChannelId: !Ref SlackChannelId
      SnsTopicArns: 
         - !Ref SNSTopic

Outputs:
  SNSIAMRole:
    Description: IAM Role For SNS
    Value: !GetAtt SNSIAMRole.Arn

  SNSTopicArn:
    Description: SNS Topic
    Value: !GetAtt SNSTopic.TopicArn

  SNSTopicPolicyArn:
    Description: SNS Topic Policy
    Value: !Ref SNSTopicPolicy

  EventsRuleArn:
    Description: Events Rule
    Value: !GetAtt EventsRule.Arn

  ChatbotIAMRoleArn:
    Description: IAM Role For Chatbot
    Value: !GetAtt ChatbotIAMRole.Arn

  ChatbotSlackChannelConfigurationArn:
    Description: Chatbot Slack Channel Configuration
    Value: !GetAtt ChatbotSlackChannelConfiguration.Arn

まとめ

AWS Health のイベントを Slack に通知するための仕組みの CloudFromation を使って作ってみました。このやり方はシンプルかと思いますが、管理するAWSアカウント数が増えてくると都度CloudFormationスタックを作成する必要があるので、その辺りをStackSetsを使うなどで解決する仕組みも確立していく必要がありそうだなと思いました。

AWS Health Aware は AWS Health API を使用します。AWS Health API はビジネスまたはエンタープライズサポートプランに加入している AWS のお客様のみが利用でき、次の機能を利用することができます。

参考