5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AWS Configを使ってリソースの手動変更→Slack通知をCloudFormationで書く

Posted at

はじめに

タイトルの通り、1年ほど前にAWS Configを使ってリソースの手動変更が起きた際にSlackで通知するCloudFormationのコードを作成したので、記録に残します。

目次

実現したこと

実現したこととしては以下の通りです。

  • 前提
    • CloudFormationでAWSのリソースを全て管理していること(=スタックで作成しているリソースが今回の監視対象)

アーキテクチャ図

  • 仕組み
    • 1時間に1回ドリフト検出のルール1を走らせる
      • ドリフトが検出された(=リソースの手動変更があった)場合、EventBridgeが発火し、SNSトピック→ChatbotからSlackの任意のチャンネルへ通知がいく

コード

ドリフト検出ルールのテンプレート

'awsconfig-rule.yml'
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  # AWS config-rule
  CheckForCloudformationStackDriftDetection:
    Type: AWS::Config::ConfigRule
    Properties:
      ConfigRuleName: 'cloudformation-stack-drift-detection-check'
      Description: 'CloudFormationスタックの実際の構成が、予想される構成と異なるかどうか、またはずれているかどうかを確認します。'
      Source:
        Owner: AWS
        SourceIdentifier: 'CLOUDFORMATION_STACK_DRIFT_DETECTION_CHECK'
      MaximumExecutionFrequency: 'One_Hour'
      Scope:
        ComplianceResourceTypes:
          - 'AWS::CloudFormation::Stack'
      InputParameters:
        cloudformationRoleArn: !Sub arn:aws:iam::${AWS::AccountId}:role/config-rules-role

Slack通知設定のテンプレート

'awsconfig-notify.yml'
AWSTemplateFormatVersion: '2010-09-09' 
Parameters:
  SlackWorkspaceIdParameter:
    Type: String
  SlackChannelIdParameter:
    Type: String
  SNSTopicConfigNotificationParameter:
    Type: String

Resources:
  # Chatbot
  ChatbotSlackChannelConfigurationConfigNotification:
    Type: AWS::Chatbot::SlackChannelConfiguration
    Properties:
      ConfigurationName: !Sub config-notification
      IamRoleArn: !GetAtt IAMRoleSlackChannelConfigurationRole.Arn
      SlackChannelId: !Ref SlackChannelIdParameter
      SlackWorkspaceId: !Ref SlackWorkspaceIdParameter
      SnsTopicArns:
        - !Ref SNSTopicConfigNotificationParameter

 # Shared Resources
  IAMRoleSlackChannelConfigurationRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: !Sub slack-channel-cofiguration-config-role
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Action:
              - sts:AssumeRole
            Effect: Allow
            Principal:
              Service:
                - chatbot.amazonaws.com
      Policies:
        - PolicyName: slack-channel-cofiguration-policy
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Action:
                  - cloudwatch:Describe*
                  - cloudwatch:Get*
                  - cloudwatch:List*
                Effect: Allow
                Resource:
                  - '*'

AWS Configの設定テンプレート

'awsconfig-template'
AWSTemplateFormatVersion: '2010-09-09'

Resources:
  # IAM Role
  IAMRoleConfigRulesRole:
    Type: AWS::IAM::Role
    Properties:
      RoleName: config-rules-role
      Description: IAM role for CloudFormation Drift Detection
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - config.amazonaws.com
                - cloudformation.amazonaws.com
            Action:
              - sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/ReadOnlyAccess
      Policies:
        - PolicyName: AllowAccessToDriftDetection
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - cloudformation:DetectStackResourceDrift
                  - cloudformation:DescribeStackDriftDetectionStatus
                  - cloudformation:DetectStackDrift
                Resource: '*'
                
  # AWS config
  ConfigBucket:
    DeletionPolicy: Retain
    Type: AWS::S3::Bucket
    Properties:
      BucketEncryption:
          ServerSideEncryptionConfiguration:
            - ServerSideEncryptionByDefault:
                SSEAlgorithm: AES256
  ConfigBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref ConfigBucket
      PolicyDocument:
        Version: 2012-10-17
        Statement:
          - Sid: AWSConfigBucketPermissionsCheck
            Effect: Allow
            Principal:
              Service:
                - config.amazonaws.com
            Action: s3:GetBucketAcl
            Resource:
              - !Sub "arn:${AWS::Partition}:s3:::${ConfigBucket}"
            Condition:
              StringEquals:
                AWS:SourceAccount: !Ref "AWS::AccountId"
          - Sid: AWSConfigBucketDelivery
            Effect: Allow
            Principal:
              Service:
                - config.amazonaws.com
            Action: s3:PutObject
            Resource:
              - !Sub "arn:${AWS::Partition}:s3:::${ConfigBucket}/AWSLogs/${AWS::AccountId}/*"
            Condition:
              StringEquals:
                AWS:SourceAccount: !Ref "AWS::AccountId"
          - Sid: AWSConfigBucketSecureTransport
            Action:
              - s3:*
            Effect: Deny
            Resource:
              - !Sub "arn:${AWS::Partition}:s3:::${ConfigBucket}"
              - !Sub "arn:${AWS::Partition}:s3:::${ConfigBucket}/*"
            Principal: "*"
            Condition:
              Bool:
                aws:SecureTransport:
                  false
  ConfigRecorderRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: 2012-10-17
        Statement:
          - Effect: Allow
            Principal:
              Service:
                - config.amazonaws.com
            Action:
              - sts:AssumeRole
      Path: /
      ManagedPolicyArns:
        - !Sub "arn:${AWS::Partition}:iam::aws:policy/service-role/AWS_ConfigRole"
  ConfigRecorder:
    Type: AWS::Config::ConfigurationRecorder
    DependsOn:
      - ConfigBucketPolicy
    Properties:
      RoleARN: !GetAtt ConfigRecorderRole.Arn
      RecordingGroup:
        AllSupported: False
        IncludeGlobalResourceTypes: False
        ResourceTypes: 
          - AWS::CloudFormation::Stack
        ExclusionByResourceTypes:
          ResourceTypes: []
        RecordingStrategy:
          UseOnly: INCLUSION_BY_RESOURCE_TYPES
  ConfigDeliveryChannel:
    Type: AWS::Config::DeliveryChannel
    DependsOn:
      - ConfigBucketPolicy
    Properties:
      S3BucketName: !Ref ConfigBucket

  # EventsRule
  EventRuleForConfig:
    Type: AWS::Events::Rule
    Properties:
      Description: 自動リソースに手動で修正が入ったときに検知します
      EventBusName: default
      EventPattern:
        source:
          - aws.config
        detail-type:
          - Config Rules Compliance Change
        detail:
          messageType:
            - ComplianceChangeNotification
          configRuleName:
            - cloudformation-stack-drift-detection-check
          resourceType:
            - AWS::CloudFormation::Stack
          newEvaluationResult:
            complianceType:
              - NON_COMPLIANT
      Name: config-notify-resource-rule
      State: ENABLED
      Targets:
        - Id: snsid
          Arn: !Sub arn:aws:sns:ap-northeast-1:${AWS::AccountId}:config-notification-resource

  # SNS Topic
  SNSTopicConfigNotification:
    Type: AWS::SNS::Topic
    Properties:
      TopicName: config-notification-resource
      DisplayName: config-notification-resource
      Subscription:
        - Endpoint: 'https://global.sns-api.chatbot.amazonaws.com'
          Protocol: https
  SNSTopicPolicyConfigNotification:
    Type: AWS::SNS::TopicPolicy
    Properties:
      PolicyDocument:
        Version: '2008-10-17'
        Id: '__default_policy_ID'
        Statement:
          - Sid: 'AWSEvents_config-notify-resource-rule_snsid'
            Effect: Allow
            Principal:
              Service:
                - 'events.amazonaws.com'
            Action:
              - 'SNS:Publish'
            Resource: 
              - !Ref SNSTopicConfigNotification
      Topics:
        - !Ref SNSTopicConfigNotification

参考

  1. スタックのテンプレートと実際のリソースの差分を検出してくれる機能。詳しくはこちら

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?