MFA認証を強制したい！

## はじめに

こんにちは、Nishiです。
本記事はANGEL Calendar11日目の記事として投稿しています。
1日目～の記事一覧は[こちら](https://qiita.com/organizations/2024-angel-dojo/items)をご参照ください！

今回は各ユーザーにMFA設定を強制するための方法について書いていきます。
MFAの概要や設定方法については、以下の記事で丁寧にご説明いただいているので、ぜひ見てみてください。

https://qiita.com/AGI_12/items/18ded0b3ab73575646ab

## MFA認証を強制しよう
セキュリティ面から、各ユーザーにMFAの設定を強制したいケースを想定し、MFA認証の設定を行っていないユーザーのサービス利用を制限します。
設定はAWSマネジメントコンソールから行います。

### IAMポリシー作成
まずはMFA認証を強制するためのIAMポリシーを作成していきます。

①IAMポリシーの設定画面から「ポリシーの作成」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600806/0ec6017c-9dda-999e-608d-f141e5d8c482.png)

②JSON形式でポリシーエディタに以下の内容を記載し、「次へ」をクリック

　MFAが設定されていない場合、iamの一部アクション(※)を除くすべてのアクション実行を拒否する内容です。
　※パスワード変更やMFA認証設定は、MFA未設定の状態でも拒否されないようにしています。

```JSON:MFA強制用ポリシー
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Deny",
      "NotAction": [
        "iam:CreateVirtualMFADevice",
        "iam:DeleteVirtualMFADevice",
        "iam:DeactivateMFADevice",
        "iam:EnableMFADevice",
        "iam:ResyncMFADevice",
        "iam:ListMFADevices",
        "iam:ListVirtualMFADevices",
        "iam:ChangePassword"
      ],
      "Resource": "*",
      "Condition": {
                "BoolIfExists": {
                    "aws:MultiFactorAuthPresent": "false"
                }
        }
    }
  ]
}

```

③ポリシー名を設定のうえ、「ポリシーの作成」をクリック
　本記事ではポリシー名をMFAEnforcePolicyとします。

### IAMグループへの適用

作成したIAMポリシーをIAMグループに適用します。

①ユーザーグループの設定画面からMFA設定を強制したいIAMユーザーが所属する任意のグループ名をクリック
 本記事では別途作成したReadOnlyGroupに設定します。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600806/9b831105-b13f-bb6e-6d29-c82880775aeb.png)

②「許可」タブを選択のうえ、「許可を追加」から「ポリシーをアタッチ」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600806/2f23aeb6-7bf9-f311-057c-f799353651b9.png)

③先ほど作成したIAMポリシー（本記事ではMFAEnforcePolicy）を選択し、「ポリシーをアタッチ」をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600806/ab1d7fb6-386c-702b-3ea2-f3cc8a69173b.png)

### IAMユーザーでの動作確認

作成したIAMポリシーが適用されたIAMユーザーにてマネジメントコンソールにログインします。
MFAを設定していない状態でいくつかのサービスを確認し、各アクション(例の画像ではリソース一覧の参照)ができないことを確認できました:raised_hands:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600806/5d18fc92-92ad-a2a3-60eb-842598aebceb.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600806/6b55206c-5d32-f833-d9ce-64f41b253a95.png)


この状態ではIAMユーザー一覧を表示できず、自身のIAMユーザーを選択することもできないので、IAMダッシュボード画面からMFAを設定してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600806/ee95d3fc-02b8-ac05-53b1-d48d509b1224.png)

MFA設定後に再ログインすると、先ほど見られなかったリソースの情報が確認できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600806/4aea41a9-58be-d253-1307-4a11c5764cf7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600806/891d6f10-0a29-7129-8c43-74bbaa2a5f5d.png)


## 補足①　MFA設定に必要な権限について

今回作成したMFA強制用ポリシーでは、MFA未設定時にパスワード変更やMFA設定の操作が拒否されないようにしていますが、操作自体を許可する権限は付与していません。
たとえばReadOnlyAccessポリシーやPowerUserAccessのみを許可しているIAMユーザーは、iam関連の権限が足りないのでMFAの設定時に拒否されてしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600806/354f42f8-2428-f333-0390-19ee13a88504.png)

この場合、以下のIAMポリシーを作成のうえ適用して、対象ユーザーがパスワード変更やMFA設定が行えるようにしてください。

```JSON:パスワード変更・MFA設定を許可するポリシー
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "iam:CreateVirtualMFADevice",
                "iam:DeleteVirtualMFADevice"
            ],
            "Resource": "arn:aws:iam::*:mfa/*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "iam:DeactivateMFADevice",
                "iam:EnableMFADevice",
                "iam:ResyncMFADevice",
                "iam:ListMFADevices",
                "iam:ChangePassword"
            ],
            "Resource": "arn:aws:iam::*:user/${aws:username}"
        },
        {
            "Effect": "Allow",
            "Action": "iam:ListVirtualMFADevices",
            "Resource": "*"
        }
    ]
}

```

## 補足②　AWS CLIを利用する場合

MFAを強制した状態でAWS CLIを利用する場合、マネジメントコンソール側でMFA設定の上ログインを行っていても、CLIのコマンドにはMFAのトークンの情報が含まれてないのでMFA認証されていない扱いになり権限不足となってしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600806/5c82b810-a3b5-9c1e-82b0-f37fd8a276e9.png)

これを回避するため、MFA認証済みの一時的なアクセスキーの発行を行います。

:::note warn
本手順で発行するアクセスキーの有効期限は12時間なので、有効期限が切れた場合は再度、本作業を実施する必要があります。
:::

①PowerShell等で以下コマンドを実行
```
aws sts get-session-token --serial-number <マネジメントコンソールから確認可能なMFAデバイスのARN※> --token-code 000000（MFAデバイスに表示されている6ケタのトークン番号を入力） --profile プロファイル名（設定している場合）
```
※サービス＞IAM＞ユーザー＞自身のユーザー名＞[セキュリティ認証情報]タブ＞多要素認証(MFA)の識別子からコピー

```text:コマンドの例
aws sts get-session-token --serial-number arn:aws:iam::123456789012:mfa/mfa_device_phone --token-code 123456 --profile test-user
```

②コマンド実行結果が以下の形式で出力されることを確認
```
{
    "Credentials": {
        "AccessKeyId": "XXXXXXXXXXXX"
        "SecretAccessKey": "XXXXXXXXXXXXXXXXXXX",
        "SessionToken": "XXXXXXXXXXXXXXXXXXXX",
        "Expiration": "expiration-date-time",
    }
}
```

③PowerShellは開いたまま、ホームディレクトリの.aws/credentialsを適当なエディタで開く
④ファイルの末尾に以下を追記し、MFA認証済みの一時的なアクセスキーの情報を保存
```
[任意のプロファイル名]
aws_access_key_id = ②のAccessKeyIdの値（前後の" "は不要）
aws_secret_access_key = ②のSecretAccessKeyの値（前後の" "は不要）
aws_session_token = ②のSessionTokenの値（前後の" "は不要）
```

⑤PowerShell等で以下コマンドを実行
```
aws configure --profile ④で記載したプロファイル名
```
```text:コマンドの例
aws configure --profile test-user-mfa
```

⑥画面に従い、MFA認証済みの一時的なアクセスキーの情報(追加分)を登録する
```
AWS Access Key ID [****XXXX]: //空白のままEnter（④で入力済みのため）
AWS Secret Access Key [****XXXX]: //空白のままEnter（④で入力済みのため）
Default region name [none]: ap-northeast-1（任意のリージョン名）
Default output format [none]:json
```
⑦MFA認証済みの一時的なアクセスキーで、AWS CLIの操作が行えることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600806/723a36d7-9f7f-573d-6b59-8bcc540a3c07.png)

## まとめと所感

MFA認証の強制によってセキュリティ意識を向上できる一方、AWS CLIでの開発では一時的なアクセスキーを発行する必要があることに注意が必要です。
必要に応じて、MFA強制用ポリシー内の"NotAction"内にMFA強制から除外したいアクションを設定する等、調整したうえで設定いただければと思います！

実際にANGELDojoの活動の中でも、このあたりの権限で引っかかってエラーが出ていたので、どんなアクションを許可する必要があるか等、適切な権限の管理が大切だと改めて感じました。
使うサービスが定まっていない試行錯誤の開発期間中というよりは、運用が始まってから等、権限が必要なアクションについて明確になってからMFAを強制するような使い方がよさそうです。

ANGEL Calendarは9月末まで更新されるので、明日以降の記事もお楽しみに～:wave: