こんにちは。たかやまです。
Organizationsを運用している環境でアカウント発行者とアカウント利用者が別れていることがあります。
このような場合に、アカウント発行後にアカウント利用者側で後続作業を行うために、アカウントが作成されたことを知りたいというニーズがあるかと思います。
今回はアカウント発行後にアカウント利用者側で気付けるように、OrganizationsとControlTowerでアカウントが発行された際にSlackへ通知する方法をご紹介します。
さきにポイント
- Organizationsのアカウント発行イベントはus-east-1(バージニア北部)で記録される
- アカウント発行イベント名は
CreateAccount
- ControlTowerによるアカウント発行でもトリガーされるため、
principalId
で判断する
- アカウント発行イベント名は
- ControlTowerのアカウント発行イベントはホームリージョンで記録される
- アカウント発行イベント名は
CreateManagedAccount
- アカウント発行イベント名は
構成図
今回の検証ではControlTowerをap-northeast-1に設定しています。
やってみた
通知に必要なEventBridge、SNS、Chatbotは、CloudFormationで作成します。
ControlTowerの通知リソース作成
はじめにControlTowerのイベントを通知するためにホームリージョンでリソースを作成します。
ControlTowerはap-northeast-1
をホームリージョンとしています。
AWSTemplateFormatVersion: "2010-09-09"
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: ""
Parameters:
- ProjectName
- Environment
ParameterLabels: {}
Parameters:
ProjectName:
Type: String
ConstraintDescription: This parameter is required.
Description: The name of the project.
MinLength: 1
Environment:
Type: String
ConstraintDescription: This parameter is required.
Description: The name of the environment.
MinLength: 1
Resources:
SnsTopic:
Type: AWS::SNS::Topic
Properties:
DisplayName: !Sub "${ProjectName}-${Environment}-sns"
TopicName: !Sub "${ProjectName}-${Environment}-sns"
SnsTopicPolicy:
Type: "AWS::SNS::TopicPolicy"
Properties:
PolicyDocument:
Version: "2012-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"
Resource: !Ref SnsTopic
Condition:
StringEquals:
"AWS:SourceOwner": !Sub ${AWS::AccountId}
- Sid: "AWSEvents_Allow"
Effect: "Allow"
Principal:
Service: "events.amazonaws.com"
Action: "sns:Publish"
Resource: !Ref SnsTopic
Topics:
- !Ref SnsTopic
EventBridgeRuleControlTower:
Type: AWS::Events::Rule
Properties:
Name: !Sub "${ProjectName}-${Environment}-controltower-events"
Description: "EventBridge Rule for AWS Control Tower events"
EventPattern:
source:
- "aws.controltower"
detail-type:
- "AWS Service Event via CloudTrail"
detail:
eventName:
- "CreateManagedAccount"
State: "ENABLED"
Targets:
- Arn: !Ref SnsTopic
Id: "TargetSnsTopicCT"
Outputs:
SnsTopicArn:
Description: "The ARN of the SNS topic."
Value: !Ref SnsTopic
CloudFormation作成後、出力
でSNS TopicのARNが表示されます。
こちらは後続のOrganizations向けの通知テンプレート作成で使用するので控えます。
また、作成されたEventBridgeのRuleは以下のようになります。
{
"detail-type": ["AWS Service Event via CloudTrail"],
"source": ["aws.controltower"],
"detail": {
"eventName": ["CreateManagedAccount"]
}
}
Account Factory を使用したアカウント作成の場合、CreateManagedAccount
でトリガーされます。
AWS Control Tower でのライフサイクルイベント(CreateManagedAccount) - AWS Control Tower
Organizationsの通知リソース作成
次にOrganizationsのイベントを通知するためのリソースを作成していきます。
Organizationsのイベントはus-east-1(バージニア北部)
でのみ記録されます。そのためOrganizationsのイベントを通知するリソースはus-east-1(バージニア北部)でリソースを作成していく必要があります。
重要
AWS Organizations の CloudTrail に関するすべての情報は、米国東部 (バージニア北部) リージョンのみで表示できます。CloudTrail コンソールで AWS Organizations アクティビティが表示されない場合は、右上隅のメニューを使用して、コンソールを 米国東部 (バージニア北部) に設定します。AWS CLI または SDK ツールを使用して CloudTrail のクエリを実行する場合、クエリを米国東部 (バージニア北部) エンドポイントに指定します。
テンプレートでは以下のパラメータを指定する必要があります。
ProjectName
: 任意のプロジェクト名Environment
: 任意の環境名SlackWorkspaceId
: 事前に用意しているSlackのWorkspace IDSlackChannelName
: 任意のSlackのChannel IdSNSTopicArn
: 先ほど作成したControlTowerのSNS TopicのARN
AWSTemplateFormatVersion: "2010-09-09"
Metadata:
AWS::CloudFormation::Interface:
ParameterGroups:
- Label:
default: ""
Parameters:
- ProjectName
- Environment
- SlackWorkspaceId
- SlackChannelName
- SNSTopicArn
ParameterLabels: {}
Parameters:
ProjectName:
Type: String
ConstraintDescription: This parameter is required.
Description: The name of the project.
MinLength: 1
Environment:
Type: String
ConstraintDescription: This parameter is required.
Description: The name of the environment.
MinLength: 1
SlackWorkspaceId:
Type: String
Default: ""
Description: Slack Workspace ID
SlackChannelName:
Type: String
Default: ""
Description: Slack Channel Name
SNSTopicArn:
Type: String
Description: The ARN of the SNS topic.
MinLength: 1
Resources:
SnsTopic:
Type: AWS::SNS::Topic
Properties:
DisplayName: !Sub "${ProjectName}-${Environment}-sns"
TopicName: !Sub "${ProjectName}-${Environment}-sns"
SnsTopicPolicy:
Type: "AWS::SNS::TopicPolicy"
Properties:
PolicyDocument:
Version: "2012-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"
Resource: !Ref SnsTopic
Condition:
StringEquals:
"AWS:SourceOwner": !Sub ${AWS::AccountId}
- Sid: "AWSEvents_Allow"
Effect: "Allow"
Principal:
Service: "events.amazonaws.com"
Action: "sns:Publish"
Resource: !Ref SnsTopic
Topics:
- !Ref SnsTopic
EventBridgeRuleOrganizations:
Type: AWS::Events::Rule
Properties:
Name: !Sub "${ProjectName}-${Environment}-organization-events"
Description: "EventBridge Rule for AWS Organizations events"
EventPattern:
source:
- "aws.organizations"
detail-type:
- "AWS API Call via CloudTrail"
detail:
eventName:
- "CreateAccount"
userIdentity:
principalId:
- anything-but:
suffix: "CreateManagedAccount"
State: "ENABLED"
Targets:
- Arn: !Ref SnsTopic
Id: "TargetSnsTopicOrg"
ChatBotConfigurationRole:
Type: AWS::IAM::Role
Properties:
RoleName: !Sub "${ProjectName}-${Environment}-chatbot-role"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service: "chatbot.amazonaws.com"
Action: "sts:AssumeRole"
ChatBot:
Type: AWS::Chatbot::SlackChannelConfiguration
Properties:
ConfigurationName: !Sub "${ProjectName}-${Environment}-chatbot"
IamRoleArn: !GetAtt ChatBotConfigurationRole.Arn
SlackChannelId: !Ref SlackChannelName
SlackWorkspaceId: !Ref SlackWorkspaceId
SnsTopicArns:
- !Ref SnsTopic
- !Ref SNSTopicArn
こちらで作成されたEventBridgeのRuleは以下のようになります。
{
"detail-type": ["AWS API Call via CloudTrail"],
"source": ["aws.organizations"],
"detail": {
"eventName": ["CreateAccount"],
"userIdentity": {
"principalId": [{
"anything-but": {
"suffix": "CreateManagedAccount"
}
}]
}
}
}
Organizationsのアカウント作成イベントはCreateAccount
でトリガーされます。
ただこちらのイベントはControlTowerによるアカウント作成でもトリガーされるため、principalId
でControlTowerによる呼び出しかユーザによる呼び出しかを判断しています。
ちなみに、バックグラウンドワークフローが正常に完了した際に発行されるCreateAccountResult
イベントもありますが、こちらはOrganizations/ControlTower両方の処理でトリガーされ判別が難しかったため通知のトリガーには使用していません。Organizationsでのみアカウントを発行している環境であれば、CreateAccountResult
イベントを使用するのが良いかと思います。
通知を確認する
Organizationsからアカウントを作成します。
作成したあとのSlack通知がこちらです。
作成されたアカウントについての情報はありませんが、CreateAccount
イベントからOrganizationsによるアカウント作成であることがわかります。
次にControlTowerのAccountFactoryからアカウントを作成します。
作成したあとのSlack通知がこちらです。
ControlTowerの通知では作成されたアカウントの名前や配置されたOU情報が含まれており内容がすこしリッチになっています。
最後に
今回、OrganizationsとControlTowerでアカウントが作成された際にSlackに通知する方法をご紹介しました。
アカウント発行者とアカウント利用者が別々の場合でも、アカウントが作成されたことを通知することで、アカウント利用者がアカウントを利用できるようになるまでのスピードを向上させることができるかと思います。
こちらの内容が誰かの助けになれば幸いです。
以上、たかやま(@nyan_kotaroo)でした。