AWS IAMポリシー:JSON構造・種類・評価とサービス連携

AWS IAMポリシーをアタッチ先と管理方法で分類し、JSON要素、Condition演算子、権限評価、権限制限ポリシー、AWSサービス間連携の許可設定までDVA向けに解説します。

学習順Step 3 / 101サービスIAM試験ドメインセキュリティ

AWS IAMポリシーの構造とアクセス制御

AWS Identity and Access Management(IAM)ポリシーは、AWSへのリクエストに対して「どの主体が、どのリソースに、どの操作を行えるか」を定義する権限ルールです。ポリシーの大部分はJSON文書で記述され、AWSはリクエストの主体・操作・対象リソース・条件とポリシーを照合して許可または拒否を判断します。

ポリシーを読むときは、まずどこにアタッチされているか、次にどの主体・操作・リソースを対象にしているか、最後に別のポリシーによる制限がないかを確認します。アタッチ先による分類と、再利用・管理方法による分類は別の軸です。

IAMポリシーの種類とアクセス判定に関わる許可・制限の関係

アタッチ先で分けるポリシー

アイデンティティベースポリシー

アイデンティティベースポリシー(identity-based policy)は、IAMユーザー、IAMグループ、IAMロールといったIAMアイデンティティにアタッチします。ポリシーの中で、そのアイデンティティに許可する操作(Action)、対象リソース(Resource)、必要なら追加条件(Condition)を定義します。

この種類のポリシーでは、通常、許可対象の主体を示すPrincipalは書きません。アタッチ先のアイデンティティが、権限を受ける主体を決めるためです。たとえば、帳票を生成するLambda関数の実行ロールに、特定のDynamoDBテーブルへの書き込みを許可するポリシーを付けると、そのロールを引き受けた関数が許可範囲でAPIを呼び出せます。

リソースベースポリシー

リソースベースポリシー(resource-based policy)は、対応するAWSリソースそのものにアタッチし、そのリソースへのアクセスをどの主体に認めるかを記述します。許可・拒否する相手をPrincipalで指定するのが基本です。S3バケットポリシー、Lambda関数のリソースポリシー、IAMロールの信頼ポリシーなどが代表例です。サービスによってサポートされるリソースとポリシー要素は異なります。

リソースポリシーは、同一アカウントの主体だけでなく、条件やサービスの仕様を満たす別アカウント・AWSサービスの主体にアクセスを認める用途にも使えます。クロスアカウントアクセスでは、呼び出し元側の許可とリソース所有側の許可など、両アカウントに必要な設定がそろっているかを確認します。

IAMロールの信頼ポリシーは、どの主体にそのロールを引き受けさせるかを定めるリソースベースポリシーです。信頼ポリシーが許可するのはロールセッションを取得することです。引き受けたロールで何ができるかは、ロールに付いたアイデンティティベースポリシーなどで別に定義します。「ロールを引き受けられること」と「引き受けた後の操作権限」を混同しないでください。

管理方法で分けるポリシー

管理ポリシーとインラインポリシーは、アイデンティティに対する権限をどのように管理するかの分類です。これはアイデンティティベースとリソースベースの分類とは異なり、「アタッチ先」と「管理形態」を組み合わせて考えます。

種類 管理者・再利用 運用上の特徴
AWS管理ポリシー AWSが作成・管理し、複数のIAMアイデンティティで共有できる 一般的な用途に早く適用できる。利用者が内容を直接変更できず、AWSによる更新がアタッチ先すべてに影響するため、権限内容と更新を確認する
カスタマー管理ポリシー 利用者が作成・更新し、複数のIAMアイデンティティで共有できる 自組織の用途に応じて調整でき、複数の主体に共通の権限を一元管理しやすい。更新するとそのポリシーを使う主体すべてに反映される
インラインポリシー 単一のユーザー、グループ、ロールに直接埋め込む ポリシーとアイデンティティが一対一で強く結び付く。アイデンティティの削除に伴ってポリシーも削除される。複数主体で共有する権限には管理ポリシーを検討する

一般的には、共有・再利用する権限を管理ポリシーで管理すると、変更の一貫性を保ちやすくなります。AWS管理ポリシーは便利ですが、名前が「読み取り専用」「フルアクセス」などであっても、実際のActionとResourceを確認して用途に適合するか判断します。必要な権限を自分たちで細かく管理するなら、カスタマー管理ポリシーを設計します。特定のアイデンティティだけに固有の権限を閉じ込める場合はインラインポリシーが選択肢になります。

JSONポリシー文書の基本構造

ポリシーは一つ以上のStatementを持ち、各ステートメントが独立した許可または拒否のルールを表します。次の例は架空のアプリケーションが、特定のAWSリージョンにある一つのDynamoDBテーブルで項目を読み取るためのアイデンティティベースポリシーです。自分の環境で使うときはアカウントID・リージョン・テーブル名を実際の値に置き換え、サービスのアクションとARN形式が正しいことを確認してください。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "ReadShipmentRecords",
      "Effect": "Allow",
      "Action": "dynamodb:GetItem",
      "Resource": "arn:aws:dynamodb:ap-northeast-1:123456789012:table/ShipmentLedger"
    }
  ]
}
要素 意味と読み方
Version ポリシー言語のバージョンを表す。通常使う2012-10-17は言語仕様の識別子であり、ポリシー作成日や有効期限として更新する日付ではない。古い値として2008-10-17も存在するが、新しい機能を含む現在の記述では通常2012-10-17を指定する
Statement 権限ルールを入れる要素。単一ならオブジェクト、複数なら配列にする。ステートメントの順序そのものに意味はない
Sid ステートメントに付ける任意の識別子。人がルールを見分ける助けになる。権限の対象や効果を決定する要素ではない
Effect ルールの効果をAllowまたはDenyで指定する。該当する明示的Denyは、他のポリシーにあるAllowより優先する
Principal リソースポリシーで許可または拒否する主体を指定する。アイデンティティベースポリシーには通常書かず、信頼ポリシーやS3・Lambda等のリソースポリシーで使う
Action 対象サービスのAPI操作を指定する。サービス名前空間と操作名をservice:ActionNameで表す。複数指定でき、サービスや操作によりリソースレベルの権限制御に対応するかが異なる
Resource 操作対象をARNなどで指定する。操作によっては特定リソースを指定できず、"*"が必要なものもある。ワイルドカードを使うと対象が広がるため、サービスの認可リファレンスを確認する
Condition リクエストコンテキストの値と条件キーを比較し、条件を満たす場合だけステートメントを適用する。ネットワーク、タグ、主体、日時などの制約に利用する

Version、StatementなどのJSON要素名やEffectの値は、記述どおりの大文字・小文字を使います。複数の許可・拒否ルールを置くときは、Statement配列にオブジェクトを並べます。Sidは任意であり、付けてもポリシーの許可範囲は変わりません。

Principalの有無はポリシーの種類を見分ける重要な手掛かりです。たとえば、後述するLambdaのリソースポリシーでは呼び出し元サービスをPrincipalに置きます。一方、Lambdaの実行ロールに付けるアイデンティティポリシーは、関数が呼び出す先の操作を許可し、通常Principalを含みません。

アクション、リソース、ワイルドカード

Actionには具体的なAPI操作を指定します。サービスごとに操作名が決められ、読み取り・書き込み・管理などのアクセスレベルも異なります。許可範囲を狭くするには、必要な操作だけを並べます。"*"を指定すると、そのステートメント内で対象となるあらゆるアクションに一致し得ます。たとえば、効果がAllowなら非常に広い許可になり、Denyなら一致する操作を明示的に拒否します。

アクションのワイルドカードは、サービス名前空間を含むパターンにも利用できますが、単に"*"を使うことと、特定サービス内の操作だけに制限することでは範囲が大きく異なります。同様に、Resource: "*"はすべてのリソースに及ぶ可能性があります。サービス操作ごとにResourceの指定可否と対応ARNが異なるため、広い指定が必要なアクションと、個別リソースに絞れるアクションを分けて設計します。

Conditionで条件を加える

Conditionは、Condition演算子、条件キー、比較する値の組み合わせで記述します。次の架空の例では、Denyを用い、aws:RequestedRegionが東京リージョンと一致しないリクエストを拒否します。これはIAM JSONの構造を示す例であり、組織の全AWS操作をこの条件だけで安全に制御できるという意味ではありません。サービスやグローバルエンドポイント、必要な例外を考慮した検証が必要です。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "RejectOutsideApprovedRegion",
      "Effect": "Deny",
      "Action": "*",
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:RequestedRegion": "ap-northeast-1"
        }
      }
    }
  ]
}

代表的な演算子は次のとおりです。実際に使える演算子は条件キーやサービスのサポートに依存するため、キーに対応する演算子を公式のサービス認可情報で確認します。

演算子 判定内容 代表的な用途
StringEquals 大文字・小文字を区別して文字列全体が一致するか判定 タグ値、リージョン名、主体属性などの完全一致
StringLike 文字列を大文字・小文字を区別して比較する。*は0文字以上、?は任意の1文字に一致 名前・ARN等のパターン照合
StringNotLike StringLikeで一致しないことを判定 指定した文字列パターン以外を条件にする
NumericEquals 数値が等しいか判定 数値として定義されたリクエスト条件
NumericLessThan / NumericGreaterThan 数値が小さいか/大きいか判定 時間・サイズ・件数など数値条件の境界
Bool trueまたはfalseの真偽値を判定 MFA利用の有無や、条件キーで表される真偽値の照合
ArnEquals ARN全体が一致するか判定 実行元リソースやロールなどのARNを特定
DateEquals 日時が一致するか判定 日付・時刻条件の比較

Conditionの比較で見落としやすい点は次のとおりです。

  • 条件キーはポリシー側の名前だけで決まる値ではなく、AWSが認可時のリクエストコンテキストに持つ値です。キーがリクエストに存在しないと通常の肯定演算子は一致せず、条件は成立しません。
  • StringLikeの*や?は文字列条件値の中のパターン記号です。StringEqualsで部分一致を作ることはできません。
  • 複数の条件キーや異なる条件演算子を一つのConditionに記述すると、それぞれの条件を満たすことが求められます。配列で比較値を複数指定したときの一致の意味は演算子やForAllValues / ForAnyValueなどの集合演算子で変わるため、単純に「全部一致」などと決めつけず仕様を確認します。
  • StringNotLikeのような否定演算子は、条件キーが存在しない場合に肯定演算子と異なる結果になり得ます。キーの欠如自体を判定するにはNull、キーが存在する場合だけ比較したいときは...IfExistsの利用可能性を確認します。
  • 複数条件を組み合わせると、要件を厳しくする一方で正規リクエストも拒否することがあります。必要なAWSサービス、複数リソースを伴うAPI、キーが提供されないケースを含めてポリシーシミュレーターや実環境で検証します。

ポリシーの評価と「Allowがあるのに拒否」の理由

IAMでは、ポリシーの一つに許可が書かれているかだけで最終結果を決めません。認証後のリクエストについて、適用対象となるポリシーを評価します。基本原則は明示的な拒否は許可に優先すること、そして明示的な許可がない操作は許可されないことです。

同一アカウントで、アイデンティティベースポリシーとリソースベースポリシーが適用される場合、一般にそれらの許可は和集合として評価されます。いずれかで許可されれば認められ得ますが、どちらかの明示的Denyが優先します。一方、権限境界やSCP、セッションポリシーなどの権限上限は、許可を与えるポリシーとは役割が異なり、実効権限を制限します。異なるアカウント間では、リソース所有側と呼び出し側の許可などが必要となり、片側の設定だけで成立しないケースがあります。

ポリシー種別 役割 権限を直接付与するか
アイデンティティベースポリシー IAMアイデンティティの操作許可を定義 Allowによって付与する
リソースベースポリシー リソースへのアクセスを許す主体と操作を定義 Allowによって指定主体へ付与する。アカウント境界を越える場合は追加条件がある
権限境界(Permissions boundary) ユーザーまたはロールに対し、アイデンティティポリシーが付与できる上限を定める 付与しない。境界と許可ポリシーの両方に認められる範囲に制限する
サービスコントロールポリシー(SCP) Organizations配下の対象アカウントでIAM主体に適用される権限の上限を定める 付与しない。SCPが許す範囲に加えて、権限を付与するポリシーが必要
リソースコントロールポリシー(RCP) Organizationsで対象リソースに適用する権限の上限を定める 付与しない。サポート範囲と適用条件を確認する
セッションポリシー ロール引き受け等で発行される一時セッションの権限をさらに狭める 付与しない。基になるロール等の権限を超えない
信頼ポリシー ロールを引き受けることができる主体を定める ロールセッションの取得を許可するが、セッションの操作権限そのものは別途定義する

権限境界では、アイデンティティベースポリシーが許可する権限と境界が許す権限の共通部分が上限になります。SCPも同様に、対象アカウントの主体が利用できる範囲を組織側で制約します。セッションポリシーもセッションに付与される許可を狭めます。これらにAllowを記述しても、それだけでAPI操作が許可されるわけではありません。実際の許可を与えるポリシーが別途必要です。

SCPは、Organizationsの管理アカウント内の主体に対して通常のメンバーアカウントと同じように適用されるわけではありません。また、SCPやRCPはサポートされるアカウント種別・リソース・ポリシー機能に範囲があります。すべてのAWSリソースに一律に適用されると想定せず、AWS公式の適用条件を確認します。

拒否の原因をたどる手順

あるAPI呼び出しが拒否された場合は、次の順に照合すると原因を分離しやすくなります。

  1. リクエストを送ったプリンシパルと、実際に引き受けているロール・セッションを確認する。
  2. Actionのサービス名前空間・API名と、ResourceのARNが一致しているか確認する。アクションによっては複数の関連リソースに対する権限が必要になる。
  3. ポリシー条件キーがリクエストコンテキストに存在し、値と演算子の組み合わせが意図どおりか確認する。
  4. 適用されるポリシー全体を検索し、明示的Denyがないか調べる。別のAllowを追加しても明示的拒否は打ち消せない。
  5. 権限境界、OrganizationsのSCP/RCP、ロールセッションに付いたセッションポリシー、VPCエンドポイントポリシーなど追加の制限を確認する。
  6. 別アカウントのリソースなら、呼び出し元とリソース所有者の双方の許可要件を調べる。信頼ポリシーを使うロール引き受けなら、引き受け許可と引き受け後の操作許可を別々に確認する。

AWSサービス連携では許可の向きを考える

サービス間連携で権限不足が起きるのは、どの主体がAWS APIを実行するかと、アクセス許可をどこで表現するかを取り違える場合が多いためです。呼び出し元の実行ロールに付けるアイデンティティポリシーと、呼び出し先リソースに付けるリソースポリシーは別物です。構成に応じて片方または両方が必要になります。

AWSサービス連携における呼び出し元ロールとリソースポリシーの許可方向

CloudFrontからS3オリジンを読む

CloudFrontから非公開のS3バケットをオリジンとして利用する場合、Origin Access Control(OAC)を設定し、S3バケットポリシーでCloudFrontディストリビューションからのアクセスを許可する構成が代表的です。CloudFront側のID/ソース条件を適切に限定し、対象オブジェクトへの読み取りなど必要な操作だけを認めます。OACでは、OAI(Origin Access Identity)と混同せず、S3のオブジェクト所有権や署名設定などの前提も確認します。

ここで注目するのは、閲覧者にバケットを直接公開するのではなく、リソース側のバケットポリシーでCloudFront経由のアクセスを許可する点です。CloudFront設定だけを作ってバケットポリシーの許可を追加し忘れると、オリジン取得が拒否されることがあります。

AWSサービスからLambda関数を起動する

イベントを送るAWSサービスがLambda関数を直接呼び出す構成では、Lambda関数のリソースベースポリシーに呼び出し元サービスのPrincipalとlambda:InvokeFunctionを許可する設定が必要になることがあります。許可対象を特定のバケットやルールなどに制限するため、aws:SourceArnやaws:SourceAccountなどの条件も検討します。サービスプリンシパルだけを広く許可するのではなく、想定したイベントソースに限定します。

一方、SQSをLambdaのイベントソースマッピングで読み取る方式では、Lambdaがキューをポーリングします。Lambda実行ロールにSQSからメッセージを受信・削除する権限などを付与する構成が基本であり、SQSがLambdaを直接呼び出すリソースポリシー方式とは異なります。連携名称だけで判断せず、実際のイベント配送方式を見分けます。

Lambdaから他のAWSサービスを操作する

Lambda関数のコードがS3へ書き込む、DynamoDBを更新する、SNSへ発行するといった操作を行う場合、通常はLambda関数に割り当てた実行ロールのアイデンティティベースポリシーで、その操作と対象リソースを許可します。Lambda関数のリソースポリシーは、この場合の関数の呼び出し元を許可するためのものです。実行ロールのポリシーとLambdaのリソースポリシーは方向が逆です。

たとえば、画像メタデータを登録する関数が特定のDynamoDBテーブルに項目を追加するなら、実行ロールに当該テーブルのdynamodb:PutItemを許可します。データベース全体への操作や全アカウントのリソースを許可する必要はありません。

EC2・キュー・Step Functionsの連携

EC2上のアプリケーションがAWSサービスを利用する場合は、EC2インスタンスプロファイルを通じてIAMロールをインスタンスに関連付けます。アプリケーションはロールの一時認証情報を利用し、ロールのアイデンティティベースポリシーに許された範囲でS3やDynamoDBなどを呼び出します。インスタンス内に長期アクセスキーを固定する方法を避けられます。ここでも、EC2自体のリソースポリシーがサービスへのアクセスを許可するのではなく、インスタンスに付いたロールが呼び出し元として認可されます。

Amazon SQSキューをLambdaイベントソースマッピングで処理する場合は、Lambda実行ロールがキューからメッセージを取得・削除する権限を持つ必要があります。キューがLambdaを直接呼び出す構成ではないため、Lambda関数ポリシーにSQSをPrincipalとして記述する形式と混同しないようにします。キューへのアクセスを別アカウントのプロデューサーにも許すなら、キューポリシーで送信元の主体と必要なSQS操作を許可する構成を検討します。

AWS Step FunctionsのステートマシンがLambdaをタスクとして実行する場合、Step Functionsは実行ロールの権限でタスクを呼び出します。Lambda側でサービスからの呼び出しを明示的に許可する構成では、関数のリソースポリシーにstates.amazonaws.comなどのサービスプリンシパルと、対象のステートマシンを限定するソース条件を設定します。ステートマシンの実行ロールが持つタスク実行権限と、Lambda関数が呼び出しを受け付けるためのリソース側の許可を、連携方法に応じて確認します。

IAMに関連するその他のポリシー

AWSのアクセス制御には、ここで扱ったアイデンティティベースポリシーとリソースベースポリシー以外にも複数のポリシーがあります。主な位置付けは次のとおりです。

  • 権限境界はIAMユーザーまたはロールに設定し、アイデンティティポリシーが与えられる上限を制御します。
  • 信頼ポリシーはロールのリソースベースポリシーであり、sts:AssumeRoleなどのロール引き受けをどの主体に認めるかを定めます。
  • SCPはAWS Organizationsで組織・OU・アカウントに適用し、メンバーアカウントのIAM主体が使える権限の上限を管理します。
  • セッションポリシーは一時的なロールセッションなどに付け、セッションの権限を一段と狭めます。
  • VPCエンドポイントポリシーは対象エンドポイントを通るアクセスに適用する追加の境界です。
  • RCPはOrganizationsで対象リソースのアクセス許可に対する上限を管理します。

これらも多くはJSONで記述されますが、すべてのポリシー種別が同じ要素・効果・対象を持つわけではありません。どの主体・リソース・通信経路に適用される制御なのかを見極め、権限付与ポリシーと上限・ガードレールを区別します。

DVAで押さえる判断ポイント

  • ポリシーは「どこに付くか」でアイデンティティベースとリソースベースに分かれ、「共有管理するか」で管理ポリシーとインラインポリシーに分かれる。
  • アイデンティティベースポリシーは通常Principalを書かず、リソースベースポリシーではアクセスを受ける主体をPrincipalで指定する。
  • Version: "2012-10-17"はポリシー言語の版であり、作成日や期限ではない。Sidは任意の識別名で、許可範囲を変えない。
  • Effect: "Allow"、該当するAction、Resource、Conditionが揃っても、明示的Denyや権限制限ポリシーがあれば拒否され得る。
  • 権限境界、SCP、RCP、セッションポリシーは、それ自体が操作権限を与える許可ポリシーではなく、実効権限を制限する。
  • ロールの信頼ポリシーは誰がロールを引き受けられるかを決め、ロールに付けたポリシーは引き受け後に何ができるかを決める。
  • CloudFrontからS3、サービスからLambda、Lambdaから別サービスのそれぞれで、呼び出し方向と必要なポリシーのアタッチ先を整理する。
  • "*"を使ったアクション・リソース指定は許可または拒否の範囲を大きく変える。AWS管理ポリシーも中身を点検し、必要な操作とリソースだけに絞る。

公式ドキュメント

重要ポイント

  • ▸アイデンティティベースポリシーは主体に、リソースベースポリシーは対応するAWSリソースに付け、後者は許可対象のPrincipalを指定する
  • ▸AWS管理・カスタマー管理ポリシーは再利用できる管理ポリシーであり、インラインポリシーは単一のIAMアイデンティティに結び付く
  • ▸Versionはポリシー言語の版、Statementは権限ルール、Effect・Action・Resource・Conditionは許可範囲を表す
  • ▸StringEquals、NumericLessThan、Bool、ArnEquals、DateEqualsなどのCondition演算子でリクエスト条件を比較できる
  • ▸Allowがあっても明示的Denyや権限境界・SCP・セッションポリシーなどの上限により拒否されることがある
  • ▸AWSサービス連携では呼び出し元の実行ロールと呼び出し先リソースポリシーのどちらが必要かを連携方式ごとに見分ける

このトピックの学習を完了しますか?

完了状態はいつでも切り替えられます