AWS CDK でデプロイするときの最小権限について考えてみる

2023.10.16

こんにちは。ゲーソル新屋です。

今までAWS CDKのデプロイメントポリシーの最小権限について考えたことはなく、なんかCDKがいい感じにやってくれてるんだろうくらいに思っていたのですが(実際そうですが)

AWS CDK Security And Safety Dev Guideを読んでみて、AWS CDKデプロイメントで登場するロールとポリシーとその最小権限について、いくらか理解できた部分があるので、それを共有します。

※本記事はCDKv2であることを前提にしています。

TL;DR

  • CDKはCloudFormationがAWSリソースの変更をデプロイする
    • アクター(開発者または自動システム)はデプロイをしない
  • CloudFormationはアクターから CloudFormationExecutionRole というロールをPassRoleされ AdministratorAccess でデプロイを実行する
  • アクターは自身でデプロイをしないのでデプロイ準備のみを実行できることが最小権限であり、そのロールとポリシーはCDK初回実行時(Bootstrapping)に作成される

詳しく解説していきます。

デプロイ権限(準備と実行)の分離

CDKは、デプロイの準備をする「アクター(開発者または自動システム)」とデプロイを実行する「CloudFormation」が登場し、それぞれに別のロールが付与されます。 今回のGithub Actionsは「アクター」に相当します。

ここに登場するロールは5つあります。

  • DeploymentActionRole
  • FilePublishingRole
  • ImagePublishingRole
  • LookupRole
  • CloudFormationExecutionRole

これらのロールは cdk bootstrap 実行時(CDK初回実行時)に作成され CDKToolkit という名称のCloudFormationスタックで管理されます。このBootstrappingについては後述します。

デプロイフローの全体としては以下の図のようになります。

全体像

上記の図は弊社の過去記事よりお借りしました。

cdk deploy の最小権限

これら登場する5つのロールとそれらにアタッチされているポリシーは、CDKのデフォルトで最小権限の原則の則っているため、アクターとしては AssumeRole のみできることが最小権限となります。

上記の図でいうと緑の線で表されている部分です。

つまり cdk deploy 実行時のロールは以下のポリシーを持つことが最小権限です。

{
  "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"
        ]
      }
    }
  }]
}

https://github.com/aws/aws-cdk/wiki/Security-And-Safety-Dev-Guide#bootstrapping

このポリシーが本記事の結論です。

ここからはアクターが AssumeRole しようとしている、これらのロールは一体何なのか、解説していきます。

Bootstrapping

AWS CDKのデベロッパーガイドには以下のように説明されています。

Bootstrapping is the process of provisioning resources for the AWS CDK before you can deploy AWS CDK apps into an AWS [environment](https://docs.aws.amazon.com/cdk/v2/guide/environments.html). (An AWS environment is a combination of an AWS account and Region).

These resources include an Amazon S3 bucket for storing files and IAM roles that grant permissions needed to perform deployments.

The required resources are defined in an AWS CloudFormation stack, called the bootstrap stack, which is usually named CDKToolkit. Like any AWS CloudFormation stack, it appears in the AWS CloudFormation console once it has been deployed.

https://docs.aws.amazon.com/cdk/v2/guide/bootstrapping.html

簡単に言うと cdk bootstrap を実行すると cdk deploy で必要となるロールやリソースを事前に準備してくれます。準備した内容は CDKToolkit という名称のCloudFormationスタックに出力されています。DeploymentActionRole, CloudFormationExecutionRoleなどのロールはこのタイミングで作成されます。

CFnテンプレートに出力するとより理解できると思います。

cdk bootstrap --show-template > bootstram.yaml

StackSynthesizer

Your AWS CDK app needs to know about the bootstrapping resources available to it in order to successfully synthesize a stack that can be deployed. The *stack synthesizer* is an AWS CDK class that controls how the stack's template is synthesized. This includes how it uses bootstrapping resources (for example, how it refers to assets stored in the bootstrap bucket).

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

StackSynthesizerは、Bootstrappingの振る舞いを定義します。

この定義は cdk bootstrap または cdk synth を実行したときに cdk.out/manifest.json に出力され、この内容にしたがってコマンドが実行されます。

特に何も指定しない場合、デフォルトの振る舞いが出力されます。これを DefaultStackSynthesizer と呼び、多くの方が DefaultStackSynthesizer を利用しているかと思います(ベストプラクティスです)

DefaultStackSynthesizer を利用することで、CDKが推奨するデプロイメントを適用でき、先述の 全体像 で示したデプロイフローを取ることが出来ます。

繰り返しになりますが、ここでアクターがAssumeRoleする5つのロールが作成されます。

  • DeploymentActionRole
    • AWS CDKがCloudFormationスタックをデプロイするために使用します。具体的には、CloudFormationの変更セットの作成、削除、記述、スタックの操作など、デプロイメントに必要な一連の操作を許可します。また、S3バケットとオブジェクトの取得、リスト、削除、作成など、アーティファクトの管理に必要な操作も許可します。
  • FilePublishingRole
    • AWS CDKがアプリケーションの一部としてファイルを公開するために使用します。たとえば、S3バケットに静的ウェブサイトのコンテンツをアップロードする場合などです。
  • ImagePublishingRole
    • AWS CDKがアプリケーションの一部としてDockerイメージを公開するために使用します。たとえば、ECRにDockerイメージをプッシュする場合などです。
  • LookupRole
    • AWS CDKがCloudFormationスタックを作成・変更する時に既存のAWSリソースの情報を取得するために使用します。たとえば、特定のリソースが既に存在するかどうかを確認したり、その設定詳細を取得したりする場合などです。
  • CloudFormationExecutionRole
    • AWS CloudFormationがスタックの作成や更新を行うために使用します。このロールを使用することで、CloudFormationはAWSリソースを作成、更新、または削除する権限を得ます。
    • デフォルトで AdministratorAccess ポリシーが適用されます。
      • これはIaCのコード開発者の権限昇格問題を引き起こしますが、このロールに Permissions boundary を設定することで最小権限に近づけることが出来ます(本記事では割愛します、詳しくはデベロッパーガイドをご覧ください)

cdk bootstrap の最小権限

cdk bootstrap は AdministratorAccess 権限、もしくは以下のポリシーで実行されることが推奨されています。これは DefaultStackSynthesizer は将来変更される可能性があるためです。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "cloudformation:*",
                "ecr:*",
                "ssm:*",
                "s3:*",
                "iam:*"
            ],
            "Resource": "*"
        }
    ]
}

https://github.com/aws/aws-cdk/wiki/Security-And-Safety-Dev-Guide#policies-for-bootstrapping

CliCredentialsStackSynthesizer

一方でStackSynthesizerはカスタマイズすることができます。これを CliCredentialsStackSynthesizer と呼びます。 DefaultStackSynthesizerの時と違い、ローカルのAWS認証情報(例えば、AWS CLIやSDKで設定された認証情報)を使用してAWSリソースをデプロイ(準備と実行の両方)します。

実装・実行方法のサンプルは以下の通りです。

./bin/main.ts

import * as cdk from '@aws-cdk/core';
import { CliCredentialsStackSynthesizer } from '@aws-cdk/core';

class MyStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, {
      synthesizer: new CliCredentialsStackSynthesizer(),
      ...props,
    });

    // スタックのリソース定義
  }
}
cdk deploy --profile <...>

以上です。