[新機能]CloudFormationのGit同期機能を稼働検証してみた

## はじめに
AWS re:Invent2023において発表された新機能・アップデートの中に、CloudFormationのGit同期機能が紹介されていました。CloudFormation大好き人間の私は、早速当該新機能の稼働検証をしてみました。本記事では、その稼働検証結果をご紹介します。

## 事前準備
### GitHubリポジトリの作成
GitHubのID自体は持っていますが、これまで自分専用のリポジトリを作成したことは一度もありませんでした。今回の稼働検証の為、初めてテスト用のリポジトリを作成しました。なお、リポジトリの属性はパブリックにする必要はなく、プライベートで全く問題ありません。今回の検証で使用したリポジトリは下記になります。

https://github.com/duelist2021jp/CloudFormation_ClientVPN



### CloudFormationテンプレートの用意
作成したGitHubリポジトリにCloudFormationテンプレートを事前にアップロードしておきます。テンプレートの中身は何でもよいので、ここ最近投稿した下記Qiita記事で使用したものを活用します。

https://qiita.com/duelist2020jp/items/4ea07456de2fee99296b

実は上記記事を作成する過程で、当該新機能の検証を実施してました。検証内容として、GitHubからのコード初回実行、及び、GitHub側でのコード更新後の同期処理の2ケースを実施しています。そのため、上記記事に記載のコードは2ケース実施完了後のイメージになっている点、ご容赦ください。

### CodeStar-Connections機能を使用するためのIAMポリシー作成
CloudFormationはGit連携を行う際に、CodeStar-Connectionsの機能を使用します。その為、下記のようなIAMポリシーを作成し、CloudFormationコードの実行IAMユーザーが所属するIAMグループにアタッチします。
```markdown:CoreStarConnectionsCreate
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "codestar-connections:*"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}
```

なお、IAMのポリシー一覧から検索しても、CodeStar-Connections機能に対するAWS管理ポリシーが見つからなかったため、個別にカスタマー管理ポリシーとして作成しています。

今回は検証を簡単に進めるために、CodeStar-Connections全てのアクション項目に対してアクセス権を付与しましたが、実際の運用を行う際には最小限の権限設定の方針に基づいたアクセス権付与を実施ください。

:::note warn
CodeStarのアクションとCodeStar-Connectionのアクションは全くの別物になります。私は最初どちらも同じだと思ってCodeStarのアクションに対するフルアクセス権を付与してみましたが、実行時にCodeStar-Connectionsアクセス権が無いと言われてエラーになりましたので、注意が必要です。
:::



## Git同期機能使用時のCloudFormation画面イメージ
STEP1のスタック作成画面です。下記赤枠部分が今回新規に追加されたオプションです。
![p1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/782966f6-c60e-5911-e66a-102f70d2207b.jpeg)
STEP2のスタック詳細を指定する画面です。スタック名は「MyClientVPN」としておきます。
![p2_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/799e6f25-0957-552b-de23-5e6ecb623884.jpeg)
画面真ん中の[デプロイファイル](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/git-sync-concepts-terms.html#git-sync-concepts-terms-depoyment-file)については、実行の際にCloudFormationに自動的に作成してもらう方法と、事前に自身のリポジトリにファイルを用意しておく2つのパターンから選ぶことが可能です。結論としては、どちらの方式を採用しても問題なく稼働できました。本記事では、コード実行時にデプロイファイルを自動作成してもらう方式を紹介します。

一番下のテンプレート定義リポジトリについては、今回初めて定義しますので、「Gitリポジトリをリンクする」を選択します。すると更なる選択項目が表示されます。
![p3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/cefe9258-61fe-953c-f52b-606cecc547a3.jpeg)
リポジトリプロバイダーは「GitHub」を選択します。一番下に表示されている「接続」は、CloudFormationとGitHubとのコネクション確立を行うための設定になります。初回はコネクションはありませんので、青字の「新しい接続を作成する」をクリックします。ここで事前準備の所で記載したCodeStar-Connectionsのアクションにおけるアクセス権限が適切に付与されていないと、次の画面への遷移時にエラーになります。
### GitHubとの接続作成
先の画面からの遷移先が下記の画面になります。
![p4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/8dec3ffd-a0cd-52e5-f7dc-70a62a158dc4.jpeg)
プロバイダーには「GitHub」を選択し、GitHubアプリ接続名は任意で良いので、ここでは「Connections_GitHub」という名前にしています。その後、画面右下の「GitHubに接続する」ボタンを押下します。すると下記画面に遷移します。
![p5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/e32098ab-7dcc-7c2f-7e55-58599ac941dd.jpeg)
赤枠で囲んでいる「新しいアプリをインストーする」ボタンを押下すると、GitHubとの接続作成が開始されます。
![p6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/95c3fdba-1f50-7499-3d99-b8cfec1ca61c.jpeg)
GitHubとの接続をしたいアカウントを選択し、先に進みます。
![p7.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/c414ab4b-e538-d16d-4522-b095a7264180.jpeg)
全てのリポジトリに対して共通の接続にすることも可能です。ここではテスト用のリポジトリに対する接続のみとして、左下の「Install」ボタンを押下します。
![p8.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/62c9c8c1-b124-e918-34d9-dddc084fb8d1.jpeg)
GitHubアカウントのパスワードを聞いてくるので、パスワード入力後「Confirm」ボタンを押下します。元のAWSコンソールの画面に自動的に遷移し、赤枠で囲んでいる箇所に接続番号が表示されているのがわかります。
![p9.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/23221551-d95a-c857-f953-03b8b59835b7.jpeg)
画面右下の「接続」ボタンを押せば接続設定作業は完了です。完了イメージは下記の通りです。
![p10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/222590de-9aeb-126d-1231-18a73165053c.jpeg)
### CloudFormationコンソールでの作業継続
GitHubとの接続作成が完了すると、CloudFormationコンソールのプルダウンメニューにて、GitHubリポジトリ名やブランチ等を選択することが可能になります。デプロイファイルのパスについては、自動作成したいファイル名を入力しておけば問題ありません。
![p11_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/afb61f66-8f9f-c7a3-8052-54da899b7011.jpeg)
一番下のIAMロールの箇所には、CloudFormationにGitリポジトリからスタックを更新するためのアクセス許可ということで、今回は事前に作成しておいた「my-updatestack-git」という名前のIAMロールを指定しました。ロールの作成においては、下記マニュアルにおける「Required permissions」、「Trust Policy」の記述を参考にしています。

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/git-sync-prereq.html


画面をスクロールし、デプロイファイルパラメーターのテンプレートファイルパスには、GitHubリポジトリからロードされるCloudFormationテンプレート名を入力します。
![p11_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/6e27ca97-1f6a-0754-24b2-2f3621c9cbcd.jpeg)
その後、右下の「次へ」ボタンを押下します。

アクセス許可のIAMロールには、CloudFormationがサービスのプロビジョニングに必要なアクセス権を付与したIAMロールを指定します。今回は、VPC、EC2、SSMに対するアクセス権を付与した「My-UpdateStack-GitHub」という名前のロールを指定しました。
![p12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/eb654679-16ae-0db9-1bf0-4fe95fc33ec3.jpeg)

:::note warn
S3にCloudFormationテンプレートをアップロードした上で実行する場合には、これまで一度もここにIAMロール名を指定しなくても問題なく実行できていました。一方、Git連携を使用してGitHubからコードをロードして実行する場合には、明示的にIAMロールを指定しておかないと、コード実行中にVPCに対するアクセス権が無いとかいった権限エラーが発生しましたので、Git連携を使用される際には注意が必要です。
:::

### コード実行前の最終設定確認
各々の項目に対して問題が無いことを確認します。
![p13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/89fff887-a61a-7713-dc07-c9d6884a6559.jpeg)
![p14_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/be231df7-1fc5-37a4-e92c-a48f8df6d20a.jpeg)
デプロイファイルパラメーターに記載されている中身が、コード実行処理の過程において、GitHubリポジトリ側に「Deployment_File.yaml」という名前で作成されます。
![p15_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/685bd296-d195-e9de-35fe-c43b1a27100d.jpeg)
ここまで確認したら、最後に「送信」ボタンを押下します。

### AWSからGitHubリポジトリへのPull通知
「送信」ボタン実行後、しばらくするとGitHubリポジトリに対してPullリクエストが行われます。GitHub側では「Pull Requests」をクリックすると、下記のようなAWSからのリクエストが来ているのがわかります。ちなみに、同じタイミングでGitHubアカウントに登録しているEメールアドレスにもメールが飛んできます。

![p16_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/4431772d-c97f-dcdd-c86e-20b88fab9343.jpeg)

上記リクエストの中身を確認後、左下の「merge pull request」を押下します。

![p16_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/f54ebaf5-62e6-ffe9-8ae8-142f0ec91991.jpeg)

内容確認後、AWSからのPullリクエストをコミットするために「Confirm merge」ボタンを押下します。

![p16_3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/0f7c6d87-11e2-bc62-de1c-75a684533f13.jpeg)
Pullリクエストのコミット処理完了後は下記のようになります。

![p16_4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/98fe7fbb-2d66-5218-456a-1d02ea7566ea.jpeg)

リポジトリの中身を見ると、下記図の赤枠に見られるように、自動的に「Deployment_File.yaml」という名前のファイルが作成されていることがわかります。

![p16_5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/d6f4bce5-8107-fab2-3249-8314f6671e03.jpeg)
ファイルの中身は下記の通りで、想定通りの物が作成されていることがわかります。
![p16_6.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/4dbd04e9-90d3-083b-0956-709dd7455657.jpeg)

### コード実行開始
AWSからのPullリクエストがGitHubリポジトリ側でコミットされると、GitHubリポジトリからCloudFormationテンプレートがロードされて、AWSのリソース作成が始まります。
![p16.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/8e3b5194-9bc8-5b3d-7228-0cd97550d776.jpeg)
Pullリクエストがコミットされるまでは、「MyClientVPN」スタックのステータスは「CREATE_COMPLETE」状態で待機してますが、コミット後はステータスが「UPDATE_IN_PROGRESS」となり、以降次々とAWSリソースのプロビジョニングが実施されていきます。

### 新規「Gitと同期 - 新規」タブが追加
CloudFormationのコンソール上に、「Gitと同期 - 新規」という名のタブが新しく追加されています。この画面において、現状のGit同期のステータス等を確認することができます。AWSからのPullリクエストがコミットされるとリポジトリ同期のステータスが「成功しました。」となります。(赤枠参照)
![p19.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/4aa5cbd9-0824-e115-bcb1-10a17aaf1935.jpeg)
この画面をスクロールすると、最新の同期イベント一覧を確認することができます。
![p18.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/61802f83-cad4-7230-0dc4-30c760df6324.jpeg)

### スタック作成完了イメージ

「MyClientVPN」スタックの「イベント」タブにおけるスタック完了イメージは下記の通りです。
![p20.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/9580025b-e976-b923-f9d7-f4edb0c2fc5d.jpeg)

「Gitと同期 - 新規」タブにおけるスタック完了後の出力イメージは下記の通りです。赤枠部分が着目ポイントです。
![p21.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/bf98cad3-8fe0-ceb2-0bb1-ce6e03be88eb.jpeg)
![p22.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/679fb3f9-93a7-0ba8-cbee-3cea494891a0.jpeg)

## GitHub側でのコード更新後の同期確認
GitHubリポジトリ内のCloudFormationテンプレートに下記赤枠で囲んでいる部分のコードを追記します。
![p43.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/65337308-2232-16d1-4b89-735b6a16c1ca.jpeg)
コード保存時に表示される更新確認画面上でコミットすると、即座にCloudFormation側への同期処理が行われます。「Git同期 - 新規」タブ内の表示も更新されます。
![p35.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/ab0e9757-bda1-abaa-a91c-5a9728279825.jpeg)
![p34.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/165e8256-acbe-9348-f6a7-b2015cba9eb8.jpeg)
「イベント」タブにおける、コード更新後の同期完了時の「MyClientVPN」スタックのステータスは下記のようになります。(赤枠参照)
![p32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/d9074e1c-c297-8c24-a157-51b153061ec8.jpeg)
「出力」タブにGitHubリポジトリのコードへ追記した3つの情報を確認できます。(赤枠参照)
![p33_1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/1f8f09c3-8916-4027-238a-294fbbed3c57.jpeg)
「テンプレート」タブにもコードへ追加した内容が反映されていることを確認できます。(赤枠参照)
![p36.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/a20fd824-cd00-4312-f05b-0820d5a8a2d0.jpeg)

以上により、GitHubリポジトリ上のCloudFormationテンプレート更新後の同期処理が問題なく行われたことを確認できました。

## スタック削除完了後のイメージ
作成されたスタックの削除方法は、Git同期機能を使用する場合も従来のテンプレートをS3にアップロードする場合の手順と同様です。削除完了後の「Git同期 - 新規」タブ内の画面表示は下記のようになります。
![p44.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1567099/edc0fe22-5944-734b-acab-f8ac2f02c2c7.jpeg)

## さいごに
本記事では、AWS re:Invent2023で発表された新機能・アップデートの内、CloudFormationの新規Git同期機能に関する稼働検証を実施しました。使用してみた感想としては、GitHubを普段から利用しているような場合には便利な機能かと思いました。

* 必要リソースは全てGitHub上で管理できて便利。
  * S3に毎度毎度テンプレートをアップロードする手間が省ける。

* デプロイメントファイルは、事前にGitHubリポジトリ側に配置して置く方が望ましい。
  * Pullリクエストへのコミット処理手続きの省略化が可能。(意外と手間だった。)

今後また新たな新機能やアップデートの発表に期待しています。