PulumiでAWS OrganizationsとControl Towerを完全自動化:マルチアカウント管理の極限プラクティス
こんにちは。大規模クラウドインフラの設計・運用において、手動でのAWSアカウント発行やマネジメントコンソールでのSCP(サービスコントロールポリシー)ポチポチ設定に絶望したことはないだろうか。
「アカウントが増えるたびにチケットを切る」「統制(Governance)と開発スピード(Velocity)がトレードオフになる」——この永遠のジレンマをコードで完全に粉砕するのが、Pulumiを用いたAWS OrganizationsとControl Towerの完全自動化だ。
HCL(HashiCorp Configuration Language)の呪縛から解放され、TypeScript/Python等の真のプログラミング言語でインフラを記述するPulumiは、マルチアカウント管理において神のツールと化す。本記事では、理論と現場で即座に使える実践コードを交え、組織の基盤をコードで完全に支配する方法を伝授する。
—
1. 組織階層(OU)とSCPのコード管理手法
マルチアカウント戦略の根幹は、適切なOU(組織単位)の設計と、それを強制するSCPだ。Pulumiでは、これらをTypeScriptを用いてオブジェクト指向的にモジュール化し、DRY(Don’t Repeat Yourself)原則を徹底して管理する。
チーム開発を加速する設定とプラグイン
Pulumiの生産性を極限まで高めるため、以下のエディタ設定(VS Code前提)とプラグインを導入せよ。
- 必須プラグイン: `Pulumi Snippets` (コード補完の爆速化)
- 共有設定 (`Pulumi.yaml`):
プロジェクトのルートには必ずスタック共通の設定を定義する。
name: aws-org-control-tower
runtime:
name: nodejs
options:
packagemanager: npm
description: Enterprise AWS Organizations & Control Tower Automation via Pulumi
OU・SCP定義のベストプラクティスコード
以下は、セキュリティベースライン(ログ収集、外部公開禁止など)を強制するOU構造をコード化した例である。
import as pulumi from “@pulumi/pulumi”;
import as aws from “@pulumi/aws”;
// 1. 組織のルート情報を取得
const org = aws.organizations.getOrganization({} );
// 2. セキュリティOUとワークロードOUの作成
const securityOu = new aws.organizations.OrganizationalUnit(“security-ou”, {
parentId: org.then(o => o.roots[0].id),
name: “Security-OU”,
});
const workloadOu = new aws.organizations.OrganizationalUnit(“workload-ou”, {
parentId: org.then(o => o.roots[0].id),
name: “Workloads-OU”,
});
// 3. 厳格なSCPの定義:S3バケットのパブリック公開を絶対的に禁止
const denyPublicS3Policy = new aws.organizations.Policy(“deny-public-s3”, {
name: “DenyPublicS3Access”,
description: “Global policy to prevent public S3 buckets”,
type: “SERVICE_CONTROL_POLICY”,
content: JSON.stringify({
Version: “2012-10-17”,
Statement: [{
Sid: “MandatoryDenyPublicS3”,
Effect: “Deny”,
Action: [
“s3:PutBucketAcl”,
“s3:PutBucketPolicy”
],
Resource: “”,
Condition: {
StringEquals: {
“s3:x-amz-acl”: [“public-read”, “public-read-write”, “authenticated-read”]
}
}
}]
}),
});
// 4. ワークロードOUへのSCPアタッチ
const attachment = new aws.organizations.PolicyAttachment(“workload-scp-attach”, {
policyId: denyPublicS3Policy.id,
targetId: workloadOu.id,
});
—
2. AWS Organizationsプロバイダを活用した新規アカウント自動発行パイプライン
「開発チームから新しいAWS環境が欲しいと言われたら即座に発行される」状態を作る。`aws.organizations.Account`リソースを使用し、メールアドレスの動的生成とIAMロールの引き渡しを自動化する。
ここで重要なのは、冪等性(Idempotency)の担保だ。同じアカウント名で誤って二重作成されないよう、タグベースでリソースの状態をPulumiのステートに安全にマッピングする。
// 新規サンドボックスアカウントの自動プロビジョニング
const sandboxAccount = new aws.organizations.Account(“sandbox-account-01”, {
name: “sandbox-app-team-a”,
email: “aws-landing-zone+sandbox-a@example.com”, // 実際にはドメイン+エイリアスで自動生成
parentId: workloadOu.id,
iamUserAccessToBilling: “DENY”,
tags: {
Environment: “Sandbox”,
ManagedBy: “Pulumi”,
},
});
// アカウント作成完了後、クロスアカウントで操作するためのロール ARN をエクスポート
export const sandboxAccountId = sandboxAccount.id;
—
3. Control Towerライフサイクルイベントと連携した自動デプロイ設計
AWS Control Towerの「Account Factory」を用いてアカウントがプロビジョニングされた瞬間、あるいはライフサイクルイベント(`AWS Control Tower Lifecycle Event`)が発火した瞬間に、Pulumiの自動デプロイパイプラインを走らせるアーキテクチャがエンタープライズのデファクトスタンダードだ。
イベント駆動型アーキテクチャのフロー
1. Control Tower で新規アカウント作成(または変更)。
2. Amazon EventBridge が `CreateManagedAccount` などのライフサイクルイベントをキャッチ。
3. AWS Lambda / Webhook を経由して、Pulumi Automation API を実行するコンテナ(ECS/AWS CodeBuild)をキック。
4. Pulumiが新しいアカウントに対して、ベースラインリソース(CloudTrail、GuardDuty、IAM Identity Centerの権限など)を自動適用。
Pulumi Automation APIを活用したLambdaスクリプトの核心
インフラ構築をプログラム内部から制御するPulumi Automation APIのコードスニペットを示す。これにより、CI/CDパイプラインを外側に持たせず、イベントハンドラ自体にインフラ構築能力を持たせることが可能になる。
import as pulumi from “@pulumi/pulumi”;
import as auto from “@pulumi/pulumi/automation”;
export async function handler(event: any) {
const targetAccountId = event.detail.serviceEventDetails.createManagedAccountStatus.account(id);
// スタックのインラインプログラム定義
const inlineProgram = async () => {
// 新規作成されたアカウントに対するベースライン設定をここに記述
// 例: 特定のSNSトピック作成やConfigの有効化など
};
// Automation APIを使用してプログラム的にスタックを実行
const stack = await auto.LocalWorkspace.createOrSelectStack({
stackName: `auto-baseline-${targetAccountId}`,
projectName: “ControlTowerLifecycleHook”,
program: inlineProgram,
});
await stack.setAllConfig({
“aws:region”: { value: “ap-northeast-1” },
});
// 変更の適用(Up)
const upResult = await stack.up();
console.log(`Successfully provisioned baseline for account: ${targetAccountId}, Output: ${upResult.summary.result}`);
}
—
プロからの最後のアドバイス
マルチアカウント管理において、手動オペレーションは「技術的負債の爆弾」でしかない。Pulumiを用いたOrganizationsとControl Towerのコード化は、単なる省力化ではなく、「セキュア・ビ・デザイン(Security by Design)」を組織に強制するための唯一の解である。
コードを書き、プルリクエストをレビューし、テストを経てインフラが自動展開される世界線へ今すぐ移行せよ。あなたのチームのベロシティは、今日から劇的に跳ね上がるはずだ。