Control TowerのガードレールでRootユーザーを制限しつつCentralized root accessを使う方法
はじめに
皆様こんにちは、あかいけです。
最近AWS OrganizationsのCentralized root access(ルートアクセス管理)を有効化する機会がありました。
設定自体はマネジメントコンソールから数クリックで完了するのですが、実際に特権アクションを使おうとしたところ、SCPに拒否されて実行できない事象に遭遇しました。
というわけで今回は、この事象の原因と、Control Towerのガードレールを維持しつつCentralized root accessを使うための設定方法をまとめます。
前提条件
- Control Towerを導入済みで、ガードレール [AWS-GR_RESTRICT_ROOT_USER] Disallow actions as a root user を有効化していること
- Centralized root access(ルートアクセス管理)を有効化済みであること
事象と原因
エラー内容
Centralized root accessを有効化した状態で、IAMコンソールの「ルートアクセス管理」を開くと、アカウント一覧の「ルートユーザー認証情報」列が以下のように「アクセス拒否」と表示されました。

この列は各メンバーアカウントのルートユーザー認証情報の有無を表示するためのものですが、その情報を取得するAPI呼び出し自体が拒否されている状態です。実際に該当アカウントで「特権的なアクションを実行する」を試すと、以下のエラーになりました。

エラーメッセージを見ると、iam:GetAccountSummaryがSCPによって明示的に拒否されています。ユーザーはarn:aws:iam::アカウントID:root、つまりルートユーザーとして評価されていました。
原因
Control Towerのガードレール「AWS-GR_RESTRICT_ROOT_USER」は、ルートユーザーによる操作を一律禁止するSCPを適用します。プリンシパルのARNがルートユーザーのパターン(arn:*:iam::*:root)に一致する場合、すべてのアクションを拒否する、というシンプルなポリシーです。
一方、Centralized root accessの「特権的なアクションを実行する」機能は、内部的にsts:AssumeRootというAPIを呼び出し、対象メンバーアカウントのルートユーザーとして一時的なセッションを発行します。このセッションもポリシー評価上は「ルートユーザーによる操作」として扱われるため、先述のガードレールに引っかかって拒否されていました。
つまり、ルートユーザーの操作を禁止するガードレールと、ルートユーザーとして操作するCentralized root accessは、デフォルトの設定では両立できません。
設定方法
このガードレールには、この組み合わせのために用意された設定パラメータ「ExemptAssumeRoot」があります。これを有効にすると、ガードレールが適用するSCPの拒否条件に、aws:AssumedRootというグローバル条件キーが存在しないことという条件が追加されます。
aws:AssumedRootは、リクエストがAssumeRoot(つまりCentralized root access経由の特権アクション)で行われた場合に設定されるキーです。
なので ExemptAssumeRootを有効にすると、通常のルートユーザーによる直接操作は引き続き拒否されますが、Centralized root access経由の特権アクションは通るようになります。
ガードレール設定
設定はControl Towerコンソールから行います。
コントロールの一覧から「AWS-GR_RESTRICT_ROOT_USER」を選択肢、対象OU(今回はSandbox)を選択して「更新が有効なコントロール」をクリックします。

パラメータ設定画面で「AssumeRoot を使用して行われたリクエストを除外する」にチェックを入れて更新します。

動作確認
設定が有効になっているか、実際にCentralized root accessの特権アクションを使って確認します。
今回は「誤って全プリンシパルを拒否するバケットポリシーを設定してS3バケットをロックアウトしてしまい、それを特権アクションで復旧する」というシナリオで試しました。
S3バケット作成
検証用のS3バケットに、以下のバケットポリシーを設定します。

{
"Version": "2012-10-17",
"Statement": [
{
"Action": "s3:*",
"Effect": "Deny",
"Resource": [
"arn:aws:s3:::sandbox-002-test-s3",
"arn:aws:s3:::sandbox-002-test-s3/*"
],
"Principal": "*"
}
]
}
Principalが*のため、バケットの所有者アカウントであっても操作できなくなります。オブジェクト一覧を開くと「オブジェクトを一覧表示するアクセス許可が不十分です」と表示され、ロックアウトされました。

こうなるとルートユーザー以外でバケットを変更できなくなるため、今回はこれをCentralized root accessの特権アクションで復旧します。
特権的なアクションを実行する
まず、ガードレールにExemptAssumeRootを設定した効果を確認します。IAMコンソールの「ルートアクセス管理」を開くと、アカウント一覧の表示が「アクセス拒否」から「存在しない」に変わっていました。
「存在しない」はルートユーザーの認証情報(パスワードやアクセスキー)が実際に存在しないことを示す、正常な状態です。

続いて、対象アカウントで「特権的なアクションを実行する」を選びます。アクションには「S3バケットポリシーを削除」を選択し、対象のS3 URIを指定します。

削除前のバケットポリシーが表示されるので内容を確認します。
「確認」と入力して削除を実行します。

削除後、S3バケットのオブジェクト一覧に問題なくアクセスできるようになりました。

以上のことから、ガードレールを維持したまま、Centralized root accessの特権アクションが問題なく動作することを確認できました。
さいごに
以上、Control TowerのガードレールでRootユーザーを制限しつつCentralized root accessを使う方法でした。
Control Towerのガードレールを使っている場合、大抵Rootユーザーを制限するガードレールを使っていると思うので、Centralized root accessを導入する際は、あわせてこのガードレールの設定も確認してみてください。
同じ事象で困っている方の助けになれば幸いです。








