[AWS CDK]組織内に展開するStackSetsをコードで管理する

CloudFormation StackSetsを組織内に展開したいときは全部CDKでいいんじゃないかな。
2022.04.23

はじめに

マルチアカウント運用をしていると、組織全体や特定のOUに対してStackSetsを使ったリソースの展開をしたくなる場面がたくさんあります。

これをもっと簡単に管理できないかなーと常々思っていたのですが、CDKを調べてみると組織内への自動デプロイなどのOrganizations統合で利用できる機能もサポートされていることを発見。早速試してみました。

class CfnStackSet (construct) · AWS CDK

具体的にはコンソールで行っていた、以下の機能をCDKから実施できるイメージです。

個人的に今後StackSetsを利用する際は全てCDKからやりたいくらい簡単だったので、ぜひお試しください。

ディレクトリ構成とコード

サンプルに今回試したコードは以下のリポジトリです。CDKはTypescriptで作成しています。

ディレクトリ構成

.
├── bin
│   └── stacksets-test.ts
├── lib
│   └── stacksets-test-stack.ts
├── template
│   └── s3bucket.yml
├── test
│   └── stacksets-test.test.ts
├── README.md
├── cdk.json
├── jest.config.js
├── package-lock.json
├── package.json
└── tsconfig.json

CDKのコード確認

主に記述したコードはここだけです。これだけで組織内の全アカウント、もしくは指定したOU・リージョンにCloudFormationスタックを展開できます。

./lib/stacksets-test-stack.ts

import { CfnStackSet,Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as fs from 'fs'
import * as path from 'path'

export class StacksetsTestStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    //指定したパスのYAMLファイルをStringに変換
    const templateFilePath = path.resolve(__dirname, `../template/s3bucket.yml`)
    const templateToString = fs.readFileSync(templateFilePath).toString()

    //スタックを展開するリージョンを指定
    const regions =  ["ap-northeast-1"]
    //スタックを展開するOUを指定 (r-xxx or ou-xxxxx-xxxxxxxx)
    const organizationalUnitIds =  ["ou-xxxxx-xxxxxxxx"]

    new CfnStackSet(this, 'S3StackSet', {
      stackSetName: `S3StackSet`,
      permissionModel: 'SERVICE_MANAGED',
      capabilities: ['CAPABILITY_NAMED_IAM'],
      autoDeployment: {
        enabled: true,
        retainStacksOnAccountRemoval: false
      },
      stackInstancesGroup: [
        {
          regions: regions,
          deploymentTargets: {
            organizationalUnitIds: organizationalUnitIds,
          },
        },
      ],
      //callAs:"DELEGATED_ADMIN",委任先から実行する場合はコメントアウトを外す
      templateBody: templateToString
    })
  }
  }

11、12行目では展開したいCloudFormationテンプレートをString型に変換して、16、18行目ではスタックを展開したいリージョンとOUを指定しています。

ここではOUのIDを指定していますがRootのID(r-xxx)を指定すれば組織内全アカウントへの展開となります。

StackSetsの展開時のオプションは新規アカウント追加時にも自動で展開できるように、サービスマネージドアクセスで自動デプロイをONにしています。

templateフォルダの中にはStackSetsで展開したいテンプレートを保存しています。今回はサンプルとしてS3バケットを作成するだけのテンプレートを用意しました。

./template/s3bucket.yml

AWSTemplateFormatVersion: 2010-09-09
Description: Create S3
Resources:
  S3Bucket:
    Type: "AWS::S3::Bucket"
    Properties:
      BucketName: !Sub test-bucket-${AWS::AccountId}-stacksets

StackSetsを展開してみる

試しに先ほど紹介したサンプルのコードを実行してみます。

CDKの準備

まずは任意のフォルダでサンプルリポジトリからコードをClone、フォルダ内に移動します。

git clone https://github.com/jun-suzuki1028/aws-cdk-sample-organizations-stacksets.git
cd aws-cdk-sample-organizations-stacksets

CDKをインストールします。

npm install aws-cdk

CDKの実行

それではCDKを使ってStackSetsを展開してみます。展開先はOrganizationsのマネジメントアカウントを指定します。

  • もしStackSetsを委任先から利用する場合はcallAs:"DELEGATED_ADMIN"のコメントアウトを外してください
  • スタックを展開する先のOUも書き換えておきましょう

初めて対象のアカウントでCDKを実行する場合は以下のコマンドでCDKToolkitを展開しましょう。

cdk bootstrap

あとはデプロイコマンドを実行するだけで展開できます

cdk deploy

CDKからデプロイするとStackSetsを展開するスタックが作成されます。

StackSetsを確認すると、指定したOU内のアカウントに展開されていることが確認できました。

もちろん更新と削除もCDKからできます。cdk destroyを実行するとStackSet内のスタックとStackSet自体も削除してくれるので、コンソールから実行するよりも非常に楽でした。

おわりに

CDKを使ってStackSetを組織内に展開してみました。短いコード量で記述できることに加え、展開する対象のリージョンとOUをコードで確認できるのは運用上とても便利だと感じました。

Control Tower環境の場合、リソースの展開には以下のようなソリューションも利用できるのですが、別のリソースを展開する必要があったり手軽に始めづらい部分があるため、CDKで利用できるのは非常にありがたいですね。

個人的には今後マルチアカウント運用で独自のガードレールなどStackSetsで展開するときは全部CDKで実装していきたいなというお気持ちです。そのくらい簡単に実装できたので、ぜひマルチアカウントを運用されている方は試してみてください。

参考