はじめに
タイトルの通り、1年ほど前にAWS Configを使ってリソースの手動変更が起きた際にSlackで通知するCloudFormationのコードを作成したので、記録に残します。
目次
実現したこと
実現したこととしては以下の通りです。
- 前提
- CloudFormationでAWSのリソースを全て管理していること(=スタックで作成しているリソースが今回の監視対象)
- 仕組み
- 1時間に1回ドリフト検出のルール1を走らせる
- ドリフトが検出された(=リソースの手動変更があった)場合、EventBridgeが発火し、SNSトピック→ChatbotからSlackの任意のチャンネルへ通知がいく
- 1時間に1回ドリフト検出のルール1を走らせる
コード
ドリフト検出ルールのテンプレート
'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
参考
- AWSで新しくリソース作成されたときに通知を受け取りたい~Configのリソースタイプで検知しよう~
- ConfigのConfigurationItemStatus一覧
- Configサポートのリソースタイプ一覧