AWS IAMポリシーでのMFAの強制とポリシードキュメントの書き方について

# はじめに
AWSを運用していると、「`AWSマネジメントコンソール`を触れる人を増やしたいけど、`MFA`はセキュリティの観点から最低限設定して欲しい」とか「`IAMユーザ`ごとに権限を適正に設定したい」という要件が出てくると思います。
検索してもこの辺の内容に触れた記事があまり無いので、最近触ってみて困ったこの辺の内容について触れたいと思います。

# MFAについて

## なぜMFAを設定するのか

(そんな会社そうそうないと思いますが)特に社内ルールを定めていない場合、IAMユーザを発行された人が**`MFA`を設定するかしないかは本人のセキュリティ意識に依存している**部分が強いと思います。
`Administrator`権限を付与されていても`MFA`を設定していない人がたまに(ゲフンゲフン

`ID`と`パスワード`だけの運用であれば、もし同じ`パスワード`を他社サービスで使っていた場合、他社サービスから漏洩する可能性があります。
その場合、以下の様なリスクがあります。

* アカウントを乗っ取られ高額EC2インスタンスを起動されてビットコインマイニングなどに利用されて数百万の支払いが発生する
* 他社のサイトへの不正アクセスの踏み台として使われるなどする

`MFA`を設定しておくと、**もし`ID`と`パスワード`が漏洩してもログインを防げる**ので安心です。

## MFAを強制するIAMポリシー

### 最低限MFAを強制させるIAMポリシー

基本的に以下の設定の様に`Condition`にMFAのパラメータ判定を入れるだけでMFAを強制できるようになります。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ForceSettingOFMFASample",
            "Effect": "Allow or Deny",
            "Action": "許可/拒否させたいAction",
            "Resource": "許可/拒否させたいResource",
            "Condition": {
                "Bool": {
                    "aws:MultiFactorAuthPresent": "true or false"
                }
            }
        }
    ]
}
```

しかし、こちらの**`IAMポリシー`だけ**では設定が不十分です。
こちらの**`IAMポリシー`だけ**では、**ログインした人自身で`MFA`の編集ができない**ため、管理が煩雑になってしまいます。

そこで、もう少し色々できるように権限を付与する`IAMポリシー`を調べたところ、`AWS ドキュメント`にある通り以下の設定にした方がより取り回しが良かったです。
(以前はこのドキュメント無かった気がするんですがいつからあるんだろう:thinking:)

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowListActions",
            "Effect": "Allow",
            "Action": [
                "iam:ListUsers",
                "iam:ListVirtualMFADevices"
            ],
            "Resource": "*"
        },
        {
            "Sid": "AllowIndividualUserToListOnlyTheirOwnMFA",
            "Effect": "Allow",
            "Action": [
                "iam:ListMFADevices"
            ],
            "Resource": [
                "arn:aws:iam::*:mfa/*",
                "arn:aws:iam::*:user/${aws:username}"
            ]
        },
        {
            "Sid": "AllowIndividualUserToManageTheirOwnMFA",
            "Effect": "Allow",
            "Action": [
                "iam:CreateVirtualMFADevice",
                "iam:DeleteVirtualMFADevice",
                "iam:EnableMFADevice",
                "iam:ResyncMFADevice"
            ],
            "Resource": [
                "arn:aws:iam::*:mfa/${aws:username}",
                "arn:aws:iam::*:user/${aws:username}"
            ]
        },
        {
            "Sid": "AllowIndividualUserToDeactivateOnlyTheirOwnMFAOnlyWhenUsingMFA",
            "Effect": "Allow",
            "Action": [
                "iam:DeactivateMFADevice"
            ],
            "Resource": [
                "arn:aws:iam::*:mfa/${aws:username}",
                "arn:aws:iam::*:user/${aws:username}"
            ],
            "Condition": {
                "Bool": {
                    "aws:MultiFactorAuthPresent": "true"
                }
            }
        },
        {
            "Sid": "BlockMostAccessUnlessSignedInWithMFA",
            "Effect": "Deny",
            "NotAction": [
                "iam:CreateVirtualMFADevice",
                "iam:EnableMFADevice",
                "iam:ListMFADevices",
                "iam:ListUsers",
                "iam:ListVirtualMFADevices",
                "iam:ResyncMFADevice"
            ],
            "Resource": "*",
            "Condition": {
                "BoolIfExists": {
                    "aws:MultiFactorAuthPresent": "false"
                }
            }
        }
    ]
}
```

**出典: IAM: IAM ユーザーに MFA デバイスの自己管理を許可する**
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_examples_iam_mfa-selfmanage.html

## 各Sidごとの解説

### AllowListActions

各`IAMユーザ`と仮想MFAデバイスのリスト表示を許可する。
『えっ？他の`IAMユーザ`の`MFAデバイス`のリスト表示許可するの？』と思うかもしれませんが、`IAMユーザ`の一覧ページに`MFAデバイス`の列があるのでそこで必要になります。

### AllowIndividualUserToListOnlyTheirOwnMFA

自信の`MFAデバイス`を`認証情報`タブで表示するために設定していると思われます。

### AllowIndividualUserToManageTheirOwnMFA

自身の`IAMユーザ`に限り`MFAデバイス`の追加・削除・有効化・再同期を許可する。

### AllowIndividualUserToDeactivateOnlyTheirOwnMFAOnlyWhenUsingMFA

自身の`仮想MFAデバイス`が有効な場合に限り、`仮想MFAデバイス`の無効化を許可する。

### BlockMostAccessUnlessSignedInWithMFA

`MFAデバイス`が有効でないとき、`MFAデバイスの`追加に関する操作以外を拒否する。

## スイッチロールで使う場合

MFAが有効になっていない場合に他の`AWSアカウント`へのスイッチを拒否する設定も行えます。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowAssumeRoleIFMFAIsEnableSample",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::123456789100:root"
            },
            "Action": "sts:AssumeRole",
            "Condition": {
                "Bool": {
                    "aws:MultiFactorAuthPresent": "true"
                }
            }
        }
    ]
}
```

# IAMポリシーの適正な設定方法について

## IAMポリシーのポリシードキュメントに関する公式リファレンス

**※2021/10/12 追記**

現在は以下の通りAWSの公式リファレンスが充実してきているようです。

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

~~この記事を書いている時点で、`AWS`の公式ドキュメントでは**IAMポリシーに対する明確なリファレンスはありません。**
`ポリシードキュメントのjsonの書き方`などはドキュメントがありますが、**どのAWSサービスに対して、どの様に設定すればいいか**が解らない状態です。~~

## IAMポリシーの設定について

ドキュメントが無いなら参照にするものは何かというと、`AWS CLI`のドキュメントを参考にそれっぽく書くようにしています。
https://docs.aws.amazon.com/cli/latest/reference/index.html#cli-aws

各種サービスの権限は、例えば参照系の場合はプリフィクスとして`get`,`describe`,`list`などが付与されていることがわかります。
そこから、**参照のみ許可**したい場合はこれらの権限をつけるといった感じです。

## IAMポリシーのポリシードキュメントに関する非公式リファレンス

**2021/10/12 追記**

現在は `The official AWS documentation has greatly improved since the beginning of this project. Check it out!` との記載が追加されており、公式リファレンスに誘導しているようです。
公式リファレンスを参照しましょう。

~~記事を書きながら改めて調べていると、非公式ではあるものの有志で作られた`IAMポリシー`に関するサイトが有りました。
この辺参考にしてみると良いかもしれませんね。~~

~~https://iam.cloudonaut.io/~~

# おわりに

一旦覚え書き的にまとめましたが、`IAMポリシー`書くとき、色々悩ましいことが発生するので今後もう少し肉付けするかもしれません。