リモート開発メインのソフトウェア開発企業のエンジニアブログです

IAM で MFA を強制する方法と CLI での認証方法

今関わっているとあるプロジェクトでは、利用している AWS のリソースを操作するすべてのユーザーに対して MFA (多要素認証) を設定する事を義務付けています。

MFA 自体は AWS に限らず、多数の Web サービスに備わっている機能で、昨今珍しくない機能かと思いますが、当プロジェクトでは、ただ設定をする事を勧告するのではなく、 IAM の機能を使って強制的に設定を行ってもらう様にしています。

尚、マネージメントコンソールだけでなく CLI での操作についても同様に MFA を必須とした運用をしているので、今回は設定例を紹介します。

MFA を強制するポリシーを作る

今回は、対象の全ユーザー (人間が使う IAM ユーザー) に対して MFA の設定を強制する為、専用のポリシーを作りました。内容は以下の通りです:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Condition": {
                "BoolIfExists": {
                    "aws:MultiFactorAuthPresent": "false"
                }
            },
            "Resource": "*",
            "Effect": "Deny",
            "NotAction": [
                "iam:*"
            ]
        },
        {
            "Action": [
                "iam:DeactivateMFADevice",
                "iam:EnableMFADevice",
                "iam:ResyncMFADevice",
                "iam:ListMFADevices",
                "iam:DeleteVirtualMFADevice",
                "iam:CreateVirtualMFADevice",
                "iam:ListUsers",
                "iam:ListVirtualMFADevices"
            ],
            "Resource": "arn:aws:iam::YOUR-AWS-ACCOUNT-ID:user/${aws:username}",
            "Effect": "Allow"
        },
        {
            "Action": [
                "iam:GetAccountPasswordPolicy"
            ],
            "Resource": "*",
            "Effect": "Allow"
        }
    ]
}

ポイントは以下の点です:

  • BoolIfExistsaws:MultiFactorAuthPresentfalse 、つまり MFA を設定していないユーザーに対して、IAM 関連以外の全リソースへのアクセスを「明示的拒否」としています
    • NotActioniam:* を指定する事で IAM 関連への「明示的拒否」を防いでいます
  • 続いて、 MFA の設定に必要な iam:DeactivateMFADevice 等のリソースに対して「明示的許可」をしています

※「明示的拒否」や「明示的許可」等の評価についてはこの記事がわかりやすくまとめています

設定が終わったら、このポリシーを必要なユーザー全員に割り当てます。尚、これらの設定は次の章で説明する CLI でも MFA も強制します。

CLI での認証を行う

先程のポリシーを設定されたユーザーは、 CLI でも MFA を強制されます。まずは、普通に MFA を通さないでコマンドを叩いてみます:

$ aws --profile issei-test --region ap-northeast-1 rds describe-db-clusters

An error occurred (AccessDenied) when calling the DescribeDBClusters operation: User: arn:aws:iam::XXXXXXXXXXXX:user/issei-test is not authorized to perform: rds:DescribeDBClusters on resource: arn:aws:rds:ap-northeast-1:XXXXXXXXXXXX:cluster:* with an explicit deny

無事(?)オペレーションが「明示的拒否」により拒否されました。

Web 上で操作するマネジメントコンソールについては、普通にログイン時にワンタイムコードを入力すれば OK ですが、 CLI についてはどのように認証を行えば良いでしょうか?

その方法は、こちらの公式ブログを見ると分かります。今回はその手順を簡単にまとめました。

まず、自分が設定した MFA デバイスの SerialNumber を知る必要があります。これは、 aws iam list-mfa-devices を使って取得する事が可能です:

$ aws --profile issei-test iam list-mfa-devices

{
    "MFADevices": [
        {
            "UserName": "issei-test",
            "SerialNumber": "arn:aws:iam::XXXXXXXXXXXX:mfa/issei-test",
            "EnableDate": "2020-10-19T08:58:35+00:00"
        }
    ]
}

続いて、この SerialNumber を使用して、 aws sts get-session-token コマンドを使って一時的な認証情報を得ます。

$ aws --profile issei-test sts get-session-token --serial-number arn:aws:iam::XXXXXXXXXXXX:mfa/issei-test --duration-seconds 129600 --token-code 123123 

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

--token-code に MFA デバイスが払い出したワンタイムコードを入力して下さい

払い出された “AccessKeyId”, “SecretAccessKey”, “SessionToken” を用いて、 “Expiration” の日時まで当該ユーザーとして認証が可能です。尚、 Expiration は --duration-seconds で 900 秒 (15 分) から 129,600 秒 (36 時間) まで指定可能で、指定しないとデフォルトで 43,200 秒 (12 時間) となります。

これらの認証情報は次の環境変数に設定する事で利用が可能です:

AWS_ACCESS_KEY_ID=払い出されたaccess-key-id
AWS_SECRET_ACCESS_KEY=払い出されたsecret-access-key
AWS_SESSION_TOKEN=払い出されたsession-token

※必要に応じて export するなりして下さい。

尚、当然ですが Expiration を過ぎるとこの認証は通らなくなるので、再度 aws sts get-session-token を行う必要があります。

実際に、これらの情報を export した状態で再度 RDS のクラスタを取得してみます。環境変数による認証を行うので、今回は --profile オプションは不要です:

$ aws --region ap-northeast-1 rds describe-db-clusters          

{
    "DBClusters": []
}

無事(?)空のクラスタ一覧を取得できました。

← 前の投稿

kedroのモデルを読み込むパイプラインにおいて、同じ型のモデルを切り替える

次の投稿 →

Scala の Option, Either とエラー処理

コメントを残す