複数アカウント時代のIAM設計入門 | Organizations・SCP・Permission Boundary統合評価

目次

1. なぜ複数アカウント時代のIAMが詰まるか — Vol1からの架橋

【IAM入門シリーズ Vol1-2 ラインナップ】

【この記事で学ぶこと 3 つ】

  • 単一アカウントで成立していたIAM運用がなぜアカウント増加で崩壊するか、3つの詰まりシーンで理解する
  • Vol1の2レイヤー評価ロジック (Identity-based / Resource-based) が、マルチアカウントでは SCP・Permission Boundary・Session Policy を加えた5レイヤーに拡張されることを把握する
  • 本記事を読み終えた後に、OU階層設計・5レイヤー評価・Permission Set 設計・開発者デリゲーションの4ゴールに到達するための全体像を把握する

1-1. 3つの詰まりシーン

単一アカウントのIAMを一通り触った経験があっても、AWSアカウントが2つ、3つと増えた瞬間に「前まで分かっていたはずのIAMが突然わからなくなる」という現象が起きる。
以下の3シーンはその典型で、筆者がAWSを導入したスタートアップや中堅企業の現場で実際に頻繁に目撃したパターンだ。

詰まりシーン①: アカウント増加でIAM管理が崩壊する

あるスタートアップでは本番・ステージング・開発の3環境を分離するため、AWSアカウントを3つ用意した。
当初は「アカウントを分けたからセキュリティが上がる」という認識で、管理者がそれぞれのアカウントでIAMユーザーを個別に作成していた。
入社する開発者が増えるたびに3アカウント分のIAMユーザーをそれぞれ手動で作成し、それぞれに異なるパスワードを設定する。
6ヶ月後、チームが10人を超えた時点で以下の問題が表面化した。

  • 「あの開発者はどのアカウントにどんな権限を持っているか?」を一覧できるダッシュボードが存在しない
  • パスワードポリシーをアカウントごとに独自に設定してしまい、MFAが義務化されているアカウントとそうでないアカウントが混在している
  • 退職した開発者のIAMユーザーを削除し忘れ、3アカウントのうち1つに有効なIAMユーザーが残存しているとセキュリティ監査で発覚した
  • 「本番に誤って触れる可能性があるため、本番アカウントのIAMユーザー作成は管理者が直接行う」というルールが暗黙の慣習になり、開発者の権限申請から付与まで平均3日かかっている

これは「アカウントを分けた」ことで解決したはずの問題が、IAM運用のスケールに対応できていないために再発した典型例だ。
IAMを一元管理する仕組みがなければ、アカウントが増えるほど管理コストは指数的に増大する。

AWS が提供する解決策が IAM Identity Center (旧 AWS Single Sign-On) だ。
Identity Center を使うと、すべてのアカウントへのアクセスを1つのポータルから一元管理でき、ユーザー追加・削除・権限変更を Identity Center 側で行うだけで全アカウントに反映される。
詳しい実装は §5 で扱うが、「複数アカウントのIAM管理コストの急増」という問題への根本的な解答として認識しておくと、後続セクションの位置づけが理解しやすくなる。

詰まりシーン②: SCP / Permission Boundary / Permission Set の3つが混同される

AWSが公式に「マルチアカウント管理の推奨構成」として紹介する際に必ず登場する3つの概念がある。
それが SCP (Service Control Policy)、Permission Boundary、そして IAM Identity Center の Permission Set だ。
ドキュメントを読んでも「何が違うのか」「どこで何を使うのか」が整理できず、理解を諦めてしまう技術者は少なくない。

現場でよく聞く混乱の声を挙げると:

  • 「SCPを設定すれば最小権限が実現できると思っていたが、SCPはDenyしか機能しないのか?」
  • 「Permission Boundary と SCP はどちらも権限の上限を設定するものでは? 同じものを2箇所で設定しているのか?」
  • 「IAM Identity Center の Permission Set は、各アカウントに IAM ロールを自動で作ってくれるらしいが、そのロールのポリシーと Permission Boundary の関係がわからない」
  • 「Vol1 で学んだ Condition キーによる細粒度制御は、SCP でも使えるのか?」

これらの混乱は、各機能が「何を制御するか (主語・客語)」と「どの評価レイヤーで機能するか」を整理しないまま個別に覚えようとするために起きる。
§3 で5レイヤー統合評価ロジックとして体系化するが、まずこの混乱が「単一アカウントの延長では整理できない」問題であることを認識することが出発点だ。

詰まりシーン③: 開発者への権限委譲が怖くてボトルネックになる

「開発者にIAMロール作成権限を与えると、過剰な権限を持つロールを作られてしまうかもしれない」という恐れから、権限設定の作業を管理者が一手に引き受けているケースは非常に多い。
管理者のボトルネックが拡大すると以下のような連鎖が生まれる。

  • 開発者が新機能のためにLambdaロールが必要になる → Jiraチケットを作成 → 管理者のレビューキュー待ち → 承認・設定まで平均3日 → スプリントを1本無駄にする
  • 権限申請の煩雑さを避けるため、開発者が既存のロールに * ポリシーを追加して「一時的に」ブロードな権限を付与する → その設定が恒久的に残る
  • アカウント数が増えると管理者が全アカウントの権限申請をレビューしきれなくなり、「急いでいるので承認だけお願い」という申請が増加する

この問題を根本的に解決するのが Permission Boundary によるデリゲーションパターンだ。
「開発者がIAMロールを自由に作成できるが、そのロールが持てる最大権限は Permission Boundary によって上限が設定されている」という仕組みにより、本番を守りながら開発の自律性を担保できる。
具体的な実装は §6 で扱うが、まず「こういう解決策がある」という認識を §1 の段階で持っておくと、後続セクションの理解が大幅に深まる。

1-2. Vol1からの架橋 — 2レイヤーから5レイヤーへ

IAMポリシー設計入門 (Vol1) では、IAMの評価ロジックを次の2種類で説明した。

  1. Identity-based Policy (IBP): IAMユーザー・ロール・グループにアタッチするポリシー。「誰が何をできるか」を定義する
  2. Resource-based Policy (RBP): S3バケットポリシーや Lambda リソースポリシーなど、リソース側にアタッチするポリシー。「誰からのアクセスを許可するか」を定義する

単一アカウント内であれば、このIBPとRBPの組み合わせでほぼすべてのアクセス制御を表現できる。
しかし複数アカウントが登場すると、評価されるレイヤーが3つ増えて合計5レイヤーになる。

単一アカウント (Vol1の世界):
  Layer 1: Identity-based Policy (IBP)
  Layer 2: Resource-based Policy (RBP)

マルチアカウント (本記事が追加する世界):
  Layer 1: Identity-based Policy (IBP)← Vol1で学習済み
  Layer 2: Resource-based Policy (RBP)← Vol1で学習済み
  Layer 3: SCP (Service Control Policy)  ← Organizations レベル。アカウント全体に上限を設定
  Layer 4: Permission Boundary  ← IAMエンティティレベル。委譲時の最大権限を設定
  Layer 5: Session Policy ← AssumeRole時のセッションに一時的な制限を付加

この5レイヤーは「全てが Allow でも、1つでも Deny があればアクセス拒否」という大原則 (Vol1の評価ロジック) の延長線上にある。
ただしSCPとPermission Boundaryは「Denyとして機能するが、明示的なAllowがない場合も拒否になる」という Implicit Deny の挙動が絡むため、Vol1以上に評価順序の理解が重要になる。

5レイヤーの概要を表にまとめると以下のようになる。

Layerポリシー種別設定主体適用スコープ主な用途
1Identity-based Policy (IBP)IAM管理者特定のユーザー・ロール誰が何をできるかの基本定義
2Resource-based Policy (RBP)リソース管理者特定のリソースクロスアカウントアクセスの許可
3SCPOrganizations管理者OU・アカウント全体アカウントレベルの権限上限設定
4Permission BoundaryIAM管理者 (委譲元)特定のIAMエンティティ委譲先が作れるロールの最大権限制限
5Session Policy呼び出し元アプリAssumeRoleセッション一時的なセッション権限の絞り込み

Layer 3 (SCP) は「このアカウントでは絶対に使わせない AWS サービス・アクション」を定義するガードレールだ。
例えば Deny: ec2:CreateVpc を含む SCP を OU に適用すれば、そのOU配下の全アカウントでどんなIAMユーザーやロールがいても VPC の作成は不可能になる。
一方 Layer 4 (Permission Boundary) は「このIAMロールは最大でこの権限まで持てる」という個別エンティティへの上限設定で、委譲パターンで力を発揮する。

Vol1で学んだ「Access Analyzer による最小権限特定」「CloudTrailを使った実際の使用状況調査」「アンチパターン演習 (ワイルドカード乱用・AdministratorAccess 安易付与等)」はすべてそのまま本記事の内容に接続する。
特に Organizations 環境では Access Analyzer の適用範囲が「アカウント外部アクセスの検出」にまで拡張されるため、§5 でその使い方を改めて解説する。

評価ロジックの全体像は §3 で改めて図解する。
§1 の段階では「5レイヤーが存在する」「各レイヤーの設定主体が異なる」という2点を把握しておけば十分だ。

1-3. 本記事のゴールと対象読者

この記事で達成できる4つのゴール

  • (a) OU階層設計: AWS Organizations の 3-tier 基本形と規模別パターンを理解し、自社環境に合ったOU設計を選択できる
  • (b) 5レイヤー統合評価ロジック: SCP × Permission Boundary × Identity-based × Resource-based × Session Policy の評価優先順位を図解で腹落ちさせ、アクセス制御の問題を自力で診断できる
  • (c) Permission Set 設計実践: IAM Identity Center の Permission Set 設計・Account Assignment・委任管理パターンを実装できる
  • (d) 開発者デリゲーション: Permission Boundary を使って本番環境を守りながら開発者に安全に権限を委ねられる

前提: 単一アカウントの IAM (User / Group / Role / Policy) を操作したことがある方を対象にしています。IAMポリシー設計入門 (Vol1) を読んでいると理解が深まります。

次のシリーズ: Vol3 では Organizations 環境のアクセス権棚卸を自動化する方法を扱う予定です。

この記事を読むと最も効果を感じられるのは以下の読者だ。

  • 単一アカウントの IAM (ユーザー・グループ・ロール・ポリシーのアタッチ) は操作したことがあるが、AWS Organizations を本格的に使った経験がない
  • AWSアカウントが2つ以上になり、「IAMをどう一元管理するか」を検討しはじめた
  • IAM Identity Center (旧 AWS SSO) の導入を検討しているが、Permission Set とロール・ポリシーの関係が整理できていない
  • 開発者にIAMロール作成権限を委譲したいが、本番環境への影響が怖くて踏み切れていない
  • SCPを導入したが「なぜかこのアクセスが拒否される」という謎のエラーに悩まされている

前提となる環境・ツールは以下の通りだ。

  • AWS マネジメントコンソールへのアクセス (Organizations の管理アカウントが望ましい、メンバーアカウントでも概念理解は可能)
  • AWS CLI (バージョン 2 系、aws configure 設定済み) があると §5・§6 のハンズオンで手を動かせる
  • Terraform の基本的な HCL 構文を読める (§7 の演習問題で使用するが、必須ではない)

この記事の構成

本記事は全8セクションで構成されている。
§1 (本セクション) で問題を定義し、§2 で環境前提を整理した後、§3〜§7 でゴール (a)〜(d) を順番に達成し、§8 でシリーズ全体のまとめを行う。

セクション内容達成ゴール
§1 (本節)詰まりシーン定義・5レイヤー概観・本記事のゴール全体像の把握
§2環境・前提・Organizations基本構造事前準備
§3SCP設計入門と5レイヤー統合評価ロジック(b) 5レイヤー評価
§4AWS Organizations OU階層設計パターン(a) OU階層設計
§5IAM Identity Center と Permission Set 設計(c) Permission Set 実践
§6Permission Boundary による開発者デリゲーション(d) 開発者デリゲーション
§7アンチパターン演習5問 (Terraform + コードレビュー)実践定着
§8まとめ・シリーズロードマップ・次巻予告振り返りと展開

§3 が本記事の核心だ。
5レイヤー統合評価ロジックを一度理解すると、「このアクセスが通らない原因はどのレイヤーにあるか」を自力で診断できるようになり、SCPやPermission Boundaryへの苦手意識が大幅に解消する。
§4〜§6 は §3 の評価ロジックを前提とした実装セクションになっているため、§3 を飛ばして後半から読むと理解が難しくなる点に注意してほしい。

経験豊富な読者が特定セクションだけ参照したい場合は以下を参考にしてほしい。

  • Organizations の OU 設計だけ確認したい → §4 から読む
  • IAM Identity Center の Permission Set 実装 → §5 から読む
  • Permission Boundary の委譲パターン → §6 から読む
  • アンチパターンとその修正方法 → §7 から読む

2. Organizations全体像 + アカウント分離 + OU階層設計

複数アカウント設計の基盤となる AWS Organizations の仕組みと、アカウントをどう分離するかの設計パターンを押さえます。「なぜ1アカウントに全部入れてはいけないのか」という問いに答えながら、OU (Organizational Unit) 階層の設計原則まで一気に整理します。

2-1. AWS Organizations の基本概念

AWS Organizations は複数の AWS アカウントを一元管理するサービスです。1つの 管理アカウント を中心に、組織を木構造で管理します。

構成要素

要素説明
Root組織全体の最上位コンテナ。1つだけ存在し、組織の起点になる
OU (Organizational Unit)アカウントをグループ化する論理コンテナ。ネスト可能 (最大5階層)
Account実際の AWS アカウント。管理アカウントとメンバーアカウントの2種がある
SCP (Service Control Policy)OU/Account に適用するアクセス制御ポリシー。§3 で詳述

Organizations を有効化すると、既存のアカウントが自動的に管理アカウントになります。管理アカウントは 組織内で特別な扱い を受けるため、日常の業務ワークロードは決して配置しないことが原則です。

管理アカウントと委任管理アカウント

区分役割SCP 適用
管理アカウントOrganizations の作成・管理。メンバーアカウントの招待・追加適用されない
委任管理アカウント一部の管理機能を委譲されたアカウント (例: 監査・脅威検知サービスの集約)適用される

管理アカウントに SCP が適用されない点は特に重要です。誤って強力な SCP を設定しても管理アカウントでは無効なため、管理アカウントを使って SCP の影響から逃れることができてしまいます。この理由から、管理アカウントへのアクセスは最小限に絞り、日常業務はメンバーアカウントで行う運用が推奨されます。

Organizations を使う主なメリット

  • 一括請求 (Consolidated Billing): 組織全体のリソース使用量を合算して割引 (Reserved Instance / Savings Plans の共有など) が受けられる
  • SCP による組織横断アクセス制御: メンバーアカウントに対して最大許可範囲を一括設定できる。特定リージョンの制限やルートユーザーの操作禁止などを組織単位で強制できる
  • IAM Identity Center による ID 一元管理: 組織全体でシングルサインオンを実現。§4 で詳述
  • CloudTrail Organization Trail による監査ログ集約: 全メンバーアカウントの API ログを1か所に集約し、改ざんを防ぐ

AWS Organizations の基本機能 (OU の作成・SCP の適用・Consolidated Billing) は 追加料金なし で利用できます。ただし AWS Control Tower や一部のガバナンス機能は別途コストが発生するサービスもあるため、導入前にコスト見積もりを行ってください。


2-2. アカウント分離設計パターン

なぜアカウントを分けるのか。最もシンプルな理由は 「本番環境への誤操作を構造的に防ぐ」 ためです。同一アカウント内で IAM ポリシーだけで環境分離を試みても、権限の設定ミスや IAM ポリシーの複雑化により、誤操作のリスクは残ります。アカウント境界は最強のガードレールです。

3つの分離軸を使いこなすことが、マルチアカウント設計の核心です。

パターン1: SDLC 分離 (環境分離)

本番 / ステージング / 開発 / テスト のアカウントを環境ごとに分離するパターンです。

アカウント用途アクセス制限
prod アカウント本番ワークロード最小権限。変更は CI/CD パイプライン経由のみ
staging アカウント本番相当の動作確認限定メンバーが直接アクセス可
dev アカウント開発・実験開発者が自由に作成・削除可
sandbox アカウント技術調査・PoC完全な自由。コスト上限アラートを設定

最もよく使われる分離パターンです。障害の影響範囲を環境単位に限定できるため、本番への影響を遮断しやすくなります。また、本番アカウントへのアクセス権限を持つ人数を最小限に抑えることができます。

パターン2: セキュリティ分離 (Security OU)

セキュリティ監査に使うアカウントを、ワークロードアカウントと完全に分離するパターンです。

アカウント用途
log-archive アカウントCloudTrail / Config / VPC Flow Logs の集約・長期保管
security-tooling アカウントセキュリティ統合・脅威検知・設定監査ツールの集約管理

このパターンの目的は ログの改ざん防止セキュリティチームの独立性確保 です。ワークロードアカウントの管理者が自分のログを削除・改ざんできないよう、ログはワークロードアカウントから切り離したアカウントに送信します。

セキュリティアカウントは原則として組織管理者とセキュリティチームのみがアクセス可能にし、通常の開発者は参照権限も持たない運用が一般的です。

パターン3: ビジネス / 機能分離 (Workload OU)

事業部門やプロダクトごとにアカウントを分離するパターンです。

アカウント用途
team-a-prodチームAの本番ワークロード
team-b-prodチームBの本番ワークロード
shared-servicesDNS / CI/CD / コンテナレジストリなど共通インフラ

コスト配賦をチーム・プロダクト単位で実施したい場合や、各チームがインフラを自律的に管理したい場合に有効です。AWS Organizations のタグポリシーと組み合わせることで、コストレポートを部門別に可視化できます。

3パターンの比較

比較軸SDLC 分離セキュリティ分離ビジネス/機能分離
主な目的誤操作防止・リスク限定ログ改ざん防止・監査独立コスト配賦・チーム自律
アカウント数3-5 (環境数に比例)2-3 固定チーム数×環境数
SCP の主眼本番の操作制限ログ/監査ツールの保護ビジネスユニット別制限
採用タイミングOrganizations 開始直後セキュリティ要件が高まった時点チーム・プロダクトが増えた段階

現実のマルチアカウント構成は、この3パターンを組み合わせて設計します。たとえば「SDLC 分離 + セキュリティ分離」を先に実装し、チームが増えた段階で「ビジネス/機能分離」を追加する段階的アプローチが一般的です。

アカウント払い出し (Account Vending Machine) の考え方

アカウント数が増えると、手動でのアカウント作成・設定は限界を迎えます。各アカウントに適用すべき設定 (CloudTrail 有効化 / Config ルール適用 / ログ転送先設定 / SCP 継承確認) を手動で行うと、設定漏れや環境間の差異が発生します。

この問題を解決するのが Account Vending Machine (AVM) パターンです。新規アカウント作成を自動化し、テンプレートどおりの初期設定を適用することで、「アカウントを追加するたびにセキュリティ設定が退行する」問題を防ぎます。

AWS が提供する AWS Control Tower は AVM の代表的な実装です。ランディングゾーン (Landing Zone) と呼ばれる初期構成を自動セットアップし、新規アカウント作成時にガードレール (SCP + AWS Config Rules) を自動適用します。中小規模での Organizations 利用では Control Tower の採用を検討することを推奨します。

比較軸AWS Control Tower手動 Organizations 構築
初期セットアップ自動 (ランディングゾーン)全て手動
ガードレール適用自動 (予防的 / 発見的)SCP を個別に設計・適用
新規アカウント払い出しAccount Factory で標準化スクリプト or 手動
カスタマイズ性制約あり (Control Tower の管理外は制限される)完全自由
推奨規模アカウント数 3-50 程度厳密な要件がある大規模環境

Control Tower を採用する場合、Control Tower が管理する OU やアカウントを手動で変更すると設定がずれる「ドリフト」が発生することに注意が必要です。Control Tower 管理下のリソースは Control Tower の仕組みを通じて変更してください。

既存の Organizations 環境に Control Tower を後から導入する「Landing Zone 移行」は可能ですが、既存の OU 構造との整合性確認や SCP の再設計が必要になります。新規に Organizations を始める場合は最初から Control Tower で構築することを推奨します。


2-3. OU 階層設計

OU の設計原則は1つです。「同じ SCP を適用したいアカウントは同じ OU に置く」。後から OU を変更すると SCP の適用も変わるため、最初の設計が重要です。

3-tier 基本形 (AWS 推奨パターン)

Organizations OU階層とアカウント分離パターン (3-tier基本形と規模別)

Root
├── Security OU  (セキュリティログ/監査専用)
│├── log-archive-account
│└── security-tooling-account
├── Infrastructure OU  (共有サービス)
│└── shared-services-account
└── Workload OU  (ビジネスワークロード)
 ├── Dev OU
 │├── team-a-dev-account
 │└── team-b-dev-account
 ├── Staging OU
 │└── team-a-staging-account
 └── Prod OU
  ├── team-a-prod-account
  └── team-b-prod-account

各 OU に適用する SCP の考え方:
Security OU: ログ削除・CloudTrail 無効化を Deny する SCP を適用
Infrastructure OU: 特定の共有サービス以外のデプロイを制限
Workload/Dev OU: 承認済みリージョン外へのアクセスを Deny (リージョン制限 SCP)
Workload/Prod OU: 本番環境を保護するための強制タグ付けや操作制限 SCP を適用

規模別パターン

スタートアップ (アカウント数 3-10)

シンプルな 2-tier 構成が現実的です。

Root
├── Security OU
│└── log-archive-account
└── Workload OU
 ├── dev-account
 ├── staging-account
 └── prod-account

Infrastructure OU は必要になった時点で追加します。最初から 3-tier にすると管理コストが上がるため、小規模では無理に適用しないことが推奨されます。

中規模 (アカウント数 10-50)

3-tier 基本形を適用します。Workload OU の中に複数チームの OU を追加し、Infrastructure OU で DNS / 共有サービスを集約します。

Root
├── Security OU
├── Infrastructure OU
│├── network-account  (Transit Gateway / Route 53)
│└── shared-services-account(ECR / CI/CD)
└── Workload OU
 ├── TeamA OU
 │├── team-a-dev-account
 │└── team-a-prod-account
 └── TeamB OU
  ├── team-b-dev-account
  └── team-b-prod-account

エンタープライズ (アカウント数 50+)

Workload OU をビジネスユニット別にサブ分割します。加えて、以下の特殊 OU を明示的に設置します。

特殊 OU用途
Suspended OU解約済みアカウントを隔離。全アクセスを Deny する SCP を適用
Exception OU特定の SCP 適用除外が必要なアカウントを隔離。理由を都度記録する

Exception OU は「なし崩し的な SCP 例外」を管理するための安全弁です。本来は例外アカウントをゼロに保つべきですが、現実には既存システムとの互換性などで SCP を適用できないケースが発生します。例外を明示的に可視化するための OU として機能します。

SCP の継承メカニズム

SCP は 親 OU から子 OU / アカウントに継承 されます。この継承の仕組みを正確に理解しておかないと、「SCP を設定したつもりが効いていない」または「SCP を変更したら思わぬ影響が出た」という事態が起きます。

継承の重要なルール:
– 親 OU に適用された SCP は子 OU・アカウントすべてに自動的に継承される
– 子 OU で「許可を追加」することはできない (SCP はガードレール。下位レイヤーで権限を広げることは不可)
– 子 OU で「さらに制限を追加」することはできる
– Root レベルには Organizations のデフォルト SCP FullAWSAccess が適用されている

実例: Root に「東京リージョン以外へのアクセスを Deny する SCP」を適用した場合、配下のすべての OU・アカウントでそのリージョン制限が有効になります。子 OU で FullAWSAccess を再設定しても、親 OU の Deny を打ち消すことはできません (Deny 優先ルール)。

SCP の継承は 深さ優先ではなく全階層に同時に適用 されます。Root → OU → Account の各階層でそれぞれ SCP が評価され、全階層の SCP が Allow しているアクションのみが最終的に許可されます。OU が深くなるほど制約が積み重なる構造を念頭に置いて設計してください。

AWS CLI での Organizations 確認コマンド

Organizations の構造や SCP 適用状況は、AWS CLI で確認できます。インシデント発生時や設計レビュー時に便利なコマンドを押さえておきましょう。

# Organizations の全体構造を取得
aws organizations describe-organization

# Root の一覧 (通常1件)
aws organizations list-roots

# Root 直下の OU・アカウントを確認 (ROOT_ID は list-roots で取得)
aws organizations list-children --parent-id <ROOT_ID> --child-type ORGANIZATIONAL_UNIT
aws organizations list-children --parent-id <ROOT_ID> --child-type ACCOUNT

# 特定アカウントに適用されている SCP の一覧
aws organizations list-policies-for-target \
  --target-id <ACCOUNT_ID> \
  --filter SERVICE_CONTROL_POLICY

# 特定アカウントの親 OU を確認 (どの OU に所属しているか)
aws organizations list-parents --child-id <ACCOUNT_ID>

list-policies-for-target は「このアカウントに現在適用されている SCP を全部見せる」コマンドで、アクセス拒否の原因調査に特に有用です。Identity-based Policy を調べても解決しない場合は、このコマンドで SCP の適用状況を先に確認するのが効率的です。


OU設計パターン: どれを選ぶか

  • アカウント数 < 10 のスタートアップ: Security + Workload の 2-tier シンプル構成。Infrastructure OU は必要になってから追加する。
  • アカウント数 10-50 の中規模: 3-tier 基本形 (Security / Infrastructure / Workload) を適用。Workload OU の中に SDLC 分離 (Dev/Staging/Prod) を設置する。
  • アカウント数 50+ のエンタープライズ: Workload OU をビジネスユニット別にサブ分割。Suspended OU と Exception OU を明示的に設置する。

設計原則: SCP を適用したい単位で OU を切る。同一 SCP を適用したいアカウントは同一 OU に置く。後から OU を変更すると SCP 適用も変わることに注意。


3. SCP設計入門 と 5レイヤー統合評価ロジック

Vol1では「Identity-based × Resource-based」の2種ポリシーを中心に学びました。複数アカウント環境になると、この2種に加えて SCP / Permission Boundary / Session Policy の3つが加わり、合計5レイヤーで評価が行われます。このセクションが本記事の山場です。5レイヤーを統合的に理解することで、「なぜ拒否されるか」を確実に特定できるようになります。


3-1. SCP(Service Control Policy)設計入門

SCP とは何か

SCP は AWS Organizations のコンポーネントで、組織全体・OU・アカウント単位に適用できる「許可の上限」 を定義するポリシーです。

重要な理解ポイントを整理します。

  • SCP は「許可を与えない」 — SCP で Allow を書いても、Identity-based ポリシーに Allow がなければ実行できない
  • SCP は「上限を設ける」 — Identity-based ポリシーが Allow していても、SCP がそのアクションを許可しない場合は拒否される
  • 管理アカウント(Management Account)には SCP が適用されない — これが管理アカウントを通常業務に使ってはいけない最大の理由
  • OU 単位または Account 単位に適用可能 — OU に適用すると配下のすべてのアカウントに伝播する

SCP の考え方を一言で表すなら「ガードレール」です。高速道路のガードレールが「走れる場所」を制限するように、SCP は Identity-based ポリシーが動作できる範囲を制約します。

SCP の2つのアプローチ

SCP の設計には ブラックリスト方式ホワイトリスト方式 の2通りがあります。

ブラックリスト方式(Deny list)

  • デフォルトですべての操作を許可(FullAWSAccess SCP を継承した状態から開始)
  • 禁止したい操作を明示的に Deny する
  • 初めて SCP を導入する組織に推奨
  • 新しい AWS サービスが追加されても自動で許可される
{
  "Version": "2012-10-17",
  "Statement": [
 {
"Sid": "DenyOutsideApNortheast1",
"Effect": "Deny",
"NotAction": [
  "iam:*",
  "sts:*",
  "s3:GetBucketLocation",
  "s3:ListAllMyBuckets"
],
"Resource": "*",
"Condition": {
  "StringNotEquals": {
 "aws:RequestedRegion": ["ap-northeast-1"]
  }
}
 }
  ]
}

上記は典型的なブラックリスト SCP です。東京リージョン(ap-northeast-1)以外のすべてのアクションを Deny します。NotAction に IAM や STS を除外しているのは、グローバルサービス(IAM は特定リージョンを持たない)を誤って制限しないためです。

ホワイトリスト方式(Allow list)

  • デフォルトで何も許可しない(FullAWSAccess SCP を削除してから開始)
  • 許可したいサービスを明示的に Allow する
  • 厳格なガバナンスが必要な本番環境 OU に適用
  • 注意: 新しいサービスを使うたびに SCP 更新が必要
{
  "Version": "2012-10-17",
  "Statement": [
 {
"Sid": "AllowApprovedServicesOnly",
"Effect": "Allow",
"Action": [
  "s3:*",
  "ec2:*",
  "rds:*",
  "lambda:*",
  "iam:*",
  "sts:*",
  "logs:*",
  "cloudwatch:*"
],
"Resource": "*"
 }
  ]
}

実務で使う SCP パターン:権限昇格禁止

もうひとつの重要な SCP パターンが「権限昇格(Privilege Escalation)禁止」です。不正アクセスが発生した際に、侵入者が自分自身の権限を昇格させる手法をガードレールで封鎖します。

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Sid": "DenyPrivilegeEscalation",
"Effect": "Deny",
"Action": [
  "iam:CreatePolicyVersion",
  "iam:SetDefaultPolicyVersion",
  "iam:CreateAccessKey",
  "iam:AttachUserPolicy",
  "iam:AttachRolePolicy",
  "iam:PutUserPolicy",
  "iam:PutRolePolicy"
],
"Resource": "*",
"Condition": {
  "ArnNotLike": {
 "aws:PrincipalArn": "arn:aws:iam::*:role/SecurityAdmin"
  }
}
 }
  ]
}

ConditionArnNotLike を使って SecurityAdmin ロールのみ除外しています。このパターンにより、オペレーションミスによる意図しない権限昇格も防止できます。


3-2. 5レイヤー統合評価ロジック(Vol1 拡張・山場)

5レイヤー統合評価ロジック (SCP × Permission Boundary × Identity-based × Resource-based × Session Policy)

Vol1 の2レイヤーから5レイヤーへの拡張

Vol1では単一アカウントを前提に「2レイヤー」で評価ロジックを学びました。複数アカウント環境では3レイヤーが追加されます。

Vol1 の2レイヤー(単一アカウント)

#レイヤー役割
1Identity-based ポリシーIAM User/Role にアタッチ。実際の権限を付与
2Resource-based ポリシーS3バケット/SNSトピック等にアタッチ。リソース側で許可

Vol2 で追加する3レイヤー(マルチアカウント)

#レイヤー役割
3SCPOrganizations レベルのアクセス上限
4Permission BoundaryIAMエンティティ(User/Role)ごとの最大権限上限
5Session PolicyAssumeRole 時に一時的に付与するポリシー

5レイヤー評価順序

IAM がリクエストを受け取ると、以下の順序で評価を行います。いずれかで Deny が確定した時点で即座に拒否され、残りのステップは評価されません。

  1. 明示的 Deny チェック(全ポリシーを横断して明示的 Deny を最初にチェック)
  2. SCP チェック(Organizations レベルの制限)
  3. Resource-based ポリシーチェック(クロスアカウントアクセスの場合)
  4. Permission Boundary チェック(IAMエンティティ単位の制限)
  5. Identity-based ポリシーチェック(実際の権限付与)
  6. Session Policy チェック(セッション使用時のみ)

ポリシータイプ・役割・管理者の全体像

レイヤー役割設定場所管理者
SCP組織全体/OU単位の操作上限Organizations コンソールセキュリティ/組織管理者
Permission BoundaryIAMエンティティの権限上限IAM コンソール(User/Role)IAM管理者 / 委任管理者
Identity-basedIAMエンティティの実際の権限IAM コンソール(User/Role)IAM管理者
Resource-basedリソース側のアクセス許可S3/SNS等のリソース設定サービス管理者
Session Policyセッションの一時的な権限制限AssumeRole API コール時アプリ/CI-CD管理者

5レイヤー統合評価フローチャート(mermaid01)

flowchart TD
 A[IAMリクエスト受信] --> B{全ポリシーに\n明示的 Deny 存在?}
 B -->|あり| DENY1[❌ Deny\n明示的Deny確定]
 B -->|なし| C{SCP:\nアクションを許可?}
 C -->|許可なし| DENY2[❌ Deny\nSCPガードレール]
 C -->|許可あり| D{Permission Boundary\n設定あり?}
 D -->|設定あり| E{Permission Boundary:\nアクションを許可?}
 D -->|設定なし| F
 E -->|許可なし| DENY3[❌ Deny\nPermission Boundary]
 E -->|許可あり| F{Identity-based または\nResource-based で Allow?}
 F -->|Allowなし| DENY4[❌ Deny\n暗黙的Deny]
 F -->|Allowあり| G{Session Policy\n使用中?}
 G -->|使用中 かつ 許可なし| DENY5[❌ Deny\nSession Policy]
 G -->|使用なし または 許可あり| ALLOW[✅ Allow]

フローチャートの3つの読み方:

  1. 最初の明示的 Deny チェックが最優先 — どのポリシータイプにあっても、"Effect": "Deny" は即座にアクセスを拒否します
  2. SCP と Permission Boundary は「上限」 — これらを通過しないと、Identity-based がどれだけ Allow していても拒否されます
  3. Session Policy は「絞り込み」 — 元のロールが持つ権限を Session Policy で狭めることはできますが、広げることはできません

3-3. SCP × Permission Boundary × Identity-based の組み合わせパターン

実務でよく遭遇する3パターンを具体例で解説します。

パターンA: SCP でガードレール / Identity-based で細かく権限付与

最も一般的な構成です。OU 単位で SCP によるガードレールを設け、各アカウントの Identity-based ポリシーで実際の権限を付与します。

Organizations
  └── Root
 ├── 管理 OU (SCP: FullAWSAccess)
 │ └── 管理アカウント
 ├── 本番 OU (SCP: Deny 危険操作 / Deny 未承認リージョン)
 │ └── 本番アカウント
 │└── IAMロール (Identity-based: S3/EC2/RDS のみ)
 └── 開発 OU (SCP: Deny 危険操作のみ)
└── 開発アカウント
  └── IAMロール (Identity-based: 本番より広め)

ポイントは「SCP の厳格度を OU 単位で変える」ことです。開発 OU は SCP を緩めて開発者の試行錯誤を許容し、本番 OU は SCP を厳格化して誤操作の被害を最小化します。

アカウントSCP の厳格度Identity-based の自由度
管理アカウントなし(SCP対象外)最も制限すべき(管理作業のみ)
本番アカウント最も厳格(Deny多め)必要最小限の権限のみ付与
ステージングアカウント中程度本番に近い構成で検証
開発アカウント最も緩い開発者の試行錯誤を許容

SCP と Identity-based の AND 評価を忘れずに: 本番 OU の SCP で ec2:TerminateInstances を Deny していれば、開発者が誤って本番 IAM ロールを AssumeRole しても EC2 の削除はできません。SCP はアカウントをまたいだ「最後の砦」として機能します。

パターンB: Permission Boundary で開発者デリゲーション

「開発者に IAM ロール作成を委任したいが、本番アカウントへの過剰権限は防ぎたい」という要件に対応するパターンです。

仕組みの概要:

  1. IAM管理者が Permission Boundary ポリシーを事前定義(例:S3 と DynamoDB のみ許可)
  2. 開発者に「Boundary 範囲内での IAM ロール作成権限」を委任iam:CreateRole に条件を付与)
  3. 開発者が作成したロールには自動的に Permission Boundary が適用される
  4. 開発者が Permission Boundary を超えた権限を付与しようとしても、実行時に拒否される
{
  "Version": "2012-10-17",
  "Statement": [
 {
"Sid": "AllowRoleCreationWithinBoundary",
"Effect": "Allow",
"Action": [
  "iam:CreateRole",
  "iam:PutRolePolicy",
  "iam:AttachRolePolicy"
],
"Resource": "*",
"Condition": {
  "StringEquals": {
 "iam:PermissionsBoundary": "arn:aws:iam::123456789012:policy/DeveloperBoundary"
  }
}
 }
  ]
}

この Condition が重要です。iam:PermissionsBoundary を条件に指定することで、DeveloperBoundary ポリシーを Permission Boundary として設定した場合のみ IAM ロール作成を許可します。Permission Boundary の詳細実装は §5 で扱います。

パターンC: Session Policy で CI-CD の権限を絞る

CI-CD パイプライン(GitHub Actions / CodePipeline 等)が本番デプロイ用ロールを AssumeRole する際に、Session Policy で権限を絞るパターンです。

import boto3

sts = boto3.client("sts")

session_policy = """{
  "Version": "2012-10-17",
  "Statement": [
 {
"Effect": "Allow",
"Action": ["s3:PutObject", "s3:GetObject"],
"Resource": "arn:aws:s3:::my-deploy-bucket/releases/*"
 }
  ]
}"""

response = sts.assume_role(
 RoleArn="arn:aws:iam::123456789012:role/DeployRole",
 RoleSessionName="cicd-deploy-session",
 Policy=session_policy
)

AssumeRole 時に Session Policy を渡すことで、デプロイ対象バケット以外への操作を一時認証情報レベルでブロックします。DeployRoleS3FullAccess など広めの権限を持っていても、そのセッション中は指定バケットへの PutObjectGetObject しかできません。

Session Policy の制約: Session Policy はロールの既存の権限を「絞り込む」ことしかできません。元のロールが持っていない権限を Session Policy で追加することはできません。


5レイヤー統合評価ロジック: 3つの鉄則

  • 鉄則1: SCP は「許可の上限」であり「許可を与えない」。SCP で Allow していても Identity-based ポリシーで Allow がなければ拒否される。逆も然り。SCP と Identity-based の両方が Allow していて初めて実行できる(同一アカウント内)。
  • 鉄則2: 管理アカウントには SCP が適用されない。管理アカウントの IAM エンティティは SCP の制限を受けない。これが管理アカウントを日常業務に使ってはいけない理由であり、管理アカウントでは最小限の操作に留めることが必須。
  • 鉄則3: Permission Boundary は Identity-based ポリシーの「最大値」を制限する。Boundary に含まれていない権限は、Identity-based でどれだけ Allow しても実行できない。開発者への権限委任設計で「意図しない権限昇格」を防ぐ要となる。

評価順序(上が強い): 明示的Deny → SCP → Permission Boundary → Identity-based / Resource-based → Session Policy

デバッグの手順: 「Access Denied」が出たら ① Organizations の SCP を確認 → ② IAMロールに Permission Boundary が設定されていないか確認 → ③ Identity-based ポリシーを確認 の順で調べる。


4. IAM Identity Center 設計実践

複数の AWS アカウントを運用する環境では、アカウントごとに IAM ユーザーを管理する従来方式は運用コストが高く、オフボーディングの漏れなどのセキュリティリスクも発生しやすい。IAM Identity Center は ID を一元管理し、1 回の認証で複数アカウントへアクセスできる仕組みを提供することで、これらの課題を解決する。本章では Permission Set 設計・Account Assignment・外部 IdP 連携・委任管理 (Delegated Administrator) の実践的な設計パターンを解説する。


4-1. IAM Identity Center とは

IAM Identity Center (旧称: AWS Single Sign-On / SSO) は 2022年7月に現在の名称に改名された AWS のシングルサインオンサービスだ。AWS Organizations と統合して動作し、組織内の複数 AWS アカウントへの一元的なアクセス管理を可能にする。

主要機能

機能概要
シングルサインオン (SSO)1 つの認証で複数 AWS アカウントにアクセス。IAM ユーザーの個別管理が不要になる
Permission Setアクセス権限テンプレート。AWS 管理ポリシー + カスタムポリシー + Permission Boundary を含められる
Account AssignmentPermission Set × AWS アカウント × ユーザー/グループ の 3 軸マッピング
外部 IdP 連携Okta / Azure AD / Google Workspace などと SAML 2.0 / SCIM で連携
ABAC (属性ベースアクセス制御)IdP の属性を基に動的にアクセス制御

IAM ロールスイッチとの違い

従来の IAM ロールスイッチ方式は、各アカウントに IAM ユーザーを作成し、コンソールや CLI でロールスイッチする方式だ。アカウント数が増えるにつれて管理の複雑さが増す。

Identity Center 方式は、ID を Identity Center で一元管理し、複数アカウントへ SSO でアクセスする。Identity Center は裏側で各アカウントに IAM ロールを自動作成・管理するため、各アカウントへの手動作業が大幅に減る。

比較軸ロールスイッチ方式Identity Center 方式
ID 管理場所アカウントごとIdentity Center で一元管理
認証回数アカウントごとに認証1 回の認証で全アカウントにアクセス
オフボーディング全アカウントで個別に無効化が必要Identity Center 側で 1 か所削除
運用コストアカウント数 × ユーザー数で増大アカウント数に依存しない
外部 IdP 連携難しい (追加設定が複雑)SAML 2.0 / SCIM で標準サポート

Identity Center 方式への移行を推奨する主な理由は オフボーディングの確実性 にある。退職者の IAM ユーザーが複数アカウントに残存するリスクを、Identity Center の一元削除で根本的に排除できる。

ID ソースの種別

Identity Center が使用できる ID ソースは 3 種類ある。

ID ソース概要適用シーン
Identity Center ディレクトリIdentity Center 組み込みのユーザーストア。AWS コンソールで直接ユーザー/グループを作成・管理する小規模チームや IdP を持たない環境
Active Directory (AWS Managed Microsoft AD)AWS Directory Service の Managed AD と連携オンプレミスの AD をクラウドに拡張したい場合
外部 IdP (SAML 2.0 + SCIM)Okta / Azure AD / Google Workspace などと連携企業標準の IdP を活用したい場合

ID ソースは一度設定すると変更時に既存のユーザー/グループ割り当てが削除されるため、導入初期にどの ID ソースを使うかを決定することが重要だ。小規模からスタートする場合は Identity Center ディレクトリで始め、IdP 連携の必要性が出てきた段階で移行する方法が安全だ。


4-2. Permission Set 設計

Permission Set は「どんな権限を与えるか」を定義するテンプレートだ。Identity Center 上で作成し、複数アカウント × 複数グループに再利用できる。

Permission Set の構成要素

1 つの Permission Set に含められる要素:

  • AWS 管理ポリシー (複数アタッチ可): AdministratorAccess / PowerUserAccess / ReadOnlyAccess など
  • カスタムインラインポリシー (1 つまで): JSON で直接記述する独自ポリシー
  • Permission Boundary (1 つまで): その Permission Set から生成されるロールの最大権限上限

設計パターン1 — AWS 管理ポリシー使用 (初期導入推奨)

適用シーン: 組織規模が小さく、まず Identity Center の仕組みを整えることを優先する段階。

Permission Set: AdminAccess
  → AWS 管理ポリシー: AdministratorAccess

Permission Set: PowerUser
  → AWS 管理ポリシー: PowerUserAccess

Permission Set: ReadOnly
  → AWS 管理ポリシー: ReadOnlyAccess

メリット: AWS が自動でポリシーを更新してくれるため、新サービスへの対応コストが低い。
デメリット: AdministratorAccess は広すぎる権限。本番環境での長期利用は推奨しない。

設計パターン2 — カスタム Permission Set (本番推奨)

適用シーン: 職能 (ロール) ごとに最小権限を設計する段階。

職能別 Permission Set の例:

Permission Set 名対象職能主な権限適用環境
NetworkAdmin-Fullネットワーク管理者VPC / Route53 / ELB / CloudFront全環境
AppDev-Fullアプリ開発者EC2 / ECS / Lambda / S3 (特定バケット)dev / staging
AppDev-ReadOnlyアプリ開発者 (参照のみ)上記の Write 系 API を除くprod
DBAdmin-FullDB 管理者RDS / DynamoDB / ElastiCachedev / staging
DBAdmin-ProdReadOnlyDB 管理者 (本番は参照のみ)上記の Read 系のみprod
SecurityAuditorセキュリティ監査監査ログ・設定情報・脅威検知結果の参照全環境

Permission Set 命名規則: {職能}-{権限レベル} の形式で統一する。

命名を統一することで、Account Assignment の棚卸し時に「どのグループがどの環境に対してどのレベルの権限を持つか」を一目で把握できる。

Permission Boundary を Permission Set に含める

カスタム Permission Set に Permission Boundary を設定することで、開発者が必要以上の権限をロールに追加しようとしても、Boundary が上限を守る。

AppDev 向け Permission Set に設定する Boundary の例:

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Effect": "Allow",
"Action": [
  "ec2:*",
  "ecs:*",
  "lambda:*",
  "s3:*",
  "logs:*",
  "cloudwatch:*"
],
"Resource": "*"
 }
  ]
}

この Boundary を設定した Permission Set から生成されるロールは、IAM / Organizations / Control Tower などのガバナンス系 API を操作できない。


4-3. Account Assignment 設計

Account Assignment は Permission Set × AWS Account × User/Group の 3 軸マッピングだ。どのグループが、どのアカウントに、どの Permission Set でアクセスできるかを定義する。

グループ単位でのアサイン (ユーザー個別アサインは非推奨)

ユーザー個別にアサインすると、入退社のたびに全アカウントの Assignment を更新する必要が生じる。グループ単位でアサインすることで、グループメンバーシップの変更だけで権限が自動的に付与・剥奪される。

グループ命名規則: aws-{account-type}-{permset-name} で統一する。

例:
aws-prod-networkadmin — 本番アカウントへの NetworkAdmin-Full 権限
aws-dev-appdev — 開発アカウントへの AppDev-Full 権限
aws-staging-appdev-readonly — ステージングアカウントへの AppDev-ReadOnly 権限
aws-all-securityauditor — 全アカウントへの SecurityAuditor 権限

設計例 (中規模チーム 30〜100人)

IAM Identity Center 配信フロー (Permission Set → Account Assignment → グループ → ロール)

グループPermission Set対象アカウント
aws-prod-networkadminNetworkAdmin-Fullprod-network-account
aws-dev-appdevAppDev-Fulldev-account
aws-staging-appdevAppDev-ReadOnlystaging-account
aws-prod-dbadmin-readonlyDBAdmin-ProdReadOnlyprod-data-account
aws-all-securityauditorSecurityAuditor全アカウント

アカウント構造との対応

ランディングゾーン (Control Tower / 手動構成) では、アカウント構造に沿った Assignment 設計が鍵になる。代表的なアカウント構造:

Root
├── Management Account (管理・請求)
├── Security OU
│├── Security Account (脅威検知・セキュリティ統合管理サービスの集約)
│└── Log Archive Account (監査ログ集約)
├── Workload OU
│├── Production Account
│├── Staging Account
│└── Development Account
└── Shared Services OU
 └── Shared Services Account (ECR / Route53 等)

この構造に対応する Assignment では、「Workload OU の全アカウントに ReadOnly」「Production Account のみ DBAdmin-ProdReadOnly」のように OU レベルと個別アカウントレベルを組み合わせて設計する。

AWS CLI による Permission Set と Account Assignment の作成

コンソール操作が不要な自動化環境では、CLI でのセットアップが有効だ。

Permission Set の作成:

# カスタム Permission Set を作成
aws sso-admin create-permission-set--instance-arn "arn:aws:sso:::instance/ssoins-xxxxxxxxxxxxxxxx"--name "AppDev-Full"--description "Application developer full access for dev/staging"--session-duration "PT8H"

# 返り値から PermissionSetArn を取得
# arn:aws:sso:::permissionSet/ssoins-xxx/ps-xxxxxxxxxxxxxxxx

カスタムポリシーを Permission Set にアタッチ:

aws sso-admin put-inline-policy-to-permission-set--instance-arn "arn:aws:sso:::instance/ssoins-xxxxxxxxxxxxxxxx"--permission-set-arn "arn:aws:sso:::permissionSet/ssoins-xxx/ps-xxxxxxxxxxxxxxxx"--inline-policy file://appdev-full-policy.json

Account Assignment の作成 (グループを特定アカウントにアサイン):

aws sso-admin create-account-assignment--instance-arn "arn:aws:sso:::instance/ssoins-xxxxxxxxxxxxxxxx"--target-id "123456789012"--target-type "AWS_ACCOUNT"--permission-set-arn "arn:aws:sso:::permissionSet/ssoins-xxx/ps-xxxxxxxxxxxxxxxx"--principal-type "GROUP"--principal-id "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"

--principal-id にはグループの ID (Identity Center コンソールの [グループ] 画面から確認できる UUID) を指定する。--target-id は対象 AWS アカウントの 12 桁 ID だ。


4-4. 外部 IdP 連携とグループ同期

企業の標準 IdP (Okta / Azure AD / Google Workspace) と Identity Center を連携することで、社員の入退社・部署異動に伴う権限変更を自動化できる。

SAML 2.0 + SCIM 連携

プロトコル役割
SAML 2.0認証フェデレーション (ログイン処理)
SCIMユーザー / グループのプロビジョニング (自動同期)

SCIM を有効化する主な利点:

  • IdP (Okta など) のグループメンバーシップ変更が Identity Center に自動反映される
  • 退職者を IdP から削除 → Identity Center のセッションが自動無効化される
  • 新入社員を IdP のグループに追加 → 対応アカウントへのアクセスが即時付与される

SCIM の設定手順:

Identity Center → Settings → Automatic provisioning を有効化
  → SCIM エンドポイント URL と Access Token を取得
  → IdP 側 (例: Okta) に SCIM 設定として入力
  → プロビジョニングを有効化

属性ベースアクセス制御 (ABAC)

ABAC は IdP の属性 (Department / CostCenter / JobTitle など) を基に動的にアクセス制御する方式だ。大規模組織で Permission Set 数を削減できる。

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Effect": "Allow",
"Action": "s3:*",
"Resource": "arn:aws:s3:::${aws:PrincipalTag/Department}/*",
"Condition": {
  "StringEquals": {
 "aws:ResourceTag/Department": "${aws:PrincipalTag/Department}"
  }
}
 }
  ]
}

この例では Department タグが同じリソースにのみアクセスを許可する。IdP の Department 属性が Identity Center に連携され、生成されたロールセッションにタグとして付与される仕組みだ。


4-5. 委任管理 (Delegated Administrator) パターン

委任管理とは

IAM Identity Center の管理権限をメンバーアカウント (通常はセキュリティアカウント) に委譲できる機能だ。これにより管理アカウントへのログインなしに、セキュリティチームが権限管理の日常運用を担当できる。

設定コマンド (管理アカウントで実行):

aws organizations register-delegated-administrator \
  --account-id <セキュリティアカウントID> \
  --service-principal sso.amazonaws.com

登録後、セキュリティアカウント側の Identity Center コンソールから Permission Set および Account Assignment の管理が可能になる。

委任管理の2つの重要な制限

制限①: 委任管理アカウント自身への Permission Set 配信不可

セキュリティアカウント (委任管理者) は、自分自身 (セキュリティアカウント) への Permission Set 配信ができない。セキュリティアカウントへのアクセス権限は、管理アカウントが直接配信する必要がある。

制限②: 管理アカウントの Permission Set は変更不可

委任管理アカウントは管理アカウント向けの Permission Set を変更できない。管理アカウントの権限管理は、管理アカウント自身が Identity Center コンソールで行う。

この 2 つの制限を把握していないと、「セキュリティアカウントにアクセスできない」「管理アカウントへの権限を変更しようとしてもエラーになる」という問題が発生する。

mermaid02: 委任管理の動作フロー

sequenceDiagram
 participant 管理AC as 管理アカウント管理者
 participant セキュリティAC as セキュリティアカウント<br/>(委任管理者)
 participant 開発AC as 開発アカウント

 管理AC->>管理AC: register-delegated-administrator 実行
 管理AC-->>セキュリティAC: Identity Center 管理権限を委譲
 セキュリティAC->>開発AC: Permission Set × Account Assignment 配信
 Note over セキュリティAC: 制限①: 自アカウントへの配信は不可
 Note over 管理AC: 制限②: 管理アカウントの Permission Set 変更は不可
 開発AC-->>開発AC: Identity Center ロールが自動作成される

委任管理の推奨タスク分担

タスク担当アカウント
セキュリティアカウントへの Permission Set 配信管理アカウント
管理アカウントの Permission Set 管理管理アカウント
Workload アカウント群への日常的な権限管理セキュリティアカウント (委任管理者)
Permission Set の新規作成・編集セキュリティアカウント (委任管理者)

この分担により、管理アカウントへのアクセス頻度を最小化しつつ、日常の権限管理をセキュリティチームに委譲できる。


IAM Identity Center 公式ドキュメント (英語)


5. Permission Boundary 実践運用

複数アカウント環境で IAM の権限管理を委任する際、最も重要なメカニズムが Permission Boundary(権限境界) だ。§3 でポリシー評価レイヤーの一つとして紹介したが、本章では実際の組織設計に落とし込む方法を掘り下げる。


5-1. Permission Boundary の概念整理

Permission Boundary を初めて学ぶとき、多くの人が Permission Set(Identity Center) との違いに戸惑う。名前が似ているが、役割はまったく異なる。

比較項目Permission BoundaryPermission Set (Identity Center)
役割IAM User/Role が持てる権限の上限を設定ユーザーに配布する権限テンプレート
適用対象IAM User または IAM RoleIdentity Center 経由のアクセス
設定場所IAM コンソール(User/Role の境界ポリシー)Identity Center コンソール
効果それ自体はアクセスを許可しない(上限の定義のみ)アクセスを直接許可する
ユースケース開発者への IAM 権限委譲・昇格防止複数アカウントへの SSO アクセス管理
削除/変更の影響Role/User 側の Boundary が外れるPermission Set の付与が取り消される

一言で整理すると:

  • Permission Boundary = 「この IAM エンティティが持てる権限の最大値(天井)」。天井より高い部分は Identity-based ポリシーでどれだけ許可しても実行できない。
  • Permission Set = 「Identity Center 経由でアカウントにアクセスするための権限パッケージ」。SSO ログイン時に一時認証情報として払い出される。

Permission Boundary の最大の特徴は「許可しない」ことだ。Boundary ポリシーに s3:* を書いても、それだけでは S3 にアクセスできない。Boundary + Identity-based ポリシーの積集合が実際に許可される権限になる。「Boundary = 上限の定義、Identity-based = 実際の許可」という分離が設計の核心だ。

この特性を活用すると「開発者が自分で IAM ロールを作成できる権限を渡しつつ、作成できるロールの権限上限を管理者が制御する」委任設計が実現できる。これをデリゲーション設計パターンと呼ぶ。


5-2. 開発者デリゲーション設計パターン

課題と解決策

課題: 開発者が素早く IAM ロールを作成・管理できる環境を提供したいが、管理者権限を持つ IAM ロールを作られると本番環境への過剰アクセスが発生する。かといって全ての IAM ロール作成を管理者が代行すると、開発速度が著しく低下する。

解決策: Permission Boundary を使って「開発者が作れる IAM ロールの権限上限」をあらかじめ定義する。開発者が IAM ロールを作成する際に必ず Boundary を適用させることで、管理者より強い権限を持つロールが作られることを防ぐ。

デリゲーション設計の3ステップ

ステップ1: Boundary ポリシーを定義する

管理者が Boundary ポリシーを事前に作成する。このポリシーが、開発者が作成した IAM ロールに適用される権限の上限になる。

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Sid": "AllowCommonServices",
"Effect": "Allow",
"Action": [
  "s3:*",
  "dynamodb:*",
  "lambda:*",
  "logs:*",
  "ec2:Describe*"
],
"Resource": "*"
 },
 {
"Sid": "DenyBoundaryModification",
"Effect": "Deny",
"Action": [
  "iam:DeleteUserPermissionsBoundary",
  "iam:DeleteRolePermissionsBoundary",
  "iam:PutUserPermissionsBoundary",
  "iam:PutRolePermissionsBoundary"
],
"Resource": "*",
"Condition": {
  "ArnNotEquals": {
 "iam:PermissionsBoundary": "arn:aws:iam::123456789012:policy/DeveloperBoundary"
  }
}
 }
  ]
}

重要なのは DenyBoundaryModification ステートメントだ。開発者が Boundary ポリシー自体を削除・変更して権限昇格を試みることを防ぐ。ArnNotEquals 条件により「DeveloperBoundary 以外の Boundary を設定する操作」のみを Deny するため、正規の Boundary 付与操作は妨げない。

ステップ2: 開発者ロールに「Boundary 適用を条件とした IAM ロール作成権限」を付与する

開発者の IAM ロールには IAM ロール作成権限を付与するが、Condition で「DeveloperBoundary を Boundary として指定すること」を必須化する。

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Sid": "AllowCreateRoleWithBoundary",
"Effect": "Allow",
"Action": [
  "iam:CreateRole",
  "iam:AttachRolePolicy",
  "iam:PutRolePolicy"
],
"Resource": "*",
"Condition": {
  "StringEquals": {
 "iam:PermissionsBoundary": "arn:aws:iam::123456789012:policy/DeveloperBoundary"
  }
}
 },
 {
"Sid": "AllowReadIAM",
"Effect": "Allow",
"Action": [
  "iam:Get*",
  "iam:List*"
],
"Resource": "*"
 }
  ]
}

ステップ3: 運用フローの確認

このポリシー設計により、以下の運用フローが実現する。

  • 開発者は iam:CreateRoleiam:PermissionsBoundary: DeveloperBoundary の組み合わせでのみ実行できる
  • Boundary なしで iam:CreateRole を実行すると Condition により拒否される
  • 作成されたロールの権限は必ず DeveloperBoundary の範囲内(S3 / DynamoDB / Lambda / CloudWatch Logs / EC2 Describe 相当)に収まる
  • 開発者は Boundary を外したり別のポリシーに変更したりできない(DenyBoundaryModification が機能する)

Terraform での実装例

上記の設計を Terraform で実装する。

# 開発者が作成するロールに適用される Boundary ポリシー
resource "aws_iam_policy" "developer_boundary" {
  name  = "DeveloperBoundary"
  description = "Permission Boundary for developer-created roles"

  policy = jsonencode({
 Version = "2012-10-17"
 Statement = [
{
  Sid = "AllowCommonServices"
  Effect = "Allow"
  Action = [
 "s3:*",
 "dynamodb:*",
 "lambda:*",
 "logs:*",
 "ec2:Describe*"
  ]
  Resource = "*"
},
{
  Sid = "DenyBoundaryModification"
  Effect = "Deny"
  Action = [
 "iam:DeleteUserPermissionsBoundary",
 "iam:DeleteRolePermissionsBoundary",
 "iam:PutUserPermissionsBoundary",
 "iam:PutRolePermissionsBoundary"
  ]
  Resource = "*"
  Condition = {
 ArnNotEquals = {
"iam:PermissionsBoundary" = "arn:aws:iam::$${var.account_id}:policy/DeveloperBoundary"
 }
  }
}
 ]
  })
}

# 開発者が作成するアプリ用ロールの例(Boundary を適用)
resource "aws_iam_role" "developer_app_role" {
  name  = "developer-app-role"
  permissions_boundary = aws_iam_policy.developer_boundary.arn

  assume_role_policy = jsonencode({
 Version = "2012-10-17"
 Statement = [
{
  Effect = "Allow"
  Principal = { Service = "lambda.amazonaws.com" }
  Action = "sts:AssumeRole"
}
 ]
  })
}

# 開発者ロールへのデリゲーションポリシー(Boundary 適用を Condition で強制)
resource "aws_iam_role_policy" "developer_iam_delegation" {
  name = "IAMDelegationPolicy"
  role = aws_iam_role.developer_role.id

  policy = jsonencode({
 Version = "2012-10-17"
 Statement = [
{
  Sid = "AllowCreateRoleWithBoundary"
  Effect = "Allow"
  Action = [
 "iam:CreateRole",
 "iam:AttachRolePolicy",
 "iam:PutRolePolicy"
  ]
  Resource = "*"
  Condition = {
 StringEquals = {
"iam:PermissionsBoundary" = aws_iam_policy.developer_boundary.arn
 }
  }
}
 ]
  })
}

permissions_boundary = aws_iam_policy.developer_boundary.arn の一行で、Terraform 管理のロールに Boundary を適用できる。IaC で Boundary を管理することで、誰かが手動で Boundary を外しても次の terraform apply で復元されるという運用上の安全網にもなる。


5-3. ガードレール構造の設計原則

Permission Boundary を使ったデリゲーション設計で守るべき3つの原則を整理する。

原則1: Boundary 自体の削除・変更を必ず Deny する(権限昇格防止)

Boundary ポリシーに DenyBoundaryModification ステートメントを含めないと、開発者が iam:PutRolePermissionsBoundary を使って自分のロールの Boundary を外したり、より緩い Boundary に変更したりして権限昇格できてしまう。このステートメントはデリゲーション設計の「鍵を守る鍵」であり、省略は厳禁だ。

原則2: Boundary はホワイトリスト(許可リスト)で設計する

Boundary に AdministratorAccess 相当の広い権限を設定してしまうと、上限の意味がなくなる。必要なサービスのみを Allow で列挙し、「使わないサービスは書かない = Deny」というホワイトリスト設計を徹底する。

チーム別に Boundary ポリシーを分けるアプローチも有効だ。バックエンドチームは S3 / DynamoDB / Lambda 中心、データチームは Glue / Athena / S3 / EMR、というように分けると、各チームのワークロードに最適化した上限を設定できる。後から権限を追加する方が、一度広げた権限を絞るより管理が容易だ。

原則3: Boundary と Identity-based ポリシーの「積集合」を常に意識する

Boundary に記述しても、Identity-based ポリシーで Allow していなければ実行できない。逆に Identity-based ポリシーで Allow しても、Boundary に記述がなければ実行できない。この「2重チェック」が委任設計の核心だ。

たとえば dynamodb:Query を実行したい場合、以下の両方が必要だ。

  • Boundary に dynamodb:* または dynamodb:Query が含まれている → ✅
  • Identity-based ポリシーに dynamodb:Query が含まれている → ✅

どちらか一方でも欠ければ実行不可(暗黙 Deny)。デバッグ時は iam:SimulatePrincipalPolicy を使って Boundary 込みの評価結果を確認する。Boundary が設定されているロールのシミュレーションでは Boundary も評価対象になるため、実際の挙動を正確に把握できる。

Permission Boundary 設計の3鉄則

  • 鉄則1: Boundary 自体を削除・変更できないようにするDenyBoundaryModification ステートメントを必ず含め、開発者が Boundary を外して権限昇格することを防ぐ。これがないとデリゲーション設計が無意味になる。
  • 鉄則2: Boundary はホワイトリスト(許可リスト)で設計する。使用するサービスのみ Allow する。FullAccess ポリシーや Action: "*" を Boundary に使うと制限の意味がなくなる。チーム・ワークロード別に Boundary を分けるのが理想的。
  • 鉄則3: Boundary と Identity-based の積集合が実際の権限。Boundary に含めても Identity-based に Allow がなければ実行できない。この「2重チェック」が委任設計の核心。Boundary は「上限」であり「許可」ではない。

6. 詰まりポイント7選 図解

詰まりポイント7パターン体系図

マルチアカウント環境の IAM 設計でよく遭遇する7つの詰まりパターンを体系化する。
それぞれに「なぜ詰まるか」「どう対処するか」を整理した。
単一アカウントでは起きにくく、マルチアカウント特有の落とし穴が多い点に注意してほしい。
§3 の5レイヤー評価ロジックと §5 の開発者デリゲーション設計を読んだ上でこの章を読むと理解が深まる。


詰まりパターン 1: SCP の評価優先度の誤解

詰まりの場面: 「SCP に Allow を書いたのに実行できない」「SCP を設定したのに何も変わらない」

SCP (Service Control Policy) は「許可の上限 (ガードレール)」であり、それ自体が権限を付与するものではない。
たとえば SCP に "Effect": "Allow", "Action": "s3:*" を書いても、メンバーアカウントのユーザー/ロールが
Identity-based ポリシーに S3 の Allow を持っていなければ S3 は操作できない。

また、SCP は 管理アカウントには適用されない。管理アカウントで操作してテストしても SCP の効果を確認できず、
「SCP が効いていない」と誤解するケースが頻発する。メンバーアカウントで必ずテストすること。

評価ロジックは「暗黙 Deny → 明示 Deny → SCP 通過 → Permission Boundary 通過 → Identity-based Allow → Session Policy 通過」の順序。
SCP を通過しただけでは実行できず、その後のレイヤーで Allow が必要だ。

対処法: IAM Policy Simulator (コンソール) または aws iam simulate-custom-policy でシミュレートする際、
SCP が含まれる形でテストする。もしくは CloudTrail の errorCode"AccessDenied" を検索し、
errorMessage の内容を確認して詰まり箇所を特定する。

パターン1 対処法まとめ

  • SCP は許可の上限。SCP Allow + Identity-based Allow の両方が必要。
  • SCP のテストは必ずメンバーアカウントで。管理アカウントは SCP の対象外。
  • 評価ロジックの5レイヤーを順番に確認する。CloudTrail の errorMessage が手がかり。
  • FullAWSAccess SCP をアタッチしないまま Deny SCP だけ追加すると「何も動かない」状態になる。

詰まりパターン 2: Permission Boundary の条件漏れ

詰まりの場面: 「Identity-based ポリシーで Allow しているのに Access Denied になる」「Boundary をアタッチしてから急に動かなくなった」

Permission Boundary は Identity-based との積集合が有効な権限になる。
Boundary に含まれていないアクションは、Identity-based ポリシーが何を Allow していても実行できない。

典型的な失敗例: Identity Center の Permission Set に PowerUserAccess (AWS 管理ポリシー) をアタッチし、
Boundary に S3FullAccess のみを設定した場合、S3 以外の全サービスが Deny になる。

また、Lambda 関数実行ロールに Boundary をアタッチする際に lambda:InvokeFunction は含めても
logs:CreateLogGroup / logs:PutLogEvents を忘れ、ログが出なくなるケースもよくある。

対処法: CloudTrail コンソールで「イベント名」フィルターに AssumeRole を入れ、
requestParameters.roleArn が対象ロールになっているエントリを確認する。
errorCode: AccessDenied かつ errorMessagePermissionsBoundary が含まれていれば Boundary が原因だ。

aws cloudtrail lookup-events \
  --lookup-attributes AttributeKey=EventName,AttributeValue=AssumeRole \
  --start-time "2024-01-01T00:00:00Z" \
  --max-results 50 \
  | jq '.Events[].CloudTrailEvent' | grep -i "permissionsboundary"
パターン2 対処法まとめ

  • Boundary = Identity-based の積集合。Boundary に含まれないアクションは常に Deny。
  • CloudTrail の errorMessage に “PermissionsBoundary” が含まれていれば Boundary が原因。
  • Lambda ロールに Boundary を設定する場合は logs:CreateLogGroup / logs:PutLogEvents を忘れずに。
  • Permission Set に Boundary を設定する際は「Permissions boundary」フィールドへ ARN を指定する (インラインポリシーフィールドではない)。

詰まりパターン 3: Session Policy の制限

詰まりの場面: 「AssumeRole したロールには十分な権限があるのに Access Denied になる」

AssumeRole / AssumeRoleWithWebIdentity のリクエスト時に --policy オプションで Session Policy を渡している場合、
セッションの有効権限はロールの Identity-based ポリシーとSession Policy の積集合になる。

CI/CD パイプライン (GitHub Actions / CircleCI など) では、ロールを引き受けるステップで
最小権限の Session Policy をデフォルトで渡す設定になっていることがある。
また、IAM Identity Center の OIDC フローでも Session Policy が埋め込まれるケースがある。

対処法: まず --policy なしで AssumeRole して再テストし、Session Policy が原因か切り分ける。

# Session Policy なしでテスト
aws sts assume-role \
  --role-arn "arn:aws:iam::222222222222:role/TargetRole" \
  --role-session-name "debug-session"
# --policy を省く

aws sts get-caller-identity で現在のセッション情報を確認し、セッション ARN に assumed-role が含まれていれば
AssumeRole 経由のセッション。CloudTrail の requestParameters.policy を確認すれば渡された Session Policy を確認できる。

パターン3 対処法まとめ

  • Session Policy を AssumeRole 時に渡している場合、ロールの権限より Session Policy が優先して絞られる。
  • --policy を外してテストすることで Session Policy が原因か切り分けられる。
  • GitHub Actions の OIDC でも Session Policy が埋め込まれることがある。ワークフローの aws-actions/configure-aws-credentials の設定を確認。

詰まりパターン 4: クロスアカウント信頼の設定ミス

詰まりの場面: 「アカウントAからアカウントBのロールを AssumeRole しようとしたが失敗する」

クロスアカウント AssumeRole には2つの設定が両方必要:

  1. アカウントB側の Trust Policy: アカウントAを Principal として信頼する
  2. アカウントA側の Identity-based ポリシー: sts:AssumeRole の Allow が必要

Trust Policy だけ設定してアカウントA側を忘れるケースが最も多い。
以下はよくある失敗パターン:

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111111111111:root" },
"Action": "sts:AssumeRole"
 }
  ]
}

アカウントBの Trust Policy はこれで正しいが、アカウントAのユーザー/ロールに以下が必要:

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::222222222222:role/TargetRole"
 }
  ]
}

また、Trust Policy に "AWS": "arn:aws:iam::111111111111:root" を設定するとアカウント内の全エンティティを信頼することになる。
特定のロール/ユーザーのみを信頼する場合は完全 ARN を指定すること。

パターン4 対処法まとめ

  • クロスアカウント AssumeRole はアカウントB の Trust Policy + アカウントA の Identity-based の2段階が必要。
  • Trust Policy の Principal: "root" はアカウント内全エンティティを信頼する。特定のロールに絞るなら完全 ARN を使う。
  • SCP でも sts:AssumeRole が Deny されていないか確認する (パターン1 と組み合わせ)。

詰まりパターン 5: 委任管理の2制限を知らない

詰まりの場面: 「委任管理アカウントから一部の Permission Set の配信が失敗する」「委任管理アカウントで管理アカウントへの配信ができない」

AWS Organizations の委任管理 (Delegated Administrator) には2つの固定制限がある:

  • 制限①: 委任管理アカウント自身への Permission Set の Account Assignment 配信ができない
  • 制限②: 委任管理アカウントから管理アカウントの Permission Set を変更できない

この制限を知らずにアーキテクチャを設計すると、特定のアカウントへの配信が失敗する。
特に Security OU の委任管理アカウントに対して同じアカウントを配信ターゲットにするケースで詰まりやすい。

対処法: 制限に引っかかる操作は管理アカウントから直接実行する。
事前に「委任管理の対象外」操作を把握し、Terraform / CDK のデプロイ先アカウントを分けて設計する。

# 委任管理アカウントから自身へのアサインは失敗する
# 管理アカウントから実行することで解決
aws sso-admin create-account-assignment \
  --instance-arn "arn:aws:sso:::instance/ssoins-xxxxxxxxxxxxxxxx" \
  --target-id "999999999999" \  # 委任管理アカウント自身
  --target-type "AWS_ACCOUNT" \
  --permission-set-arn "arn:aws:sso:::permissionSet/ssoins-xxx/ps-xxxxxxxxxxxxxxxx" \
  --principal-type "GROUP" \
  --principal-id "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"
# これは管理アカウントから実行する必要がある
パターン5 対処法まとめ

  • 委任管理の2制限 (自身への配信不可 / 管理アカウントの Permission Set 変更不可) を事前に把握する。
  • 制限操作は管理アカウントから実行する。Terraform を使う場合はプロバイダーの assume_role 設定で管理アカウントに切り替える。
  • IaC 設計時に委任管理できる操作とできない操作を分けてモジュールを構成すると管理しやすい。

詰まりパターン 6: Principal 種別の混同

詰まりの場面: 「Trust Policy に正しいプリンシパルを設定したつもりが AssumeRole できない」「EC2 インスタンスプロファイルが機能しない」

Trust Policy の Principal には Service / AWS / Federated の3種類があり、用途によって使い分けが必要だ。
混同するとロールの信頼関係が正しく機能しない。

種別書き方用途
Service"ec2.amazonaws.com"EC2 / Lambda / ECS 等 AWS サービスが引き受けるロール
AWS (IAM ロール)"arn:aws:iam::123456789012:role/RoleName"特定の IAM ロールが引き受けるロール
AWS (アカウント)"arn:aws:iam::123456789012:root"アカウント内の全 IAM エンティティ
Federated"cognito-identity.amazonaws.com"IdP フェデレーション (Cognito / SAML)

よくある失敗: EC2 インスタンスプロファイルに設定するロールの Trust Policy に
"AWS": "arn:aws:iam::123456789012:role/EC2Role" と書いてしまう (Service ではなく AWS を使ってしまう)。
正しくは "Service": "ec2.amazonaws.com" だ。

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Effect": "Allow",
"Principal": {
  "Service": "ec2.amazonaws.com"
},
"Action": "sts:AssumeRole"
 }
  ]
}
パターン6 対処法まとめ

  • AWS サービス (EC2/Lambda/ECS) が引き受けるロールは Principal: { Service: "ec2.amazonaws.com" } を使う。
  • 特定の IAM ロールが引き受ける場合は Principal: { AWS: "arn:aws:iam::AccountId:role/RoleName" } を使う。
  • "AWS": "123456789012" はアカウント root と同等で、アカウント内全エンティティを信頼する (意図しない広範な信頼になることがある)。
  • SAML IdP フェデレーションは Principal: { Federated: "saml-provider-arn" } を使う。

詰まりパターン 7: IAM Path の見落とし

詰まりの場面: 「Resource-based ポリシーで特定の IAM ロールを許可したが、新しいロールに権限が効かない」「ARN を正確に書いたはずなのにマッチしない」

IAM リソースの ARN は Path を含む形式になっている:

arn:aws:iam::123456789012:role/my-role# Path なし (デフォルト /)
arn:aws:iam::123456789012:role/team/my-role # Path = /team/
arn:aws:iam::123456789012:role/app/svc/my-role # Path = /app/svc/

Terraform や CDK で IAM ロールを作成する際に path パラメーターを設定している場合、
Resource-based ポリシーで arn:aws:iam::123456789012:role/my-role と書いてもマッチしない。

また、role/* のワイルドカードは直下の Path のみにマッチし、ネストした Path には効かない:

  • arn:aws:iam::123456789012:role/* → Path / の直下のみマッチ
  • arn:aws:iam::123456789012:role/team/*/team/ 配下のみマッチ

Organizations 環境で複数チームの IAM ロールを管理する場合、チームごとに Path を統一しておくと
Resource-based ポリシーのメンテナンスが楽になる (例: /frontend/, /backend/, /infra/)。

対処法: 既存ロールの実際の ARN を確認してパスを把握する。

aws iam get-role --role-name my-role \
  | jq '.Role.Arn, .Role.Path'
パターン7 対処法まとめ

  • IAM ARN は Path を含む。role/path/RoleName の形式になることがある。
  • Resource-based ポリシーで全パスを対象にするには arn:aws:iam::123456789012:role/* ではなく arn:aws:iam::123456789012:role* (スラッシュなし末尾ワイルドカード) を使う。
  • チームごとに IAM Path を統一しておくと Resource ポリシーの管理が容易になる。

7. アンチパターン→正解パターン変換演習

実際によくある「壊れた IAM 設定」を見て、何が問題か診断し、正解パターンに修正する演習。
Terraform (HCL) と JSON ポリシーの両形式で出題する。
各演習は「アンチパターンコード → 問い → 解答」の構成になっている。


演習1: SCP が機能しているのに S3 削除が禁止されていない

問題文:
FullAWSAccess SCP と以下の Deny SCP を Root OU にアタッチしているが、管理者ユーザーが S3 バケットを削除できてしまう。なぜか?

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Sid": "DenyS3Delete",
"Effect": "Deny",
"Action": "s3:Delete*",
"Resource": "*"
 }
  ]
}

: SCP の JSON 自体は正しいように見えるが、なぜ S3 削除が禁止されていないのか?

答え:

管理者ユーザーが管理アカウントで操作していたのが原因。SCP は管理アカウントには適用されない (Organizations の仕様)。

修正方法:
– メンバーアカウントに切り替えてテストする
– 管理アカウントを日常業務に使わない運用ポリシーを定める
– 管理アカウントのアクセスを制限するために IAM ポリシーで追加の制御を行う

# どのアカウントで操作しているか確認
aws sts get-caller-identity
# "Account": "管理アカウントID" が返ってきたら管理アカウントで操作中

演習2: Permission Boundary が権限昇格を防げていない

問題文:
開発者ロールに以下の Permission Boundary をアタッチした。しかし開発者は Boundary を外して管理者権限を取得できる。何が不足しているか?

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Effect": "Allow",
"Action": [
  "s3:*",
  "lambda:*",
  "iam:CreateRole",
  "iam:AttachRolePolicy"
],
"Resource": "*"
 }
  ]
}

: このポリシーの何が問題か? 開発者が権限昇格できる理由を説明せよ。

答え:

DenyBoundaryModification ステートメントが不足している。
iam:CreateRoleiam:AttachRolePolicy が許可されているため、開発者は:

  1. Boundary なしの新しい IAM ロールを作成
  2. そのロールに AdministratorAccess をアタッチ
  3. 新しいロールを AssumeRole して管理者権限を取得

以下の Deny ステートメントを追加し、Boundary なしのロール作成を防ぐ:

{
  "Sid": "DenyBoundaryModification",
  "Effect": "Deny",
  "Action": [
 "iam:CreateRole",
 "iam:PutRolePermissionsBoundary",
 "iam:DeleteRolePermissionsBoundary"
  ],
  "Resource": "*",
  "Condition": {
 "StringNotEquals": {
"iam:PermissionsBoundary": "arn:aws:iam::123456789012:policy/DeveloperBoundary"
 }
  }
}

演習3: クロスアカウント AssumeRole が失敗する

問題文:
アカウントA (111111111111) からアカウントB (222222222222) のロールを AssumeRole しようとしているが失敗する。アカウントBの Trust Policy は以下のように設定済み。なぜ失敗するか?

# アカウントB の IAM ロール (Terraform)
resource "aws_iam_role" "target_role" {
  name = "TargetRole"

  assume_role_policy = jsonencode({
 Version = "2012-10-17"
 Statement = [
{
  Effect = "Allow"
  Principal = { AWS = "arn:aws:iam::111111111111:root" }
  Action = "sts:AssumeRole"
}
 ]
  })
}

: Trust Policy は正しく設定されている。それでも AssumeRole が失敗する理由を説明せよ。

答え:

アカウントA の IAM エンティティ (ユーザー/ロール) に sts:AssumeRole の Allow がない。
クロスアカウント AssumeRole は Trust Policy (アカウントB側) と Identity-based ポリシー (アカウントA側) の両方が必要。

アカウントA側の IAM ポリシーに以下を追加する:

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Effect": "Allow",
"Action": "sts:AssumeRole",
"Resource": "arn:aws:iam::222222222222:role/TargetRole"
 }
  ]
}

Terraform では:

# アカウントA の IAM ポリシー
resource "aws_iam_role_policy" "assume_target" {
  name = "AssumeTargetRole"
  role = aws_iam_role.source_role.id

  policy = jsonencode({
 Version = "2012-10-17"
 Statement = [
{
  Effect= "Allow"
  Action= "sts:AssumeRole"
  Resource = "arn:aws:iam::222222222222:role/TargetRole"
}
 ]
  })
}

演習4: Permission Set に Boundary が効いていない

問題文:
Identity Center の Permission Set に以下のポリシーを「インラインポリシー」として追加した。開発者が S3 と Lambda 以外 (例: RDS) を操作できないように制限するつもりだったが、RDS を操作できてしまう。

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Effect": "Allow",
"Action": ["s3:*", "lambda:*"],
"Resource": "*"
 }
  ]
}

: このポリシーはなぜ「制限」として機能していないのか?

答え:

これは Permission Boundary ではなく、Identity-based インラインポリシーとして追加されている。
Permission Set に「インラインポリシー」として追加されたポリシーは追加の許可として機能する。
開発者がすでに PowerUserAccess 等の管理ポリシーを持っていれば、その権限に S3/Lambda が追加されるだけで、
RDS の制限にはならない。

Permission Boundary を設定するには、Identity Center コンソールの Permission Set 設定で
Permissions boundary」専用フィールドに、Boundary として機能させたいポリシーの ARN を指定する。

# Boundary ARN を指定する (インラインポリシーフィールドではなく専用パラメーターを使う)
aws sso-admin put-permissions-boundary-to-permission-set \
  --instance-arn "arn:aws:sso:::instance/ssoins-xxxxxxxxxxxxxxxx" \
  --permission-set-arn "arn:aws:sso:::permissionSet/ssoins-xxx/ps-xxxxxxxxxxxxxxxx" \
  --permissions-boundary '{"ManagedPolicyArn": "arn:aws:iam::123456789012:policy/DeveloperBoundary"}'

演習5: OU に SCP を適用したが管理アカウントに効いていない

問題文:
Root OU に以下の SCP を適用して全アカウントで us-east-1 を禁止した。しかし管理アカウントでは us-east-1 のリソースを作成できてしまう。

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Sid": "DenyNorthVirginia",
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
  "StringEquals": {
 "aws:RequestedRegion": "us-east-1"
  }
}
 }
  ]
}

: SCP の JSON 自体は正しい。なぜ管理アカウントで us-east-1 が使えてしまうのか?

答え:

SCP は管理アカウント (Organizations のルートアカウント) には適用されない。これは AWS Organizations の仕様であり、例外なく適用される。

解決策は管理アカウントを日常業務に使わないことだ。

  • 管理アカウントは Organizations 管理 (OU / SCP / アカウント作成) のみに限定する
  • 日常業務 (アプリ開発・インフラ構築) は全てメンバーアカウントで行う
  • 管理アカウントへのアクセスは複数人の承認が必要な緊急アクセス (Break Glass) 手順を定める

管理アカウントへの追加制御が必要な場合は、IAM ポリシーレベルで制限する (SCP では制御不可):

{
  "Version": "2012-10-17",
  "Statement": [
 {
"Effect": "Deny",
"Action": "*",
"Resource": "*",
"Condition": {
  "StringEquals": { "aws:RequestedRegion": "us-east-1" }
}
 }
  ]
}

このポリシーを管理アカウントの IAM ユーザー/ロールに直接アタッチすれば管理アカウント内で us-east-1 を制限できる。


演習の解答まとめを確認する ↓

演習 解答まとめ

演習アンチパターンの核心正解パターンのポイント
演習1管理アカウントで操作していた (SCP の対象外)メンバーアカウントでテスト。管理アカウントを日常業務に使わない
演習2DenyBoundaryModification がなく権限昇格できたBoundary 削除/変更を Condition で Deny するステートメントを追加
演習3アカウントA側の Identity-based に sts:AssumeRole がなかったTrust Policy + Identity-based の2段階設定が必要
演習4インラインポリシーは「追加の許可」。Boundary 専用フィールドを使う必要があったput-permissions-boundary-to-permission-set コマンドで Boundary ARN を設定
演習5SCP は管理アカウントに適用されない (Organizations 仕様)管理アカウントを日常業務に使わない。IAM ポリシーで直接制限する

8. まとめ

8-1. 本記事のまとめ

本記事では複数アカウント時代の IAM 設計について、以下4つのゴールに沿って解説した。

ゴール学んだこと
(a) OU 階層設計3-tier 基本形 (Root / Workload / Security+Log+Network) と規模別パターン。SCP の適用単位で OU を設計し、管理アカウントを日常業務から切り離す原則
(b) 5レイヤー統合評価ロジック明示的 Deny → SCP → Permission Boundary → Identity-based/Resource-based → Session Policy の評価順序。どのレイヤーで詰まっているかを CloudTrail で特定する手順
(c) IAM Identity Center 設計実践Permission Set の設計方針、Account Assignment、グループ同期、委任管理の2制限 (自身への配信不可 / 管理アカウントの Permission Set 変更不可)
(d) 開発者デリゲーションBoundary + Condition で安全に IAM ロール作成権限を委譲する3ステップ。DenyBoundaryModification による権限昇格防止

マルチアカウント設計の核心は「責任の境界を明確にすること」だ。OU と SCP でガードレールを引き、
Boundary で個人の権限上限を定め、Identity Center でアクセスを一元管理する。
この3本柱が揃うことで、規模が拡大しても破綻しないアーキテクチャになる。


8-2. 落とし穴10選

マルチアカウント IAM 設計での頻出失敗パターンを10項目にまとめた。設計レビューのチェックリストとして活用してほしい。

  1. 管理アカウントを日常業務に使う — SCP が効かないため、誤った動作確認をしてしまう。管理アカウントは Organizations 管理のみに限定する
  2. SCP を「許可ポリシー」として誤解する — SCP は許可の上限。FullAWSAccess SCP なしに Deny SCP だけ追加すると何も動かなくなる
  3. Permission Boundary の削除を Deny しない — DenyBoundaryModification がないと開発者が Boundary を外して権限昇格できる
  4. 委任管理の2制限を知らずに設計する — 委任管理は自身への配信と管理アカウント Permission Set の変更ができない。IaC 設計前に把握が必要
  5. クロスアカウント AssumeRole で Trust Policy だけ設定する — Source 側の Identity-based に sts:AssumeRole Allow がなければ失敗する
  6. Permission Set と Permission Boundary を同一視する — Permission Set は「権限のテンプレート」、Boundary は「権限の上限」。全く別の概念
  7. Session Policy を渡していることを忘れる — AssumeRole に --policy を渡した CI/CD パイプラインで「権限があるのに動かない」と悩む
  8. FullAWSAccess SCP なしに Deny SCP を設定する — Deny のみでは何も動かない。Organizations の「デフォルト deny」を理解していないと陥る
  9. IAM ロールの Path を統一しない — Resource-based ポリシーのワイルドカードにマッチせず、新規ロールに権限が効かなくなる
  10. Workload OU と Security OU に同じ SCP を適用する — Security アカウントは CloudTrail/Config の書き込み権限が必要。Workload 向け制限 SCP をかけると監査ログが止まる

8-3. Vol1 双方向クロスリンク + Vol3 予告

本記事 (Vol2) は単一アカウントの IAM ポリシー設計基礎を学んだ後に読むと理解が深まる。

関連記事:
IAMポリシー設計入門 (Vol1) — 評価ロジック・必要権限の特定法・アンチパターン演習: 本記事 §3 の5レイヤー評価ロジックの前提となる単一アカウント IAM の基礎。Identity-based ポリシーの JSON 構造・評価ロジック・Access Analyzer 活用法を解説している。

本シリーズの Vol3 では Organizations 環境でのアクセス権棚卸の自動化を扱う。
IAM Access Analyzer と Lambda を組み合わせて、定期的に不要な権限を検出・通知する仕組みを構築する。
未使用の Permission Set や不要なクロスアカウント信頼を自動検出し、アクセス権の肥大化を防ぐ実践的な内容だ。


次のステップ

  • Vol1 (基礎固め): IAMポリシー設計入門 — 単一アカウントの評価ロジック・最小権限特定・アンチパターン演習。本記事の前提知識として最適。
  • Vol3: 権限棚卸し自動化と継続運用 — IAM Access Analyzer × Lambda × Terraform で定期的な権限レビューを自動化する実践内容。

本記事の落とし穴10選をブックマークして、設計レビューのチェックリストとして活用してください。マルチアカウント IAM 設計は一度理解してしまえば、スケールしてもブレない骨格になります。


IAM入門 Vol3: 権限棚卸し自動化と継続運用 — Access Analyzer × Lambda × Terraform → 読む