Open9
CDK Pipelinesの調査メモ
- original APIとmodern APIがある
- original API:
CdkPipeline
コンストラクタ - modern API:
CodePipeline
コンストラクタ
- original API:
- modern APIのほうが、デフォルトがいい感じ、拡張性に優れている、並列デプロイのサポート、複数のsynth inputsをサポート、CodeBuildをより制御できる
- なるべくmodern APIに移行してね、とのこと
- マイグレーションガイド aws-cdk/ORIGINAL_API.md at master · aws/aws-cdk
At a glance
- アプリのCDを開始するには、まず
Stage
のサブクラスを作る- コンストラクタ内でアプリケーションのStackをインスタンス化する
-
CodePipeline
のインスタンスを作って、作りたい環境の分だけpipeline.addStage(stage)
する -
self-mutating
- StackやStageを書き換えると自身(Pipeline)を書き換えて、変更を反映する
- (そりゃそうやろと思ったが、
self-mutating
みたいな名前つけるほどのことなのかよく理解できていない)
CDK Versioning
prereleaseの機能を使うので、以下の設定をcdk.json
に追記する
{
// ...
"context": {
"@aws-cdk/core:newStyleStackSynthesis": true
}
}
Provisioning the pipeline
-
cdk deploy
の前に必ずgit commit
&git push
すること -
cdk deploy PipelineStack
- 1度目だけ管理者権限が必要。それ以降は不要なので、すぐ管理者権限を取り除いたほうがいい
Working on the pipeline
- self-mutation機能はパイプライン開発の邪魔になることもあるので、
selfMutation: false
でself-mutatingを無効化できるので、開発時に使ってね、とのこと。
Defining the pipeline
Synth and sources
-
CodePipeline
コンストラクタは、synth
パラメタを引数に取る-
cdk synth
後のcdk.out
ディレクトリに吐かれるコンテンツを生成するためのもの
-
-
ShellStep
コンストラクタ-
commands
に出力するためのコマンドを配列で書く - cdkのディレクトリがリポジトリの直下にない場合は、
commands
でcd ディレクトリ
しつつ、primaryOutputDirectory
にcdk.out
のパスを別途指定する
-
CodePipeline Sources
- ソースの置き場所を指定。
CodePipeline
クラスのファクトリメソッドを使う
// connectionを使う例(推奨)
// AWSコンソールで認証する
CodePipelineSource.connection('org/repo', 'branch', {
connectionArn: 'arn:aws:codestar-connections:us-east-1:222222222222:connection/7d2469ff-514a-4e4f-9003-5ca4a43cdc41',
});
// Githubで発行したトークンを使う
// トークンはrepo, admin:repo_hookスコープを持っている必要がある
CodePipelineSource.gitHub('org/repo', 'branch', {
// This is optional
authentication: SecretValue.secretsManager('my-token'),
});
Additional inputs
-
additionalInputs
に追加の入力を指定できる- ShellStep or CodePipelineSource
- (CDKのコードと、アプリケーションのコードを分離する、みたいなことができちゃう感じ?)
CDK application deployments
-
Stage
の追加-
Stage
: ターゲットとなる環境にデプロイされる対象
-
-
pipeline.addState(Stage)
で追加できる
// Do this as many times as necessary with any account and region
// Account and region may different from the pipeline's.
pipeline.addStage(new MyApplicationStage(this, 'Prod', {
env: {
account: '123456789012',
region: 'eu-west-1',
}
}));
- デプロイ先環境が別アカウントの場合、そのアカウントのbootstrapが事前に必要
Deploying in parallel
- デフォルトでは各Stageは直列にデプロイされる
- 並列でデプロイしたい場合は、
addWave
を使う
const europeWave = pipeline.addWave('Europe');
europeWave.addStage(new MyApplicationStage(this, 'Ireland', {
env: { region: 'eu-west-1' }
}));
europeWave.addStage(new MyApplicationStage(this, 'Germany', {
env: { region: 'eu-central-1' }
}));
Deploying to other accounts / encrypting the Artifact Bucket
- 別リージョン・アカウントへの透過的に実行するけど、
CodePipeline
コンストラクタにcrossAccountKeys: true
を付ける必要がある- artifact bucketの暗号化を有効にする設定
- (鍵の生成等は勝手にやってくれる感じ?)
Validation
-
addStage
,addWave
のpre
,post
オプション- stage, waveの前後で任意のアクションを実行できる
- Validationを追加するのに使うといい
-
ManualApprovalStep
をpre
に置くことで、手動による承認ステップを挟むことができる
Using CloudFormation Stack Outputs in approvals
- CloudFormation Stackの出力を承認時に利用可能
-
ShellStep
のenvFromCfnOutputsで指定できる
class MyApplicationStage extends Stage {
public readonly loadBalancerAddress: CfnOutput;
// ...
}
const lbApp = new MyApplicationStage(this, 'MyApp', { /* ... */ });
pipeline.addStage(lbApp, {
post: [
new ShellStep('HitEndpoint', {
envFromCfnOutputs: {
// Make the load balancer address available as $URL inside the commands
URL: lbApp.loadBalancerAddress,
},
commands: ['curl -Ssf $URL'],
});
],
});
Running scripts compiled during the synth step
- synthの出力をstageのpre/postで使う方法について
- synthの出力だけじゃなくて、他のビルドステップの出力を利用できる
const synth = new ShellStep('Synth', { /* ... */ });
const pipeline = new CodePipeline(this, 'Pipeline', { synth });
pipeline.addStage(/* ... */, {
post: [
new ShellStep('Approve', {
// Use the contents of the 'integ' directory from the synth step as the input
input: synth.addOutputDirectory('integ'),
commands: ['cd integ && ./run.sh'],
}),
],
});
ちょっと長くなったので、この後は分割して投稿する
Customizing CodeBuild Projects
- CDK pipelinesは
ShellStep
ごとにCodeBuildのプロジェクトを生成している -
CdeBuildStep
コンストラクタを使えば、より細かく設定できる - また、
CodePipeine
のcodeBuildDefaults
にCodeBuildのデフォルト値を設定できる
Arbitrary CodePipeline actions
-
Step
を継承、ICodePipelineActionFactory
を実装すれば、独自のCodePipelineアクションを定義できる
CDK Environment Bootstrapping
- environment(環境) = account + region
- 最低2つの環境: Pipelineがプロビジョンされる環境、アプリケーションがデプロイされる環境
- 2つの環境が同一ということもある
- 分けるのが推奨
- 環境は、bootstrapが必要
- 2つの環境が別の場合、両方にbootstrapが必要 & trust releationshipの追加が必要
- CDK PipelineはクロスアカウントのCI/CDに対応しているモダンなbootstrapが必要
-
cdk.json
に"@aws-cdk/core:newStyleStackSynthesis": true
があり、cdk.json
と同一ディレクトリでcdk bootstrap
する場合は、自動的にモダンなものにスイッチする - そうでない場合、
CDK_NEW_BOOTSTRAP=1
をつけて、cdk bootstrap
する
-
# アカウント = 111111111111, region = us-east-1のbootstrap
$ env CDK_NEW_BOOTSTRAP=1 npx cdk bootstrap \
[--profile admin-profile-1] \
--cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess \
aws://111111111111/us-east-1
アプリケーションのデプロイ先の別の環境をbootstrapする場合、--trust
にPipelineのアカウントを指定
# アカウント = 222222222222, region = us-east-1のbootstrap
# アカウント = 111111111111のPipelineからデプロイするので--trust 111111111111を付けている
$ env CDK_NEW_BOOTSTRAP=1 npx cdk bootstrap \
[--profile admin-profile-2] \
--cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess \
--trust 11111111111 \
aws://222222222222/us-east-2
Vpc.fromLookup()
等のlookupしたい場合は、--trust-for-lookup Pipelineのアカウント
を付ける
$ env CDK_NEW_BOOTSTRAP=1 npx cdk bootstrap \
[--profile admin-profile-2] \
--cloudformation-execution-policies arn:aws:iam::aws:policy/AdministratorAccess \
--trust-for-lookup 11111111111 \
aws://222222222222/us-east-2
-
--trust
付ける場合、Pipeline側のアカウントはデプロイ先のアカウントに対して--cloudformation-execution-policies
で指定した権限を持つことになるので、注意 - 管理者権限はbootstrap時、最初のPipelineのデプロイ時だけ使用して、あとは使わない
- AdministratorAccessの利用について
- PipelineのAdministratorAccessはすべてのAWSリソースをデプロイ可能にするために付けている
- CDKのコード全てが信頼できる状態じゃないと、変なリソースをデプロイされたりするので、依存関係はちゃんと管理する。また、適切なポリシーでAdministratorAccessを利用する
- CDK実行ロールにパーミッションバウンダリーを実装すること
Context Lookups
- 有効なAZの数、Route53 Hosted Zone IDなど、
cdk synth
時に自動で調べる cdk bootstrap --trust-for-lookup=<account>
Security Considerations
Confirm permissions broadening
- stageのデプロイ前に
cdk diff
で新たにIAM権限の付与等が行われていないか確認したい -
ConfirmPermissionsBroadening
をstageのpreに挟む-
cdk diff
の結果、何も無ければ自動でOK - なにかあれば、マニュアルの承認が必要
-
const stage = new MyApplicationStage(this, 'MyApplication');
pipeline.addStage(stage, {
pre: [
new ConfirmPermissionsBroadening('Check', { stage }),
],
});
SNSトピックを付けることもできる
import * as sns from '@aws-cdk/aws-sns';
import * as subscriptions from '@aws-cdk/aws-sns-subscriptions';
import * as pipelines from '@aws-cdk/pipelines';
const topic = new sns.Topic(this, 'SecurityChangesTopic');
topic.addSubscription(new subscriptions.EmailSubscription('test@email.com'));
const stage = new MyApplicationStage(this, 'MyApplication');
pipeline.addStage(stage, {
pre: [
new ConfirmPermissionsBroadening('Check', {
stage,
notificationTopic: topic,
}),
],
});
ここまでの疑問点
-
--trust
を付けた場合の適切な--cloudformation-execution-policies
のポリシーはなに?- 結局管理者権限にならない?それかPowerUserみたいなやつをつければいいのかな?
- Permission Boundaryってなに?