1. はじめに
- AWS マネジメントコンソール作業で使用するIAMグループ や IAMユーザーの設計や作成フローを、IAM ベストプラクティス を参考にして見直してみる。
- けど、IAMグループ や IAMユーザー の作成に関する IAM ベストプラクティス をすべて採用するのは窮屈なので、採用するものを決めて My IAM プラクティスを作成してみる。
- そして、My IAM プラクティスに準拠したIAM グループ、IAMユーザーの作成フローを構築してみる。
- 例として、新規に参画したAWS マネジメントコンソール作業者で、開発チームのAさんの IAM ユーザーを作成してみる。
- あと、IAMポリシーとIAMグループを Terraform で、IAMユーザーを CloudFormation でコード化する。
※ IAMユーザーの Terraform 化は、aws_iam_user_login_profile の pgp_key のところがなんか面倒いので、やむを得ず CloudFormation を使ってる。。
2. My IAM プラクティス
AWSの IAM ベストプラクティスで採用するもの
* [IAM ユーザーへのアクセス許可を割り当てるためにグループを使用する](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.html#use-groups-for-permissions) * IAMユーザーにポリシーをアタッチするのはNG。「IAMグループ作成 ⇒ IAMグループにポリシーをアタッチ ⇒ IAMユーザーをIAMグループに割り当てる」という流れでIAMユーザーに権限を与える。 * IAM グループに少なくとも 1 つの IAM ユーザーが存在するかどうかを AWS Config マネージドルール の [iam-group-has-users-check](https://docs.aws.amazon.com/ja_jp/config/latest/developerguide/iam-group-has-users-check.html) でチェックすることができる。 * IAM ユーザーが少なくとも 1 つの IAM グループのメンバーであるかどうかを AWS Config マネージドルール の [iam-user-group-membership-check](https://docs.aws.amazon.com/ja_jp/config/latest/developerguide/iam-user-group-membership-check.html) でチェックすることができる。 * IAMユーザーにポリシーがアタッチされているかどうかを AWS Config マネージドルール の [iam-user-no-policies-check](https://docs.aws.amazon.com/ja_jp/config/latest/developerguide/iam-user-no-policies-check.html) でチェックすることができる。何かしらのポリシーがアタッチされていたら、非準拠となる。 * [AWS 管理ポリシーを使用したアクセス許可の使用開始](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.html#bp-use-aws-defined-policies) * 例えば、開発者用ユーザーには 「AWSにより管理」されている [PowerUserAccess](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/access_policies_job-functions.html#jf_developer-power-user) ポリシー の権限を与える。 * [インラインポリシーではなくカスタマー管理ポリシーを使用する](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.html#best-practice-managed-vs-inline) * 「AWSにより管理」されているポリシーリストに適切なポリシーがない場合は、利用者側でポリシーを作成する。 * このとき、インラインポリシーとしてIAMグループにアタッチするのではなく、「カスタマー管理(ユーザーによる管理)」ポリシーとして作成して、IAMグループにアタッチする。 * [ユーザーの強力なパスワードポリシーを設定](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.html#configure-strong-password-policy) * IAM ユーザーのアカウントパスワードポリシーが、指定した要件を満たしているかどうかを AWS Config マネージドルール の [iam-password-policy](https://docs.aws.amazon.com/ja_jp/config/latest/developerguide/iam-password-policy.html) でチェックすることができる。 * [MFA の有効化](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/best-practices.html#enable-mfa-for-privileged-users) * コンソールパスワードを使用するすべての IAM ユーザーについて MFA が有効になっているかどうかを AWS Config マネージドルール の [mfa-enabled-for-iam-console-access](https://docs.aws.amazon.com/ja_jp/config/latest/developerguide/mfa-enabled-for-iam-console-access.html) でチェックすることができる。AWSの IAM ベストプラクティスで採用しないもの
- 最小権限を付与する
- 例えば、開発者には PowerUserAccess ポリシーをがっつり割り当てる。
次も My IAM プラクティスに追加する
- AWS マネジメントコンソール作業で使用するIAMユーザーには、プログラムによるアクセスを許可しない(アクセスキー ID と シークレットアクセスキー を作成しない)。
- IAMユーザー 自身が AWS マネジメントコンソール のパスワードを変更できるようにする。
- IAMユーザー 自身が MFA を設定/変更できるようにする。
3. My IAM プラクティスに準拠したIAMユーザーを作成するフロー
- 新規に参画したAWS マネジメントコンソール作業者に与える権限(ポリシー)を決定する。2. へ。
もし、適切な AWS管理ポリシーがなければ、ポリシー(インラインポリシーではなく、カスタマー管理ポリシー)を作成してIAMグループにアタッチする。4. へ。 4. IAMユーザーを作成する。
・共有ではなく個々に作る。
・ポリシーはアタッチしない。
・所属するIAMグループを設定する。
4. My IAM プラクティスで開発者AさんのIAMユーザーを作成する例
1. ユーザーの強力なパスワードポリシーを設定する(IAMユーザー全体に影響する設定)
↓ |
↓ |
↓ |
こんな感じに設定 |
2. ユーザーにパスワード変更を許可する設定(IAMユーザー全体に影響する設定)
パスワードポリシー設定で、「ユーザーにパスワードの変更を許可する」にチェックする。
これにチェックしておけば、AWSによる管理の「IAMUserChangePassword」ポリシーをアタッチしなくても、自身がパスワードを変更できるようになる。
3. 開発者Aさんに PowerUserAccess 権限を与えることにする
-
注意点その1:AdministratorAccess とか、PowerUserAccess ポリシー
-
AWSによる管理の AdministratorAccess ポリシーも、 PowerUserAccess ポリシーも、IAM 操作権限がない。
-
なので、AWS管理者がIAM周りの作業を行うためには、AdministratorAccess ポリシーに加えて、IAMFullAccess ポリシーをアタッチする。
-
開発者Aが自身のMFAを設定/変更できるようにするためには、PowerUserAccess ポリシーに加えて、MFA デバイスの自己管理を許可する ポリシーをアタッチする。(マネジメントコンソールのパスワード変更は、パスワードポリシーのところで許可してあれば、IAMUserChangePassword ポリシーはアタッチ不要)
-
注意点その2:MFA デバイスの自己管理を許可する ポリシー
-
このポリシーについては、数日前にクラスメソッドに素敵な記事が上がっていたので、説明は省く。
-
気をつけないといけないのは、次の3点。
- MFA認証でサインインしないと、アタッチされているポリシーがすべて無効になる。例えば、PowerUserAccess ポリシーをアタッチしていたとしても、マネジメントコンソールのすべてのAWSサービスのページで権限がないと表示されてしまう。
例)
$ aws s3 ls
An error occurred (AccessDenied) when calling the ListBuckets operation: Access Denied
↓
次の方法でMFAをパスする必要がある
[MFA トークンを使用して、AWS CLI 経由で AWS リソースへのアクセスを認証する方法を教えてください。](https://aws.amazon.com/jp/premiumsupport/knowledge-center/authenticate-mfa-cli/)
- 手順例
- セッショントークンを発行する
$ aws sts get-session-token --serial-number "MFAのarn" --token-code "MFAデバイスから発行される6桁の数字"
必要に応じて --profile オプションを付ける場合
$ aws --profile hogehoge sts get-session-token --serial-number "MFAのarn" --token-code "MFAデバイスから発行される6桁の数字"
MFAのARNは、AWSマネジメントコンソールのIAMから確認できる
- パスが通ると次のような情報が返ってくる。このSessionTokenにはExpiration(有効期限)がある。
{
"Credentials": {
"AccessKeyId": "aaaaaaaaaaaaaaaaaaaa",
"SecretAccessKey": "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
"SessionToken": "cccccccc....",
"Expiration": "2020-11-05T17:08:48+00:00"
}
}
- シェルに環境変数を設定する
$ export AWS_ACCESS_KEY_ID=aaaaaaaaaaaaaaaaaaaa
$ export AWS_SECRET_ACCESS_KEY=bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
$ export AWS_SESSION_TOKEN=cccccccc....
- これで、トークンが有効期間中 AWS CLIが使えるようになった
$ aws --profile hogehoge s3 ls
2020-10-16 19:29:24 AAAA
2020-08-03 22:01:02 BBBB
2020-08-11 17:03:37 CCCC
-
MFA デバイスの自己管理を許可する ポリシーをアタッチしている IAMユーザー の初回サインイン時のパスワード変更エラーの例
-
パスワード変更できない!
「ユーザーに iam:ChangePassword を実行する権限がないか、入力されたパスワードが管理者によって設定されたアカウントパスワードポリシーに準拠していません」
4. IAMグループを作成する
- 開発者用のIAMグループ「developers」を作成する。
- IAMグループ「developers」に次のポリシーをアタッチする。
- PowerUserAccess ポリシー
- MFA デバイスの自己管理を許可する ポリシー
5. IAMユーザーを作成する
- 開発者A用のIAM ユーザー「userA」を作成する。
- 初回サインイン時にパスワード変更しない設定する。
- MFA デバイスの自己管理を許可する ポリシーのため、パスワードを変更できない。
- アカウントパスワードポリシーのルールで90日後には強制的にパスワードを変更させる。
- IAMグループ「developers」に割り当てる。
6. IAMユーザー作成後の初回のサインイン時にやること
-
再度、サインインする
5. AWS Config ルールでチェック、チェック!
AWS Configの初期設定とマネージドルールを Terraform で設定して、非準拠項目を確認して対処してみる
6. コード化
-
MFA デバイスの自己管理を許可する ポリシー を Terraform で作成する。
※ AWS Documentの方は、AWSアカウントIDのところが「*」になっている。
※ 下記の Terraform では、実際のアカウントIDが入るようにしている。
data "aws_caller_identity" "current" {
}
data "aws_iam_policy_document" "policy-document_enable-mfa-device" {
version = "2012-10-17"
statement {
effect = "Allow"
actions = [
"iam:ListUsers",
"iam:ListVirtualMFADevices"
]
resources = [
"*"
]
}
statement {
effect = "Allow"
actions = [
"iam:ListMFADevices"
]
resources = [
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:mfa/*",
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:user/$${aws:username}"
]
}
statement {
effect = "Allow"
actions = [
"iam:CreateVirtualMFADevice",
"iam:DeleteVirtualMFADevice",
"iam:EnableMFADevice",
"iam:ResyncMFADevice"
]
resources = [
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:mfa/$${aws:username}",
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:user/$${aws:username}"
]
}
statement {
effect = "Allow"
actions = [
"iam:DeactivateMFADevice"
]
resources = [
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:mfa/$${aws:username}",
"arn:aws:iam::${data.aws_caller_identity.current.account_id}:user/$${aws:username}"
]
condition {
test = "Bool"
variable = "aws:MultiFactorAuthPresent"
values = ["true"]
}
}
statement {
effect = "Deny"
not_actions = [
"iam:CreateVirtualMFADevice",
"iam:EnableMFADevice",
"iam:ListMFADevices",
"iam:ListUsers",
"iam:ListVirtualMFADevices",
"iam:ResyncMFADevice"
]
resources = [
"*"
]
condition {
test = "BoolIfExists"
variable = "aws:MultiFactorAuthPresent"
values = ["false"]
}
}
}
resource "aws_iam_policy" "policy_enable-mfa-device" {
name = "enable-mfa-device"
policy = data.aws_iam_policy_document.policy-document_enable-mfa-device.json
}
- IAMグループ「developers」を Terraform で作成する。
-
PowerUserAccess ポリシーと、MFA デバイスの自己管理を許可する ポリシーの「enable-mfa-device」をアタッチする。
- 「************」のところは、実際のAWSアカウントIDに置き換えて
resource "aws_iam_group" "developers" {
name = "developers"
path = "/"
}
resource "aws_iam_group_policy_attachment" "developers-PowerUserAccess" {
group = aws_iam_group.developers.name
policy_arn = "arn:aws:iam::aws:policy/PowerUserAccess"
}
resource "aws_iam_group_policy_attachment" "developers-enable-mfa-device" {
group = aws_iam_group.developers.name
policy_arn = "arn:aws:iam::************:policy/enable-mfa-device"
}
- IAMユーザー「userA」を CloudFormation で作成する。
- Groups は、「developers」を設定する
- UserNaameは、「userA」を設定する
- Password は、パスワードポリシーに準拠したもの
- PasswordResetRequired(パスワードのリセットが必要)は無効にする。
AWSTemplateFormatVersion: 2010-09-09
Description: IAM User - userA
Resources:
IAMUser:
Type: 'AWS::IAM::User'
Properties:
Groups:
- developers
Path: /
UserName: userA
LoginProfile:
Password: ************
PasswordResetRequired: false
Outputs:
IAMUser:
Description: IAM User Name
Value: !Ref IAMUser