AWS CloudFormation StackSetsを利用してPermissions boundary用IAMポリシーを複数アカウントで作成してみる
マルチアカウント環境で Permissions boundary (アクセス許可の境界) を利用する場合において、事前に Permissions boundary としてアタッチするための IAM ポリシーを各 AWS アカウントで作成しておきたい場合があります。
本ブログでは、AWS CloudFormation StackSets を利用して複数の AWS アカウントに IAM ポリシーを作成する方法を試してみます。
Permissions boundary の利用例は次のブログで紹介しています。
AWS CloudFormation StackSets については次のブログが参考になります。
作成する IAM ポリシー
AWS ナレッジセンターで紹介されている Permissions boundary 用の IAM ポリシーを作成してみたいと思います。
2023.2.27 追記
参照していた AWS ナレッジセンターのページは削除されていることを確認しました
作成するポリシーです。AccountID
には IAM ポリシーを作成する AWS アカウントのアカウント ID を指定する必要があります。
{ "Version": "2012-10-17", "Statement": [ { "Sid": "AllowAdminAccess", "Effect": "Allow", "Action": "*", "Resource": "*" }, { "Sid": "DenyAccessToCostAndBilling", "Effect": "Deny", "Action": [ "account:*", "aws-portal:*", "savingsplans:*", "cur:*", "ce:*" ], "Resource": "*" }, { "Sid": "DenyPermBoundaryIAMPolicyAlteration", "Effect": "Deny", "Action": [ "iam:DeletePolicy", "iam:DeletePolicyVersion", "iam:CreatePolicyVersion", "iam:SetDefaultPolicyVersion" ], "Resource": [ "arn:aws:iam::<AccountID>:policy/test-permissions-boundary-policy" ] }, { "Sid": "DenyRemovalOfPermBoundaryFromAnyUserOrRole", "Effect": "Deny", "Action": [ "iam:DeleteUserPermissionsBoundary", "iam:DeleteRolePermissionsBoundary" ], "Resource": [ "arn:aws:iam::<AccountID>:user/*", "arn:aws:iam::<AccountID>:role/*" ], "Condition": { "StringEquals": { "iam:PermissionsBoundary": "arn:aws:iam::<AccountID>:policy/test-permissions-boundary-policy" } } }, { "Sid": "DenyAccessIfRequiredPermBoundaryIsNotBeingApplied", "Effect": "Deny", "Action": [ "iam:PutUserPermissionsBoundary", "iam:PutRolePermissionsBoundary" ], "Resource": [ "arn:aws:iam::<AccountID>:user/*", "arn:aws:iam::<AccountID>:role/*" ], "Condition": { "StringNotEquals": { "iam:PermissionsBoundary": "arn:aws:iam::<AccountID>:policy/test-permissions-boundary-policy" } } }, { "Sid": "DenyUserAndRoleCreationWithOutPermBoundary", "Effect": "Deny", "Action": [ "iam:CreateUser", "iam:CreateRole" ], "Resource": [ "arn:aws:iam::<AccountID>:user/*", "arn:aws:iam::<AccountID>:role/*" ], "Condition": { "StringNotEquals": { "iam:PermissionsBoundary": "arn:aws:iam::<AccountID>:policy/test-permissions-boundary-policy" } } }, { "Sid": "DenyIAMActions", "Effect": "Deny", "Action": "iam:PassRole", "Resource": "arn:aws:iam::<AccountID>:role/*" } ] }
CloudFormation テンプレート
作成するポリシーにおいて、ポイントになる部分は``です。CloudFormation テンプレートでリソースを作成するアカウント毎に値を変える必要があります。その解決策として疑似パラメータ参照が利用できます。
擬似パラメータ参照 - AWS CloudFormation
疑似パラメータ参照を利用して、上述の IAM ポリシーを作成する CloudFormation テンプレートの例を示します。
AWSTemplateFormatVersion: 2010-09-09 Description: Create IAM Policy for Permissions boundary Parameters: ManagedPolicyName: Description: Managed policy name for permissions boundary Type: String Resources: IamManagedPolicy: Type: AWS::IAM::ManagedPolicy Properties: Description: Managed policy for permissions boundary ManagedPolicyName: !Sub ${ManagedPolicyName} Path: / PolicyDocument: Version: 2012-10-17 Statement: - Sid: AllowAdminAccess Effect: Allow Action: '*' Resource: '*' - Sid: DenyAccessToCostAndBilling Effect: Deny Action: - 'account:*' - 'aws-portal:*' - 'savingsplans:*' - 'cur:*' - 'ce:*' Resource: '*' - Sid: DenyPermBoundaryIAMPolicyAlteration Effect: Deny Action: - 'iam:DeletePolicy' - 'iam:DeletePolicyVersion' - 'iam:CreatePolicyVersion' - 'iam:SetDefaultPolicyVersion' Resource: !Sub arn:aws:iam::${AWS::AccountId}:policy/${ManagedPolicyName} - Sid: DenyRemovalOfPermBoundaryFromAnyUserOrRole Effect: Deny Action: - 'iam:DeleteUserPermissionsBoundary' - 'iam:DeleteRolePermissionsBoundary' Resource: - !Sub arn:aws:iam::${AWS::AccountId}:user/* - !Sub arn:aws:iam::${AWS::AccountId}:role/* Condition: StringEquals: iam:PermissionsBoundary: !Sub arn:aws:iam::${AWS::AccountId}:policy/${ManagedPolicyName} - Sid: DenyAccessIfRequiredPermBoundaryIsNotBeingApplied Effect: Deny Action: - 'iam:PutUserPermissionsBoundary' - 'iam:PutRolePermissionsBoundary' Resource: - !Sub arn:aws:iam::${AWS::AccountId}:user/* - !Sub arn:aws:iam::${AWS::AccountId}:role/* Condition: StringNotEquals: iam:PermissionsBoundary: !Sub arn:aws:iam::${AWS::AccountId}:policy/${ManagedPolicyName} - Sid: DenyUserAndRoleCreationWithOutPermBoundary Effect: Deny Action: - 'iam:CreateUser' - 'iam:CreateRole' Resource: - !Sub arn:aws:iam::${AWS::AccountId}:user/* - !Sub arn:aws:iam::${AWS::AccountId}:role/* Condition: StringNotEquals: iam:PermissionsBoundary: !Sub arn:aws:iam::${AWS::AccountId}:policy/${ManagedPolicyName} - Sid: DenyIAMActions Effect: Deny Action: 'iam:PassRole' Resource: !Sub arn:aws:iam::${AWS::AccountId}:role/*
テンプレートでは IAM ポリシー名をパラメータとして指定できるようにしています。
ポリシーを定義する PolicyDocument では疑似パラメータ参照である${AWS::AccountId}
を利用してアカウント ID を記載しています。
CloudFormation StackSets でリソース作成
StackSets で複数のアカウントにリソースを作成してみます。
StackSets を利用するためには事前準備が必要です。
AWS Organizations を利用している環境の場合は、次のブログの「(準備) アクセスの有効化」を参考に、AWS CloudFormation StackSets の「アクセスの有効化」を行います。
AWS Organizations を利用していない環境の場合は、次のブログの「事前準備」を参考に StackStes を実行する管理アカウントと実行されるアカウントのそれぞれに対して事前に IAM ロールを作成します。
本ブログでは AWS Organizations を利用している環境で StackSets を展開してみます。
CloudFormation の StackSets メニューにおける「StackSets の作成」から設定を行います。AWS Organizations でアクセスの有効化をしているため「サービスマネージドアクセス許可」を選択し、今回はテンプレートファイルをアップロードします。
StackSets 名とパラメータを入力します。パラメータは作成する IAM ポリシー名を入力します。
今回は、オプションはデフォルト設定のまま進めます。
デプロイは 2 つのアカウントが存在する OU を指定しています。「同時アカウントの最大数」は OU に存在するアカウント数に合わせて 2 としています。
最後にレビューを行い、実行します。
2 つのアカウントに展開されました。
2 つのアカウントで作成されたポリシーを確認してみます。
アカウント ID は例示の値に置換していますが、アカウント毎にアカウント ID が異なるポリシーの作成を確認できました。表示が長いので折りたたんでいます。
アカウント 111122223333 の test-permissions-boundary-policy
{ "Version": "2012-10-17", "Statement": [ { "Action": "*", "Resource": "*", "Effect": "Allow", "Sid": "AllowAdminAccess" }, { "Action": [ "account:*", "aws-portal:*", "savingsplans:*", "cur:*", "ce:*" ], "Resource": "*", "Effect": "Deny", "Sid": "DenyAccessToCostAndBilling" }, { "Action": [ "iam:DeletePolicy", "iam:DeletePolicyVersion", "iam:CreatePolicyVersion", "iam:SetDefaultPolicyVersion" ], "Resource": "arn:aws:iam::111122223333:policy/test-permissions-boundary-policy", "Effect": "Deny", "Sid": "DenyPermBoundaryIAMPolicyAlteration" }, { "Condition": { "StringEquals": { "iam:PermissionsBoundary": "arn:aws:iam::111122223333:policy/test-permissions-boundary-policy" } }, "Action": [ "iam:DeleteUserPermissionsBoundary", "iam:DeleteRolePermissionsBoundary" ], "Resource": [ "arn:aws:iam::111122223333:user/*", "arn:aws:iam::111122223333:role/*" ], "Effect": "Deny", "Sid": "DenyRemovalOfPermBoundaryFromAnyUserOrRole" }, { "Condition": { "StringNotEquals": { "iam:PermissionsBoundary": "arn:aws:iam::111122223333:policy/test-permissions-boundary-policy" } }, "Action": [ "iam:PutUserPermissionsBoundary", "iam:PutRolePermissionsBoundary" ], "Resource": [ "arn:aws:iam::111122223333:user/*", "arn:aws:iam::111122223333:role/*" ], "Effect": "Deny", "Sid": "DenyAccessIfRequiredPermBoundaryIsNotBeingApplied" }, { "Condition": { "StringNotEquals": { "iam:PermissionsBoundary": "arn:aws:iam::111122223333:policy/test-permissions-boundary-policy" } }, "Action": [ "iam:CreateUser", "iam:CreateRole" ], "Resource": [ "arn:aws:iam::111122223333:user/*", "arn:aws:iam::111122223333:role/*" ], "Effect": "Deny", "Sid": "DenyUserAndRoleCreationWithOutPermBoundary" }, { "Action": "iam:PassRole", "Resource": "arn:aws:iam::111122223333:role/*", "Effect": "Deny", "Sid": "DenyIAMActions" } ] }
アカウント 444455556666 の test-permissions-boundary-policy
{ "Version": "2012-10-17", "Statement": [ { "Action": "*", "Resource": "*", "Effect": "Allow", "Sid": "AllowAdminAccess" }, { "Action": [ "account:*", "aws-portal:*", "savingsplans:*", "cur:*", "ce:*" ], "Resource": "*", "Effect": "Deny", "Sid": "DenyAccessToCostAndBilling" }, { "Action": [ "iam:DeletePolicy", "iam:DeletePolicyVersion", "iam:CreatePolicyVersion", "iam:SetDefaultPolicyVersion" ], "Resource": "arn:aws:iam::444455556666:policy/test-permissions-boundary-policy", "Effect": "Deny", "Sid": "DenyPermBoundaryIAMPolicyAlteration" }, { "Condition": { "StringEquals": { "iam:PermissionsBoundary": "arn:aws:iam::444455556666:policy/test-permissions-boundary-policy" } }, "Action": [ "iam:DeleteUserPermissionsBoundary", "iam:DeleteRolePermissionsBoundary" ], "Resource": [ "arn:aws:iam::444455556666:user/*", "arn:aws:iam::444455556666:role/*" ], "Effect": "Deny", "Sid": "DenyRemovalOfPermBoundaryFromAnyUserOrRole" }, { "Condition": { "StringNotEquals": { "iam:PermissionsBoundary": "arn:aws:iam::444455556666:policy/test-permissions-boundary-policy" } }, "Action": [ "iam:PutUserPermissionsBoundary", "iam:PutRolePermissionsBoundary" ], "Resource": [ "arn:aws:iam::444455556666:user/*", "arn:aws:iam::444455556666:role/*" ], "Effect": "Deny", "Sid": "DenyAccessIfRequiredPermBoundaryIsNotBeingApplied" }, { "Condition": { "StringNotEquals": { "iam:PermissionsBoundary": "arn:aws:iam::444455556666:policy/test-permissions-boundary-policy" } }, "Action": [ "iam:CreateUser", "iam:CreateRole" ], "Resource": [ "arn:aws:iam::444455556666:user/*", "arn:aws:iam::444455556666:role/*" ], "Effect": "Deny", "Sid": "DenyUserAndRoleCreationWithOutPermBoundary" }, { "Action": "iam:PassRole", "Resource": "arn:aws:iam::444455556666:role/*", "Effect": "Deny", "Sid": "DenyIAMActions" } ] }
diff
コマンドで 2 つのポリシーを比較してみるとアカウント ID に違いがあることが分かります。
% diff 111122223333.json 444455556666.json 29c29 < "Resource": "arn:aws:iam::111122223333:policy/test-permissions-boundary-policy", --- > "Resource": "arn:aws:iam::444455556666:policy/test-permissions-boundary-policy", 36c36 < "iam:PermissionsBoundary": "arn:aws:iam::111122223333:policy/test-permissions-boundary-policy" --- > "iam:PermissionsBoundary": "arn:aws:iam::444455556666:policy/test-permissions-boundary-policy" 44,45c44,45 < "arn:aws:iam::111122223333:user/*", < "arn:aws:iam::111122223333:role/*" --- > "arn:aws:iam::444455556666:user/*", > "arn:aws:iam::444455556666:role/*" 53c53 < "iam:PermissionsBoundary": "arn:aws:iam::111122223333:policy/test-permissions-boundary-policy" --- > "iam:PermissionsBoundary": "arn:aws:iam::444455556666:policy/test-permissions-boundary-policy" 61,62c61,62 < "arn:aws:iam::111122223333:user/*", < "arn:aws:iam::111122223333:role/*" --- > "arn:aws:iam::444455556666:user/*", > "arn:aws:iam::444455556666:role/*" 70c70 < "iam:PermissionsBoundary": "arn:aws:iam::111122223333:policy/test-permissions-boundary-policy" --- > "iam:PermissionsBoundary": "arn:aws:iam::444455556666:policy/test-permissions-boundary-policy" 78,79c78,79 < "arn:aws:iam::111122223333:user/*", < "arn:aws:iam::111122223333:role/*" --- > "arn:aws:iam::444455556666:user/*", > "arn:aws:iam::444455556666:role/*" 86c86 < "Resource": "arn:aws:iam::111122223333:role/*", --- > "Resource": "arn:aws:iam::444455556666:role/*",
さいごに
Permissions boundary としてアタッチするための IAM ポリシーを AWS CloudFormation StackSets を利用して複数の AWS アカウントに作成する方法を試してみました。
他の用途として、AWS IAM Identity Center でアタッチする IAM ポリシーを各アカウントで作成する場合にも利用できるかもしれません。
以上、このブログがどなたかのご参考になれば幸いです。