はじめに
あるシステムにおいて、CodeCommitのあるAWSアカウントから別のアカウントのCodePipelineを起動したいという要件がありました。
別のアカウントのリポジトリを参照してCodePipelineを起動するには、主に「別アカウントのリポジトリの変更を検知してパイプラインを起動する」と「パイプラインから別アカウントのリポジトリリソースの参照」が必要になります。
この記事ではEventBridgeを使って、アカウントをまたいで通知する方法について説明します。
この記事のゴール
この記事のゴールは、CodeCommitのmasterブランチに変更が加わったら別アカウントでそれを検知できるところまでです。
クロスアカウントでのCodePipelineの実行については次の機会にでも説明します。
リポジトリアカウントの環境を作る
以降はアカウントは以下のように呼びます
リポジトリアカウント : CodeCommitのRepositoryがある方のアカウント
パイプラインアカウント : CodePipelineがある方のアカウント
リポジトリアカウント側で以下のCFn(CloudFormation)テンプレートを使って
CodeCommit リポジトリ
Event Rule
を作成します。さらに、Eventの内容や状態を確認するためにCloudWatch Logsへも書き込むように構成します。
(CloudWatch Logsは確認用なので不要になったら削除して良いです)
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
# イベント通知先のAWSアカウントID
ExternalAccountId:
Type: String
TargetBranchName:
Type: String
Resources:
# リポジトリ
Repo:
DeletionPolicy: Retain
Type: AWS::CodeCommit::Repository
Properties:
RepositoryName: "Repo"
# 流れているイベントを確認するためのLogGroup
# 不要になったら削除してOK
EventDebugLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub "/aws/events/${AWS::StackName}-EventDebugLog"
# RuleからLogsに書き込むためのポリシー
EventDebugLogGroupPolicy:
Type: AWS::Logs::ResourcePolicy
Properties:
PolicyName: !Sub "${AWS::StackName}-EventDebugLogGroupPolicy"
PolicyDocument: !Sub |
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"events.amazonaws.com",
"delivery.logs.amazonaws.com"
]
},
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
# CodeCommitからのイベントで起動するRuleのRole
CodeCommitBranchEventRuleRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Principal:
Service:
- events.amazonaws.com
- delivery.logs.amazonaws.com
Action: sts:AssumeRole
Path: /
Policies:
# 別アカウントのEventBusにイベントを送信する
- PolicyName: default
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: events:PutEvents
Resource: !Sub arn:aws:events:${AWS::Region}:${ExternalAccountId}:event-bus/default
# CloudWatchEventの実行ルール
CodeCommitBranchEventRule:
Type: AWS::Events::Rule
Properties:
Name: !Sub "${AWS::StackName}-CodeCommitBranchEventRule"
EventPattern:
source:
- aws.codecommit
detail-type:
- CodeCommit Repository State Change
resources:
- !Sub "arn:aws:codecommit:${AWS::Region}:${AWS::AccountId}:${Repo.Name}"
detail:
event:
- referenceCreated
- referenceUpdated
referenceType:
- branch
referenceName:
- !Ref TargetBranchName
Targets:
- Arn: !Sub arn:aws:events:${AWS::Region}:${ExternalAccountId}:event-bus/default
RoleArn: !GetAtt CodeCommitBranchEventRuleRole.Arn
Id: external
# 動作確認用CloudWatch Logs出力
- Arn: !GetAtt EventDebugLogGroup.Arn
Id: log-debug
CFn Stackが作成されたら EventBridgeでRuleが作成されていることを確認します。
(余談ですが、AWSとしてはアカウントIDは秘匿すべき情報ではないというアナウンスをしていてもなんとなく隠したい気持ちになります)
リポジトリにソースをPushする
CodeCommitリポジトリのmasterブランチに変更をpushして、CloudWatch Logsにイベントが記録されることを確認します。
(この時点でTargetに指定しているパイプラインアカウントのEventBusにもメッセージは送ろうとしていますが、まだパイプラインアカウント側で許可していないのでエラーになっていることがモニタリングで記録されているはずです)
パイプラインアカウントの環境を作る
パイプラインアカウント側で以下のCFn(CloudFormation)テンプレートを使って
Event Rule
を作成します。リポジトリアカウントと同様に、Eventの内容や状態を確認するためにCloudWatch Logsへも書き込むように構成します。
(こちらもCloudWatch Logsは確認用なので不要になったら削除して良いです)
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
# リポジトリののAWSアカウントID
RepositoryAccountId:
Type: String
# リポジトリ名
RepositoryName:
Type: String
# 変更を検知するCodeCommitのブランチ名
TargetBranchName:
Type: String
Resources:
# EventBusがリポジトリアカウントからのメッセージを受信することを許可
EventBusPolicy:
Type: AWS::Events::EventBusPolicy
Properties:
StatementId: default
Statement:
Effect: Allow
Principal:
AWS: !Sub arn:aws:iam::${RepositoryAccountId}:root
Action: events:PutEvents
Resource: !Sub arn:aws:events:${AWS::Region}:${AWS::AccountId}:event-bus/default
# 流れているイベントを確認するためのLogGroup
# 不要になったら削除してOK
EventDebugLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub "/aws/events/${AWS::StackName}-EventDebugLog"
# RuleからLogsに書き込むためのポリシー
EventDebugLogGroupPolicy:
Type: AWS::Logs::ResourcePolicy
Properties:
PolicyName: !Sub "${AWS::StackName}-EventDebugLogGroupPolicy"
PolicyDocument: !Sub |
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"events.amazonaws.com",
"delivery.logs.amazonaws.com"
]
},
"Action": [
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "*"
}
]
}
# CloudWatchEventの実行ルール
CodeCommitBranchEventRule:
Type: AWS::Events::Rule
Properties:
Name: !Sub "${AWS::StackName}-CodeCommitBranchEventRule"
EventPattern:
source:
- aws.codecommit
detail-type:
- CodeCommit Repository State Change
resources:
- !Sub "arn:aws:codecommit:${AWS::Region}:${RepositoryAccountId}:${RepositoryName}"
detail:
event:
- referenceCreated
- referenceUpdated
referenceType:
- branch
referenceName:
- !Ref TargetBranchName
Targets:
# 動作確認用CloudWatch Logs出力
- Arn: !GetAtt EventDebugLogGroup.Arn
Id: log-debug
CFn Stackが作成されたら EventBridgeでRuleが作成されていることを確認します。
確認
再度リポジトリに変更をpushします。
パイプラインアカウントのRuleのターゲットに指定したCloudWatch Logsにメッセージが到達していることを確認します。
ちなみに、リポジトリアカウントのLogsのメッセージとパイプラインアカウントのメッセージは当たり前なのですが同じですね。
また、私の評価した環境ではそれぞれのログの記録時刻は同時でした。
これでリポジトリの変更イベントを別のアカウントで検出することができました。
後はパイプラインアカウント側のRuleのTriggerで好きな処理を起動することができます。
次回はCodePipelineの起動までいってみたいと思います。
Comentários