【AWS】IAMユーザーのMFAの設定をマストにする

# 概要
* AWS IAMのドキュメントのチュートリアルで[MFAのマスト化](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/tutorial_users-self-manage-mfa-and-creds.html)は（ベストプラクティス的にも）最低限行なっておいたほうが良いと感じたので、その手法をまとめました
* 対象読者はIAM管理、IAMのベストプラクティスにのっとったセキュリティ管理に興味のある方です

# 0. 事前準備
[IAMのダッシュボード](https://console.aws.amazon.com/iam/)で、AWSマネジメントコンソールへのアクセスのみ許可されたテストユーザー(test_user)を作成し、ポリシーやアクセス許可が一切行われていないテストグループ（TestGroup)を作成してください

# 1. MFAサインインを強制するポリシーの作成
1. 管理者権限のあるIAMでAWSマネジメントコンソールにサインインしてください。（ルートユーザでのサインインはベストプラクティス上非推奨です。）
2. [IAMコンソール](https://console.aws.amazon.com/iam/)を開きます
3. 左側のナビゲーションメニューから**ポリシー**を選択し、左上の青色の**ポリシーの作成**を選択してください
4. デフォルトでは**ビジュアルエディタ**が選択されているので、**JSON**たぶに切り替え、[json](#json)をコピペしください。
5. 右下の青色の**ポリシーの確認**を選択してください（構文エラーがある場合は報告されます）
6. 確認ページでポリシー名として好きな名前（例えば`ForceMFA`など）を入力してください。
7. ポリシーの詳細としては適当に（`This policy allows users to manage their own passwords and MFA devices but nothing else unless they authenticate with MFA.`など)入力してください。（英文のみ許可されています。）

## json
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowViewAccountInfo",
            "Effect": "Allow",
            "Action": [
                "iam:GetAccountPasswordPolicy",
                "iam:GetAccountSummary",       
                "iam:ListVirtualMFADevices"
            ],
            "Resource": "*"
        },       
        {
            "Sid": "AllowManageOwnPasswords",
            "Effect": "Allow",
            "Action": [
                "iam:ChangePassword",
                "iam:GetUser"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnAccessKeys",
            "Effect": "Allow",
            "Action": [
                "iam:CreateAccessKey",
                "iam:DeleteAccessKey",
                "iam:ListAccessKeys",
                "iam:UpdateAccessKey"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnSigningCertificates",
            "Effect": "Allow",
            "Action": [
                "iam:DeleteSigningCertificate",
                "iam:ListSigningCertificates",
                "iam:UpdateSigningCertificate",
                "iam:UploadSigningCertificate"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnSSHPublicKeys",
            "Effect": "Allow",
            "Action": [
                "iam:DeleteSSHPublicKey",
                "iam:GetSSHPublicKey",
                "iam:ListSSHPublicKeys",
                "iam:UpdateSSHPublicKey",
                "iam:UploadSSHPublicKey"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnGitCredentials",
            "Effect": "Allow",
            "Action": [
                "iam:CreateServiceSpecificCredential",
                "iam:DeleteServiceSpecificCredential",
                "iam:ListServiceSpecificCredentials",
                "iam:ResetServiceSpecificCredential",
                "iam:UpdateServiceSpecificCredential"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnVirtualMFADevice",
            "Effect": "Allow",
            "Action": [
                "iam:CreateVirtualMFADevice",
                "iam:DeleteVirtualMFADevice"
            ],
            "Resource": "arn:aws:iam::*:mfa/${aws:username}"
        },
        {
            "Sid": "AllowManageOwnUserMFA",
            "Effect": "Allow",
            "Action": [
                "iam:DeactivateMFADevice",
                "iam:EnableMFADevice",
                "iam:ListMFADevices",
                "iam:ResyncMFADevice"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Sid": "DenyAllExceptListedIfNoMFA",
            "Effect": "Deny",
            "NotAction": [
                "iam:CreateVirtualMFADevice",
                "iam:EnableMFADevice",
                "iam:GetUser",
                "iam:ListMFADevices",
                "iam:ListVirtualMFADevices",
                "iam:ResyncMFADevice",
                "sts:GetSessionToken"
            ],
            "Resource": "*",
            "Condition": {
                "BoolIfExists": {
                    "aws:MultiFactorAuthPresent": "false"
                }
            }
        }
    ]
}
```

# 2. テストグループにポリシーを関連づける
1. IAMコンソールの左側のナビゲーションメニューで**グループ**を選択します
2. 検索ボックスに[事前準備](#事前準備)で作成したテストグループ(TestGroupなど)を入力し、選択してください
3. デフォルトで**アクセス許可**のタブが選択されているので、その下の青色の**ポリシーのアタッチ**を選択してください
4. 検索ボックスで先ほど作成したポリシー(ForceMFA)を入力し、チェックボックスをオンにします（まだ変更保存はしない）
5. さらに、そのテストユーザーに認証を与えるポリシーにチェックを付けます（例えばEC2に対するフルアクセスを許可する場合は`AmazonEC2FullAccess`のチェックボックスをオンにします）
6. 右下の青色の**ポリシーのアタッチ**を選択してください

# 3. テストユーザーでアクセスをテストする
1. 作成したテストユーザーでAWSアカウントにサインインしてください（URL: `https://<alias or account ID number>.signin.aws.amazon.com/console`）
2. Amazon EC2コンソールを開き、一切の捜査権限がないことを確認してください
3. 右上のナビゲーションバーを選択し、**マイセキュリティ資格情報**を選択してください
4. ここで[MFA認証](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_credentials_mfa.html)を有効にしてください
5. コンソールからサインアウトし、もう一度テストユーザーとしてサインインしてください（このときMFAが有効になっているはずです）
6. Amazon EC2コンソールを開き、全てのアクションを実行することができることを確認してください（ただし、EC2以外のコンソールに移動すると、アクセス拒否されていることが確認できます）