AWS CLI で MFA を有効化してみた

# はじめに

[前回の記事](https://qiita.com/sugimount-a/items/1e8fdd1c9c965e2fa839)では、セルフサービスな MFA 環境を作るための IAM Policy の方法を学びました。今回は、AWS CLI から MFA を利用するときの方法を整理したいと思います。

　

まず、前提知識として整理すると、AWS のマネージメントコンソールで MFA を有効化する設定項目があります。

![image-20221229120242464.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/45502778-7fc1-9c34-4405-2074083e0ce4.png)

　

これを有効化すると、マネージメントコンソールにログインするときに、MFA 認証が求められます。

![image-20221229120000886.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/eeb8c26f-e0c3-0339-1950-f42be3829715.png)

　

この機能を有効化しただけでは、この IAM User に紐づくアクセスキーをつかった **AWS CLI の実行には何も影響しません**。表現を変えると、アクセスキーを払い出したら、MFA 関係なくいろいろな API が実行できるわけですね。

これだと困るので、IAM Policy で MFA が無いときにアクセスを禁止するルールを設定すると、AWS CLI でも MFA が有効になります。すごいシンプルな例だと、以下のとおりです。`MultiFactorAuthPresent` が `false` のときには、全てのアクションを禁止にしています。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllDenyWithoutMFA",
            "Effect": "Deny",
            "Action": [
                "*"
            ],
            "Resource": [
                "*"
            ],
            "Condition": {
                "BoolIfExists": {
                    "aws:MultiFactorAuthPresent": false
                }
            }
        }
    ]
}
```

　

なお、[前回の記事](https://qiita.com/sugimount-a/items/1e8fdd1c9c965e2fa839)でこれと同等な IAM Policy を設定していたので、この記事を参考にすると、すでに AWS CLI でも MFA が有効になっています。ちょっと試してみましょう。



# アクセスキーの生成

上記の IAM Policy を紐づけている User でアクセスキーを生成します。

![image-20221229120928757.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/4ec30696-f055-a6a6-5a3b-d793016dbbc5.png)



AWS CLI の Profile を作成します。

```
> aws configure --profile mfa
AWS Access Key ID [None]: secret1
AWS Secret Access Key [None]: secret2
Default region name [None]: ap-northeast-1
Default output format [None]: json
```



きちんと設定されました

```
> aws sts get-caller-identity --profile mfa
{
    "UserId": "AIDA5WQZQQ3JP5PXAB573",
    "Account": "xxxxxxxx",
    "Arn": "arn:aws:iam::xxxxxxx:user/mfauser01"
}
```



# AWS CLI が利用できない

アクセスキーを設定しても、MFA を使っていないので AWS CLI の実行ができません。想定通りですね。

```
> aws ec2 describe-instances --profile mfa

An error occurred (UnauthorizedOperation) when calling the DescribeInstances operation: You are not authorized to perform this operation.
```

```
> aws s3 ls --profile mfa

An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied
```



# AWS CLI で MFA を入力する

AWS CLI で MFA を利用するときには、`aws sts get-session-token` コマンドで一時的なアクセスキーを取得できます。このコマンドを実行するために、MFA Device の ARN が必要です。

マネージメントコンソール上で ARN を確認してコピーします。

![image-20221229122252465.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1002774/e8d44a0f-fd46-8143-a469-6e2a071ed21d.png)

　

`aws sts get-session-token` コマンドを実行します。

- serial-number : コピーしてきた MFA Device の ARN を指定
- token-code : この MFA Device が生成する 6 桁の数字を指定

```
aws sts get-session-token \
  --serial-number arn:aws:iam::xxxxxxxxx:mfa/test-mfa3 \
  --token-code 627292 \
  --profile mfa
```

　

入力した値が正しければ、12 時間だけ使える一時的なアクセスキーが発行されます。永続的なものではないので、万が一流出しても 12 時間後には使えないため、セキュリティレベルが向上するわけですね。

```
{
    "Credentials": {
        "AccessKeyId": "secret1",
        "SecretAccessKey": "secret2",
        "SessionToken": "secret3",
        "Expiration": "2022-12-29T15:19:29+00:00"
    }
}
```

　

一時的に取得したアクセスキーは、export で環境変数に入れたりすると実際に AWS CLI で使えます。bash ですが、次のように簡単に環境変数に入れられます。Bash Script など作ってもいいかもしれないですね。

```
OUTPUT=$(aws sts get-session-token \
  --serial-number arn:aws:iam::xxxxxxxx:mfa/test-mfa3 \
  --token-code 311758 \
  --profile mfa)

export AWS_ACCESS_KEY_ID=$(echo $OUTPUT | jq -r .Credentials.AccessKeyId)
export AWS_SECRET_ACCESS_KEY=$(echo $OUTPUT | jq -r .Credentials.SecretAccessKey)
export AWS_SESSION_TOKEN=$(echo $OUTPUT | jq -r .Credentials.SessionToken)
```

　

さきほどまではエラーだったコマンドが実行できました。

```
$ aws ec2 describe-instances
{
    "Reservations": [
        {
            "Groups": [],
            "Instances": [
                {
                    "AmiLaunchIndex": 0,
                    "ImageId": "ami-0adb5d1dc8c5aa555",
                    "InstanceId": "i-0b5a7eef21d818f5b",
                    "InstanceType": "t2.large",
省略
```

```
$ aws s3 ls
2021-06-24 01:51:35 testsugi001001
2021-05-03 02:04:08 vmimport-bucket-sugi01
2021-07-23 22:33:00 vpcflowlogs001
2021-06-24 01:56:50 webpushtest-sugi01
```



# 便利ツール

AWS CLI 上で、毎回環境変数にセットするのは大変なので、次のツールや Shell Script が紹介されていました。このあたりを利用すると、とても便利になると思います。

https://qiita.com/hoto17296/items/38f8575265a514660745

https://qiita.com/sasasin/items/bd2ed19614737413b794



# Tips : 有効期限の指定

`duration-seconds` をオプションで指定することで、一時的なクレデンシャルの有効期限を指定可能。最大値は 129600 (36 時間) となる。

```
aws sts get-session-token \
  --serial-number arn:aws:iam::xxxxxxxx:mfa/test-mfa3 \
  --token-code 812568 \
  --duration-seconds 129600 \
  --profile mfa
```





# 検証を通じてわかったこと

- AWS マネージメントコンソールで MFA を設定にしただけでは、AWS CLI 側には何も影響しない。MFA なくてもコマンド実行ができる
- 上記を防ぐために、IAM Policy で `MultiFactorAuthPresent` を使ったルールを指定することで、AWS CLI を経由した API 実行でも MFA を強制できる
- AWS CLI 上では、get-session-token コマンドで MFA のトークンを入力すると、一時的なクレデンシャル情報を取得可能
- 一時的なクレデンシャルは、デフォルトだと 12 時間で有効期限がきれる。`duration-seconds` を指定することで、最大 36 時間まで伸ばせる。



# 参考 URL

AWSコンソールとCLI利用時にMFA認証を必須にする
https://www.karakaram.com/requiring-mfa-authentication-when-using-aws-console-and-cli/

AWS: MFA で認証された IAM ユーザーが [My Security Credentials] (マイセキュリティ資格情報) ページで自分の認証情報を管理できるようにする
https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/reference_policies_examples_aws_my-sec-creds-self-manage.html

AWS CLI で MFA 必須のアクセス制御を設定
https://blog.nijot.com/aws/aws-cli-mfa-force-setting/