AWS IAMとその他各種ポリシーの評価ロジックを整理しよう

AWSにおける認証認可のコアとなる[IAM](https://aws.amazon.com/jp/iam/)。
そしてIAMと絡んで「認可」のAllow/Denyを決定する各種ポリシーたち。

言うまでもないことですが、ワークロードを構築し運用する上で、認証認可はとても重要な分野。
最近、組織内の勉強会で参加者の皆さんと会話する中で、あらためてこのへんの理解を自分自身でも整理しておくべきと感じました。

私が「これはきっちり整理しておきたい」というものをリストアップした形になるので、読者の皆さんからすると散漫だったり物足りなかったりするかもしれませんが、ご容赦ください。

# IAMとは

Identity and Access Management（IDとアクセス管理）。
AWSが提供するクラウド基盤において認証と認可を司るコアサービス。
リージョンに属さないグローバルサービスで、その機能の中心部はバージニア北部リージョンに存在。

# IAMポリシーとIAM**の関係

* IAMポリシーは __アクション__（例：EC2をどうするこうする、CloudWatchをどうするこうする） __の許可・拒否の定義__ 。JSON形式で記述されたモノ。
* IAMポリシーはIAMユーザー、グループ、ロールに関連付けることで、それらに権限を付与する。
* IAMポリシーで定義された許可・拒否は、他のポリシーたちとともに評価されて、結果的にIAMユーザーやグループやロールが特定のアクションを実行できるかどうかを決める。
* IAMポリシーのうち __インラインポリシー__ は、特定のIAMユーザー、グループ、ロールに、直接記述（定義）されたポリシー。特定の「このユーザー」（あるいはグループやロール）に固有の権限であって、他のユーザー（あるいはグループやロール）に使いまわしたくない権限で利用。
* IAMポリシーのうち __管理ポリシー__ は、その逆で、一定の汎用性のある権限設定を記述（定義）するために利用。
* IAMポリシーと他のポリシーを区別するとき、 ここまで述べてきたIAMポリシーは __IDベース（アイデンティティベース）のポリシー__ と呼ばれる。

# IAMロールの役割

* __IAMの提供するアイデンティティへの権限付与__ ─ IAMユーザーが IAMロールを引き受けると、当該のIAMユーザーにはそのロールで記述された許可・拒否が適用される。ロールの引き受け（AssumeRole。Switch Roleとも）はAWSアカウントを跨いで行うこともできる →マルチアカウント構成の基礎
* __AWSリソースへの権限付与__ ─ AWSリソースが IAMロールを引き受けると、当該のAWSリソースにはそのロールで記述された許可・拒否が適用される（例：EC2インスタンスにロールを引き受けると、当該インスタンス上で実行されるプログラムに対して、他のAWSリソースに対するアクションの許可・拒否が適用される）
* __IDフェデレーションにおける権限制御__ ─ IDフェデレーションされたユーザー（≠ AWS IAMユーザー）は、フェデレーションの設定であらかじめ指定されたIAMロールを引き受けることによって、AWSリソースに対するアクションの許可・拒否の適用をうける

# その他のポリシーたち

* __リソースベースのポリシー__ ─ S3バケットをはじめとした、アクションの対象となる側（≠ アクションの実行主体の側）で指定するポリシー。当該リソースに対して「誰が何をできる／できない」を制御する。後述の評価ロジックにおいてやや特殊な評価を受ける。IAMロールの「信頼関係」はIAMロールに付与されたリソースベースポリシーの一例。
* __SCP（サービスコントロールポリシー）__ ─ AWS Organizationsの「組織」とそこに属するAWSアカウントに対して ガードレールを設定するためのポリシー。ガードレールはそれ自体では許可（Allow）を与えず、他のポリシーによる許可の上限を定める。
* __アクセス許可の境界（パーミッションバウンダリー）__ ─ IAMユーザーやロールに対して ガードレールを設定するためのポリシー。
* __セッションポリシー__ ─ ロールの引き受け時（フェデレーションされたユーザーによるロールの引き受けなど）に CLIやAPIを通じて都度設定するもの。ガードレールを設定するためのポリシー。

リソースベースポリシーで、プリンシパルにユーザーやロールのARNを指定した場合：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/591902f6-5e9b-f4db-fc18-c143da956d42.png)

リソースベースポリシーで、プリンシパルにセッションのARNを指定した場合：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/5401955b-1684-8bab-e071-2d3f4f3dbc48.png)

アクセス許可の境界で、ガードレールを設定した場合：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/6e00d310-503c-43f1-a60a-a1d7069fc1d2.png)
（いずれの図も2023/08/03現在、 [Policies and permissions in IAM](https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies.html#policies_session) に掲載されている図をもとに作成）

# ポリシーの評価ロジック

各種のポリシーの評価ロジックは以下の通り：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/17a496c6-b6cf-c5bf-fb9d-b62529ede3e6.png)
（2023/08/03現在、[ポリシーの評価論理](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_evaluation-logic.html)に掲載されている図をもとに作成）

特筆すべきこととして
* なによりも拒否（Deny）は優先されること。これは許可・拒否の記述が同一ポリシー内にあるかどうかに関わらず、また許可・拒否の記述されたポリシーの種別に関わらず、 __とにかくどこかに明示的に拒否の記述があれば、他では許可（Allow）されていても評価結果は拒否__ となる。 → 明示的な拒否（Explicit Deny）
* したがって、基本的には「明示的な拒否、しかるのち明示的な許可、いずれにも該当しないなら暗黙的な拒否」という順序で評価が決まる。 → 暗黙的な拒否（Implicit Deny）
* ただし、SCPやアクセス許可の境界といった __ガードレールが許可の上限を定めている__  （ガードレールはそれ自体では許可を与えず、他のポリシーによる許可の上限を定める）。
* また、リソースベースのポリシーによる許可（Allow）は特殊な扱いを受けており、図をみるとIDベースのポリシーやアクセス許可の境界などに先立って評価され、ここで許可が決まると後続のポリシーは評価が端折られることが読み取れる。これにより __「[アクセス権限の境界で明示的に許可していないアクションでも条件次第で実行できる](https://dev.classmethod.jp/articles/iam-policies-evaluation-logic-rikai/)」__ ということも起こる。