public note

AWS CloudFormationスタックのドリフトを検出してSlackに通知する

AWS CloudFormation(以下、Cfn) のスタックドリフトを検出して、Slackに通知してみました。

ドリフト検出とは

Cfn で定義したスタック内のリソースについて、定義した内容から変更が加わっていないかをチェックする機能です。Cfn で管理していることを知らずに、マネジメントコンソールから変更を加えてしまうケースに備えたものです。

ドリフト検出の実行や結果確認はマネジメントコンソールからできますが、自動で検出してSlack に通知できると便利です。

利用したサービス

以下のサービスを組み合わせることで、ドリフトステータスの変化の検出や、その通知を自動化することができます。

f:id:ts223:20210925222204p:plain

テンプレート

こちらで公開しています。

github.com

Parameters

以下をパラメータにしています。

  • ドリフトチェック周期
  • 通知先のSlack Workspace ID
  • 通知先のSlack Channel ID

Slack チャンネルがプライベートの場合は、/invite @aws をしてください。

Getting started with AWS Chatbot - AWS Chatbot

Config Rule

すべてのスタックがドリフトしていないかをチェックするルールになっています。 MaximumExecutionFrequency で指定した周期でチェックを行いますが、ステータスを確認するだけでなく、ドリフト検出の実行もしてくれます。実行してくれないかと思って Lambda Function も作ったのですが、いらなかったですね...

  ConfigRule:
    Type: AWS::Config::ConfigRule
    Properties:
      ConfigRuleName: stack_drift_detected_config
      InputParameters:
        cloudformationRoleArn: !GetAtt DetectDriftRole.Arn
      Scope:
        ComplianceResourceTypes:
          - AWS::CloudFormation::Stack
      Source:
        Owner: AWS
        SourceIdentifier: CLOUDFORMATION_STACK_DRIFT_DETECTION_CHECK
      MaximumExecutionFrequency: !Ref MaximumExecutionFrequency

アタッチしているロールでは、ドリフト検出に必要なポリシーを AWS Config に Assume Role しています。

EventBrige

さきほどの Config Rule に基づくドリフト検出でステータスの変化があった場合に、後述の SNS Topic へメッセージ送信するように指定しています。

  EventsRule:
    Type: AWS::Events::Rule
    Properties: 
      Name: stack_drift_detected_event_rule
      EventPattern:
        source:
          - aws.config
        detail-type:
          - Config Rules Compliance Change
        detail:
          messageType:
            - ComplianceChangeNotification
      Targets:
        - Arn: !Ref EventsTopic
          Id: EventsTopic

SNS

ステータス変化メッセージは、SNS Topic の Subscriber として指定している Chatbot に送信されます。

  EventsTopic:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: stack_drift_detected_topic

  EventsSubscription:
    Type: AWS::SNS::Subscription
    Properties:
      TopicArn: !Ref EventsTopic
      Endpoint: https://global.sns-api.chatbot.amazonaws.com
      Protocol: https
      RawMessageDelivery: false
      Region: !Ref AWS::Region

Chatbot

SNS を経由して届いたメッセージは、Parameters で指定した Slack ワークスペース・チャンネルに送信されます。

  ChatbotSlackChannel:
    Type: AWS::Chatbot::SlackChannelConfiguration
    Properties: 
      ConfigurationName: stack_drift_detected_chatbot
      IamRoleArn: !GetAtt ChatbotIamRole.Arn
      LoggingLevel: ERROR
      SlackWorkspaceId: !Ref SlackWorkspaceId
      SlackChannelId: !Ref SlackChannelId
      SnsTopicArns: 
        - !Ref EventsTopic

Slack 通知結果

このように通知されます。通知内のリンクから Cfn のスタック管理画面に飛べますので、どのリソースがドリフトしたのかを確認できます。

f:id:ts223:20210925223706p:plain

ドリフトが解消されると、Compliance Type COMPLIANT と通知されます。

AWS Chatbot と連携できるサービスが増えたので気になっていたのですが、けっこう簡単に通知できて便利だったので、積極的に使っていこうと思います。