課題:CDK v2 で組んだ IaC を安全に CD したい
AWS のサーバーレスリソースを使ったウェブサイトやウェブアプリの構築にトライしています。
インフラは CDK v2 を使った IaC(Infrastructure as Code)にしたので、さらに Git にプッシュしたら自動的にデプロイされるよう CD(Continuous Delivery, 継続的デリバリー)を設定したいと考えました。
CD するには CD サービスに対し私の AWS アカウントの操作権を委ねる必要がありますが、できるだけリスクを下げて安全に行いたいものです。
これには AssumeRole を使うベストプラクティスがありますが、 CDK v2 では少し気を付ける点がありましたので、ここでまとめます。
TL;DR (先に結論)
- CDK v2 の bootstrap でデプロイ時に必要なロールが自動的に作られる。
- このロールに AssumeRole できるユーザーを作り、そのユーザーの Access Key ID と Secret Access Key を CI/CD に登録する
CD の安全性を高める一般的なベストプラクティス
CD では、 CD サービスに対して AWS アカウントの操作を委ねることになるため、クレデンシャルの漏洩などのリスクがあり得ます。漏洩したクレデンシャルに強い権限をつけないようにして、リスクを下げて安全に行いたいものです。
この課題には定石の解決策があり、 Classmethod さんの記事を参考にしました。
なお、記事中は開発者に与える権限を制限するという文脈になっていますが、 CD でも同じ考えで問題ありません。
私の理解でまとめると、まず、CloudFormation サービスに私のアカウントでリソースを操作することを許可するための「ロール1」と、CloudFormation の起動のみを行える「ロール2」を作ります。
そして、ロール1を利用できるがリソースを直接作れない「ユーザー」を作り、そのユーザーのクレデンシャルを CI サービスに登録します。
CDK v2 ではそのままでは実行できない
さて、Classmethod さんの記事などを参考に、ロール1,ロール2、ユーザーを作り、 cdk diff
などのコマンドを使って試してみますと、次のような警告が出るようになりました。
current credentials could not be used to assume 'arn:aws:iam::123456789012:role/cdk-xxxxxxxxx-aaaa-bbbbbbb-role-123456789012-yyyyyyyy', but are for the right account. Proceeding anyway.
また、 cdk diff
では GetTemplate できないとか、 cdk deploy
の場合はテンプレートを S3 に転送する部分あたりで Access Denied エラーになってしまうなど、いろいろな問題がでて実行できません。
権限を追加していけばよいのでしょうが、本当にそれが正解なのでしょうか・・・。
CDK はベストプラクティスの集合体でもあるので、もっとスマートな解決策を用意してくれているのでは・・・??
CDK v2 は自動的にロールを用意してくれる
いろいろ調べた結果、 Stack Overflow に正解がありました!
CDK v2 ではデプロイ作業に必要なロールを bootstrap コマンド実行時に自動的に作ってくれるため、自分で作る必要はないようです!
AWS コンソールの IAM サービス画面から調べてみると、下記のロールがありました。実際には xxxxxxxxx
はランダム文字列、 yyyyyyyy
はリージョンが入ります。
cdk-xxxxxxxxx-cfn-exec-role-123456789012-yyyyyyyy
cdk-xxxxxxxxx-deploy-role-123456789012-yyyyyyyy
cdk-xxxxxxxxx-file-publishing-role-123456789012-yyyyyyyy
cdk-xxxxxxxxx-image-publishing-role-123456789012-yyyyyyyy
cdk-xxxxxxxxx-lookup-role-123456789012-yyyyyyyy
5つもロールがあるのは、操作によってロールを使い分けるためのようです。
cdk コマンドは、テンプレートの差分を調べたり、テンプレートを S3 に送信したり、ウェブサイトコンテンツの送信で BucketDeployment を使っている場合など、 CloudFormation 起動以外のいろいろな操作を行ってくれます。
これらの操作が使う権限を調べて自力でロールを作るのも大変ですから、自動作成されたロールをそのまま使うのが、 CDK v2 を使う上での正しい作法といえそうです。
bootstrap のバージョンに注意
なお、 bootstrap は何度かバージョンアップされています。作られるロールもアップデートされてきているようですので、上記のようなロールが見当たらない場合は bootstrap をアップグレードしてみるとよいかもしれません。
なお、自分の bootstrap のバージョンは、 AWS コンソールから AWS Systems Manager / パラメータストア を開き、 /cdk-bootstrap/xxxxxxxxx/version
という名前のパラメータで確認できるようです。
記事執筆時点(2022年8月15日)で最新版の CDK 2.37.1 (build f15dee0) で bootstrap したものでは 14
という値が入っていました。
結論:CD 用のユーザーを作るだけでよい
結論としては、CDK v2 が作ったロールを利用するユーザーを作り、 CD はそのユーザーで行うように設定すれば OK でした。
具体的には、まず CDK v2 で bootstrap を行います。
cdk bootstrap
作られたロールへの AssumeRole を許可する下記のようなポリシーを持つユーザーを作ります。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"sts:AssumeRole"
],
"Resource": [
"arn:aws:iam::*:role/cdk-*"
]
}
]
}
その後、 AWS コンソールの IAM サービスを開き、そのユーザーのアクセスキーを作成します。
取得したアクセスキーを CD サービスに設定します。
私の場合、 Git ホスティングに GitLab.com を使っているので、標準の GitLab CI/CD 機能を使います。GitLab の Settings > CI/CD > Variables より、 AWS_ACCESS_KEY_ID と AWS_SECRET_ACCESS_KEY という環境変数を設定しておけば CD スクリプト実行時に使われます。
なお、CI スクリプトに記述する cdk deploy
コマンドに対して何か特別な設定は不要です。このアクセスキーで認識されるユーザーを用いて、自動的に AssumeRole して各種操作を実行してくれるようです。
(なお、私はリージョンは CDK コードで設定しています。必要に応じて変数に追加ください)
おわり。
補足1:CDK のプロンプトをOFFにするには
cdk deploy
コマンドの実行中、特に IAM 関連の操作が必要になる場合などに、実行してよいか y
の入力を求めるプロンプトが出てくることがあります。 CD ではプロンプトが出てくると実行が止まってしまうので困ります。プロンプトを抑制するためには --require-approval never
という自動承認するオプションを付ければ OK です。
cdk deploy --require-approval never
補足2:bootstrap自体をどうするのか
さて、 cdk bootstrap
コマンドを実行できる前提でまとめましたが、よく考えると bootstrap はどういう権限で行えばいいでしょう?
私はルートユーザーで実行してしまいました・・・が、本当は良くないですね。
Classmethod さんの説明にある一般的な定石に従うのが良さそうです。