#構成#
Configで設定変更を検知 >> Event Bridge をトリガーに SNSトピックに通知 >> SNSトピックに設定されているChatbotに情報送信 >> ChatbotがSlackに通知
というのを CloudFormation でデプロイしていこうと思います。
#パターン1#
1アカウント1つのリージョンにのみ、Configで設定変更を検知した場合に、Slackへ通知するようにしてみたいと思います。
##Chatbot##
###ワークスペースID###
チャットクライアントで、Slack
を選択し、「クライアントを設定」をする。
AWS Chatbot が XXX Slack ワークスペースにアクセスする権限をリクエストするので、「許可する」。
ワークスペースID
を控えておく。(後で、CloudFormation へ埋め込むのに必要)
###チャネルID###
Slack のチャネルで右クリックして、「リンクをコピー」。
https://XXX.slack.com/archives/1234567890
の 1234567890
の部分をチャネルID
として控えておく。(後で、CloudFormation へ埋め込むのに必要)
##Config##
CloudFormation から
AWSConfigDeliveryChannel
AWSConfigRecorder
を作成しようとした際に、次のように 1 つまでですと怒られることがある。
Failed to put configuration recorder 'AWSConfigRecorder'
because the maximum number of configuration recorders: 1 is reached.
この場合、次のページに書かれている内容で、CLIから削除する必要がある。(コンソールからは削除できない。)
とはいえ、Config は既に有効化されていることが多いので、Config をまだ有効化していないパターンと既に有効化済の2パターンをCloudFormation でデプロイしてみたいと思う。
###Config をまだ有効化していない場合###
コメントの<>の箇所は適宜自分のものに修正する。
AWSTemplateFormatVersion: 2010-09-09
Description: aws config sns slack
Resources:
#S3#
ConfigS3Bucket:
Type: AWS::S3::Bucket
Properties:
BucketName: <<BucketName>> ##
S3BucketPolicy:
Type: AWS::S3::BucketPolicy
DependsOn: ConfigS3Bucket
Properties:
Bucket: !Ref ConfigS3Bucket
PolicyDocument:
Version: 2012-10-17
Statement:
-
Sid: AWSConfigBucketPermissionsCheck
Effect: Allow
Principal:
Service: config.amazonaws.com
Action: s3:GetBucketAcl
Resource: arn:aws:s3:::<<BucketName>> ##
-
Sid: AWSConfigBucketExistenceCheck
Effect: Allow
Principal:
Service: config.amazonaws.com
Action: s3:ListBucket
Resource: arn:aws:s3:::<<BucketName>> ##
-
Sid: AWSConfigBucketDelivery
Effect: Allow
Principal:
Service: config.amazonaws.com
Action: s3:PutObject
Resource: !Sub arn:aws:s3:::<<BucketName>>/AWSLogs/${AWS::AccountId}/Config/* ##
Condition:
StringEquals:
s3:x-amz-acl: bucket-owner-full-control
#IAM#
ConfigIAMManagedPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: naata-AWS-Chatbot-NotificationsOnly-Policy
Path: /service-role/
PolicyDocument: |
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"cloudwatch:Describe*",
"cloudwatch:Get*",
"cloudwatch:List*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
ConfigIAMRole:
Type: AWS::IAM::Role
DependsOn: ConfigIAMManagedPolicy
Properties:
Path: /service-role/
RoleName: naata-Chatbot-role
AssumeRolePolicyDocument: "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"chatbot.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}"
MaxSessionDuration: 3600
ManagedPolicyArns:
- !Ref ConfigIAMManagedPolicy
Description: naata AWS Chatbot Execution Role
#Chatbot#
ConfigChatbotSlackChannelConfiguration:
Type: AWS::Chatbot::SlackChannelConfiguration
DependsOn: ConfigSNSTopic
Properties:
ConfigurationName: naata-ConfigChatbot
IamRoleArn: !GetAtt ConfigIAMRole.Arn
LoggingLevel: ERROR
SlackChannelId: <<>SlackChannelId> ##
SlackWorkspaceId: <<SlackWorkspaceId>> ##
SnsTopicArns:
- !Ref ConfigSNSTopic
#SNS#
ConfigSNSTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: naata-ConfigSNSTopic
ConfigSNSTopicPolicy:
Type: AWS::SNS::TopicPolicy
DependsOn: ConfigSNSTopic
Properties:
PolicyDocument: !Sub "{\"Version\":\"2008-10-17\",\"Id\":\"__default_policy_ID\",\"Statement\":[{\"Sid\":\"__default_statement_ID\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Action\":[\"SNS:GetTopicAttributes\",\"SNS:SetTopicAttributes\",\"SNS:AddPermission\",\"SNS:RemovePermission\",\"SNS:DeleteTopic\",\"SNS:Subscribe\",\"SNS:ListSubscriptionsByTopic\",\"SNS:Publish\",\"SNS:Receive\"],\"Resource\":\"${ConfigSNSTopic}\",\"Condition\":{\"StringEquals\":{\"AWS:SourceOwner\":\"${AWS::AccountId}\"}}}]}"
Topics:
- !Ref ConfigSNSTopic
ConfigSNSSubscription:
Type: AWS::SNS::Subscription
DependsOn: ConfigSNSTopic
Properties:
TopicArn: !Ref ConfigSNSTopic
Endpoint: https://global.sns-api.chatbot.amazonaws.com
Protocol: https
RawMessageDelivery: "false"
Region: !Ref AWS::Region
#config#
ConfigConfigurationRecorder:
Type: AWS::Config::ConfigurationRecorder
Properties:
Name: default
RecordingGroup:
AllSupported: true
IncludeGlobalResourceTypes: true
RoleARN: !Sub arn:aws:iam::${AWS::AccountId}:role/aws-service-role/config.amazonaws.com/AWSServiceRoleForConfig
ConfigDeliveryChannel:
Type: AWS::Config::DeliveryChannel
DependsOn:
- ConfigS3Bucket
- ConfigSNSTopic
Properties:
Name: default
S3BucketName: !Ref ConfigS3Bucket
SnsTopicARN: !Ref ConfigSNSTopic
ConfigSnapshotDeliveryProperties:
DeliveryFrequency: Six_Hours
#Events#
ConfigEventsRule:
Type: AWS::Events::Rule
Properties:
Name: naata-ConfigEventsRule
EventPattern: "{\"source\":[\"aws.config\"],\"detail-type\":[\"Config Configuration Item Change\"],\"detail\":{\"messageType\":[\"ConfigurationItemChangeNotification\"]}}"
State: "ENABLED"
Targets:
-
Arn: !Sub "arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${ConfigSNSTopic.TopicName}"
Id: naata-ConfigSNSTopic
EventBusName: default
###Configを既に有効化済の場合###
AWSTemplateFormatVersion: 2010-09-09
Description: aws config sns slack
Resources:
#IAM#
ConfigIAMManagedPolicy:
Type: AWS::IAM::ManagedPolicy
Properties:
ManagedPolicyName: naata-AWS-Chatbot-NotificationsOnly-Policy
Path: /service-role/
PolicyDocument: |
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"cloudwatch:Describe*",
"cloudwatch:Get*",
"cloudwatch:List*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
ConfigIAMRole:
Type: AWS::IAM::Role
DependsOn: ConfigIAMManagedPolicy
Properties:
Path: /service-role/
RoleName: naata-Chatbot-role
AssumeRolePolicyDocument: "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"chatbot.amazonaws.com\"},\"Action\":\"sts:AssumeRole\"}]}"
MaxSessionDuration: 3600
ManagedPolicyArns:
- !Ref ConfigIAMManagedPolicy
Description: naata AWS Chatbot Execution Role
#Chatbot#
ConfigChatbotSlackChannelConfiguration:
Type: AWS::Chatbot::SlackChannelConfiguration
DependsOn: ConfigSNSTopic
Properties:
ConfigurationName: naata-ConfigChatbot
IamRoleArn: !GetAtt ConfigIAMRole.Arn
LoggingLevel: ERROR
SlackChannelId: <<>SlackChannelId> ##
SlackWorkspaceId: <<SlackWorkspaceId>> ##
SnsTopicArns:
- !Ref ConfigSNSTopic
#SNS#
ConfigSNSTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: naata-ConfigSNSTopic
ConfigSNSTopicPolicy:
Type: AWS::SNS::TopicPolicy
DependsOn: ConfigSNSTopic
Properties:
PolicyDocument: !Sub "{\"Version\":\"2008-10-17\",\"Id\":\"__default_policy_ID\",\"Statement\":[{\"Sid\":\"__default_statement_ID\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Action\":[\"SNS:GetTopicAttributes\",\"SNS:SetTopicAttributes\",\"SNS:AddPermission\",\"SNS:RemovePermission\",\"SNS:DeleteTopic\",\"SNS:Subscribe\",\"SNS:ListSubscriptionsByTopic\",\"SNS:Publish\",\"SNS:Receive\"],\"Resource\":\"${ConfigSNSTopic}\",\"Condition\":{\"StringEquals\":{\"AWS:SourceOwner\":\"${AWS::AccountId}\"}}}]}"
Topics:
- !Ref ConfigSNSTopic
ConfigSNSSubscription:
Type: AWS::SNS::Subscription
DependsOn: ConfigSNSTopic
Properties:
TopicArn: !Ref ConfigSNSTopic
Endpoint: https://global.sns-api.chatbot.amazonaws.com
Protocol: https
RawMessageDelivery: "false"
Region: !Ref AWS::Region
#Events#
ConfigEventsRule:
Type: AWS::Events::Rule
Properties:
Name: naata-ConfigEventsRule
EventPattern: "{\"source\":[\"aws.config\"],\"detail-type\":[\"Config Configuration Item Change\"],\"detail\":{\"messageType\":[\"ConfigurationItemChangeNotification\"]}}"
State: "ENABLED"
Targets:
-
Arn: !Sub "arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${ConfigSNSTopic.TopicName}"
Id: naata-ConfigSNSTopic
EventBusName: default
##動作確認1##
まず、Chatbot >> Slack に通知されるか確認してみたいと思います。
Chatbot の作成されたチャネルを開くと、画面右上に「テストメッセージを送信」があるのでクリックする。
次に適当な変更を加えて、Slack に通知されるか確認してみたいと思います。
今回は、S3の暗号化を有効にしてみました。
#パターン2#
1アカウント全リージョンに対して、Configで設定変更を検知した場合に、Slackへ通知するようにしてみたいと思います。
##Config##
AWS CloudFormation StackSets サンプルテンプレートを使って、全リージョンにConfigを有効化することも可能である。
ただし、今回は既に有効化されているリージョンもあるためコンソールから個別に有効化していく。設定項目は次の通り。基本的に余計な設定は行わない。SNSはEventBridgeから飛ばすので設定しない。
##IAMロール##
セルフマネージド型のアクセス許可を付与する にある 2 つのIAMロールをCloudFormationスタックを使って作成する。
-
AWSCloudFormationStackSetAdministrationRole
https://s3.amazonaws.com/cloudformation-stackset-sample-templates-us-east-1/AWSCloudFormationStackSetAdministrationRole.yml -
AWSCloudFormationStackSetExecutionRole
https://s3.amazonaws.com/cloudformation-stackset-sample-templates-us-east-1/AWSCloudFormationStackSetExecutionRole.yml
AWSTemplateFormatVersion: 2010-09-09
Description: Creating AWSCloudFormationStackSetAdministrationRole and AWSCloudFormationStackSetExecutionRole
Parameters:
MasterAccountId:
Type: String
Description: AWS Account Id of the master account (the account in which StackSets will be created).
MaxLength: 12
MinLength: 12
Resources:
#AdministrationRole
AdministrationRole:
Type: AWS::IAM::Role
Properties:
RoleName: AWSCloudFormationStackSetAdministrationRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service: cloudformation.amazonaws.com
Action:
- sts:AssumeRole
Path: /
Policies:
- PolicyName: AssumeExecutionRole
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- sts:AssumeRole
Resource:
- "arn:aws:iam::*:role/AWSCloudFormationStackSetExecutionRole"
#ExecutionRole
ExecutionRole:
Type: AWS::IAM::Role
Properties:
RoleName: AWSCloudFormationStackSetExecutionRole
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
AWS:
- !Ref MasterAccountId
Action:
- sts:AssumeRole
Path: /
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AdministratorAccess
##EventBridge、SNSTopic##
Cloudformation StackSets で、EventBridge、SNSTopic を全リージョンにデプロイする。
AWSTemplateFormatVersion: 2010-09-09
Description: Config Slack notification, EventBridge adn SNSTopic creation
Resources:
#Events#
ConfigEventsRule:
Type: AWS::Events::Rule
Properties:
Name: ConfigEventsRule
EventPattern: "{\"source\":[\"aws.config\"],\"detail-type\":[\"Config Configuration Item Change\"],\"detail\":{\"messageType\":[\"ConfigurationItemChangeNotification\"]}}"
State: "ENABLED"
Targets:
-
Arn: !Sub "arn:aws:sns:${AWS::Region}:${AWS::AccountId}:${ConfigSNSTopic.TopicName}"
Id: ConfigSNSTopic
EventBusName: default
#SNS#
ConfigSNSTopic:
Type: AWS::SNS::Topic
Properties:
TopicName: ConfigSNSTopic
ConfigSNSTopicPolicy:
Type: AWS::SNS::TopicPolicy
Properties:
PolicyDocument: !Sub "{\"Version\":\"2008-10-17\",\"Id\":\"__default_policy_ID\",\"Statement\":[{\"Sid\":\"__default_statement_ID\",\"Effect\":\"Allow\",\"Principal\":{\"AWS\":\"*\"},\"Action\":[\"SNS:GetTopicAttributes\",\"SNS:SetTopicAttributes\",\"SNS:AddPermission\",\"SNS:RemovePermission\",\"SNS:DeleteTopic\",\"SNS:Subscribe\",\"SNS:ListSubscriptionsByTopic\",\"SNS:Publish\",\"SNS:Receive\"],\"Resource\":\"${ConfigSNSTopic}\",\"Condition\":{\"StringEquals\":{\"AWS:SourceOwner\":\"${AWS::AccountId}\"}}},{\"Sid\":\"AWSEvents_config_Iddbe4eadd-2e0e-433e-acae-40e14a8cf397\",\"Effect\":\"Allow\",\"Principal\":{\"Service\":\"events.amazonaws.com\"},\"Action\":\"sns:Publish\",\"Resource\":\"${ConfigSNSTopic}\"}]}"
Topics:
- !Ref ConfigSNSTopic
ステップ 1 テンプレートの選択
ここは、スタックの作成と同じように、Amazon S3 URLまたは、テンプレートファイルのアップロードを行う。
ステップ 2 StackSet の詳細を指定
ステップ 3 StackSet オプションの設定
「セルフサービスのアクセス許可」を選択。
IAM 管理ロール ARN は先程CloudFormationスタックで作成されたIAMロールを選択。
ステップ 4 StackSet にスタックを追加
「スタックをアカウントにデプロイ」を選択し、「アカウント番号」を入力。
ステップ 5 レビュー
「AWS CloudFormation によって IAM リソースがカスタム名で作成される場合があることを承認します。」にチェックを入れる。
##Chatbot##
ChatbotワークスペースとChatbotチャンネルを作成していく。
- Chatbotワークスペース:この記事の最初の部分で紹介済なので作成方法は割愛する。
- Chatbotチャンネル:CloudFormationスタックで作成していく。
AWSTemplateFormatVersion: '2010-09-09'
Description: Creating a slack channel
Parameters:
SnsTopicName:
Type: String
Default: ConfigSNSTopic
SlackWorkspaceId:
Type: String
Default: XXXXXXXXX
SlackChannelId:
Type: String
Default: YYYYYYYYY
Resources:
#Chatbot用 IAMロール
ChatbotIamRole:
Type: AWS::IAM::Role
Properties:
RoleName: ChatbotIamRole
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Action: "sts:AssumeRole"
Principal:
Service: "chatbot.amazonaws.com"
Policies:
- PolicyName: AWS-Chatbot-NotificationsOnly-Policy
PolicyDocument:
Version: "2012-10-17"
Statement:
- Action:
- "cloudwatch:Describe*"
- "cloudwatch:Get*"
- "cloudwatch:List*"
Effect: "Allow"
Resource: "*"
#Chatbot
ChatbotConfiguration:
Type: AWS::Chatbot::SlackChannelConfiguration
Properties:
ConfigurationName: Config-Chatbot-SlackChanel
IamRoleArn: !GetAtt ChatbotIamRole.Arn
LoggingLevel: ERROR
SlackChannelId: !Ref SlackChannelId
SlackWorkspaceId: !Ref SlackWorkspaceId
SnsTopicArns:
- !Sub 'arn:aws:sns:ap-northeast-1:${AWS::AccountId}:${SnsTopicName}'
- !Sub 'arn:aws:sns:ap-northeast-2:${AWS::AccountId}:${SnsTopicName}'
- !Sub 'arn:aws:sns:ap-northeast-3:${AWS::AccountId}:${SnsTopicName}'
- !Sub 'arn:aws:sns:ap-south-1:${AWS::AccountId}:${SnsTopicName}'
- !Sub 'arn:aws:sns:ap-southeast-1:${AWS::AccountId}:${SnsTopicName}'
- !Sub 'arn:aws:sns:ap-southeast-2:${AWS::AccountId}:${SnsTopicName}'
- !Sub 'arn:aws:sns:ca-central-1:${AWS::AccountId}:${SnsTopicName}'
- !Sub 'arn:aws:sns:eu-central-1:${AWS::AccountId}:${SnsTopicName}'
- !Sub 'arn:aws:sns:eu-north-1:${AWS::AccountId}:${SnsTopicName}'
- !Sub 'arn:aws:sns:eu-west-1:${AWS::AccountId}:${SnsTopicName}'
- !Sub 'arn:aws:sns:eu-west-2:${AWS::AccountId}:${SnsTopicName}'
- !Sub 'arn:aws:sns:eu-west-3:${AWS::AccountId}:${SnsTopicName}'
- !Sub 'arn:aws:sns:sa-east-1:${AWS::AccountId}:${SnsTopicName}'
- !Sub 'arn:aws:sns:us-east-1:${AWS::AccountId}:${SnsTopicName}'
- !Sub 'arn:aws:sns:us-east-2:${AWS::AccountId}:${SnsTopicName}'
- !Sub 'arn:aws:sns:us-west-1:${AWS::AccountId}:${SnsTopicName}'
- !Sub 'arn:aws:sns:us-west-2:${AWS::AccountId}:${SnsTopicName}'
##動作確認2##