Amazon EventBridgeを活用してSlackへ通知する

Y
2025-04-07
2025-04-07

EventBridge を利用されたことはありますか?
Amazon EventBridge は、AWS サービスやアプリケーションのイベントをトリガーとして、
ルールに基づいて特定のターゲットへ送信できるサービスです。

今回、AWS CloudTrail の証跡ログから操作履歴を Slack に通知したいという要望があり、
検証も兼ねて IAM の操作履歴を Slack に通知する仕組みを CloudFormation でコード化してみました。

以下手順のようにSlackとAWS Chatbotの連携は手動で行います。

手順

1. 「Amazon Q Developer in chat applications」から「新しいクライアントを設定」をクリックします。
1-Apr-04-2025-01-19-31-7581-AM

2. 「Slack」を選択し「設定」を選択するとSlackとのアクセス連携画面に遷移します。
2-Apr-04-2025-01-19-31-5244-AM
3. 連携したいSlack ワークスペースを選択し「許可する」を選択で事前準備完了です。
3-Apr-04-2025-01-19-31-6947-AM

4. 米国(バージニア北部)リージョンにて、CloudFormationを開きます。
4-Apr-04-2025-01-19-31-7321-AM

5. スタックの作成から「テンプレートファイルのアップロード」を選択し、以下のyamlファイルをアップロードします。

Cloudformation.yml

AWSTemplateFormatVersion: '2010-09-09'
Description: 'CloudTrail IAM操作履歴のSlack通知システム(EventBridge版)'

Parameters:
  SlackWorkspaceId:
    Type: String
    Description: 'Slack ワークスペースID'
  SlackChannelId:
    Type: String
    Description: 'Slack チャンネルID'

Resources:
  # CloudTrail用のS3バケット
  CloudTrailBucket:
    Type: 'AWS::S3::Bucket'
    Properties:
      BucketName: !Sub '${AWS::AccountId}-cloudtrail-logs'
      VersioningConfiguration:
        Status: Enabled
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

  # CloudTrail用のS3バケットポリシー
  CloudTrailBucketPolicy:
    Type: 'AWS::S3::BucketPolicy'
    Properties:
      Bucket: !Ref CloudTrailBucket
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Sid: 'AWSCloudTrailAclCheck'
            Effect: 'Allow'
            Principal:
              Service: 'cloudtrail.amazonaws.com'
            Action: 's3:GetBucketAcl'
            Resource: !GetAtt CloudTrailBucket.Arn
          - Sid: 'AWSCloudTrailWrite'
            Effect: 'Allow'
            Principal:
              Service: 'cloudtrail.amazonaws.com'
            Action: 's3:PutObject'
            Resource: !Sub '${CloudTrailBucket.Arn}/*'
            Condition:
              StringEquals:
                's3:x-amz-acl': 'bucket-owner-full-control'

  # CloudTrailの証跡
  CloudTrail:
    Type: 'AWS::CloudTrail::Trail'
    DependsOn:
      - CloudTrailBucketPolicy
    Properties:
      IsLogging: true
      IsMultiRegionTrail: true
      IncludeGlobalServiceEvents: true
      EnableLogFileValidation: true
      S3BucketName: !Ref CloudTrailBucket
      EventSelectors:
        - ReadWriteType: WriteOnly
          IncludeManagementEvents: true

  # SNSトピック
  SNSTopic:
    Type: 'AWS::SNS::Topic'
    Properties:
      TopicName: 'iam-events-notification'

  # EventBridgeルール
  EventBridgeRule:
    Type: 'AWS::Events::Rule'
    Properties:
      Name: 'IAMEventDetection'
      Description: 'IAMの変更操作を検知するルール'
      State: 'ENABLED'
      EventPattern:
        source:
          - "aws.iam"
        detail-type:
          - "AWS API Call via CloudTrail"
        detail:
          eventSource:
            - "iam.amazonaws.com"
      Targets:
        - Arn: !Ref SNSTopic
          Id: "IAMEventToSNS"

  # AWS Chatbot用のIAMロール
  ChatbotRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: chatbot.amazonaws.com
            Action: 'sts:AssumeRole'
      Policies:
        - PolicyName: ChatbotBasicPolicy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - 'sns:GetTopicAttributes'
                  - 'sns:SetTopicAttributes'
                  - 'sns:Subscribe'
                  - 'sns:Unsubscribe'
                Resource: !Ref SNSTopic

  # AWS Chatbot設定
  AWSChatbotConfiguration:
    Type: 'AWS::Chatbot::SlackChannelConfiguration'
    Properties:
      ConfigurationName: 'IAMEventsNotification'
      IamRoleArn: !GetAtt ChatbotRole.Arn
      SlackWorkspaceId: !Ref SlackWorkspaceId
      SlackChannelId: !Ref SlackChannelId
      SnsTopicArns:
        - !Ref SNSTopic

  # EventBridgeからSNSへの権限
  SNSTopicPolicy:
    Type: 'AWS::SNS::TopicPolicy'
    Properties:
      Topics:
        - !Ref SNSTopic
      PolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: events.amazonaws.com
            Action: 'sns:Publish'
            Resource: !Ref SNSTopic

Outputs:
  SNSTopicArn:
    Description: 'SNSトピックのARN'
    Value: !Ref SNSTopic
  CloudTrailBucketName:
    Description: 'CloudTrail用S3バケット名'
    Value: !Ref CloudTrailBucket

6. 「スタック名(任意)」とSlackのチャンネルId、ワークスペースIDを入力します。
ブラウザからSlackを利用している場合、
WorkspaceIdは「XXXXXXXX」SlackChannelIdは「YYYYYYYYY」になります。
https://app.slack.com/client/XXXXXXXX/YYYYYYYYY
5-Apr-04-2025-01-19-31-5790-AM

7. 試しにIAMユーザーを作成してみると、問題なく通知が来ることが確認できました。

7-Apr-04-2025-01-19-31-2166-AM

 

 

終わりに

詳細は割愛しますが、以下の AWS サービスを組み合わせて実装しています。
AWS CloudTrail(操作履歴の記録)
Amazon EventBridge(イベントルールの設定)
Amazon SNS(通知メッセージの送信)
AWS Chatbot(Slack への連携)

実際に運用する場合は、通知対象のサービスの選定や設定内容の詳細設計が必要になりますが、
CloudFormationでコード化することで、要望のあるお客様にもスムーズに展開できそうですね。

【参考サイト】
https://dev.classmethod.jp/articles/eventbridge-cross-region-expands/
https://techblog.cartaholdings.co.jp/entry/archives/641