IAMのポリシー書き方 json編

先日、初めてポリシーを設定したのですがjsonでの書き方をまとめている記事があまりなかったのでメモ。
ビジュアルエディタは使用しなかったのでその内容は入っておりません。

#公式ドキュメント
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies.html

#ポリシーとは
AWSにおける特定の操作を許可するか、禁止するかの設定です。
普通IAM単位で設定します。
全許可の場合コンソールからサーバーを削除とかもできてしまいますので、セキュリティ上非常に重要な設定になります。

#jsonで書く際の最小構成

```
{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Sid": "hoge",
        "Effect": "Allow",
        "Action": "*",
        "Resource": "*"
      }
     ]
}
```

コンソールから「ポリシー作成」を選択すると初めから入ってる記述+必須パラメータです。
Statementの中にjson形式で許可設定を書いていく形。

#パラメータ概要
記述例を公式ドキュメントから引用します。
許可設定の具体的な内容はドキュメント参照。

```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "FirstStatement",
      "Effect": "Allow",
      "Action": ["iam:ChangePassword"],
      "Resource": "*"
    },
    {
      "Sid": "SecondStatement",
      "Effect": "Allow",
      "Action": "s3:ListAllMyBuckets",
      "Resource": "*"
    },
    {
      "Sid": "ThirdStatement",
      "Effect": "Allow",
      "Action": [
        "s3:List*",
        "s3:Get*"
      ],
      "Resource": [
        "arn:aws:s3:::confidential-data",
        "arn:aws:s3:::confidential-data/*"
      ],
      "Condition": {"Bool": {"aws:MultiFactorAuthPresent": "true"}}
    }
  ]
}
```

`{}`で囲まれてる部分が一つの許可設定の塊。
（ドキュメント内では「ステートメント」と呼称されてます。）
必須パラメータは下記4つ。

|  |  |
|:-:|:-:|
| Sid  | ステートメントID。見る限り任意っぽいのでわかりやすい命名が必要  |
| Effect  | Allow / Deny<br>Allowを設定すると「許可」。Denyを設定すると「禁止」になります。  |
| Action  | 操作内容。詳しくは後述しますがサービスごとに内容が違います。  |
| Resource  | 操作対象？<br>これもサービスによって違うので一概には言えません。詳細は後述。  |

##Conditionについて
必須でないパラメータで、ここに書いた内容を満たす場合のみステートメントを適用します。
「MFAログインしてなければ全ての操作を禁止する」とかも可能。

##ワイルドカードについて
`*`はワイルドカードです。

```
"Resource": "*"
```

とすれば「全ての対象に適用」になりますし、

```
      "Action": [
        "s3:List*",
        "s3:Get*"
      ],
```

と設定すれば「S3のList、Get操作全てに適用」みたいなこともできます。

#Actionについて
「どのサービスのどの操作」を表す文字列を設定するのですが、

```
{サービス名を表すprefix}:{操作内容}
```

となっています。
「S3での操作全てに適用」なら

```
"Action": "s3:*",
```

とすればいいわけです。
Actionの一覧は

https://docs.aws.amazon.com/ja_jp/service-authorization/latest/reference/reference_policies_actions-resources-contextkeys.html

参照。
サービス固有のAction（CodeCommitにおけるpushとかS3におけるバケット作成とか）を含むかなりの数があります。
許可に組み込みたかったらとりあえずこちらを探すのが良さそうです。

#Resourceについて
Resource一覧も同様に上記リンクから確認できます。
見ればわかりますが、Actionほどの量はありません。
例えばCodeCommitならARNを指定できるだけです。

```
arn:${Partition}:codecommit:${Region}:${Account}:${RepositoryName}
```

「特定ユーザー」「特定リポジトリ」に対する許可設定を指定できます。
基本的な使い方をするにはこれで十分ですが、変わったことをやりたければ工夫が必要かも？

#作成したポリシーを組み込む際の注意点
##AWS管理ポリシーについて
AWSが用意してくれてるポリシーです。
詳しくは下記

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_managed-vs-inline.html

よく使うであろう許可設定が網羅されているので、ポリシーを作成する前にこちらを探すのが良いです。
IAMユーザーにしろグループにしろ複数のポリシーをアタッチできるので、組み込む際には

- 部分的にでもやりたいことをできるAWS管理ポリシーを探す
- 足りない部分は自分でポリシーを作成する
- 必要なポリシーを全てアタッチ

の手順でやると余計なポリシーが増えません。

##動作確認について
自分でテスト用のIAMを作ってやってもいいですが、シミュレータもあります。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_testing-policies.html

・MFAログインの有無
・アカウントID
・リソース
などをアクションごとに設定して挙動をチェックできるのでオススメ

##矛盾するステートメントがある場合の挙動

```
{
    "Version": "2012-10-17",
    "Statement": [
      {
        "Sid": "allAllow",
        "Effect": "Allow",
        "Action": "*",
        "Resource": "*"
      },
      {
        "Sid": "allDeny",
        "Effect": "Deny",
        "Action": "*",
        "Resource": "*"
      }
     ]
}
```

と明らかに矛盾する場合はどちらが優先されるか、ガッツリ決まっています。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_evaluation-logic.html

上記ドキュメントを見る限り、

>ポリシー内の明示的な拒否は、すべての許可に優先します。

ということなので上記の例ではallDenyが優先されます。
上記はかなりわかりやすい例ですが、仮に複数のポリシーをアタッチし、それぞれに同じアクションのAllow/Denyが混ざってたりすると非常にややこしくなります。
この場合、

- 同じアクションは同じポリシーにまとめる
- 不要なポリシーを外す

などで整理できそうです。
ポリシーの数はできるだけ少ない方がいいですね。