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"
}
]
}
ポイントは以下の点です:
BoolIfExists
でaws:MultiFactorAuthPresent
がfalse
、つまり MFA を設定していないユーザーに対して、IAM 関連以外の全リソースへのアクセスを「明示的拒否」としていますNotAction
でiam:*
を指定する事で 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": []
}
無事(?)空のクラスタ一覧を取得できました。
コメントを残す