イラストで理解するIAMポリシー

## はじめに
今回は分かったふりをしながら使っていたIAMポリシーについて勉強したので記事にしてみました。

## ポリシーってなんのためにあるの
いきなりですが、
「誰が」「どのリソースの」「何に対して」「どんな操作を」「許可 or 拒否する」
ポリシーの考え方はこれだけです

そして、作ったポリシーを「何か」に割り当てるだけ、です。
その「何か」には
- アイデンティティ
- リソース

があります。

### アイデンティティ

アイデンティティというのはこんな感じです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880800/10e29496-76d3-113e-1aeb-43fd5b415e45.png)
IAMユーザーやIAMロールに割り当てます。
このポリシーをアイデンティティベースのポリシーと言います。

### リソース

リソースはAWSの各リソースですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880800/50dee6e5-f900-c0c1-6245-a3bc502137a3.png)
LambdaやS3に割り当てます。
このポリシーをリソースベースのポリシーと言います。

この二つのポリシーには少し違いがありますが、ポリシーに対する考え方的な部分ははじめに書いた通り
「誰が」「どのリソースの」「何に対して」「どんな操作を」「許可 or 拒否する」
だけです。

### ポリシーの書き方

上記の考え方をもとにポリシーを書く際は
- 誰が：Principal
- どのAWSリソースの：Actionの左側
- 何に対して：Resource
- どんな操作：Actionの右側
- 許可 or 拒否：Effect

このようになります。
細かい設定もありますが、まずはこれを覚えていれば概要は把握できるはずです。

## ポリシーの割り当て方

では、ポリシーの何がややこしいのかイラストを交えながら見ていきましょう。
今回の登場人物は

- ジョン
- Lambda
- S3

です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880800/094d7cb3-c882-2e57-4340-4a02f674f0b1.png)


ジョン(IAMユーザー)とLambdaはそれぞれ、S3のオブジェクトを取得したいと思っています。

この時、誰にどんなポリシーを割り当てればいいでしょうか？
私はここがIAMポリシーでつまずく部分でした。

いくつかパターンがあるので分解しながら見ていきましょう。

パターン１：ジョンにS3を操作するポリシーを割り当てる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880800/5de3f5fe-484e-9c40-ef11-dbf7316bcc22.png)
パターン２：S3にジョンとLambdaから操作できるポリシーを割り当てる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880800/3eb9076a-850e-e123-2b01-50084a4c3c75.png)
パターン３：LambdaにS3を操作するポリシーを割り当てる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880800/9343a7e9-492e-450d-2e6e-652671c7a57d.png)

ざっくり分解するとこうなります。

先に軽く触れますが、この「パターン３」は正確ではないです。
正確には「LambdaにS3を操作できるポリシーを割り当てたロールを割り当てる」です。
詳細は後述します。

それを踏まえて再度、全体像をあら表すとこうなります
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880800/272adb8f-0274-75a4-0364-d093c555fb4d.png)

### ジョンのアイデンティティベースのポリシー

ではまず、ジョンがS3のhtmlバケットを取得するポリシーを見ていきます。
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::html/*"
        }
    ]
}

```

これは単純ですね。
- Actionの左側：S3
- Resource：S3のhtmlオブジェクト
- Actionの右側：GetObject（オブジェクトを取得する）
- Effect：Allow（許可する）

です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880800/61ad6fe7-a36d-2b7d-1b48-f22680a4ee35.png)

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

次はS3がLambdaとジョンからのアクセスを許可するポリシーです

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "arn:aws:iam::{ACCOUNT_ID}:user/John",
                    "arn:aws:iam::{ACCOUNT_ID}:role/service-role/{lambdaに割り当てたrole名}"
                ]
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::html/*"
        }
    ]
}
```
基本的な考え方はジョンに対するポリシーと同じなので省略します。

しかし、このリソースベースのポリシーにはアイデンティティベースのポリシーにはなかった「Principal」があります。
Principalは翻訳すると「主体」や「主要」という意味です。
「誰が」の部分です。

これは、アイデンティティベースのポリシーは対象となる相手が決まっているのでPrincipalは必要ありません。
ジョンに割り当てるポリシーにわざわざ「これはジョンのポリシーです」と書く必要はありませんね。

しかし、リソースベースのポリシーは主体がS3自身ではなく別のリソースのため、Principalを書く必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880800/e01df464-e551-e4da-4f92-a70558ed8dde.png)

### Lambdaにロールを割り当てる

では、最後にLambdaです。

先に書いた通り、Lambdaに直接S3を操作するためのポリシーを割り当てることはできません。
ポリシーを作成して、一旦IAMロールにポリシーを割り当てる必要があります。

::: note info
Lambdaにもリソースベースのポリシーは存在しますが、それは別のリソースやユーザーがLambdaを操作する場合に使用します。
自分に対しての「許可」「拒否」はできるけど、他のリソースに対しての「許可」「拒否」はできない、ということです。
:::

少し前置きが長くなってしまいましたが、Lambda用にIAMロールに割り当てるポリシーを見てみましょう

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::HTML/*"
        }
    ]
}
```

このポリシーはロールに割り当てるので「Principal」がありません。
ロールに割り当てるので、これはアイデンティティベースのポリシーです。

LambdaからS3を操作するには、このポリシーを割り当てたロールをLambdaに割り当てる必要があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/880800/a2b6cc6f-d890-018e-982d-12c5c1a13db1.png)

### 信頼ポリシー

上記のポリシーで{アカウントID}というのを指定していました。

もし、これを他のアカウントのIDにするとどうなるでしょう？
そうです、アカウントを跨いで操作を実行することができます。

しかし、これには信頼ポリシーというものを使って権限の付与を行う必要があります。

これに関しては私の説明の100万倍わかりやすい記事があったので、こちらを参考にして下さい。本当にわかりやすいです。
参考：https://dev.classmethod.jp/articles/iam-role-passrole-assumerole/

## まとめ

ポリシーはリソース同士を組み合わせる時には必ずと言ってもいいほど使われます。
よく触る設定なので、なんとなく分かっているフリをしていましたが、実際に勉強してみると理解できていない部分がありました。 
これを機に、よくわからず作成した無駄なカスタムポリシーを削除して綺麗なポリシー管理をしていきたいと思います。