AWS Tools for PowerShellとAWS CLIでロール切替なしのMFA認証

AWS Tools for PowerShellやAWS CLIでロール切替時にMFAするには `.config` ファイル内でロールにMFAデバイスを設定しておけばいい。ロール切替用に、「[サポートされるconfigファイル設定 - 設定ファイルと認証情報ファイルの設定](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-files.html#cli-configure-files-settings)」にある `role_arn` `source_profile` を持つ名前付きプロファイルを作ると思うのだけど、そこに `mfa_serial` も追加しておく。

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-files.html#cli-configure-files-settings

ロール切替時に、MFAコード（6桁の数字）を聞いてくれる。ではロール切替しない、IAMユーザー認証してそのまま要MFAの作業するにはというと、この手法が使えなさそうな感じ。

> 注意: 永続的な IAM 認証情報で mfa_serial パラメータを使用することはできません。
> （[AWS CLI 経由で MFA を使用してアクセスを認証する - AWS ナレッジセンター](https://aws.amazon.com/jp/premiumsupport/knowledge-center/authenticate-mfa-cli/)）

大まかに言えば、このAWSナレッジセンターのドキュメントにある手順でセッショントークンを取得し、一時的な認証情報として設定する必要がある。

# AWS CLI

上の引用文出典と同じだけど、こちらを参照。

https://aws.amazon.com/jp/premiumsupport/knowledge-center/authenticate-mfa-cli/

ダイジェストで手順をまとめておくと。まず以下でセッショントークンを取得する。

```
aws sts get-session-token --serial-number arn-of-the-mfa-device --token-code code-from-token
```

こんな出力が返ってくる。

```
{
    "Credentials": {
        "SecretAccessKey": "secret-access-key",
        "SessionToken": "temporary-session-token",
        "Expiration": "expiration-date-time",
        "AccessKeyId": "access-key-id"
    }
}
```

ここに含まれている値を、環境変数 `AWS_ACCESS_KEY_ID` `AWS_SECRET_ACCESS_KEY` `AWS_SESSION_TOKEN` に設定する。

* Linuxでは `export AWS_ACCESS_KEY_ID=secret-access-key` など。削除するときは `unset AWS_ACCESS_KEY_ID` など。
* Windowsでは `set AWS_ACCESS_KEY_ID=secret-access-key` など。削除するときは `set AWS_ACCESS_KEY_ID=` など。

セッショントークンが期限切れした時は再取得する。この時は設定した環境変数を削除したり、非MFAで使っているものに戻したりして、セッショントークンを再取得してから、再設定する。何回もやってると消耗するので、戻り値をsedとかjqとかで解析して環境変数に入れる何かを作るとかしておくと楽かもしれない。あるいはこれとかもよさげです。

https://blog.usize-tech.com/sts-temp-credential-by-oneliner/

あと環境変数は、[AWS SDK for Python（boto3）とかも見てくれる](https://qiita.com/tsukamoto/items/00ec8ef7e9a4ce4fb0e9)ので、各種SDKとかでもこの方式でイケると思う。

# AWS Tools for PowerShell

同様に[Get-STSSessionToken](https://docs.aws.amazon.com/ja_jp/powershell/latest/reference/items/Get-STSSessionToken.html)コマンドレットでセッショントークンを取得し、[Set-AWSCredential](https://docs.aws.amazon.com/ja_jp/powershell/latest/reference/items/Set-AWSCredential.html)で一時認証情報に格納する。

```PowerShell
$sts = Get-STSSessionToken -SerialNumber arn-of-the-mfa-device -TokenCode code-from-token
Set-AWSCredential -AccessKey $sts.AccessKeyId -SecretKey $sts.SecretAccessKey -SessionToken $sts.SessionToken
```

セッショントークンが期限切れした時は再取得する。この時は、設定した一時認証情報を戻すのだけど、AWS Tools for PowerShellの場合これだけ。

* 普段 `Set-AWSCredential` で名前付きプロファイルを指定している → `Set-AWSCredential` する。
* 普段はデフォルトか環境変数の認証情報を使っている → [Clear-AWSCredential](https://docs.aws.amazon.com/ja_jp/powershell/latest/reference/items/Clear-AWSCredential.html)する。

`Set-AWSCredential` した認証情報は環境変数より優先されるし、だから環境変数を書き換える必要がなくて、書き戻す必要もない。なので、こちらを使うのがいいと思う。

# 終わりに

できるとは言えMFAシリアルを都度入力する時点で基本めんどくさいので、権限管理はIAMロール使う、EC2インスタンス等からの実行はIAMユーザー認証じゃなくインスタンスプロファイル（ロール付与）使う、というのがいいと思います。それができなければ、AWS CLIよりAWS Tools for PowerShellの方がまだ楽。でもセッションマネージャーでの画面転送がAWS CLIでしかできないので、ワーストめんどくさいケースはいつか来る。IAMロールとインスタンスプロファイル使うのお勧めです（というか使わせてください）。

# 参考情報

以下を参照してまとめています。参照先情報と本記事の情報が合致しない場合、多分参照先の情報が正しいです。

* [AWS CLI 経由で MFA を使用してアクセスを認証する - AWS ナレッジセンター](https://aws.amazon.com/jp/premiumsupport/knowledge-center/authenticate-mfa-cli/)
* [Get-STSSessionToken](https://docs.aws.amazon.com/ja_jp/powershell/latest/reference/items/Get-STSSessionToken.html)
* [Set-AWSCredential](https://docs.aws.amazon.com/ja_jp/powershell/latest/reference/items/Set-AWSCredential.html)
* [Clear-AWSCredential](https://docs.aws.amazon.com/ja_jp/powershell/latest/reference/items/Clear-AWSCredential.html)
* [サポートされるconfigファイル設定 - 設定ファイルと認証情報ファイルの設定 - AWS Command Line Interface](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-files.html#cli-configure-files-settings)