AWSのハンズオン用のCLI/CDK環境をEC2で作る

## はじめに
公式のワークショップやブログ、非公式の記事などでCDKやCLIを使って実装されている環境を試したいときに、最低限の環境を繰り返し作ることがあります。その際いつもあれなんだっけ？って調べることがあるので、コピペやユーザデータで作れるように備忘録として残しておきます。

## ユースケース
+ 公式のハンズオンやワークショップを自分のAWSアカウントで行いたい
+ 自身のローカル環境や開発端末、CloudShellといった既存環境の設定変更は行いたくない
+ CLI・CDKの実行やgitのクローンなどで済んで、自前でコードの改修は必要としない
+ 一時的なものなので、使い終わったらクリーンアップしておきたい（何ならアカウントごと消してもOK）
+ とはいえ、多少はセキュアな環境にしておきたい
## 前提条件
以下の条件で進めておきます
+ OS: Amazon Linux 2023
+ EC2への接続：EC2 Instance Connectを使用
+ EC2が構築されるVPCは構築済み
## 実装方法
### IAMロールの作成
今回利用するEC2インスタンスに必要な権限は以下の通りです。
+ AWS CDKのアクターの権限
+ CDK Bootstrapを起動できる権限
+ （⁺α）AWS CLIで実行する必要のある権限
上二つに限った場合、以下のロールになります。
```
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Sid": "AssumeCDKRoles",
			"Effect": "Allow",
			"Action": "sts:AssumeRole",
			"Resource": "*",
			"Condition": {
				"ForAnyValue:StringEquals": {
					"iam:ResourceTag/aws-cdk:bootstrap-role": [
						"image-publishing",
						"file-publishing",
						"deploy",
						"lookup"
					]
				}
			}
		},
		{
			"Sid": "GetCallerIdentity",
			"Effect": "Allow",
			"Action": "sts:GetCallerIdentity",
			"Resource": "*"
		},
		{
			"Sid": "CDKToolKitDeploy",
			"Effect": "Allow",
			"Action": [
				"cloudformation:*",
				"ecr:*",
				"ssm:*",
				"s3:*",
				"iam:*"
			],
			"Resource": "*"
		}
	]
}
```
### セキュリティグループの作成
EC2のインバウンドルールにEC2 Instance Connectのマネージドプレフィックスリストを許可します。
| プロトコル | ソース | ポート |
|:-----------|:------------|:------------|
| TCP | com.amazonaws.region.ec2-instance-connect | 22 |
| TCP | com.amazonaws.region.ipv6.ec2-instance-connect | 22 |

プライベートアドレスに限定したい場合は、EC2 Instance Connect Endpointを作成し、EC2のインバウンドルールを下記のようにします。
| プロトコル | ソース | ポート |
|:-----------|:------------|:------------|
| TCP | エンドポイントセキュリティグループの ID | 22 |

### EC2の作成
もともとあるVPCに先ほどのIAMロールとセキュリティグループを利用して作成します。
後述の設定をユーザデータ化してやると楽ですが、解説のためにここではユーザデータを利用せずに設定していきます。

### EC2の設定
EC2 Instance Connectを利用してEC2に接続します。

ルートユーザへ昇格
```
sudo -i
```

yumアップデート
~~~
yum update -y
~~~

npmとNode.jsのインストール
~~~
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
nvm install --lts
~~~

AWS CLIの最新化
~~~
yum remove -y awscli
curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
unzip awscliv2.zip
./aws/install
~~~

AWS CDKのインストール
~~~
npm install -g aws-cdk
~~~

環境変数にAWSアカウントIDを指定
~~~
export AWS_ACCOUNT_ID=`aws sts get-caller-identity --query "Account" --output text`
~~~

CDK bootstrapの起動
~~~
npx cdk bootstrap aws://$AWS_ACCOUNT_ID/us-east-1
~~~

Gitのインストール
~~~
yum install -y git
~~~

(オプション)Dockerやその他の資材がハンズオンで必要なら適宜インストールします

## 簡単な解説
### IAMロールについて
今回CDKが起動するよう、IAMロールを限定するパターンとしました。
各項目について簡単に解説していきます。
#### AssumeCDKRolesについて
CDKはデプロイの準備をするアクターとデプロイを行うCloudFormationに分かれます。アクター自身はデプロイを行わず、準備のみを行います。デプロイ準備のみを実行できることが最小権限であり、そのロールとポリシーはCDK初回実行時（Bootstrapping）に作成されます。
この場合、下記の5つが作成されるので、下記にAssumeRoleできるようにします。
+ DeploymentActionRole
+ FilePublishingRole
+ ImagePublishingRole
+ LookupRole
+ CloudFormationExecutionRole
#### GetCallerIdentityについて
AWSアカウントIDを指定するために使っています。CDK Bootstrapの実行コマンドに利用するAWSアカウントIDをコピペでやるのであれば不要です。
#### CDKToolKitDeployについて
こちらは公式ドキュメント通りです。個人的にはもう少し絞りたいのですが、将来的にブートストラップのリソースが変更になる可能性があるため、このような記述が推奨されています。

### EC2 Instance Connectについて
今回はEC2 Instance Connectとしました。Systems Managerでもよいのですが、ハンズオンでOSのRoot権限を使用する可能性があるため、こちらを選択しています。
ブートストラップでは、下記のリソースを利用します。
⁺ Amazon S3 バケット – AWS Lambda関数コードやアセットなどの CDK プロジェクトファイルを保存するために使用します。
+ Amazon ECRリポジトリ – 主に Docker イメージの保存に使用されます

+ IAMロール – デプロイを実行するために必要なアクセス許可を AWS CDK に付与するように設定されています

パブリックサブネットかプライベートサブネットの選択ですが、今回は一時的な環境のためパブリックサブネットでも構わないと思いますが、よりセキュアに行いたい場合はプライベートサブネットが良いと思います。
その場合は、各種リポジトリへの通信のために、NAT GatewayやEgres-only Internet Gatewayを適切に設定してください。

### AWS CLIの最新化について
Amazon Linux 2023にはAWS CLIがインストールされていますが、CLIの最新化にはいったんアンインストールが推奨されているため、アンインストール→再インストールの手順を利用しています。

### CDKのインストールについて
CDKをインストールするためにはNPMが必要となるため、Node.jsとNPMをインストールしています。基本的には最新版で構いませんがハンズオンによってはCDKのバージョン指定があるので、CDKの特定のバージョンをインストールする場合には下記を使用します。

~~~
npm install -g aws-cdk@X.YY.Z
~~~
X.YY.Zはバージョン

## まとめ
誰かが作ったサンプルアプリをちょっと試したいけど、CDKが必要だったり、必要なコンポーネントがGitHubにあって・・・というときによく作ってます。
是非ハンズオンやワークショップで使ってみてください！

## 参考文献

https://qiita.com/minorun365/items/f5289163795d5d7b21e2

https://dev.classmethod.jp/articles/cdk-minimum-deploy-policy/

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/eice-security-groups.html

https://docs.aws.amazon.com/ja_jp/cdk/v2/guide/bootstrapping.html#bootstrapping-template

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/ec2-instance-connect-configure-IAM-role.html

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html

https://docs.aws.amazon.com/ja_jp/sdk-for-javascript/v2/developer-guide/setting-up-node-on-ec2-instance.html

https://docs.aws.amazon.com/ja_jp/AWSEC2/latest/UserGuide/eice-security-groups.html