

AWSのポリシーを使いこなそう ポリシー設計につまづかないためのポイントを整理
プラットフォーム技術部の小林正彦です。
本記事では「わかるようでよくわからないポリシー」のお話をしていきたいと思います。
AWSの公式ドキュメントにはポリシーに関する膨大な情報が掲載されています。しかしながらそれらの内容を机上で整理して理解するのは難しいです。「どういう場合にどのポリシーを定義するとよいのか」「それらを適用する上での注意点は何か」をつかめていないと、がんばって実装してみたのにメンテナンス困難なポリシー設計になってしまったなんてことになりかねません。
そういった事態に陥らないために「どういう場合にどのポリシーを定義するとよいのか」、「それらを適用する上での注意点は何か」を整理していきますが、すべてを解説しようとするととんでもない量になってしまうので本記事では「タイプの違い」に注目してポイントを記載していきます。
ポリシーの基礎的な話からまとめていきますので、これからポリシーを触り始める方にも、すでにポリシーを理解している方にも参考になれば幸いです。
ポリシーとは
Q. ポリシーとは何でしょうか。
A. アクセス管理を行うための「IAM」サービスの機能です。
はい、正解です。
しかしながら、その回答の裏で重要な観点が漏れているかもしれません。AWSが提供するポリシー機能とは、IAMサービスが扱う「ユーザー」を対象としたアイデンティティ管理及びアクセス管理だけに留まらず、「もの」である各種サービスリソース間のアクセス管理までも含まれます。つまりユーザーだけに注目していては不十分ということです。
ポリシーを3行で
ポリシーとは何かを3行で。
- アイデンティティやリソースにアタッチしてアクセス許可を定義するJSONドキュメント
- アクション実行のリクエスト内容とポリシー定義を評価してアクセス許可or拒否を判断
- 6つのタイプがある
ポリシーのタイプ
3行目に書いた「ポリシーには6つのタイプがある」についてですが、AWSは用途に応じて異なるタイプのポリシーを提供しています。それら6つのポリシータイプと用途を、使用頻度で階層化した図がこちらです。
下層になるほど利用シーンが限定されていくので「階層の深さ」が「実現したいセキュリティポリシーの強度」に直結します。
一般的には上から2番目までのポリシータイプを使用します。
3階層目以降のポリシーを使えばより細かなアクセス制御を実現できます。2層目までで定義した許可範囲をさらに制限したい、あるいは、特別なリソースに対してアクセス許可を付与したいといった高度な設定を実現する場合に使用できますが、複数のタイプを併用するとそれだけポリシーの評価方法が複雑になり管理者(というか人間)が実態を把握できなくなってしまうかもしれません。
きめ細やかなアクセス制御の実現と管理作業の負荷はトレードオフであることを理解して、適切なレベルのアクセス管理を行いましょう。
冒頭に述べた「ポリシーとは」の回答が正解かどうかは、回答者がどの階層まで意識しているかによると思います。リソースベースポリシーまで使用するべきなのにアイデンティティベースポリシーの層までしか理解していないとすれば、適切なポリシー設計ができません。
以降では、1階層目の「アイデンティティベースポリシー」と2階層目の「リソースベースポリシー」に焦点を当てて、それぞれの性質・考慮点を記載していきます。3階層目以降のタイプの詳細な説明はポリシーとアクセス許可の内容を参照してください。
アイデンティティベースとリソースベースを比較
まずは両ポリシーの特徴を簡単にまとめます。
アイデンティティベースポリシーの特徴
「誰がどのリソースに対してどんなアクションを実行できるか」を指定します。
AWS管理ポリシー、カスタマー管理ポリシー及びインラインポリシーを用いてポリシーを定義し、IAMアイデンティティ(=ユーザー/グループ/ロール)に「直接アタッチ」して使います。


リソースベースポリシーの特徴
「このリソースに対して誰がどんなアクションを実行できるか」を指定します。
誰(=プリンシパル(依頼者)エンティティ)がどんなアクションを実行できるかを指定したポリシーを作成し、リソースにアタッチします。リソースにアタッチすると、ポリシーの中で指定した誰(=プリンシパルエンティティ)に対してアクセス許可が付与されます。


両者を下記の3つの観点で比較してみます。
- アタッチ先・・・作成したポリシーを何に紐づけるか
- アクセス許可の付与先・・・アクセス許可を何に与えるか
- 作成方法・・・ポリシーをどこに定義するか
アイデンティティベースとリソースベースをこれらの観点で下表に整理しました。
ここから、2つのポリシーの違いについて説明します。
違い1 アタッチ先とアクセス許可の付与先
まず1つ目は、アイデンティベースとリソースベースとではポリシーのアタッチ先とアクセス許可の付与先が異なるという点です。
アイデンティティベースポリシーの場合は、アタッチ先とアクセス許可の付与先が同じです。
つまり「あるユーザーにアイデンティティポリシーをアタッチしたら、アタッチしたそのユーザーにアクセス許可が付与される」ということです。
一方、リソースベースポリシーの場合はアタッチ先とアクセス許可の付与先が異なります。
付与先が異なるとはどういうことか、S3を例に説明します。
S3のリソースにはバケットが該当します。リソースベースポリシーのアタッチ先はリソースなので「S3のバケットにリソースベースポリシーをアタッチする」ということです。※1
しかしながらアクセス許可の付与先はバケットではありません。アクセス許可の付与先は「リソース」ではなく「プリンシパル」です。「プリンシパル=自アカウント / 他アカウントのユーザーまたはアプリケーション」ですので、バケットにアクセスしてくるエンティティにアクセス許可を与える。ということです。
アタッチ先とアクセス許可の付与先の違いを簡易な図で表してみます。
※1 S3バケットにアタッチするリソースベースポリシーのことを「バケットポリシー」と呼んでいます。名称は異なりますが実態は同じものを指しているので、別のポリシーであると勘違いしないようにしてください。リソースベースポリシーを別の名称で呼んでいる他の例として、IAMロールにアタッチする信頼ポリシーがあります。
違い2 リソースベースはインラインポリシーのみ
つづいて2つ目の違いは、リソースベースポリシーはインラインポリシーしか作成できないという点です。
インラインポリシーしか作成できないということは「テンプレートとなるAWS管理ポリシーが用意されていない」ということです。いちから定義を作成しなければなりません。
また、リソースベースという名前の通りでリソースにポリシーをアタッチするので「リソースベースポリシーはインラインポリシーしか作成できない=リソースごとにポリシーをいちから作成する」ということです。
SQSのリソースベースポリシー作成を例に説明すると、
SQSでのポリシーを定義する単位は「キュー」です。マネジメントコンソールあるいはCLIコマンドでキューごとにポリシーを作成します。利用しているキューの数が少ない場合はそれほど面倒な作業ではないと思いますが、数十・数百とキューが増えたときに1つ1つベタ書きしていく作業の煩雑さは想像に難くありません。
SQSの場合はポリシー作成を支援するエディター[※2]が用意されているのでエディターの画面に従ってアクションや条件の要素を選択していけば作成できますが、リソースごとに同じ作業をくり返すことに変わりありません。
ロールをアタッチするように複数のリソースでポリシーを共有できる構成だと楽だな、と、思います。
※2 エディター上で条件(Condition)を選択できますが、すべてのCondition要素が選択肢として用意されているわけではありません。選択肢に存在しないCondition要素を使用したい場合はJSONドキュメントを作成する必要があります。
アイデンティティベースとリソースベースの併用
ここまで両ポリシーを対比させてきましたが、アイデンティティベースポリシーとリソースベースポリシーを併用する場面を検討してみます。
あえて冗長な書き方をすると「アイデンティティベースポリシーをアタッチしたアイデンティティエンティティ(がアタッチされたリソースも含む)から、リソースベースポリシーをアタッチしたリソースに対して任意のアクションを実行する」ということです。
具体的なアクセスケースとして下図のような場面を設定します。
3つのサービス(ユーザー / インスタンス / Lambda)がS3にアクセスする構成です。アクセス元のエンティティにはアイデンティティベースポリシーを定義、アクセス先のエンティティ(S3)にはリソースベースポリシーを定義します。
ケース1 ユーザーからS3へのアクセス
あるユーザーがマネージドコンソールを操作して、S3に対してアクションを行う。実行可能なアクションはユーザーにアタッチしたポリシーに定義したアクションのみを想定。
ケース2 EC2からS3へのアクセス
インスタンス上でAPIリクエストを実行し、S3に対してアクションを行う。実行可能なアクションはアイデンティティベースポリシー(をアタッチしたロール)に定義したアクションのみを想定。
EC2それ自体はアイデンティティエンティティではないのでアイデンティティベースのポリシーをアタッチできませんが、アイデンティティベースのポリシーにアタッチされたロールを介して、EC2をアイデンティティエンティティのように扱うことができます。
ケース3 LambdaからS3へのアクセス
他サービスのイベントをトリガーにLambdaを起動し、S3に対してアクションを行う。実行可能なアクションはアイデンティティベースポリシー(をアタッチしたロール)に定義したアクションのみを想定。
LambdaはAWS CLI経由でリソースベースポリシーを定義できます。マネージドコンソールからトリガーとなるサービスを指定した場合は、自動的に適切なサービスロールが割り当てられるので通常はポリシーの内容を意識する必要はありません。
ポリシー設計のポイント
さきほどの図のアクセスケースの場合、両ポリシーの内容はどのように評価されるでしょうか。
ポイント1 アカウント構成
サービス間のアクセスが同一アカウント内アクセスであるか、クロスアカウントアクセスであるかによってポリシーの評価方法が異なります。
クロスアカウントアクセスである場合
AアカウントとBアカウントが連携するクロスアカウント構成を想定します。
AアカウントのEC2からBアカウントのS3に対して特定のアクションのみを許可したい場合は、AアカウントEC2のアイデンティティベースポリシーに「BアカウントS3へのアクション許可」を定義し、かつ、BアカウントS3のリソースベースポリシーに「プリンシパルをAアカウントに指定して同じアクションを許可」する定義が必要です。
つまり、両アカウントで明示的なALLOWを定義しないとアクションは許可されないということです。どちらか一方にのみ定義しても許可されません。
同一アカウントアクセスである場合
Aアカウント内で閉じた構成を想定してみます。
同一アカウント内でEC2からS3へアクセスをする場合は、アイデンティティベースとリソースベースの両ポリシーによって付与されているすべてのアクセス許可を合わせて評価します。
つまり、どちらか一方のポリシーにALLOWの定義があればもう一方のポリシーにアクション許可を定義しなくてもよいということです。
アイデンティティベースを先に評価して、次にリソースベースを評価するといったように順次評価していくのではなく、両方をあわせて一緒に評価するという動きです。
不要なポリシー定義が後々悪影響を出して混乱しないように、アクセス元/先が同一アカウントか、クロスアカウントであるかを確認して極力シンプルな設計になるように注意しましょう。
ポイント2 明示的なDENYの必要性
クロスアカウントアクセスである場合は、どちらか一方のALLOWの定義を削除すればリクエストは拒否されるという評価をする仕様なので明示的なDENYは必須ではありません。
同一アカウントアクセスである場合は、アクセス元/先サービスのどちらか一方にALLOWを定義すると、意図しないアクセスまで許可されるリスクが生じます。アクセスを受ける側が想定していないアクセスであっても、アクセス元のアイデンティティベースポリシーにALLOWを定義すると許可されてしまうのです。
このリスクを防ぐには明示的なDENYをリソースベースポリシーに定義しなければなりません。
明示的なDENYを使用する際に注意するのが評価の順序です。明示的なDENYはすべてのALLOWに優先して評価されます。そのため、通したいリクエストがALLOWになるように、通したいリクエスト以外のすべてのリクエストを明示的にDENYするポリシーを定義しなければなりません。
明示的なDENYを使用する場合のポリシーのイメージを以下に示します。図中の実線が通したいリクエスト、灰色四角が明示的なDENYを表しています。
バケット側では通したいリクエスト以外はすべて明示的にDENYするようなリソースベースのポリシーを定義します。例えば、「ユーザーAのXXXXアクション」でも「InstanceのYYYYアクション」でも「LambdaのZZZZアクション」でもないリクエストはすべて拒否、というような複雑な論理式の設計が必要です。
明示的なDENYのAND/ORを組み合わせることで上図のような要件を満たすことはできるのですが、設計そのものが非常に複雑であり管理者に高い経験値が要求されることや、設定ミスによる影響[※3]を考慮すると明示的なDENYを使用したアクセス制御は推奨しません。
※3 明示的なDENYを適用する範囲を誤ると「通したいリクエストが通らない」、「通したくないリクエストが通る」という状況になり、該当サービスを設計意図どおりに管理できなくなる恐れもありますので十分にご注意ください。
職務機能とポリシーについて
ポイント1,2で説明した内容はポリシーの仕様に関する話です。ここでは「ポリシーの仕様」とは別の観点として「職務機能とポリシーの関係」について簡単にまとめます。
職務機能とは「誰がどのような役割でどのようなタスクを実行できる権限を持つかを整理したルール」であり、一般的に「ロール」と呼ばれるものと言えます。
ルールの例としてAWSの「職務機能のAWS管理ポリシー」を参照すると、「管理者 / 開発者パワーユーザー / 閲覧者専用ユーザー」などの役割を用意し、役割ごとの権限を定義したポリシーを作成しています。
この「役割と権限」のルールをまもるためにポリシー/ロールを使用します。ここで述べている役割をあたえられる「誰が」とは、操作をするユーザーだけではなく各種リソースにアクセスを行うAWSサービスなどの「もの」も指しますのでS3やLambdaも該当します。ポリシー設計のポイントで記載したアクセスケースでのアクセス元がその例です。
つまり、そもそもの話として「ユーザー」や「もの(サービスリソース)」にどのような許可を与え、どのようなリスクから保護する必要があるか、といったルール(役割と権限の関係)がきちんと整理されていないと、必要なポリシーを定義しようがありません。明確なルールがあってはじめて、ポイント1,2で書いたような仕様を踏まえた適切なポリシーが定義できるのです。
誰がどの範囲まで管理するのか、それがアカウント単位か、ネットワーク単位か、サービス単位なのか。各利用者が実行するタスク(AWS API処理)をどこまで許可するのか、参照だけか、削除も許可するか。他者が管理しているリソースを使いたい場合に、そのリソースの管理者と利用者の両者の合意が必要か、あるいは利用者は任意にリソースを使用してよいかなどのルールを整備しましょう。
まとめ
ポリシーの基本的な情報と、設計のポイントを述べてきました。繰り返しになりますが要点を記載します。
ポリシーとは
- アイデンティティやリソースにアタッチしてアクセス許可を定義するJSONドキュメント
- アクション実行のリクエスト内容とポリシー定義を評価してアクセス許可or拒否を判断
- 6つのタイプがある
ポリシー設計のポイント
- 同一アカウントかクロスアカウントか
- 明示的なDENYの必要性
- 職務機能設計
本記事ではAWSが提供するポリシー機能のごく一部にしか触れていませんが、この範囲だけでもシステム適用とその後の管理が大変であることは想像できると思います。しっかりしたルールを定めず場当たり的にポリシーを作成した結果、管理業務がどんどん煩雑化していく泥沼に陥らないように、ポリシー設計の初期段階からルールの明確化と標準化を心がけましょう。