こんにちは!クラウドインフラの世界へようこそ。
今日は、私たちが日々のインフラ管理で直面する「マルチアカウント環境の混沌」を美しく、そして完全に自動化するための話をしよう。
「AWSで本番環境、検証環境、開発環境……とアカウントが増えるたびに、手動でポチポチと設定していませんか?」
「OrganizationのOU(組織単位)構成を変えるたびに、SCP(サービスコントロールポリシー)の適用漏れに怯えていませんか?」
もし心当たりがあるなら、今日がその悪夢からの卒業日だ。
今回は、次世代のインフラ構成管理ツール Pulumi を使って、AWS OrganizationsとControl Towerを完全にコード化し、マルチアカウント管理を全自動化するベストプラクティスを、優しく、そして骨太に解説しよう。これをマスターすれば、あなたのインフラ管理は劇的に楽になるだけでなく、圧倒的な堅牢性を手に入れることができる。
—
1. なぜPulumiでマルチアカウント管理なのか?
世の中にはTerraformやCloudFormationといった素晴らしいツールがある。しかし、なぜ私たちはあえてPulumiを選ぶのか?
最大の理由は、「TypeScriptやPythonといった使い慣れた汎用プログラミング言語で、インフラを記述できる」という点にある。
JSONやYAML、独自のHCLの記述にイライラさせられる時代はもう終わりだ。ループ処理、条件分岐、関数化、そしてユニットテスト――ソフトウェア開発で私たちが当たり前に使っている強力な武器をそのままインフラコードに持ち込める。これがPulumiの真骨頂だ。
AWS OrganizationsやControl Towerの管理は、複雑な階層構造(OU)やアカウント間の依存関係が絡み合う。これらをコードで表現し、冪等性(何度実行しても同じ状態が保たれる性質)を担保しながら自動化するには、Pulumiの表現力がベストマッチするのだ。
—
2. 開発環境のセットアップと基礎知識
まずは、手元のマシンにPulumiの世界を構築しよう。
今回は、最も型にはまった安心の組み合わせである TypeScript を用いて解説する。
2.1 必要なツールのインストール
以下のツールがインストールされていることを確認してほしい。
- Node.js (LTS推奨)
- AWS CLI (認証情報が設定済みであること)
- Pulumi CLI
Pulumi CLIのインストールは一瞬だ(MacならHomebrewでいける)。
brew install pulumi
2.2 プロジェクトの初期化
適当なディレクトリを作成し、Pulumiプロジェクトを初期化する。
mkdir pulumi-aws-controltower
cd pulumi-aws-controltower
pulumi new aws-typescript
途中でプロジェクト名やパスワード(暗号化用)を聞かれるので、適宜Enterを押して進めよう。これだけで、TypeScriptのプロジェクト骨格が自動生成される。
—
3. 組織階層(OU)とSCPのコード管理手法
ここからが本番だ。AWS Organizationsのルートの下に、セキュリティ統制のためのOU構造を作り、そこにSCP(Service Control Policies)をビシッと適用するコードを書こう。
以下のコードは、`index.ts` に記述する。
import as pulumi from “@pulumi/pulumi”;
import as aws from “@pulumi/aws”;
// 1. 組織のルート情報を取得
const org = aws.organizations.getOrganization({});
// 2. セキュリティ統制用OU(Sandbox, Workloads)の作成
const rootId = org.then(o => o.roots[0].id);
const workloadsOu = new aws.organizations.OrganizationalUnit(“workloads-ou”, {
name: “Workloads”,
parentId: rootId,
});
const securityOu = new aws.organizations.OrganizationalUnit(“security-ou”, {
name: “Security”,
parentId: rootId,
});
// 3. 例:不審なリージョンでのリソース作成を禁止するSCPの定義
const denyRegionsPolicy = new aws.organizations.Policy(“deny-regions-policy”, {
name: “DenyUnapprovedRegions”,
description: “許可されていないリージョンでのアクションを禁止する”,
content: JSON.stringify({
Version: “2012-10-17”,
Statement: [{
Sid: “DenyRegionsExceptTokyo”,
Effect: “Deny”,
NotAction: [
“iam:”,
“sts:”,
“support:”
],
Resource: “”,
Condition: {
StringNotEquals: {
“aws:RequestedRegion”: [
“ap-northeast-1”, // 東京リージョンのみ許可
“us-east-1” // グローバルサービス用
]
}
}
}]
}),
});
// 4. 作成したSCPをWorkloads OUにアタッチ
const attachment = new aws.organizations.PolicyAttachment(“workloads-scp-attachment”, {
policyId: denyRegionsPolicy.id,
targetId: workloadsOu.id,
});
// エクスポートして確認できるようにする
export const workloadsOuId = workloadsOu.id;
export const securityOuId = securityOu.id;
先輩からのワンポイントアドバイス:
TypeScriptを使っているため、JSONの部分もIDEの補完や型チェックが効く。うっかりミスでJSONの構文エラーを起こす心配がぐっと減るのが分かるだろうか?
—
4. 新規アカウント自動発行パイプラインの構築
「新しい開発チームができたので、アカウントを1つ生やしてほしい」
こんな依頼、もう手動で受ける必要はない。Pulumiを使えば、コードに1行追加して `pulumi up` するだけで、アカウントのプロビジョニングが自動で行われる。
AWS Organizationsプロバイダを使用して、新規メンバーアカウントを発行するコードを追加しよう。
// 5. 開発チーム用サンドボックスアカウントの自動発行
const sandboxAccount = new aws.organizations.Account(“sandbox-account”, {
name: “team-a-sandbox”,
email: “aws-sandbox-team-a@example.com”, // 実際の環境では一意なメールアドレスが必要
parentId: workloadsOu.id,
closeOnDeletion: false, // 誤削除の防止
tags: {
Environment: “Sandbox”,
Owner: “Team-A”,
},
});
export const sandboxAccountId = sandboxAccount.id;
これだけで、AWS Organizations内に新しいAWSアカウントが自動作成され、指定したOU(Workloads)に自動配置される。まさに全自動の境地だ。
—
5. Control Towerライフサイクルイベントと連携した自動デプロイ設計
さて、ここからがシニアエンジニアの腕の見せ所だ。
AWS Control Towerを使うと、アカウントファクトリー経由でアカウントが作られたり、OUに新しい変更が加わったりする。この時、AWS EventBridge (CloudWatch Events) がライフサイクルイベントを発火する。
このイベントをトリガーにして、Pulumiのデプロイを自動実行(GitOps的なアプローチや、AWS Lambda / CodeBuild経由での実行)するアーキテクチャを組むのが、エンタープライズ環境におけるベストプラクティスだ。
[Control Tower / Account Factory]
│
▼ (アカウント作成・変更)
[EventBridge ライフサイクルイベント]
│
▼ (イベント検知)
[AWS CodeBuild / Lambda]
│
▼ (自動実行)
[Pulumi Engine] ──> AWS環境の完全同期(冪等性の担保)
設計上の極意:
1. 状態管理(Backend)の分離: Pulumiの状態ファイル(State)は、必ず暗号化されたS3バケットとDynamoDB(ステートロック用)を組み合わせたリモートバックエンドで管理すること。複数人やCI/CDパイプラインから同時に実行しても競合しない仕組みが必須だ。
2. 権限の最小化: Control Towerの管理アカウント(Management Account)から、各メンバーアカウントへのクロスアカウントAssumeRoleを適切に設定し、Pulumiを実行するロールには必要最小限の権限(Least Privilege)を与えよう。
—
6. 動作確認:いざ、世界を構築する
コードが書けたら、いよいよデプロイだ。以下のコマンドを叩いてみよう。
pulumi up
Pulumiが現在のAWS上のリソースと、あなたが書いたコードの差分(Diff)を美しくカラー表示してくれる。
内容に問題がなければ、そのまま `yes` を選択する。
数分後、コンソールに成功のメッセージが表示されれば完了だ。
AWSマネジメントコンソールを開いて確認してみてほしい。見事にOUが作成され、SCPがアタッチされ、新しいアカウントが生み出されているはずだ。
—
まとめ
今回は、Pulumiを用いたAWS OrganizationsとControl Towerの完全自動化について、その基礎から実践的なコードまでを解説した。
- TypeScriptの表現力を活かして、インフラを美しくコード化できること。
- OUとSCPの管理をコードに集約し、セキュリティ統制を強固にできること。
- 新規アカウントの自動発行により、運用負荷をゼロに近づけられること。
これをマスターすれば、あなたのインフラ管理は手作業の恐怖から解放され、コードを書く喜びを取り戻すことができる。
さあ、明日からのインフラ構築を、もっとスマートに、もっとエキサイティングに変えていこう!