AWS Organizations不要:CloudFormation StackSetsを使って、マルチアカウント環境でJumpアカウント方式を実装してみた
こんにちは!クラウド事業本部のおつまみです。
みなさん、マルチアカウント環境のユーザー管理に悩んでいませんか?私は悩んでいました。
AWSアカウントでユーザー管理するには、以下のような方法があります。
- 各 AWS アカウントで IAM ユーザーを個別に管理する
- 1 つのアカウントで IAM ユーザーを一元管理し、他のアカウントにスイッチロールする(Jumpアカウント方式)
- AWS IAM Identity Center で管理する
通常マルチアカウント環境であれば、AWS OrganizationsとAWS IAM Identity Center を利用するのが一般的ですが、組織の事情によりAWS Organizationsが使えない場合もありますよね。
そこで、「2. 1 つのアカウントで IAM ユーザーを一元管理し、他のアカウントにスイッチロールする(Jumpアカウント方式)」を実装してみたのでご紹介します。
実装にあたりこちらのブログを参考にさせていただきました。
ありがとうございます。
3行まとめ(実装のポイント)
- AWS Organizationsなしでも、IAMグループを活用してマルチアカウント環境を効率的に管理可能
- CloudFormation StackSetsを使用することで、複数アカウントに同じIAMリソースを一括デプロイ可能
- MFA強制とスイッチロール方式により、セキュリティを保ちながら運用負荷を大幅に軽減
Jumpアカウント方式とは
概要
はじめてJumpアカウント方式を知った方のために、おさらいしましょう。
Jumpアカウント方式は、一つの管理用アカウント(管理アカウント)にIAMユーザーを集約し、そこから各プロジェクトアカウントへスイッチロールでアクセスする仕組みです。
この方式では、以下のような構成になります。
- 管理アカウント:IAMユーザーを一元管理する拠点アカウント
- プロジェクトアカウント:実際のワークロードが動作するアカウント(本番・ステージング等)
メリット
この方式を利用すると、各アカウント別にIAMユーザーを管理する方法と比較し、以下のようなメリットがあります。
項目 | 各アカウント別IAMユーザー管理 | Jumpアカウント方式 |
---|---|---|
ユーザー管理 | アカウント数×ユーザー数分のIAMユーザーを個別管理 | 1つのアカウントでIAMユーザーを一元管理 |
新規ユーザー追加 | 必要なアカウント数分の作業が発生 | 1回の作業で完了(グループ割り当てのみ) |
退職時の処理 | 全アカウントでユーザー削除作業が必要 | Jumpアカウントのみでユーザー削除 |
パスワードポリシー | アカウントごとに個別設定・管理 | 統一されたポリシーを一元管理 |
MFA設定 | ユーザーがアカウントごとに個別設定 | 統一されたMFA強制ポリシー |
権限変更 | 対象アカウントで個別にポリシー変更 | グループ変更のみで権限調整 |
アカウント追加時 | 新アカウントに全ユーザーを個別作成 | StackSetsインスタンス追加のみで対応可 |
セキュリティリスク | 削除漏れ・設定漏れのリスクが高い | 一元管理によりリスク軽減 |
運用工数 | アカウント数に比例して増加 | アカウント数に関係なく一定 |
今後アカウントの増加が見込める場合はこの方式により管理コストを大幅に削減することができます。
実装してみた
前提条件
- AWSアカウントは3つ
- 管理用アカウント
- IAMユーザの管理
- 後述するStackSetsの管理用アカウント
- プロジェクトA本番用アカウント
- プロジェクトAステージング用アカウント
- プロジェクト用の作業アカウント
- 管理用アカウント
- アカウントには、以下3つの役割でアクセスする想定。
- 管理者
- 全ての権限を持つ(AdministratorAccess相当)
- 開発者
- 開発者用の権限を持つ(PowerUserAccess相当)
- 運用者
- 読み取り権限のみを持つ(ReadOnlyAccess相当)
- 管理者
構成図
今回実装する構成の概要です。
IAMグループを全アカウントにアクセス可能なグローバルグループと特定プロジェクトのみアクセス可能なグループに分けることで、組織全体の権限管理を効率化しつつ、プロジェクト単位での適切なアクセス制御を実現できます。
構成要素
管理アカウント
- IAMグループ
- グローバルグループ:全アカウントにアクセス可能(Jump向け)
group-admin
:全アカウントの管理者ロールにアクセスgroup-developer
:全アカウントの開発者ロールにアクセスgroup-operator
:全アカウントの運用者ロールにアクセス
- プロジェクト固有グループ:特定プロジェクトのみアクセス可能
group-admin-<projectname>
:特定プロジェクトの管理者権限group-developer-<projectname>
:特定プロジェクトの開発者権限group-operator-<projectname>
:特定プロジェクトの運用者権限
- グローバルグループ:全アカウントにアクセス可能(Jump向け)
- IAMユーザー: AWSマネジメントコンソールにログインするユーザー
- IAMロール: 各権限レベルに対応したロール(管理者用、開発者用、運用者用)
- CloudFormation: テンプレート管理とStackSets機能を活用
- Amazon S3: CloudFormationテンプレートの保存場所
プロジェクトAアカウント
- IAMロール: 各権限レベルに対応したロール(管理者用、開発者用、運用者用)
実装手順
今回利用するコードは以下リポジトリに格納しています。
適宜cloneしてお使いください。
1.事前準備
1-1.管理アカウントにてS3バケットの作成、CloudFormationテンプレートアップロード
このステップで、管理アカウントでS3バケットを作成し、テンプレートをアップロードします。
- AWSマネジメントコンソールの右上からCloudShellを起動します
- CloudShellが開いたら、画面上部の「アクション」メニューから「ファイルのアップロード」を選択します
- ファイル選択ダイアログが表示されるので以下のファイルを選択し、アップロードします。
- stackset-admin-role.yaml
- iam-global-groups.yaml
- iam-groups.yaml
- iam-roles.yaml
- 以下のコマンドをコピー&ペーストして実行します。
# バケット名はグローバルで一意になるように設定してください
export ADMIN_ACCOUNT_ID=$(aws sts get-caller-identity --query "Account" --output text)
export BUCKET_NAME=aws-iam-templates-${ADMIN_ACCOUNT_ID}
export REGION=ap-northeast-1
# S3バケットを作成
aws s3 mb s3://${BUCKET_NAME} --region ${REGION}
# CloudFormationテンプレートをアップロード
aws s3 cp stackset-admin-role.yaml s3://${BUCKET_NAME}/
aws s3 cp iam-global-groups.yaml s3://${BUCKET_NAME}/
aws s3 cp iam-groups.yaml s3://${BUCKET_NAME}/
aws s3 cp iam-roles.yaml s3://${BUCKET_NAME}/
# バケットポリシーを設定して管理アカウント内のみアクセス可能にする
aws s3api put-bucket-policy --bucket ${BUCKET_NAME} --policy '{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::'${ADMIN_ACCOUNT_ID}':root"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::'${BUCKET_NAME}'/*"
}
]
}'
# S3バケットが作成されたことを確認
aws s3 ls | grep ${BUCKET_NAME}
# テンプレートファイルがアップロードされたことを確認
aws s3 ls s3://${BUCKET_NAME}/
- S3バケット名「aws-iam-templates-<ADMIN_ACCOUNT_ID>」が表示され、ファイルがアップロードされていることが確認できれば完了です
2. デプロイ手順
2-1. StackSets実行ロール作成
このステップで、管理アカウントからCloudFormation StatckSetsを実行するためのIAMロールを各アカウントに作成します。
「2-1-1. マネジメントコンソールで手動実行」もしくは「2-1-2. AWS CLIでコマンド実行」の手順を実行します。
2-1-1. マネジメントコンソールで手動実行
- 管理アカウントでCloudFormation コンソールを開きます
- 「スタックの作成」>「新しいリソースを使用(標準)」をクリックします
- 「既存のテンプレートを選択」を選択し、「テンプレートファイルのアップロード」を選択します
- 「stackset-execution-role.yaml」をアップロードします
- 「次へ」をクリックし、スタック名を
stackset-execution-role
と入力します - パラメータで「AdminAccountId」に管理アカウントのIDを入力します
- 「次へ」をクリックし、「スタックの作成オプション」セクションで「削除保護」を「アクティブ化済み」、「機能」セクションで「AWS CloudFormation によって IAM リソースがカスタム名で作成される場合があることを承認します。」にチェックを入れます
- 「次へ」をクリックし、「送信」を選択します
- スタックが作成され、「CREATE_COMPLETE」と出力されることを確認します
※ プロジェクト用の本番・ステージングアカウントも同手順で実施します
2-1-2. AWS CLIでコマンド実行
- AWSマネジメントコンソールの右上からCloudShellを起動します
- CloudShellが開いたら、画面上部の「アクション」メニューから「ファイルのアップロード」を選択します
- ファイル選択ダイアログが表示されるので、「stackset-execution-role.yaml」ファイルを選択します
- アップロードが完了したら、以下のコマンドで<ADMIN_ACCOUNT_ID> を置換し、CloudFormationスタックを作成します
aws cloudformation create-stack \
--stack-name stackset-execution-role \
--template-body file://stackset-execution-role.yaml \
--parameters ParameterKey=AdminAccountId,ParameterValue=<ADMIN_ACCOUNT_ID> \
--capabilities CAPABILITY_NAMED_IAM \
--enable-termination-protection
- 数分経過してから、スタックの作成状況を以下のコマンドで確認します
aws cloudformation describe-stacks --stack-name stackset-execution-role --query "Stacks[0].StackStatus"
- 「CREATE_COMPLETE」が表示されれば完了です
※ プロジェクト用の本番・ステージングアカウントも同手順で実施します
2-2. 管理アカウントでのStackSets管理ロール作成
このステップで、管理アカウントからCloudFormation StatckSetsを実行するためのIAMロールを管理アカウントに作成します。
- 管理アカウントで、以下のURLにて<ADMIN_ACCOUNT_ID> を置換し、ブラウザで開いてテンプレートをデプロイします
https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/create/review?templateURL=https://aws-iam-templates-<ADMIN_ACCOUNT_ID>.s3.ap-northeast-1.amazonaws.com/stackset-admin-role.yaml&stackName=stackset-admin-role
- 「スタックの作成オプション」セクションで「削除保護」を「アクティブ化済み」、「機能」セクションで「AWS CloudFormation によって IAM リソースがカスタム名で作成される場合があることを承認します。」にチェックを入れ、「送信」を選択します
- スタックが作成され、「CREATE_COMPLETE」と出力されることを確認します
2-3. 管理アカウントでのIAMグループとポリシー作成
2-3-1. グローバル管理者グループ(管理用)の作成
このステップで、全アカウントにログインできるグローバルグループ(「group-admin」、「group-developer」、「group-operator」)と共通で使用するMFAポリシー「policy-enforce-mfa」が作成されます。グローバルグループのメンバーは全アカウントの対応するロールにアクセスできます。
- グローバル管理者グループ(group-admin)のメンバーは全アカウントの管理者ロール(role-admin)にアクセス可能
- グローバル開発者グループ(group-developer)のメンバーは全アカウントの開発者ロール(role-developer)にアクセス可能
- グローバル運用者グループ(group-operator)のメンバーは全アカウントの運用者ロール(role-operator)にアクセス可能
- 管理アカウントで、以下のURLで<ADMIN_ACCOUNT_ID> を置換し、ブラウザで開いてグローバルグループのテンプレートをデプロイします
https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/create/review?templateURL=https://aws-iam-templates-<ADMIN_ACCOUNT_ID>.s3.ap-northeast-1.amazonaws.com/iam-global-groups.yaml&stackName=iam-global-groups
- 「スタックの作成オプション」セクションで「削除保護」を「アクティブ化済み」、「機能」セクションで「AWS CloudFormation によって IAM リソースがカスタム名で作成される場合があることを承認します。」にチェックを入れ、「送信」を選択します
- スタックが作成され、「CREATE_COMPLETE」と出力されることを確認します
2-3-2. プロジェクト固有のグループの作成
このステップで、プロジェクト固有のグループを管理者・開発者・運用者に分けて作成します。各グループのメンバーはポリシーによりプロジェクトのアカウントに対して、それぞれの役割に応じたアクセス権限が付与されます。作成されるグループとロールの対応は以下の通りです:
group-admin-<projectname>
→ 本番・ステージングの両アカウントのrole-admin
にアクセス可能group-developer-<projectname>
→ 本番・ステージングの両アカウントのrole-developer
にアクセス可能group-operator-<projectname>
→ 本番・ステージングの両アカウントのrole-operator
にアクセス可能
各グループには自動的にMFA強制ポリシーが適用され、ユーザーは多要素認証を設定しないとロールを引き受けることができません。
- 管理アカウントで、以下のURLで<ADMIN_ACCOUNT_ID> を置換し、ブラウザで開いてプロジェクト固有グループのテンプレートをデプロイします
https://console.aws.amazon.com/cloudformation/home?region=ap-northeast-1#/stacks/create/review?templateURL=https://aws-iam-templates-<ADMIN_ACCOUNT_ID>.s3.ap-northeast-1.amazonaws.com/iam-groups.yaml&stackName=iam-groups-<projectname>
- パラメータを以下のように入力します:
- 「ProdAccountId」にプロジェクト本番アカウントのIDを入力します
- 「StagingAccountId」にプロジェクトステージングアカウントのIDを入力します(ステージングアカウントがない場合は空欄でも可)
- 「HasStagingAccount」にステージングアカウントの有無を選択します(デフォルトは「true」)
- 「ProjectName」にプロジェクト名を入力します(例:
projectA
)
- 全画面で「次へ」をクリックし、「送信」を選択します
- スタックが作成され、「CREATE_COMPLETE」と出力されることを確認します
2-4. スイッチロール用IAMロールの作成(StackSets使用)
このステップで、本番・ステージングアカウントに必要なIAMロール(role-admin、role-developer、role-operator)を一括して作成します。CloudFormation StackSetsを使用することで、複数のアカウントに同じテンプレートを適用できます。これらのロールは管理アカウントのIAMユーザーがスイッチロールする際に利用される重要なリソースです。各ロールには適切な権限が付与され、MFA認証が強制されます。
「2-4-1. マネジメントコンソールで手動実行」もしくは「2-4-2. AWS CLIでコマンド実行」の手順を実行する
2-4-1. マネジメントコンソールで手動実行
- 管理アカウントでCloudFormation StackSetsコンソールを開きます
- 「StackSetの作成」をクリックします
- 「アクセス許可」セクションの「IAM実行ロール」に「AWSCloudFormationStackSetExecutionRole」を入力します
- 「テンプレートの指定」>「Amazon S3 URL」を選択し、以下のテンプレートURLの<ADMIN_ACCOUNT_ID> を置換し、を入力します
https://aws-iam-templates-<ADMIN_ACCOUNT_ID>.s3.ap-northeast-1.amazonaws.com/iam-roles.yaml
- 「次へ」をクリックし、StackSetの名前を
iam-roles
と入力します - パラメータ「AdminAccountId」に管理アカウントのIDを入力します
- 「次へ」をクリックし、「機能」セクションで「AWS CloudFormation によって IAM リソースがカスタム名で作成される場合があることを承認します。」にチェックを入れます
- 「次へ」をクリックし、「デプロイオプション」の設定で以下を選択します
- 「スタックセットにスタックを追加」で「新しいスタックのデプロイ」を選択
- 「デプロイ先」で「スタックをアカウントにデプロイ」を選択
- 「アカウント番号」管理アカウント、プロジェクトAの本番・開発アカウントのIDをカンマ区切りで入力(例.111111111111,222222222222,333333333333)
- 「リージョンの指定」で「ap-northeast-1」を選択
- 「デプロイオプション」はデフォルトのまま
- 「次へ」をクリックし、設定を確認して「送信」をクリックします
- 「オペレーション」タブからステータスが「SUCCEEDED」になっていることを確認する
2-4-2. AWS CLIでコマンド実行
AWS CLIでスイッチロール用IAMロールをStackSetsで作成する手順です
- 管理アカウントでCloudShellを起動します
- 以下のコマンドで<ADMIN_ACCOUNT_ID> を置換し、StackSetを作成します
aws cloudformation create-stack-set \
--stack-set-name iam-roles \
--template-url https://aws-iam-templates-<ADMIN_ACCOUNT_ID>.s3.ap-northeast-1.amazonaws.com/iam-roles.yaml \
--parameters ParameterKey=AdminAccountId,ParameterValue=<ADMIN_ACCOUNT_ID> \
--capabilities CAPABILITY_NAMED_IAM \
--permission-model SELF_MANAGED \
--execution-role-name AWSCloudFormationStackSetExecutionRole
- 以下のコマンドでStackSet
iam-roles
がActive
であることを確認します
aws cloudformation describe-stack-set --stack-set-name iam-roles --query "StackSet.Status" --output text
- 作成したStackSetに対して、本番アカウントとステージングアカウント、および管理アカウント自身へのスタックインスタンスをデプロイします
aws cloudformation create-stack-instances \
--stack-set-name iam-roles \
--accounts <PROJECTA_PRD_ACCOUNT_ID>,<PROJECTA_STG_ACCOUNT_ID>,<ADMIN_ACCOUNT_ID> \
--regions ap-northeast-1 \
--operation-preferences MaxConcurrentPercentage=100,FailureTolerancePercentage=0
- 4で出力されたオペレーションIDを取得し、以下のコマンドの<オペレーションID>に置換します。コマンドを実行し、ステータスが「SUCCEEDED」と表示されることを確認します。
aws cloudformation describe-stack-set-operation \
--stack-set-name iam-roles \
--operation-id <オペレーションID> \
--query "StackSetOperation.Status" \
--output text
2-5. IAMユーザーの作成
このステップで、管理アカウントにAWSマネジメントコンソールへのアクセス権を持つIAMユーザーを作成します。作成したユーザーは適切なIAMグループに所属させることで、スイッチロールを通じてプロジェクトアカウントのリソースにアクセスできるようになります。ユーザーには初回ログイン時に変更が必要な一時パスワードが発行され、MFA認証の設定が強制されます。
「2-5-1. マネジメントコンソールで手動実行」もしくは「2-5-2. AWS CLIでコマンド実行」の手順を実行します。
2-5-1. マネジメントコンソールで手動実行
- AWSマネジメントコンソールにログインし、IAMサービスを開きます
- 左側のナビゲーションメニューから「ユーザー」を選択し、「ユーザーを作成」をクリックします
- ユーザー詳細の設定
- ユーザー名を入力(例:global-admin-yamada.taro)
- 「AWS マネジメントコンソールへのユーザーアクセスを提供する」にチェックを入れる
- 「自動生成されたパスワード」、「ユーザーは次回のサインイン時に新しいパスワードを作成する必要があります」にチェックを入れる
- 「次へ」をクリック
- アクセス許可の設定
- 「ユーザーをグループに追加」を選択
- ユーザーの役割に応じて適切なグループを選択:
- グローバル管理者:
group-admin
(全アカウントの管理者ロールにアクセス可能) - グローバル開発者:
group-developer
(全アカウントの開発者ロールにアクセス可能) - グローバル運用者:
group-operator
(全アカウントの運用者ロールにアクセス可能) - プロジェクト管理者:
group-admin-<projectname>
(特定プロジェクト管理者) - プロジェクト開発者:
group-developer-<projectname>
(特定プロジェクト開発者) - プロジェクト運用者:
group-operator-<projectname>
(特定プロジェクト運用者)
- グローバル管理者:
- 「次へ」をクリック
- 確認と作成
- 設定内容を確認し、「ユーザーの作成」をクリック
- 成功画面で「.csv ファイルをダウンロード」を選択します。
- ダウンロードしたcsvファイル、および適用したIAMグループを安全な方法でユーザーに通知してください
2-5-2. AWS CLIでコマンド実行
- 以下のコマンドでユーザーを作成します
aws iam create-user --user-name <ユーザー名>
- ユーザーをグループに追加します
# 管理管理者の場合(グローバル管理者グループ)
aws iam add-user-to-group --user-name <ユーザー名> --group-name group-admin
もしくは
# 管理開発者の場合(グローバル開発者グループ)
aws iam add-user-to-group --user-name <ユーザー名> --group-name group-developer
もしくは
# 管理運用者の場合(グローバル運用者グループ)
aws iam add-user-to-group --user-name <ユーザー名> --group-name group-operator
もしくは
# 特定プロジェクトの管理者/開発者/運用者の場合
aws iam add-user-to-group --user-name <ユーザー名> --group-name group-admin-<projectname>
グループ名は役割に応じて以下から選択:
- グローバル管理者:
group-admin
(全アカウントの管理者ロールにアクセス可能) - グローバル開発者:
group-developer
(全アカウントの開発者ロールにアクセス可能) - グローバル運用者:
group-operator
(全アカウントの運用者ロールにアクセス可能) - プロジェクト固有管理者:
group-admin-<projectname>
- プロジェクト固有開発者:
group-developer-<projectname>
- プロジェクト固有運用者:
group-operator-<projectname>
1ユーザーあたり10グループまで所属可能です。
複数のグループに所属させたい場合は、各グループに対して個別にコマンドを実行します。
- 以下のコマンドで<ユーザー名>を置換後、コピー&ペーストして、ランダムパスワードを生成して設定します
# ランダムパスワードを生成
PASSWORD=$(openssl rand -base64 12)$(echo '!@#$%^&*()_+-=' | fold -w1 | shuf | head -n1)
# ユーザーにパスワードを設定
aws iam create-login-profile --user-name <ユーザー名> --password "$PASSWORD" --password-reset-required
# 生成されたパスワードを表示
echo "初期パスワード: $PASSWORD"
- 以下の情報を利用ユーザーに通知してください。初期パスワードが含まれているため、安全な方法でユーザーに通知してください。
- コンソールサインイン URL:https://<ADMIN_ACCOUNT_ID>.signin.aws.amazon.com/console
- ユーザー名:<ユーザー名>
- 初期パスワード:手順3で出力された$PASSWORD
- 適用したIAMグループ:所属するグループ名を記載
以上で実装は完了です!
以下はその後の運用も加味した手順を記載いたします。
3. 利用ユーザー手順
このステップで、作成されたIAMユーザーが初めてAWSマネジメントコンソールにログインし、多要素認証(MFA)を設定して、スイッチロールを利用するための手順を説明します。
セキュリティを確保するため、全てのユーザーはMFAを設定する必要があり、これがないとスイッチロールができないよう制限されています。
3-1. MFAの設定(新規ユーザー向け)
- ユーザーは受領した情報でAWSマネジメントコンソールにログインします
- 初回ログイン時にパスワードを変更します
- 「IAM」 > 「ユーザー」 > 「自分のユーザー名」 > 「セキュリティ認証情報」 > 「多要素認証(MFA)」 > 「MFAデバイスの割り当て」 をクリックします
- 仮想MFAデバイスを選択し、スマートフォンのGoogle Authenticatorや1Password等のアプリでQRコードをスキャンします
- アプリに表示される6桁のMFAコードを2回(連続する2つのコード)入力します
- 「MFAの割り当て」をクリックしてMFAの設定を完了します
※ 手順4にて、仮想MFAデバイスでなく、パスキーでの指定も可能です。
参考:AWS Management Consoleでパスキーやセキュリティキーを割り当てる - AWS Identity and Access Management
3-2. スイッチロールの利用方法
- AWSマネジメントコンソールに再ログインします
- 画面右上のユーザー名をクリックし、「ロールの切り替え」を選択します
- 以下の情報を入力します
- アカウント: スイッチロール先のアカウントID(本番、ステージング、管理、または任意のアカウント)
- ロール: 付与されたロール名(以下のいずれか)
- グローバルグループメンバー: 全アカウントの対応するロールのみアクセス可能
group-admin
→role-admin
group-developer
→role-developer
group-operator-
→role-operator
- プロジェクト固有グループメンバー: 所属グループに対応するロールのみアクセス可能
group-admin-<projectname>
→role-admin
group-developer-<projectname>
→role-developer
group-operator-<projectname>
→role-operator
- グローバルグループメンバー: 全アカウントの対応するロールのみアクセス可能
- 表示名: 任意の名前
- 「ロールの切り替え」をクリックします
参考:ユーザーから IAM ロールに切り替える (コンソール) - AWS Identity and Access Management
4. 利用ユーザーの追加手順
4-1. ユーザーの役割と必要なアクセス権限を確認
利用ユーザーにて、必要なアクセス権を確認します。
- グローバル管理者:全アカウントへの管理者アクセスが必要 →
group-admin
- グローバル開発者:全アカウントへの開発者アクセスが必要 →
group-developer
- グローバル運用者:全アカウントへの運用者アクセスが必要 →
group-operator
- プロジェクト管理者:特定アカウントへの管理者アクセスが必要 →
group-admin-<projectname>
- プロジェクト開発者:特定アカウントへの開発者アクセスが必要 →
group-developer-<projectname>
- プロジェクト運用者:特定アカウントへの運用者アクセスが必要 →
group-operator-<projectname>
4-2. 新規ユーザー用のIAMユーザー作成
管理アカウントで「2-5. IAMユーザーの作成」を実行します。
4-3. アクセス権限設定
- ユーザーの役割に応じて適切なグループに追加します
- グローバル管理者:
group-admin
- グローバル開発者:
group-developer
- グローバル運用者:
group-operator
- プロジェクト管理者:
group-admin-<projectname>
- プロジェクト開発者:
group-developer-<projectname>
- プロジェクト運用者:
group-operator-<projectname>
- 複数のアクセス権限が必要な場合は、複数のグループに追加も可能(最大10個)
- 利用ユーザーにて、「3. 利用ユーザー手順」を実施します。
5. 新規アカウントの追加手順
5-1. 新規アカウントでのStackSets実行ロール作成
新規アカウントで「2-1. 本番・ステージングアカウントでのStackSets実行ロール作成」を実行します。
5-2. 新規アカウント用のIAMグループ作成
管理アカウントで「2-3-2. プロジェクト固有の管理グループの作成」の手順に従い、新規アカウント用のグループを作成します。
- 「ProdAccountId」に新規プロジェクト本番アカウントのIDを指定
- 「StagingAccountId」に新規プロジェクトステージングアカウントのIDを指定(ステージングアカウントがない場合は空欄でも可)
- 「HasStagingAccount」にステージングアカウントの有無を選択(ステージングアカウントがない場合は「false」を選択)
- 「ProjectName」に新規プロジェクト名を指定(例:
new-project
)
※ プロジェクトがステージングアカウントを持たない場合は、「HasStagingAccount」を「false」に設定し、「StagingAccountId」は空欄のままでも問題ありません。
5-3. StackSetsインスタンスの追加
管理アカウントのStackSetsコンソールから、以下の手順で新規アカウントにIAMロールをデプロイします
「5-3-1. マネジメントコンソールで手動実行」もしくは「5-3-2. AWS CLIでコマンド実行」の手順を実行します。
5-3-1. マネジメントコンソールで手動実行
- CloudFormation StackSetsコンソールを開きます
- StackSets名「iam-roles」を選択し、「アクション」から「StackSetにスタックを追加」を選択します
- 「デプロイオプション」の設定で以下を選択します
- 「スタックセットにスタックを追加」で「新しいスタックのデプロイ」を選択
- 「デプロイ先」で「スタックをアカウントにデプロイ」を選択
- 「アカウント番号」新規アカウントIDを入力
- 「リージョンの指定」で「ap-northeast-1」を選択
- 「デプロイオプション」はデフォルトのまま
- 「次へ」をクリックし、「パラメータ」は上書きせずデフォルトのまま
- 「次へ」をクリックし、設定を確認して「送信」をクリックします
5-3-2. AWS CLIでコマンド実行
- 管理アカウントでCloudShellを起動します
- 以下のコマンドにて、
<新規アカウントID>
には、新規アカウントのIDを置換し、実行します。管理アカウント自身にもデプロイする場合は管理アカウントのIDも含めます。
# 新規アカウントへStackSetインスタンスをデプロイ
aws cloudformation create-stack-instances \
--stack-set-name iam-roles \
--accounts <新規アカウントID> \
--regions ap-northeast-1 \
--operation-preferences MaxConcurrentPercentage=100,FailureTolerancePercentage=0
- コマンド実行後に出力されたオペレーションIDを取得し、以下のコマンドの<オペレーションID>に置換します。以下のコマンドで実行状況を確認します。
# <オペレーションID>を実際に出力されたIDに置き換えてください
aws cloudformation describe-stack-set-operation \
--stack-set-name iam-roles \
--operation-id <オペレーションID> \
--query "StackSetOperation.Status" \
--output text
- ステータスが「SUCCEEDED」と表示されれば完了です。
これで既存ユーザーから新しいアカウントへのスイッチロールが可能になります。
- グローバル管理者(group-admin,group-developer,group-operatorのメンバー)は、追加の設定なしで新アカウントにアクセス可能
- プロジェクトメンバーは、新アカウントへのアクセス権限が必要な場合、対応するグループに追加する必要あり(以下「5-4. プロジェクトメンバーの設定」を参考に設定する)
5-4. プロジェクトメンバーの設定
5-4-1. 既存メンバーの場合(既にIAMユーザーが存在する場合)
既存のプロジェクトメンバーに新規アカウントへのアクセス権を付与する場合
- 管理アカウントでIAMサービスを開きます
- 左側のナビゲーションメニューから「ユーザーグループ」を選択します
- 新規プロジェクト用のグループ(
group-admin-<projectname>
)を選択します - 「ユーザー」タブで「ユーザーを追加」をクリックします
以下のコマンドでもグループへのユーザー追加が可能です
aws iam add-user-to-group --user-name <ユーザー名> --group-name group-admin-<projectname>
5-4-2. 新規メンバーの場合(IAMユーザーが存在しない場合)
新規プロジェクトのために新たにIAMユーザーを作成する場合は、「2-5. IAMユーザーの作成」の手順に従って実施します
- 「2-5-1. マネジメントコンソールで手動実行」または「2-5-2. AWS CLIでコマンド実行」の手順に従ってユーザーを作成します
- ユーザー作成時に、新規プロジェクト用のグループ(
group-admin-<projectname>
)に所属させます- グループ選択時に、新規プロジェクト用のグループを選択:
- グローバル管理者:
group-admin
- グローバル開発者:
group-developer
- グローバル運用者:
group-operator
- プロジェクト管理者:
group-admin-<projectname>
- プロジェクト開発者:
group-developer-<projectname>
- プロジェクト運用者:
group-operator-<projectname>
- グローバル管理者:
- グループ選択時に、新規プロジェクト用のグループを選択:
- ユーザー作成後、「3. 利用ユーザー手順」の手順に従って初期セットアップを行うよう新規メンバーに指示します
新規メンバーは、MFA設定後に新規アカウントにスイッチロールでアクセスできるようになります。
スイッチロールしてみた
実際に構築したJumpアカウント方式でスイッチロールを試してみます!今回は以下の2つのロールでそれぞれ動作確認を行います。
1. グローバル管理者グループでのスイッチロール
IAMユーザー名:global-admin-yamada.taro
所属するIAMグループ:global-admin
はじめてログインした状態だと、何も権限を持っていないため「アクセス拒否」になっています。
この状態で管理者ロール(role-admin)にスイッチロールしようとすると、以下のエラー画面が表示されます。これはMFAを設定しないと、スイッチロールできない仕組みになっているためです。
「3. 利用ユーザー手順」に従って、MFAを設定し、再ログインした後、再度管理者ロール(role-admin)でスイッチロールしてみます。
スイッチロールに成功しました!
またCloudShellで以下のコマンドを実行し、AdministratorAccess相当の権限であることが確認できました。
~ $ # 現在のロール名を変数に格納
~ $ ROLE_NAME=$(aws sts get-caller-identity --query 'Arn' --output text | cut -d'/' -f2)
~ $
~ $ # アタッチされているマネージドポリシーを確認
~ $ aws iam list-attached-role-policies --role-name $ROLE_NAME
{
"AttachedPolicies": [
{
"PolicyName": "AdministratorAccess",
"PolicyArn": "arn:aws:iam::aws:policy/AdministratorAccess"
}
]
}
なお他のロールで(role-developer)でスイッチロールしようとすると、同様のエラー画面が表示されます。
2. プロジェクトA運用者グループでのスイッチロール
- IAMユーザー名:global-operator-project-a-tanaka.hanako
- 所属するIAMグループ:group-operator-project-a
MFA設定済みの状態で、所属しているプロジェクトのアカウントに運用者ロール(role-operator)でスイッチロールしてみます。問題なくスイッチロールに成功しました。
ReadOnlyのため、CloudShellは実行できません。
次に、別プロジェクトのアカウントへのスイッチロールを試してみます。同様に以下のエラー画面が表示されます。
こちらも期待通りの動作で、プロジェクト固有グループのメンバーは、そのプロジェクトのアカウントにのみアクセス可能という制御が正しく機能していることを確認できました。
まとめ
今回はAWS Organizationsを使わないマルチアカウント環境でのJumpアカウント方式実装についてご紹介しました。
この方式を採用することで、組織の制約がある環境でも効率的でセキュアなマルチアカウント管理が実現できます。
特にCloudFormation StackSetsとIAMのスイッチロール機能を組み合わせることで、スケーラブルで保守性の高いシステムを構築できました。
AWS Organizationsが使えない環境でマルチアカウント管理にお困りの方は、ぜひこのJumpアカウント方式を検討してみてください!
最後までお読みいただきありがとうございました!
以上、おつまみ(@AWS11077)でした!