複数AWSアカウントのユーザ管理を、ログイン用AWS環境に集約してみた

2016.12.29

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

AWSチームのすずきです。

IAM権限の分離や、請求情報の明確化を実現する手段として、AWSアカウントの分割を実施する事があります。

統合認証基盤と連携したSSOなどを利用しない場合、ユーザ管理の煩雑化が問題となる事がありましたが、 複数のAWSアカウントで構成された環境のIAMユーザ管理と、その権限管理を ログイン専用のAWS環境を用意し、効率化する機会がありました。

その内容について紹介させて頂きます。

概要図

iam-login-04

基本方針

当該環境のAWS、IAMの利用方針は以下としました。

  • 開発、本番環境では、IAMはRoleの利用を原則とします。
  • IAMユーザはログイン環境のみに設置します。
  • Roleに対応しないツールに限り、例外としてIAMユーザ(アクセスキー)の設置を認めます。
  • 全てのIAMユーザは定期的な棚卸し対象とし、放置を回避します。
  • 開発、本番環境のRole、2種類、参照専用(readonly)、変更可能(admin)を用意します。
  • 変更可能(admin)なRoleは、管理者グループに所属するユーザに限定して提供します。
  • Roleを利用(スイッチロール)する際、MFA必須、事前登録済みのIPアドレス以外での利用を禁止します。
  • ログイン環境のIAMユーザの不正利用に備えます。

参考

ログイン環境から、開発本番環境の操作にはスイッチロールを利用します。その概要、利用方法は以下をご覧ください。

実装詳細

ログイン環境

IAMグループ

  • IAMグループを利用し、ログイン環境のIAMユーザに付与する権限を管理します
  • インラインポリシーを作成し、付与するIAM権限を設定します。
IAM更新用ポリシー
  • 自身の認証情報(パスワード、MFA設定)に必要とするIAM権限を付与します。
  • 「000000000000」はログイン環境のAWSアカウントIDに置き換えます。
  • Policy-allow-iam-mfa-password
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"iam:ListUsers"
],
"Resource": [
"arn:aws:iam::000000000000:user/"
],
"Effect": "Allow"
},
{
"Action": [
"iam:ListVirtualMFADevices"
],
"Resource": [
"arn:aws:iam::000000000000:mfa/"
],
"Effect": "Allow"
},
{
"Action": [
"iam:EnableMFADevice",
"iam:DeactivateMFADevice",
"iam:ResyncMFADevice",
"iam:ListMFADevices",
"iam:ChangePassword"
],
"Resource": [
"arn:aws:iam::000000000000:user/${aws:username}"
],
"Effect": "Allow"
},
{
"Action": [
"iam:DeleteVirtualMFADevice",
"iam:CreateVirtualMFADevice"
],
"Resource": [
"arn:aws:iam::000000000000:mfa/${aws:username}"
],
"Effect": "Allow"
},
{
"Action": [
"iam:GetAccountPasswordPolicy"
],
"Resource": [
"arn:aws:iam::000000000000:*"
],
"Effect": "Allow"
}
]
}
Role利用ポリシー
  • 203.0.113.0/24、192.0.2.0/24、198.51.100.0/24 は、作業拠点、VPN環境などのグローバルIPに置き換えます。
  • 開発環境(000000000001)、本番環境(000000000002)に設置したRoleの利用許可を、対象リソースを明示して与えます。
  • PolicyGroupAdmin(管理者用)
{
"Version": "2012-10-17",
"Statement": [
{
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"203.0.113.0/24",
"192.0.2.0/24",
"198.51.100.0/24"
]
}
},
"Action": [
"sts:AssumeRole"
],
"Resource": [
"arn:aws:iam::000000000001:role/role-readonly*",
"arn:aws:iam::000000000001:role/role-admin*",
"arn:aws:iam::000000000002:role/role-readonly*",
"arn:aws:iam::000000000002:role/role-admin*"
],
"Effect": "Allow"
}
]
}
  • PolicyGroupReadOnly(参照用)
{
"Version": "2012-10-17",
"Statement": [
{
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"203.0.113.0/24",
"192.0.2.0/24",
"198.51.100.0/24"
]
}
},
"Action": [
"sts:AssumeRole"
],
"Resource": [
"arn:aws:iam::000000000001:role/role-readonly*",
"arn:aws:iam::000000000002:role/role-readonly*",
],
"Effect": "Allow"
}
]
}

開発、本番環境

共通

  • 信頼関係「sts:AssumeRole」の許可先として、ログイン環境のAWSアカウントを指定します
  • ログイン環境のIAMユーザの「sts:AssumeRole」は、「Resource:」を明示して設定されているものとします。

  • AWS操作をMFA必須とするため、条件として「aws:MultiFactorAuthPresent」を「true」とします。

管理者用

  • 「Administrator」の管理ポリシーに相当する、IAMの全権限の許可を与えます
  • 実環境では、開発、運用のフェーズや担当者の役割に応じた、より適切な管理ポリシー、ロールの利用をお勧めします。

iam-login-01

参照専用

  • 平時の確認作業を想定し、「ReadOnlyAccess」の管理ポリシーを付与しています。
  • 管理ポリシー「ReadOnlyAccess」では不足するサービスの権限はインラインポリシーを追加します
  • 今回、DynamoDBの不正参照や、スロットル回避の為、DynamoDBのScanを禁止(Deny)としています。

iam-login-02

まとめ

AWSアカウントを複数用意した場合、アカウントの管理工数の増加が課題となる事がありましたが、 ログイン用のAWSアカウントを用意し、そのIAMを適切に設定する事で集約管理が実現できました。

Unixの「sudo」的にAWSアカウントをスイッチロールを実施する事で、 接続元IPの限定や、MFA利用の徹底、変更ログ(Cloudtrail)の作業者の明確化も可能になります。

ログイン環境で利用するIAMやSTSなどのAWSのサービスは課金対象外のサービスとなるため、 追加費用負担なく、多数のAWSアカウントを管理する環境として利用する事が可能です。

※CloudTrail、AWS Configなどを利用した場合、若干の費用は生じます。

複数のAWSアカウントの管理を効率化するサービスとしてAWS Organizationsが発表され、 2016年12月現在プレビュー募集が開始されていますが、 既存環境で、複数のAWSアカウントで構成されているIAM管理の見直しの機会がありましたら、 ログイン用のAWS環境を是非お試しください。

サンプル

  • 今回紹介したサンプル環境を再現可能なCloudFormationテンプレートです。

ログイン環境用

  • IAMグループ、IAMユーザを生成します
  • 接続元IP(203.0.113.0/24、192.0.2.0/24、198.51.100.0/24) は置き換えます
  • スイッチ先ロールのアカウント(000000000001、000000000002)も置き換えます
AWSTemplateFormatVersion: "2010-09-09"
Description: "login account (IAM user, group)"

Mappings:
#IP制限の許可対象
IpAddress:
base01:
ip01: "203.0.113.0/24"
ip02: "192.0.2.0/24"
ip03: "198.51.100.0/24"

Resources:
#IAMユーザ(ログイン用)
#パスワードはAWSマネジメントコンソールを利用して発行
IamUser01:
Type: "AWS::IAM::User"
Properties:
UserName: "hogehoge"
Groups:
- Ref: GroupAdmin
IamUser02:
Type: "AWS::IAM::User"
Properties:
UserName: "fugafuga"
Groups:
- Ref: GroupReadonly

#IAMグループ(Admin用)
#000000000001、000000000002はスイッチ先のAWSアカウントに差替
GroupAdmin:
Type: "AWS::IAM::Group"
Properties:
GroupName: "group-admin"
Policies:
- PolicyName: PolicyGroupAdmin
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "sts:AssumeRole"
Resource:
- "arn:aws:iam::000000000001:role/role-readonly*"
- "arn:aws:iam::000000000001:role/role-admin*"
- "arn:aws:iam::000000000002:role/role-readonly*"
- "arn:aws:iam::000000000002:role/role-admin*"
Condition:
IpAddress:
"aws:SourceIp":
- "Fn::FindInMap":
- IpAddress
- base01
- ip01
- "Fn::FindInMap":
- IpAddress
- base01
- ip02
- "Fn::FindInMap":
- IpAddress
- base01
- ip03

#IAMグループ(ReadOnly用)
GroupReadonly:
Type: "AWS::IAM::Group"
Properties:
GroupName: "group-readonly"
Policies:
- PolicyName: PolicyGroupReadonly
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "sts:AssumeRole"
Resource:
- "arn:aws:iam::000000000001:role/role-readonly*"
- "arn:aws:iam::000000000002:role/role-readonly*"
Condition:
IpAddress:
"aws:SourceIp":
- "Fn::FindInMap":
- IpAddress
- base01
- ip01
- "Fn::FindInMap":
- IpAddress
- base01
- ip02
- "Fn::FindInMap":
- IpAddress
- base01
- ip03

#IAMポリシー(共通:自身のパスワードとMFA変更を許可)
PolicyAllowIamMfaPassword:
Type: "AWS::IAM::Policy"
Properties:
PolicyName: "Policy-allow-iam-mfa-password"
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "iam:ListUsers"
Resource:
- "Fn::Join":
- ""
- - "arn:aws:iam::"
- Ref: "AWS::AccountId"
- ":user/"
- Effect: Allow
Action:
- "iam:ListVirtualMFADevices"
Resource:
- "Fn::Join":
- ""
- - "arn:aws:iam::"
- Ref: "AWS::AccountId"
- ":mfa/"
- Effect: Allow
Action:
- "iam:EnableMFADevice"
- "iam:DeactivateMFADevice"
- "iam:ResyncMFADevice"
- "iam:ListMFADevices"
- "iam:ChangePassword"
Resource:
- "Fn::Join":
- ""
- - "arn:aws:iam::"
- Ref: "AWS::AccountId"
- ":user/${aws:username}"
- Effect: Allow
Action:
- "iam:DeleteVirtualMFADevice"
- "iam:CreateVirtualMFADevice"
Resource:
- "Fn::Join":
- ""
- - "arn:aws:iam::"
- Ref: "AWS::AccountId"
- ":mfa/${aws:username}"
- Effect: Allow
Action:
- "iam:GetAccountPasswordPolicy"
Resource:
- "Fn::Join":
- ""
- - "arn:aws:iam::"
- Ref: "AWS::AccountId"
- ":*"
Groups:
- Ref: GroupAdmin
- Ref: GroupReadonly

開発、本番環境用

  • 開発(000000000001)、本番(000000000002)のAWS環境に設置する、スイッチ先となるIAMロールを作成します。
  • スイッチ元、ログイン環境のAWSアカウント(000000000000)を差し替えて利用します。 - Roleの種類を増やさない場合、各アカウント共通で利用可能です。
AWSTemplateFormatVersion: "2010-09-09"
Description: "Create IAM Role (switch target) 201612"
Parameters:
OriginalAWSaccountID:
Description: "Switch original AWSaccount ID"
Type: String
Default: "000000000000"
Resources:
RoleAdmin:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS:
"Fn::Join":
- ""
- - "arn:aws:iam::"
- Ref: OriginalAWSaccountID
- ":root"
Action: "sts:AssumeRole"
Condition:
Bool:
"aws:MultiFactorAuthPresent": true
Policies:
- PolicyName: RolepolicyAdmin
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Action:
- "*"
Resource:
- "*"
RoleName: "role-admin"
RoleReadonly:
Type: "AWS::IAM::Role"
Properties:
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/ReadOnlyAccess"
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Allow
Principal:
AWS:
"Fn::Join":
- ""
- - "arn:aws:iam::"
- Ref: OriginalAWSaccountID
- ":root"
Action: "sts:AssumeRole"
Condition:
Bool:
"aws:MultiFactorAuthPresent": true
Policies:
- PolicyName: RolepolicyDeny
PolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: Deny
Action:
- "dynamodb:Scan"
Resource:
- "*"
RoleName: "role-readonly"