0. はじめに
久しぶりの技術記事かつAWSのネタになります。
昨年は資格取得に時間を費やしたため、書きたかった記事のネタが永遠に下書きへ溜まっていました。
昨今話題のClaude Codeは私もバリバリ使っているのですが、この記事の叩きもAI君にサクッと書いてもらって、細かい部分のブラッシュアップをするだけで良くなるので本当に助かっています。
さて、本題ですが、今回は自宅に構築しているGitLabのSelf-Managed環境とAWSを接続し、CloudFormation GitSync(以下GitSync)で実際に同期させる実験を行いました。
GitSyncとはCloudFormationのスタックをGitリポジトリと同期させる機能で、リポジトリへのpushをトリガーに自動的にスタックの更新が走ります。
Gitの同期する資材は単純なIAMのユーザーやグループですが類似の構成を検討している人の参考になればと思い記事にしました。
構成は大まかに以下の通りです。
- CodeConnectionsのHost・Connectionおよびそれに付随するIAMを構築(自宅環境ではTerraformを使用していますが、わかりやすさ重視でGUIのキャプチャを貼っています。)
- GitSyncで管理するCloudFormationテンプレートのリポジトリを自宅GitLabに用意
- AWS コンソール上でGitSyncの設定を行いリポジトリと同期
なお、本記事では構築に使用したTerraformのコードは最後にGitHubのリンクを載せておきます。
1. 全体構成
構成のイメージは以下の通りです。
自宅GitLab
│ (HTTPS/VPN)
▼
AWS CodeConnections Host
│
▼
AWS CodeConnections Connection
│
▼
CloudFormation GitSync
│
▼
CloudFormation Stack(資材反映)
本来自宅GitLabはインターネットに直接公開しておらず、AWS Site-to-Site VPN経由でアクセスできる構成になっていますが、今回の記事ではパブリックなネットワークでアクセスできる環境で検証し記事にしています。
VPN経由でも問題なく構築はできていたのですが、自宅とAWSを繋ぐSite-to-Site VPNの記事がまだ出来上がっていないので、そちらが完成したらこちらもアップデートしようかと思います。
2. 自宅GitLabをAWS CodeConnectionsで接続する
2-1. Connection/Host構築
CodeConnections Connection
「CodeConnections Host」を別に作成することも可能ですが、以下の手順でまとめて作成できてしまうので、一緒に作ります。
自宅のオンプレGitLabに接続するためのHostリソースおよびHostとGitLabリポジトリを紐づけるConnectionリソースとなります。
CodeCommit > 設定 > 接続 から「接続を作成」をクリックし、以下のように入力します。
ホスト名はわかりやすい名前でよいと思います。
| 項目 | 設定内容 |
|---|---|
| プロバイダーを選択する | GitLab Self Managed |
| 接続名 | GitLabSelfManagedHost |
| URL | 自宅のGitLabのURL |
| VPC を使用 | チェックを外す |
2-2. GitLab認証設定
この状態で「GitLab Self Managed に接続」をクリックすると、ステータスが保留中となり、保留中の接続を更新というボタンが上部に現れます。
これをクリックすると、別ウインドウでGitLabのアクセストークンを入力する画面となります。
なおトークンはグループユーザーなどのBotはダメで管理者ユーザーのPATしかダメなようです。
You must have already created a GitLab personal access token (PAT) with the following scoped-down permission only: api, admin_mode.
ただし、認証が終わったらPATは削除してしまって問題ないと記載があります。
Your PAT is used to authorize the host and is not otherwise stored or used by connections. To set up a host, you can create a temporary PAT and then after you set up the host, you can delete the PAT.
PATを入力すると以下のようにGitLabのOAuth認証画面が表示されますので、認証を許可します。

エラー等が起きなければ以下のようにステータスが利用可能となっているはずです。
これで自宅GitLabとAWSの接続が完了しました。

3. GitSyncでIAM管理の同期構築を行う
3-1. 同期対象のリポジトリ構成
自宅GitLabにaws-gitsync-cfnという名前のリポジトリを用意しています。
このリポジトリにCloudFormationテンプレートとデプロイ設定ファイルを格納しています。
aws-gitsync-cfn/
├── cfn-deployments/
│ └── dev/
│ └── iam-deployment.yml # GitSync用のデプロイ設定ファイル
└──cfn-templates/
└── iam.yml # CloudFormationテンプレート本体
CloudFormationテンプレート (iam.yml)
IAMグループとユーザを作成するシンプルなテンプレートです。
管理者グループ/ユーザーと閲覧者グループ/ユーザーを作成します。
AWSTemplateFormatVersion: "2010-09-09"
Description: "Create IAM groups and users"
Parameters:
Environment:
Type: String
Description: "Environment name (dev | stg | prod)"
AllowedValues:
- dev
- stg
- prod
Default: dev
GroupNames:
Type: List<String>
Description: "List of IAM group names to create (e.g. admins-cfn,viewers-cfn)"
AdminsGroupPolicies:
Type: List<String>
Description: "Managed policy ARNs to attach to AdminsGroup (e.g. arn:aws:iam::aws:policy/AdministratorAccess)"
ViewersGroupPolicies:
Type: List<String>
Description: "Managed policy ARNs to attach to ViewersGroup (e.g. arn:aws:iam::aws:policy/ReadOnlyAccess)"
UserNames:
Type: List<String>
Description: "List of IAM user names to create (e.g. admins,viewers)"
Resources:
AdminsGroup:
Type: AWS::IAM::Group
Properties:
GroupName: !Join
- "-"
- - !Ref Environment
- !Select [0, !Ref GroupNames]
ManagedPolicyArns: !Ref AdminsGroupPolicies
ViewersGroup:
Type: AWS::IAM::Group
Properties:
GroupName: !Join
- "-"
- - !Ref Environment
- !Select [1, !Ref GroupNames]
ManagedPolicyArns: !Ref ViewersGroupPolicies
AdminsUser:
Type: AWS::IAM::User
Properties:
UserName: !Join
- "-"
- - !Ref Environment
- !Select [0, !Ref UserNames]
Groups:
- !Ref AdminsGroup
Tags:
- Key: Environment
Value: !Ref Environment
- Key: ManagedBy
Value: cloudformation
ViewersUser:
Type: AWS::IAM::User
Properties:
UserName: !Join
- "-"
- - !Ref Environment
- !Select [1, !Ref UserNames]
Groups:
- !Ref ViewersGroup
Tags:
- Key: Environment
Value: !Ref Environment
- Key: ManagedBy
Value: cloudformation
Outputs:
AdminsGroup:
Description: "Administrators IAM group"
Value: !Ref AdminsGroup
Export:
Name: !Sub "${Environment}-AdminsGroupName"
ViewersGroup:
Description: "Viewers IAM group"
Value: !Ref ViewersGroup
Export:
Name: !Sub "${Environment}-ViewersGroupName"
AdminsUser:
Description: "Administrators IAM user"
Value: !Ref AdminsUser
ViewersUser:
Description: "Viewers IAM user"
Value: !Ref ViewersUser
デプロイ設定ファイル (iam-deployment.yml)
GitSyncはリポジトリ内の*-deployment.ymlファイルを参照してスタックを更新します。
template-file-pathでテンプレートのパス、parametersでスタックに渡すパラメータを指定します。
template-file-path: ./cfn-templates/iam.yml
parameters:
Environment: dev
GroupNames: "admins-cfn,viewers-cfn"
UserNames: "admin-user,viewers-user"
AdminsGroupPolicies: "arn:aws:iam::aws:policy/AdministratorAccess"
ViewersGroupPolicies: "arn:aws:iam::aws:policy/ReadOnlyAccess"
tags:
ManagedBy: cloudformation
Project: aws-cfn-gitsync
3-2. GitSync同期で使用するIAMロール
GitSyncの動作に必要なIAMロールが2つあります。
GitSync用サービスロール (CloudFormationGitSyncRole)
cloudformation.sync.codeconnections.amazonaws.comがAssumeするロールで、リポジトリの変更を検知してCloudFormationのChangeSetを作成・実行する役割を担います。
詳細は以下のドキュメントに作成するポリシーの例が載っています。
Confused Deputy攻撃対策として、信頼ポリシーに自アカウントのConnectionのARNを条件として設定しています。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"cloudformation:ListChangeSets",
"cloudformation:GetTemplate",
"cloudformation:ExecuteChangeSet",
"cloudformation:DescribeStacks",
"cloudformation:DescribeStackEvents",
"cloudformation:DescribeChangeSet",
"cloudformation:DeleteChangeSet",
"cloudformation:CreateChangeSet"
],
"Effect": "Allow",
"Resource": "arn:aws:cloudformation:*:*:stack/*",
"Sid": "CloudFormationStack"
},
{
"Action": [
"cloudformation:ValidateTemplate",
"cloudformation:ListStacks"
],
"Effect": "Allow",
"Resource": "*",
"Sid": "CloudFormationGlobal"
},
{
"Action": [
"events:PutTargets",
"events:PutRule"
],
"Condition": {
"StringEquals": {
"events:ManagedBy": "cloudformation.sync.codeconnections.amazonaws.com"
}
},
"Effect": "Allow",
"Resource": "*",
"Sid": "EventBridgeManagedRules"
},
{
"Action": "events:DescribeRule",
"Effect": "Allow",
"Resource": "*",
"Sid": "EventBridgeDescribeRule"
}
]
}
このロールに付与しているポリシーは以下の通りです。
- CloudFormationのChangeSet作成・実行・確認
- EventBridge管理ルールの操作(GitSyncがPRイベントを受け取るため)
また、トラストポリシーは以下のように設定しています。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CfnGitSyncTrustPolicy",
"Effect": "Allow",
"Principal": {
"Service": "cloudformation.sync.codeconnections.amazonaws.com"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "xxxxxxxxxxxx"
}
}
}
]
}
CFnデプロイロール (CloudFormationDeploymentRole)
cloudformation.amazonaws.comがAssumeするロールで、実際のリソース(今回はIAM)の作成・更新・削除を行います。
今回の検証で本IAMロールは重視していなかったので、とりあえずAdministratorAccessを付与しています。
3-3. AWSコンソールでGitSyncを設定する
IAMロールとConnectionの準備ができたら、いよいよAWSコンソールでGitSyncの設定を行います。
まず、CloudFormationのコンソールで「スタックの作成」から新規スタックを作成を選択します。
「テンプレートの指定」ではGit から同期を選択します。
Git同期の設定画面が表示されますので以下の項目を入力します。
| 項目 | 設定値 |
|---|---|
| デプロイファイルをスタック | リポジトリに自分のファイルを提供しています。 |
| 接続 | GitLab-GitSync-Connection(先ほど作成したConnection) |
| リポジトリ | aws-gitsync-cfn |
| ブランチ | main |
| デプロイファイルのパス | cfn-deployments/dev/iam-deployment.yml |
| IAM ロール | CloudFormationGitSyncRole |
次の画面ではCloudFormationを実際に実行する際に使用するロールを選択します。
| 項目 | 設定値 |
|---|---|
| CloudFormationデプロイロール | CloudFormationDeploymentRole |
設定が完了するとGitSyncが有効化され、初回の同期が走ります。
ただし、mainに資材がない場合は、以下のように資材がない旨エラー発生します。
既に資材がmainにある場合は反映されますが、今回はマージリクエスト承認で初回リリースされる想定のため、まだ資材配置はしていません。
3-4. 動作確認
今回はfeature/git-sync-testというブランチを作成し、マージリクエストを作成してみます。
マージリクエスト作成後しばらくするとAWS側が検知しマージリクエストのコメントに変更セットの差分を以下のように表示してくれます。
このままマージリクエストを承認するとCloudFormationがChangeSetを自動で作成・適用し、スタックが更新されることが確認できます。
これでGitリポジトリへのpushをトリガーにCloudFormationが自動更新される環境が完成しました!
実機でもグループやユーザー、ポリシーの紐づけなども問題ないことが確認できます!

4. 余談:古いリポジトリリンクの削除方法
GitSyncを構築していく中で、色々と試行錯誤した結果、不要になったリポジトリリンクが残ってしまうことがありました。
AWSのCloudFormationコンソールからはリポジトリリンクの削除ができないため、CLIからの削除が必要です。
参考にさせていただいた記事はこちらです。
残存リポジトリリンクの確認
まずはどのようなリポジトリリンクが残っているか確認します。
RepositoryLinkIdがリンクを特定するためのIDです。
$ aws codeconnections list-repository-links
{
"RepositoryLinks": [
{
"ConnectionArn": "arn:aws:codeconnections:ap-northeast-1:XXXXXXXXXXXX:connection/11381c98-XXXX-XXXX-XXXX-7d35b0db2975",
"OwnerId": "XXXXXXXX",
"ProviderType": "GitLabSelfManaged",
"RepositoryLinkArn": "arn:aws:codeconnections:ap-northeast-1:XXXXXXXXXXXX:repository-link/dc227dd0-XXXX-XXXX-XXXX-e9f5d3948c6d",
"RepositoryLinkId": "dc227dd0-845b-420b-bf32-e9f5d3948c6d",
"RepositoryName": "aws-gitsync-cfn"
}
]
}
紐づいているスタックを確認する
削除する前に、対象のリポジトリリンクがどのCloudFormationスタックと紐づいているか確認しておきましょう。
$ aws codeconnections list-repository-sync-definitions \
--repository-link-id cf5af44e-2c45-464c-9183-d13d3a6c2481 \
--sync-type CFN_STACK_SYNC
{
"RepositorySyncDefinitions": [
{
"Branch": "main",
"Directory": "./aws-cfn-resource/test.yml",
"Parent": "arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:stack/stacks-test",
"Target": "arn:aws:cloudformation:ap-northeast-1:XXXXXXXXXXXX:stack/stacks-test"
}
]
}
stacks-testというスタックに紐づいていることが分かりました。
本番環境で作業する場合は、スタックへの影響を考慮した上で削除を進めましょう。
リポジトリリンクの削除
delete-repository-linkコマンドでリポジトリリンクを削除します。
削除に成功すると応答が返ってきます(出力はなし)。
$ aws codeconnections delete-repository-link \
--repository-link-id dc227dd0-845b-420b-bf32-e9f5d3948c6d
再度一覧を確認すると、きれいに空になりました。
$ aws codeconnections list-repository-links
{
"RepositoryLinks": []
}
注意点として、GitSyncが有効になっているスタックに紐づくリポジトリリンクはそのままでは削除できません。
先にCloudFormationコンソールからGitSyncを無効化した後、リポジトリリンクの削除を実施してください。
5. まとめ
GitLabをAWS CodeConnectionsと接続してGitSyncを構築する手順を紹介しました。
ポイントをまとめると以下の通りです。
- HostおよびConnection構築後、コンソールから手動で認証が必要
- GitSyncには2種類のIAMロールが必要(GitSync用サービスロールとCFnデプロイロール)
- 不要なリポジトリリンクはAWS CLIで削除する
GitSyncを使えばGitのpushをトリガーにCloudFormationが自動更新されるのでかなり便利です。
CloudFormationの管理をコード化したい方はぜひ試してみてください!
本記事で使用したリポジトリ
- aws-gitsync-cfn - CloudFormationテンプレートおよびデプロイ設定ファイル
- aws-gitsync-terrofrom - CodeConnectionsおよびIAMロール構築用Terraformコード












