ローカル端末からIAMユーザのポリシー制限+MFA+STSで安全にアクセスキーを使用する

# 目的
AWSCLIを使う場合、EC2インスタンスの場合はインスタンスにEC2ロールを付与するなどで使うことができるがローカルの端末からAWSCLIを使う時にどうしてもIAMユーザのアクセスキーが必要となる。ベストプラクティスに則ってアクセスキーを発行する場合、流出時の影響を最小限にするためIAMユーザのポリシーを制限してアクセスキーを発行すると思うのだが、プライベートな学習用途などで使う場合最小ポリシーでキーを発行するとAWSCLIのちょっとした操作がAccessDeniedされまくって面倒。そこでIAMユーザのポリシー制限+MFA+STSを使ってなるべく安全かつ便利にアクセスキーを使用できるようにする。

# 手順
## 実際に作業するIAMロールを作成する
行いたい操作ができるポリシーを付与したIAMロールを作成する。ロールの作成時に「信頼されたエンティティ」に別のAWSアカウントを指定してアカウントIDに自身のAWSアカウントのアカウントIDを入力する。また、オプションの「MFAが必要」にチェックをつける。それ以降は好きなポリシーを設定してください。ただ、IAM操作系のポリシーをつけておくとアクセスキーが流出した際に、攻撃者がSTS&IAMロールの設定を変えることができてしまうので注意。

![スクリーンショット 2021-08-17 13.05.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105456/b10e9724-8efd-ac87-a8d2-621117649e12.png)

## 後述のIAMユーザを所属させるユーザグループを作成する
こんな↓感じでSTSの操作しかできない&MFAが必須のポリシーを付与したユーザグループを付与する。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": [
                "sts:GetSessionToken",
                "sts:DecodeAuthorizationMessage",
                "sts:GetAccessKeyInfo",
                "sts:GetCallerIdentity",
                "sts:GetServiceBearerToken"
            ],
            "Resource": "*",
            "Condition": {
                "BoolIfExists": {
                    "aws:MultiFactorAuthPresent": "true"
                }
            }
        },
        {
            "Sid": "VisualEditor1",
            "Effect": "Allow",
            "Action": "sts:*",
            "Resource": "arn:aws:iam::(AWSアカウントID):role/*",
            "Condition": {
                "BoolIfExists": {
                    "aws:MultiFactorAuthPresent": "true"
                }
            }
        }
    ]
}
```


## 最初にログインするIAMユーザを作成する
マネジメントコンソールからIAMユーザを作成する。作成するユーザは先ほど作ったグループに所属させ、MFAの設定とアクセスキーの生成を行う。

## AWSCLIにIAMユーザのアクセスキーを使ってプロファイルを作成する
AWSCLIのインストールは省略。インストール後、プロファイルを設定する。

```
$ aws configure --profile testprofile
AWS Access Key ID [None]: XXXXXXXXXXXXXX //IAMユーザ作成時に一緒に作ったアクセスキー
AWS Secret Access Key [None]: XXXXXXXXXXXXXX //上記のシークレットアクセスキー
Default region name [None]: ap-northeast-1 //自分がよく使うリージョン
Default output format [None]: json 
```

## STSからトークンを取得する
以下のAWSCLIを実行してSTSからトークンを取得する。

```
aws sts assume-role \
--role-arn          arn:aws:iam::XXXXXXXXXXX:role/XXXXXRole \ 作成したロールのARN
--serial-number     arn:aws:iam::XXXXXXXXXXX:mfa/test \ 作成したユーザに設定したMFAのシリアルナンバー
--role-session-name test-session \ 適当なセッション名
--profile           testprofile \ 作成したプロファイル
--duration-second   900 \ トークンの有効期限。単位は秒。
--token-code        XXXXXX IAMユーザに設定したMFAデバイスが表示している値
```

成功するとこんな↓感じの出力が返ってくる。AccessKeyId/SecretAccessKey/SessionTokenの3点セットが必要になる。それぞれ環境変数のAWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEY/AWS_SESSION_TOKENに設定しておくと、AWSCLIがそのトークンを使ってサービスを呼び出してくれる。

```json
{
    "Credentials": {
        "AccessKeyId": "XXXXXXXXXXXXXXXXXXX",
        "SecretAccessKey": "XXXXXXXXXXXXXXXXXXXXXXX",
        "SessionToken": "XXXXXXXXXXXXXXXXXXXX........XXXX==",
        "Expiration": "2021-08-18T12:54:00+00:00"
    },
    "AssumedRoleUser": {
        "AssumedRoleId": "XXXXXXXXXXXXXXXXX:XXXXXXXXXXX-session",
        "Arn": "arn:aws:sts::XXXXXXXXXXXX:assumed-role/XXXXXRole/XXXXXXXX-session"
    }
}
```

## (おまけ)トークンを楽に更新する仕掛け

上記のAWSCLIをbashのfunctionにしておくとよい。こちらの記事が参考になります。

https://dev.classmethod.jp/articles/eazy-assume-role-with-fzf/

# 最後に
なるべく安全になるようなアクセスキーの使い方を書いてみました。実際にアクセスキーが流出する原因となるのがGitHubにキーをコミットしてしまった場合みたいですが、以下の検証結果によるとアクセスキーが漏れた場合は13分ぐらいでアクセスキーの不正使用が始まってしまうみたいです。今回のSTSトークンを使えば有効期限内は色々やられてしまいますが、それを過ぎれば使えなくなるので高額な利用まで至らないのではないかなと思います。あとは不正利用を検出する仕組みについては思いついたら別記事で書いてみます。

https://qiita.com/saitotak/items/813ac6c2057ac64d5fef