【AWS IAM】MFA設定していないユーザーの権限を制限する。

# このページの想定読者
- AWSアカウントの管理者
# このページの目的
- 管理しているAWSアカウントで、IAMユーザーを払い出した時に、MFA設定をしてくれないユーザーの権限を制限するためのメモ
# 概要
- IAMポリシーでMFAが設定されているかどうかを判定する
- 判定結果によって権限を有効/無効にする
- 「MFAを設定していない場合はMFA設定以外の操作ができないようにする」と「MFA設定をしていない場合は限定的な権限(例えばReadOnlyAccess)にする」の2パターン記載する
# 詳細
## MFAを設定していない場合はMFA設定以外の操作ができないようにする
AWS公式がIAMポリシーを公開している。
[IAM: IAM ユーザーに MFA デバイスの自己管理を許可する](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_examples_iam_mfa-selfmanage.html)

▼ポリシー
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowListActions",
            "Effect": "Allow",
            "Action": [
                "iam:ListUsers",
                "iam:ListVirtualMFADevices"
            ],
            "Resource": "*"
        },
        {
            "Sid": "AllowUserToCreateVirtualMFADevice",
            "Effect": "Allow",
            "Action": [
                "iam:CreateVirtualMFADevice"
            ],
            "Resource": "arn:aws:iam::*:mfa/*"
        },
        {
            "Sid": "AllowUserToManageTheirOwnMFA",
            "Effect": "Allow",
            "Action": [
                "iam:EnableMFADevice",
                "iam:GetMFADevice",
                "iam:ListMFADevices",
                "iam:ResyncMFADevice"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowUserToDeactivateTheirOwnMFAOnlyWhenUsingMFA",
            "Effect": "Allow",
            "Action": [
                "iam:DeactivateMFADevice"
            ],
            "Resource": [
                "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ユーザーグループ(例えばmfa-group)を作成し、払い出すIAMユーザーに対して設定すれば良いだろう。
## MFA設定をしていない場合は限定的な権限にする
今回は、「MFA設定をしていない場合はReadOnlyAccess、している場合はAdministratorAccess」とする。
すべてのIAMユーザーに対して一律にAdmin権限与えるのは問題だと思うが、ここではそれらはスコープ外とするため、実際の要件に合わせてご検討願いたし。
以下のようにポリシーを付与したIAMユーザーグループを作成する。
- ReadOnlyAccess(AWSのマネージドポリシー)
- MFAが設定されている場合AdministratorAccess(独自)
- MFA設定許可(独自)


当初、「MFA設定をしていなければReadOnlyAccess」というポリシーを作れないかと試行錯誤しましたが、カスタムポリシーの文字数制限に引っかかってしまうため、上記のように作成することになりました。
(もし、「MFA設定がされている場合は、ある限定的なカスタムポリシーで許可されている操作だけをできるようにする、MFA設定がされていない場合は、MFA設定の操作以外拒否する」というような要件の場合は、ポリシー１つで足ります。)

▼MFAが設定されている場合AdministratorAccess(独自)
```
{
  "Version" : "2012-10-17",
  "Statement" : [
    {
      "Effect" : "Allow",
      "Action" : "*",
      "Resource" : "*",
      "Condition": {
        "BoolIfExists": {
          "aws:MultiFactorAuthPresent": "true"
        }
      }
    }
  ]
}
```
AWS公式の[AdministratorAccessポリシーページ](https://docs.aws.amazon.com/ja_jp/aws-managed-policy/latest/reference/AdministratorAccess.html)に、Conditionキーを足したもの。
判定をtrueにしているので、MFAが設定されている場合は、ReadOnlyAccessに加えてAdministratorAccessが許可される。

▼MFA設定許可(独自)
```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowListActions",
            "Effect": "Allow",
            "Action": [
                "iam:ListUsers",
                "iam:ListVirtualMFADevices"
            ],
            "Resource": "*"
        },
        {
            "Sid": "AllowUserToCreateVirtualMFADevice",
            "Effect": "Allow",
            "Action": [
                "iam:CreateVirtualMFADevice"
            ],
            "Resource": "arn:aws:iam::*:mfa/*"
        },
        {
            "Sid": "AllowUserToManageTheirOwnMFA",
            "Effect": "Allow",
            "Action": [
                "iam:EnableMFADevice",
                "iam:GetMFADevice",
                "iam:ListMFADevices",
                "iam:ResyncMFADevice"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowUserToDeactivateTheirOwnMFAOnlyWhenUsingMFA",
            "Effect": "Allow",
            "Action": [
                "iam:DeactivateMFADevice"
            ],
            "Resource": [
                "arn:aws:iam::*:user/${aws:username}"
            ],
            "Condition": {
                "Bool": {
                    "aws:MultiFactorAuthPresent": "true"
                }
            }
        }
    ]
}
```
AWS公式のMFA設定ポリシーから、MFA設定がされていない場合MFA設定以外の操作を禁止する、という箇所を削除したポリシー。
ReadOnlyAccessにはMFA設定許可の項目が無かったように見えたので、念の為付与しているが、もしかしたら必要ないかもしれない。
検証が必要ではあるが、実運用では問題ない。

以上です。