銀魂キャラを使ってIAMポリシーを解説する

クマ松です。

突然ですが、S3バケットのバケットポリシーの設定を誤り、バケットをロックアウトさせてしまった経験はありますでしょうか。
私はあります。

今回はAWSを勉強したての頃に誰もが一度躓くであろうポリシーの話を、銀魂のキャラを使って説明しようと思います。
わかっているようでわからない、<font color="Red">アイデンティティベースのポリシー</font>と<font color="BlueViolet">リソースベースのポリシー</font>のお話です。

※ちなみにバケットポリシーの設定をミスしたらこう↓↓なります。
こうなったらIAMユーザでは何もできないので、ルートユーザにバケットポリシーを消してもらうしかありません。
![S3バケット見れない.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307047/eeb9fd5c-af6d-7cc0-c51e-1cc75e5e1908.png)
![S3バケット見れない2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307047/3ed9701e-0d7e-b5d0-54e7-46ecbdfe505d.png)



IAMユーザにAdministratorAccessを付与して作業していると、AWSコンソール画面で何でも出来てしまうと錯覚してしまいます。
しかし実際はAdmin権限を持ったIAMユーザも最強というわけではなく、AWSサービスの設定次第では**設定変更はおろかリソースの閲覧すら**できなくなります。


#アイデンティティベースのポリシー
##IAMアイデンティティって何？
AWSのホワイトペーパーに「IAMアイデンティティ」という単語が出てきます。
IAMの勉強をしていた頃この言葉が何を指すのかよくわかっていなかったのですが、**IAMユーザ・IAMグループ・IAMロールの総称**です。

|  IAMの用語  |  意味  |
| ---- | ---- |
|  IAMユーザ  |  AWSアカウントにログインしたりAWSサービスを利用する為に必要な名前と認証情報。  |
|  IAMグループ  |  1人以上のIAMユーザを論理的にまとめたグループ。 |
|  IAMロール  |  AWSサービス（EC2・Lambda）等に、異なるAWSサービス（S3・DynamoDB等）を操作させたい場合に付与するもの。 |

##IAMポリシーって何？
IAMユーザ・IAMグループ・IAMロールというIAMアイデンティティは、それ単体では何の操作権限もありません。
私たちが普段コンソールで色々とAWSサービスを操作できるのは、そうできるようなIAMポリシーをIAMユーザにアタッチしているからです。

IAMユーザ・IAMグループ・IAMロールは、IAMポリシーがアタッチされていないと何も出来ませんし、何にもアタッチされていないIAMポリシーは無価値な存在です。

###3つのIAMポリシー
IAMポリシーには3つの種類があります。

|  IAMポリシー  |  意味  |
| ---- | ---- |
|  AWS管理ポリシー  |  様々なユースケースを想定してAWSが準備してくれたIAMポリシー。  |
|  ユーザ管理ポリシー  |  AWSではなく、ユーザが用途に応じて作ったIAMポリシー。<br>**複数のIAMアイデンティティにアタッチできる。**|
|  インラインポリシー  |  AWSではなく、ユーザが用途に応じて作ったIAMポリシー。<br>**複数のIAMアイデンティティにアタッチできない。**<br>単体のIAMアイデンティティに組み込む**刺青**のイメージ。|

AWS管理ポリシーとユーザ管理ポリシーは、IAMポリシーのコンソール画面で確認が出来ます。
AWS管理ポリシーはポリシー名の左側に**黄色い四角いマーク**がつきます。ユーザ管理ポリシーにはつきません。
またこの画面でインラインポリシーを確認することは出来ません。
![AWS管理ポリシー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307047/d6b08b43-ca39-e85b-3dce-3aeb68f06184.png)

**ユーザ管理ポリシー**がアタッチされたIAMロールを見てみると、**ポリシー名がリンクになっている**ことが分かります。
このリンクを押すとポリシー一覧の画面に飛び、ポリシーの変更やポリシーを他のIAMアイデンティティにアタッチすることが出来ます。

![ポリシー名リンク.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307047/10f087f8-58c5-148d-6ec6-4ad55c5b2a30.png)

一方**インラインポリシー**がアタッチされたIAMロールを見てみると、**ポリシー名がリンクになっていない**ことがわかります。
これはポリシーの変更が**このIAMロールの画面でしか出来ない**ことを意味します。
以下のfirehose_delivery_roleはこのIAMロールにアタッチされていて、他のIAMアイデンティティにアタッチすることは出来ません。

![インラインポリシー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307047/c62eb847-88c5-bde6-495a-f696e93f9559.png)

#リソースベースのポリシー

IAMには<font color="Red">アイデンティティベースのポリシー</font>以外にも<font color="BlueViolet">リソースベースのポリシー</font>があります。
<font color="BlueViolet">リソースベースのポリシー</font>とは、**そのリソースの利用許可・閲覧許可をリソース自身で定義できるポリシー**のことです。
リソース自体に埋め込むポリシーということでこちらのポリシーもインラインポリシーの1つです。

例えるなら武士は幕府から帯刀が許されていたが、<font color="Blue">妖刀村真紗を抜刀し使いこなせたのは土方十四郎だけだった</font>。
そんなイメージです。刀も主を選びます。

##Principalという項目

リソースベースポリシーを利用できるAWSリソースが**誰に自分自身を使わせたいか**を決めるためには、自分に組み込まれたポリシー内に**Principal**という項目を付与します。
このPrincipalですが、<font color="Red">アイデンティティベースのポリシーには設定できない</font>項目です。

|  ポリシー  |  "誰にリソースを使わせたいか"の定義方法  |
| ---- | ---- |
|  アイデンティティベースのポリシー  |  ポリシーをIAMアイデンティティにアタッチ  |
|  リソースベースのポリシー  | ポリシー内のPrincipal項目で指定 |


##リソースベースポリシーを利用できるAWSサービス
全てのサービスがリソースベースポリシーを利用して利用者を制限できるわけではありません。
どのサービスがリソースベースポリシーを利用できるかは、以下のサイトから確認できます。

以下の表を見ると、S3はリソースベースポリシーを利用でき、ESは利用できないことが分かります。
![リソースベース.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307047/42866006-c39a-caf0-71f9-061aa32f2af4.png)

Storageサービス以外のIAMを使った認証・認可の仕様についてはユーザガイドをご確認ください。
出典：[AWS services that work with IAM AWS UserGuide](https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_aws-services-that-work-with-iam.html)

#明示的Deny・明示的Allow・暗黙的Denyを説明する為の例え話

AWS SAA受験の為にIAM関連の勉強をしていると、**明示的Deny・明示的Allow・暗黙的Deny**という用語に出くわします。
そもそも勉強したての頃は覚えることが多くて、Resource・Effect・Action…何が何だか…
とりあえず「明示的Deny>明示的Allow>暗黙的Deny」と覚えていれば試験は通りますが、これがどういうことなのかを銀魂を使って説明していきます。

##前提
<font color="Red">アイデンティティベースのポリシー</font>と<font color="BlueViolet">リソースベースのポリシー</font>を例え話を使って説明しますが、ここからは**IAMアイデンティティとリソースは同一AWSアカウント内にある**という前提で読んでください。

##キャラにアタッチするポリシーの説明
まず土方十四郎にアタッチする<font color="Red">IAMポリシー（アイデンティティベースのポリシー）</font>と、妖刀村真紗に組み込む<font color="BlueViolet">リソースベースポリシー</font>を定義します。

<font color="Blue">土方十四郎</font>はあらゆる刀を使うことが許され、タバコも吸うことを許可されています。
一方で村真紗は土方以外の人間が帯刀することも使うことも出来ないです。

![銀さんは使えるか.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307047/6cf17078-1a39-a370-1773-b8a978d6f01c.png)

<font color="LightSlateGray">坂田銀時</font>は主人公なのでAdministratorAccessを付与します。
![銀さん.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307047/b65e469a-e6cb-8a13-5286-230617e50bfb.png)


##明示的Deny ~銀さんは村真紗を使えるか~

ではAdministratorAccessを付与された<font color="LightSlateGray">坂田銀時</font>は村真紗を使うことが出来るでしょうか。
答えは**NO**です。
これが**明示的Deny＞明示的Allow**と呼ばれる評価論理による制御です。
<font color="Red">アイデンティティベースのポリシー</font>か<font color="BlueViolet">リソースベースのポリシー</font>のどちらかでDenyが書かれていたら<font color="Red">Denyが優先されます</font>。

この理解が無いと、冒頭のS3バケットのようなミスが発生します。
リソースベースポリシーのDeny設定は細心の注意を払って設定しなくてはなりません。

##明示的Allow ~洞爺湖の仙人の木刀を追加~

では銀さんの愛刀**洞爺湖の仙人からもらった木刀**に以下のような<font color="BlueViolet">リソースベースポリシー</font>を設定してみましょう。
洞爺湖の木刀は「帯刀・人を守るために使う」ことに加えて**醤油差し**としての機能を持っています。
一方で、**「人を殺すために使う」ことは明示していません**。
またPrincipalには<font color="LightSlateGray">坂田銀時</font>と<font color="Blue">土方十四郎</font>を設定しています。

![洞爺湖の仙人の木刀.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307047/7865e558-df28-5441-4d1f-9577174386f8.png)


では問題です。


1. <font color="LightSlateGray">坂田銀時</font>は洞爺湖の仙人の木刀を**「人を殺すために使う」**目的で利用できますか
1. <font color="Blue">土方十四郎</font>は洞爺湖の仙人の木刀を**「刃先から醤油を垂らす」**目的で利用できますか

正解は**どちらもYes**です。
これが<font color="Red">アイデンティティベースのポリシー</font>と<font color="BlueViolet">リソースベースポリシー</font>の評価理論における明示的Allow＞暗黙的Denyの制御によるものです。
皆さんがAdministrator権限を持つIAMユーザで、特にバケットポリシーの設定が無いS3の設定変更をできるのはこの評価論理の為です。

<font color="Red">アイデンティティベースのポリシー</font>と<font color="BlueViolet">リソースベースポリシー</font>にAllowが書かれている場合、**双方に記載されたAllowが評価対象となり、両ポリシーの和集合で制御が認可されます**※。

上の例で言うと<font color="LightSlateGray">坂田銀時</font>のAdministratorの「"Action":"\*"」は全ての動作が含まれます。
そして「"Resource":"\*"」には全ての刀が含まれることになります。
よって<font color="LightSlateGray">坂田銀時</font>は洞爺湖の木刀を「人を殺すために使う」ことが出来るのです。

<font color="Blue">土方十四郎</font>が洞爺湖の仙人の木刀を「刃先から醤油を垂らす」目的で利用できるのも同じ理由です。

<font color="Blue">土方十四郎</font>のActionには「刃先から醤油を垂らす」がなく、**暗黙的にDeny**されています。
しかし洞爺湖の仙人の木刀側では<font color="Blue">土方十四郎</font>が「刃先から醤油を垂らす」目的で利用することを明示的にAllowしています。
よって<font color="Blue">土方十四郎</font>は、彼自身が意図しなかったとしても洞爺湖の木刀で刃先から醤油を垂らして卵かけご飯に醤油をかけることができます。

※あるIAMアイデンティティが異なるAWSアカウントのリソースにアクセスする場合や、AWS OrganizationsのService Control Policyが掛かっている場合等は、勝手が変わってきます。SAPやSecurity Specialtyの試験ではむしろこのような条件下でのIAMに関する知識が問われるますので注意してください。

#S3バケットで確認
本当に自分自身のIAMユーザに権限が無くても、リソースを操作出来てしまうんでしょうか。
S3バケットとIAMユーザを使って検証します。

##S3バケットポリシー
パスワードの変更権限のIAMポリシーをアタッチしたIAMユーザ「nobody」を作成します。
Resourceにはバケット名を設定し、EffectにAllow、Principalにnobodyを加えます。

![S3バケットポリシー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307047/a8221736-83fb-3707-ef7b-6800819dd5c4.png)

##バケット一覧では閲覧できない
nobodyでログインしてバケットの一覧を表示しようとしましたが、該当のバケットは表示されませんでした。

上記のバケットポリシーの設定の感じから、testバケットのみ表示されても良さそうなところですが実は現時点で一部のS3バケットのみGUIで表示することはできません。

ですのでtestバケット以外を閲覧する権利の無いnobodyは以下のようなエラーが表示されます。

![itirannバケット一覧.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307047/8aa2a9fa-4139-7832-85fe-dcece8ad4b89.png)

##バケットのURLを使って直接アクセス
ではnobodyはtestバケットに対して何もできないのかというと、そういうわけではありません。

仕様上バケット一覧から個々のバケット名のリンクを押す形でバケットの詳細画面に飛ぶことはできませんが、飛ぶためのURLさえ分かっていれば、ブラウザにURLを打ち込んでバケットの詳細画面に飛ぶことが出来ます。

※URLはこんな感じです。
https://s3.console.aws.amazon.com/s3/buckets/test-************?region=ap-northeast-1&tab=objects

![S3バケット.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307047/651a46bb-9fb1-08bb-2bcc-dbf3d78a56ef.png)

##バケットに対してオブジェクトをアップロード
この画面まで来れれば、オブジェクトのアップロードが出来ます。

![オブジェクトアップロード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/307047/f1045347-002e-a3ee-f248-e62767afa0e9.png)


以上です。