はじめに
業務でAWSアカウント作成し払い出すとき、次のような作業を毎回GUI操作で行っていました。
- AWSアカウントを作成する
- IAMのパスワードポリシーを設定する
- 共通IAMロールへポリシーをアタッチする
- CloudTrailを設定する
- AWS Configを設定する
- 引き渡し前に不要なCloudWatch Logsのロググループを削除する
- 利用者へ認証情報と作業結果を連絡する
これらをAWS CLIのシェルスクリプトにまとめ、アカウント作成から初期設定、引き渡し前の後処理までを一括実行できれば、定型操作を減らせるのではと考えたのが出発点です。
ところが、アカウント払い出しの事例を調べると、aws organizations create-account を中心に自作する例より、
AWS Control TowerのAccount FactoryやAccount Factory for Terraform(AFT)を使う例が多く見つかりました。
そこで、次の疑問を実際に検証しました。
AWS CLIの自作スクリプトとControl Towerは何が違うのか。
Control Towerを導入すると、GUI作業をどこまで減らせるのか。
先に結論を書くと、Control Towerは「コマンド入力をなくすサービス」ではなく、
「払い出したアカウントが同じルールやセキュリティ設定で運用できるようにするためのサービス」でした。
結論
今回の検証で得た結論は4つです。
- 現在のGUI払い出し手順はAWS CLIで一括自動化できる
- Organizationsによるアカウント作成だけでなく、パスワードポリシー、IAMロール、CloudTrail、Config、CloudWatch Logsの整理もAPI化できる
- ただし、実行順序、完了待ち、安全な再実行、設定変更への追従は自分たちで実装・保守する
- MFAの設定関連やクレジット決済関連がある場合は除く
- Control Towerの価値は作成後の標準化と継続的ガバナンス
- OU、コントロール、ログ集約、アクセス管理などを一貫した設計にできる
- ただしLanding Zone 4.0では各サービス統合を選択できるようになった
- Account Factory標準UIを使うだけではGUIは残る
- Control TowerまたはService Catalogから申請する操作が必要
- API化またはAFTを使って初めて、申請から初期設定までをパイプライン化できる
- 少数アカウントなら自作CLI、多数・継続運用ならCT/AFTが有力に思う
- 重要なのはアカウント数だけでなく、監査、再現性、証跡、設定変更への追従で判断すること
まず「アカウント払い出し」を分解する
「AWSアカウント作成」と一言で呼んでも、実際に設定を行わなければならないことは多岐にわたります。
| レイヤー | 具体的な作業 |
|---|---|
| アカウント作成 | メールアドレス、表示名、Organizationsへの参加 |
| 組織配置 | OUへの移動、SCPの適用 |
| アクセス | IAMユーザー、IAM Identity Center、Permission Set |
| ベースライン | CloudTrail、Config、Security Hub、共通IAMロールなど |
| 引き渡し | 完了確認、利用者通知、台帳登録 |
AWS CLIは、APIが提供されている処理であれば、アカウント作成からベースライン設定、引き渡し前の後処理まで自動化できます。
一方、Control Towerが主に解決するのは、個々のコマンド実行ではなく、
複数アカウントへ共通ベースラインを適用し、その状態を継続的に管理することです。
この違いを理解しないまま比較すると、「結局GUIが必要ならControl Towerに意味がない」という誤解につながります。
方法1: AWS CLIとシェルスクリプトで自作する
Organizationsでは、管理アカウントから次のようにメンバーアカウントを作成できます。
REQUEST_ID=$(
aws organizations create-account \
--account-name "sandbox-dev" \
--email "example+aws-sandbox-dev@example.com" \
--query 'CreateAccountStatus.Id' \
--output text
)
aws organizations describe-create-account-status \
--create-account-request-id "$REQUEST_ID"
CreateAccountは非同期APIです。最初のコマンドが成功しても、アカウントが利用可能になったとは限りません。
実運用では少なくとも次が必要です。
- 作成要求IDを保存する
-
SUCCEEDEDまたはFAILEDまでポーリングする - 失敗理由を記録する
- 作成されたアカウントIDを取得する
- 指定OUへ移動する
-
OrganizationAccountAccessRoleなどへAssumeRoleする - IAMパスワードポリシーを設定する
- 共通IAMロールを作成し、必要なポリシーをアタッチする
- CloudTrailを作成・開始する
- AWS Configのレコーダーと配信チャネルを設定・開始する
- 引き渡し対象外のCloudWatch Logsロググループを削除する
- 設定結果を検証し、台帳更新や利用者通知を行う
つまり、「アカウントを作るコマンド」は短くても、「業務として安全に再実行できる払い出し処理」は短くありません。
今回想定しているスクリプトの責務を擬似コードにすると、次の形です。
create_account_and_wait
move_account_to_ou
assume_target_account_role
configure_iam_password_policy
configure_common_iam_roles
configure_cloudtrail
configure_aws_config
delete_temporary_cloudwatch_log_groups
verify_baseline
record_result_and_notify
この方式でも、現在GUIで行っている払い出し作業の大部分は自動化できます。
Control Towerとの違いは「CLIで設定できるか」ではなく、その設定一式を自前のスクリプトとして保守するか、
AWS管理のベースラインとコントロールへ寄せるかです。
自作CLI方式の長所
- 小さく始められる(実際にスクリプトから小さく始めてAFTに移行するのもありだと思います)
- 既存の手順を1操作ずつ置き換えやすい
- Bash、Python、Step Functionsなど、チームが扱える技術を選べる
- Control Towerを導入しなくても使える
自作CLI方式で自分たちが持つ責任
- 非同期処理の状態管理
- タイムアウト、再試行、重複実行への対応
- OUやSCPとの整合性
- クロスアカウントロールの管理
- CloudTrailやConfigの全アカウント展開
- 削除してよいCloudWatch Logsロググループの安全な判定
- ベースライン変更時の既存アカウントへの再適用
単発のシェルから始めること自体は悪くありません。ただし、要件が増えるとスクリプトは徐々に「小さなAccount Factory」になります。
方法2: Control TowerとAccount Factoryを使う
Control Towerは、Organizations、IAM Identity Center、CloudTrail、Config、Service Catalogなどを組み合わせ、
マルチアカウント環境の統制をオーケストレーションします。
Account Factoryでアカウントを作るとき、利用者が入力するのは主に次の情報です。
- アカウント名
- アカウント用メールアドレス
- 配置先OU
- Identity Centerの利用者情報
標準の入口はControl TowerコンソールまたはService Catalogです。この時点ではGUI操作が残ります。
しかし、GUIの裏で動くService CatalogのProvisionProduct APIを呼べば、
同じ処理をCLIやLambdaから開始できます。さらにAFTを使えば、Gitへのアカウント要求の追加を起点にできます。
Control Towerが提供するもの
- アカウント払い出し方法の標準化
- OU単位のコントロール
- 管理対象アカウントへのベースライン適用
- IAM Identity Centerとのアクセス統合
- Account Factoryによる作成・登録フロー
- Control Tower管理リソースのドリフト検知
Control Towerだけでは提供されないもの
- 社内の申請・承認フロー
- SlackやTeamsへの独自通知
- 社内CMDBへの登録
- 会社固有のIAMロール、ネットワーク、タグの全要件
- GUI操作そのものの完全排除
これらはService Catalog API、AFT、EventBridge、Lambda、Step Functionsなどを組み合わせて実装します。
方法3: AFTで自動化する
AFTは、Control Towerのガバナンスを利用しながら、Terraformでアカウントの作成とカスタマイズを自動化する仕組みです。
アカウント要求は、概念的には次のようなTerraformコードで管理します。
module "sandbox_dev" {
source = "./modules/account-request"
account_name = "sandbox-dev"
account_email = "example+aws-sandbox-dev@example.com"
managed_organizational_unit = "Sandbox"
account_customizations_name = "sandbox"
}
Gitへ変更をpushすると、AFTのパイプラインがAccount Factoryを呼び出し、その後に共通・個別のカスタマイズを実行します。
AFTが向いているケース
- アカウント作成が継続的に発生する
- Terraformが組織に定着している
- 共通設定とアカウント固有設定をコードレビューしたい
- 既存アカウントにも標準変更を再適用したい
- 実行履歴と申請内容をコードとして残したい
AFTの導入コスト
- AFT管理用アカウントが必要
- CodePipeline、CodeBuild、Step Functionsなど多くのリソースを理解する必要がある
- 共通設定、個別設定、AFT外で管理する設定の責務分担が必要
- 小規模環境では仕組みの維持コストが手作業削減効果を上回ることがある
AFTは「Control TowerをTerraformで作るもの」ではなく、Control Tower管理下のアカウント払い出しと初期設定をGitOps化するものと捉えると分かりやすくなりました。
3方式の違い
| 観点 | Organizations CLI | CT Account Factory | AFT |
|---|---|---|---|
| アカウント作成 | CLI/API | GUIまたはAPI | Git push |
| OU指定 | 自作処理 | 入力項目 | コード |
| ベースライン | 自作 | CTの有効な統合・コントロール | CT + Terraformカスタマイズ |
| 業務固有の後処理 | スクリプトで実装 | 別途実装 | AFTカスタマイズ等で実装 |
| 既存アカウントへの再適用 | 自作 | CT管理範囲 | パイプライン化可能 |
| コードレビュー | 実装次第 | 標準GUIでは不可 | 得意 |
| 導入コスト | 低 | 中 | 高 |
| 運用の自由度 | 高 | 中 | 高 |
| 向く状況 | 少数・単純 | 統制されたセルフサービス | 継続的な大規模自動化 |
実際に検証して分かったこと
1. Control Towerの自動化範囲はLanding Zoneの選択で決まる
余談ですが今回実際にCTとAccountFactoryの作成を行いました。
設定項目として、GUIでConfigや集中ログ管理などのサービス統合を無効にし、
Controls-only相当のLanding Zone 4.0を作成しました。
APIで取得したマニフェストも、選択どおり次の状態でした。
{
"accessManagement": { "enabled": false },
"securityRoles": { "enabled": false },
"backup": { "enabled": false },
"config": { "enabled": false },
"centralizedLogging": { "enabled": false }
}
Organizationsに存在したのも管理アカウント1つだけで、AuditやLog Archiveに相当する共有アカウントは作成されていませんでした。
Landing Zone 4.0では柔軟性が増しており、このような構成も作成することができました。
「Control Towerを使っている」という情報だけでは、自動化される範囲を判断できないことが分かります。
Landing Zone 4.0では、AWS Config、CloudTrail、アクセス管理などの統合を選択できます。
マニフェストのキーとAWSサービスの対応は、次のように読みます。
| マニフェストのキー | 対応する統合 |
|---|---|
centralizedLogging |
AWS CloudTrailによる集中ログ管理 |
config |
AWS Config |
accessManagement |
IAM Identity Centerによるアクセス管理 |
securityRoles |
Security Roles |
backup |
AWS Backup |
これらは完全に独立したスイッチではなく、公式ドキュメントでは、AWS Config統合を無効にする場合、
Security Roles、IAM Identity Center、AWS Backupの各統合も無効にする必要があるとされています。
今回config、securityRoles、accessManagement、backupが揃ってfalseだったのは、この依存関係と整合します。
CloudTrailに対応するcentralizedLoggingは別途、明示的に無効化されていました。
したがって、「Control Towerを導入した環境」と一括りにせず、少なくとも次を区別する必要があります。
| Landing Zoneの構成 | 自動化される主な範囲 |
|---|---|
| Controls-only相当 | Organizationsとの統合、コントロールの有効化 |
| CloudTrail統合あり |
centralizedLoggingに基づく集中ログ管理 |
| Config統合あり | Config記録と検出コントロールの基盤 |
| 各統合を有効化 | Security Roles、Identity Center、Backupなど選択した範囲 |
「はじめに」で挙げたCloudTrail設定の標準化が目的なら、Control Towerを導入するだけで満足せず、少なくとも以下を受け入れ条件として確認する必要があります。
- CloudTrail統合(マニフェスト上は
centralizedLogging)が有効か - ログの集約先アカウントとS3バケットはどこか
- 管理対象OU・アカウントにベースラインが適用されたか
- ログの保持、暗号化、改ざん検知、削除権限が要件を満たすか
2. Terraformとの共存で重要なのは「作れるか」より「誰が所有するか」
Control Tower環境でも、自社固有のOUやカスタムSCPはTerraformで管理できます。
今回もWorkloads/Development OUを作成し、カスタムSCPのDenyLeaveOrganizationをSandbox OUへ適用できました。
ただし、最初に実装した「Workloads OUが存在すれば参照し、なければTerraformで作成する」という条件分岐には問題がありました。
初回ApplyではTerraformがWorkloadsを作成します。次回PlanではデータソースがそのWorkloadsを「既存OU」として検出するため、
作成条件が0件に切り替わり、Terraform自身が管理しているOUを削除しようとしました。
# aws_organizations_organizational_unit.workloads[0] will be destroyed
# (because index [0] is out of range for count)
Plan: 0 to add, 0 to change, 1 to destroy.
これはControl Tower固有の問題ではなく、同じリソースを「外部に存在するかもしれないもの」と「Terraformが所有するもの」の両方として扱ったことが原因です。
修正後は所有権を次のように固定しました。
- Control Towerが管理するOUやコントロールはTerraformから参照だけする
- 自社で追加する
Workloads、Development、カスタムSCPはTerraformが常に所有する - 既存OUをTerraform管理へ移す場合は、条件分岐で自動採用せず
terraform importする - Apply後に再度Planし、
No changesになることを受け入れ条件にする
状態アドレスを移行して再Planした結果はNo changesでした。
この検証から得た実務上のルールは、1つのAWSリソースに1つの管理主体を割り当てることです。
Control TowerとTerraformは共存できますが、両方が同じOUやコントロールを所有する設計は避ける必要があります。
自分の業務ならどう段階導入するか
いきなりAFTを導入するのではなく、次の順序が現実的だと考えています。
Step 1: GUI手順を棚卸しする
各作業を次に分類します。
- アカウント作成時に一度だけ必要
- 全アカウントへ共通で必要
- 利用者や用途によって異なる
- 本当に必要か再検討すべき
Step 2: 既存運用をCLI化する
まずは現在GUIで行っている払い出し処理全体を、アカウント作成と完了待ちを行う管理アカウント側の処理と、AssumeRole後に初期設定を行うメンバーアカウント側の処理に分けてスクリプト化します。
- 完了待ちと失敗記録
- OU移動
- IAMパスワードポリシー
- 共通IAMロールとポリシーアタッチ
- CloudTrail
- AWS Config
- 不要なCloudWatch Logsロググループの削除
- タグ
- 完了レポート
この段階で、手作業時間とエラー件数を計測します。
Step 3: 組織共通の監査基盤を設計する
CloudTrailやConfigを各アカウントへ個別設定するのではなく、Organizations単位で集約します。
Control Towerを採用する場合は、Landing Zone 4.0のどのサービス統合を有効にするかを明示します。Controls-onlyのままでは、今回の目的を満たさない可能性があります。
Step 4: 件数と統制要件が増えたらAccount Factoryへ移行する
Account Factoryをセルフサービスの入口とし、Service Catalog APIまたはStep Functionsで社内申請と接続します。
選定の目安
| 状況 | 第一候補 |
|---|---|
| 払い出しが少なく、設定も単純 | Organizations CLI + Terraform/スクリプト |
| 複数OUで統制し、監査設定を標準化したい | Control Tower |
| 利用者がセルフサービスで申請したい | Account Factory + 申請ワークフロー |
| Terraform/GitOpsで作成・初期設定・更新を管理したい | Control Tower + AFT |
| 既存の独自Landing Zoneが成熟している | 無理に移行せず、CTとの差分を評価 |
判断基準は「GUIを何クリック減らせるか」だけではありません。
- 1件あたりの作業時間
- 月間の払い出し件数
- 設定漏れの発生頻度
- 監査対応に必要な時間
- 標準変更を既存アカウントへ反映するコスト
- 自動化基盤そのものの保守コスト
これらを数値化すると、Control TowerやAFTの導入判断がしやすくなります。
まとめ
AWS CLIとControl Towerは競合する選択肢ではなく、担当するレイヤーが違います。
- AWS CLI: 個々のAPI操作を自動化する
- Organizations: アカウントとOUを管理する
- Control Tower: マルチアカウントの統制を標準化・継続管理する
- Account Factory: 統制されたアカウント払い出しを提供する
- AFT: 払い出しとカスタマイズをTerraform/GitOps化する
今回の学びは以下です。
既存のGUI手順をそのままCLIへ置き換えるだけでは、手作業は減っても運用設計は変わらない。
Control Towerの価値は、アカウントを作ることより、作った後も同じ統制状態を保つことにある。
まずCLI/Terraformで定型作業を減らし、共通ベースラインをControl Towerへ寄せ、
継続的な払い出しと変更管理が必要になった段階でAccount Factory APIやAFTへ進む、という順序が現実的です。
参考資料
AWS公式
- CreateAccount - AWS Organizations
- Provision accounts within AWS Control Tower
- Automate Account Provisioning in AWS Control Tower by Service Catalog APIs
- Overview of AWS Control Tower Account Factory for Terraform
- Landing Zone v4.0 migration guide - Key changes
- Set an account password policy for IAM users
- Mandatory controls - Enable Integrity Validation for CloudTrail Log File