IAM Access Analyzerの内部アクセス機能がSCP・RCP・Permission Boundaryの影響をどのように受けるか調査してみた
あしざわです。
先日のAWS re:Inforce 2025にて、IAM Access Analyzerの内部アクセス(Internal access)機能が発表されました。
この機能によって、組織内の特定のリソースにアクセスできるすべてのIAMプリンシパルを特定し、内部ガバナンスをより強化できるようになりました。
そこで今回気になったのが、Organizations環境でよく利用される SCP(Service Control Policy) 、 RCP(Resource Control Policy) 、 Permission Boundary といったアクセス制限機能が、内部アクセス機能の検知結果にどのような影響を与えるのかという点です。
AWS公式ブログには以下のような表記がありました。
この機能は、自動推論を使用してサービスコントロールポリシー (SCP)、リソースコントロールポリシー (RCP)、アイデンティティベースのポリシーを含めた複数のポリシーをまとめて評価
評価対象にSCP、RCPが含まれていることは分かりましたが実際どのように検出するのかについてはこのブログからは読み取れませんでした。
この記事では、実際にOrganizations環境でSCP・RCP・Permission Boundaryを設定した状態で内部アクセス機能を使用し、検知結果がどのように表示されるかの検証内容をご紹介します。
「権限制限されているのに検知される」「制限が反映されない」といった運用上の疑問を解決できる内容になっているはずです。
概要
内部アクセス機能は、指定したリソース(S3バケット、RDS、DynamoDBなど)にアクセス可能なIAMプリンシパルをすべて特定する機能です。
これまでのIAM Access Analyzerは以下の2つの機能を提供していました。
- 外部アクセス:信頼ゾーン外からのアクセスを検知
- 未使用アクセス:IAMプリンシパルの使用状況を監視
内部アクセス機能の登場により、外部アクセス機能における信頼ゾーン内のIAMプリンシパルに対しても最小権限の原則を適用し、機微情報が保管されているリソースへのアクセス状況を把握できるようになりました。
一方で、Organizations環境では以下のようなアクセス制限機能がよく利用されています。
- SCP(Service Control Policy):組織単位でのアクション制限
- RCP(Resource Control Policy):リソース単位でのアクセス制限
- Permission Boundary:IAMエンティティの権限上限設定
これらの制限が設定されている場合、内部アクセス機能の検知結果にどう反映されるのか、実際の権限評価と一致するのかが重要な検証ポイントとなります。
やってみた
この検証では、Organizationsを利用するため複数のアカウントが登場します。
全体の構成図はこちらです。
簡単なテキストで表現すると以下のシナリオとなります。
- 機密情報が入ったS3バケットを内部アクセスアナライザーで監視している
- 検証用のIAMロールは
S3FullAccess
権限を付与 - IAMロールに対して異なる制限機能を適用する
- SCP :
s3:DeleteObject
アクションを制限 - RCP :メンバーアカウントA以外からの
s3:PutObject
アクションを制限 - Permission Boundary :
s3:DeleteBucket
アクションを制限
- SCP :
- この状況下で内部アクセスはどのような検出結果を表示するのかを検証
ここから検証を進めます。
各アカウントには、事前に以下のリソースを準備しています。
メンバーアカウントA上のS3バケット
- バケット名:
internal-access-member-A-111111111111
- バケットポリシー:
internal-*
と名前のつくIAMプリンシパルのみに以下アクションを許可s3:GetObject
s3:DeleteBucket
s3:DeleteObject
s3:PutObject
メンバーアカウントB上のIAMロール
- ロール名:
internal-member-B-role
- ポリシー:
S3FullAccess
- Permission Boundary:
s3:DeleteBucket
を制限
はじめに、SCPを作成しました。
SCPをメンバーアカウントBにアタッチしました。
次に、RCPを有効化します。
RCPを作成する際、当初は以下のポリシーを設定しようとしました。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyPutObjectFromNonMemberA",
"Effect": "Deny",
"Principal": "*",
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::internal-access-member-a-*/*",
"Condition": {
"StringNotEquals": {
"aws:PrincipalAccount": "<AWS_Account_ID>"
}
}
}
]
}
しかし、ポリシードキュメント入力画面で以下のエラーが表示されました。
Rcp Missing Related Principal Condition Key: RCP は、IAM ロール、ユーザー、AWS サービスプリンシパルに影響を及ぼします。サービスプリンシパルを使用しユーザーに代わって動作するサービスへの意図しない影響を防ぐには、プリンシパルキー aws:PrincipalAccount が使用されるたびに、Condition ブロック "BoolIfExists": { "aws:PrincipalIsAWSService": "false"} にステートメントをさらに追加する必要があります。
提案されたaws:PrincipalIsAWSService
句を追加することで警告が解消されました。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "DenyPutObjectFromNonMemberA",
"Effect": "Deny",
"Principal": "*",
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::internal-access-member-a-*/*",
"Condition": {
"StringNotEquals": {
"aws:PrincipalAccount": "<AWS_Account_ID>"
},
"BoolIfExists": {
"aws:PrincipalIsAWSService": "false"
}
}
}
]
}
RCPを作成し、メンバーアカウントAにアタッチしました。
制限機能の動作確認
準備が完了したので、IAMロールがS3バケットにアクセスできるかテストしました。
アカウントBにあるinternal-member-B-role
にスイッチし、AWS CLIのs3api
コマンドを利用してS3バケットポリシーで許可されているS3の各APIアクションを実行していきます。
私の想定は以下です
s3:GetObject
:実行できるs3:PutObject
:失敗する(RCPの影響)s3:DeleteObject
:失敗する(SCPの影響)s3:DeleteBucket
:失敗する(Permission Boundaryの影響)
まず、s3:GetObject
は問題なく実行できました。
> aws s3api get-object \
--bucket internal-access-member-a-111111111111 \
--key test-sensitive-data.html \
./test-sensitive-data.html
{
"AcceptRanges": "bytes",
"LastModified": "2025-06-29T19:24:07+00:00",
"ContentLength": 131,
"ETag": "\"bec32468316401e363d68abea22571a5\"",
"ChecksumCRC32": "cxN1dA==",
"ChecksumType": "FULL_OBJECT",
"VersionId": "tr6a9W8gmyZkfh0e3IkxYfCwU8ezVWs9",
"ContentType": "text/html",
"ServerSideEncryption": "AES256",
"Metadata": {}
}
> cat ./test-sensitive-data.html
<!DOCTYPE html>
<html>
<head>
<title>Sensitive Data</title>
</head>
<body>
<h1>This is sensitive data!</h1>
</body>
</html>⏎
s3:PutObject
は拒否されました。RCP(resource control policy)によって拒否されたとエラー文からわかります。
> aws s3api put-object \
--bucket internal-access-member-a-111111111111 \
--key test-upload.txt \
--body ../test-file.txt
An error occurred (AccessDenied) when calling the PutObject operation: User: arn:aws:sts::961341544991:assumed-role/internal-member-B-role/test-session is not authorized to perform: s3:PutObject on resource: "arn:aws:s3:::internal-access-member-a-111111111111/test-upload.txt" with an explicit deny in a resource control policy
s3:DeleteObject
も拒否されました。SCP(service control policy)によって拒否されたとエラー文からわかります。
> aws s3api delete-object \
--bucket internal-access-member-a-111111111111 \
--key test-sensitive-data.html
An error occurred (AccessDenied) when calling the DeleteObject operation: User: arn:aws:sts::961341544991:assumed-role/internal-member-B-role/test-session is not authorized to perform: s3:DeleteObject on resource: "arn:aws:s3:::internal-access-member-a-474668392285/test-sensitive-data.html" with an explicit deny in a service control policy
s3:DeleteBucket
も拒否されました。Permission Boundaryによって拒否されたとエラー文からわかります。
> aws s3api delete-bucket \
--bucket internal-access-member-a-111111111111
An error occurred (AccessDenied) when calling the DeleteBucket operation: User: arn:aws:sts::961341544991:assumed-role/internal-member-B-role/test-session is not authorized to perform: s3:DeleteBucket on resource: "arn:aws:s3:::internal-access-member-a-111111111111" with an explicit deny in a permissions boundary
想定通りに各制限機能が動作していることを確認できました。
続いて、管理アカウントにスイッチロールして、内部アクセスアナライザーを作成します。
信頼ゾーンはOrganizations全体、分析対象リソースは作成したS3バケット単体として設定しました。
分析対象のリソースを指定する際は、以下の形式で入力する必要がありました。
<AWSアカウントID>,<S3バケットのリソースARN>
AWSアカウントIDとARNのセットで入力しないとエラーになるので注意が必要です。
内部アクセスアナライザーを作成しました。
しばらく待つと、18件の検知結果が表示されました。
大半がS3バケットと同一のAWSアカウント上にある、広めのIAM権限を持つロール(Control Tower関連のロールが多数)でしたが、検証用に作成したIAMロールもしっかり検出されていました。
詳細を確認してみます。
検知結果から以下のことがわかりました。
- このアクセス許可はバケットポリシーによって設定されている
- SCP・RCPが
Applied
のステータスになっている - Write権限とRead権限が含まれる3つのS3アクションでアクセス可能と表示されている
内部アクセス機能のAPIリファレンスによると、以下の4つの評価結果があります。
APPLIED
:組織内にSCP/RCPが存在し、権限の評価にSCP/RCPが含まれたAPPLICABLE
:組織内にSCP/RCPが存在するが、この評価結果にSCP/RCPが含まれないNOT_APPLICABLE
:組織内にSCP/RCPが存在しないFAILED_TO_EVALUATE_[RCP/SCP]
:SCP/RCPの評価中にエラーが発生した
Applied
と表示されているということは、SCP/RCPの影響で何らかの権限が制限されていることを示しています。
ここで重要な発見がありました。検出結果のAccess Levelを見ると、 Permission Boundaryによる制限は反映されているが、SCP・RCPの制限は反映されていない ということです。
実際のアクセステストでは以下の結果でした。
s3:GetObject
:成功s3:DeleteBucket
:Permission Boundaryで拒否s3:DeleteObject
:SCPで拒否s3:PutObject
:RCPで拒否
しかし、内部アクセスの検知結果ではs3:GetObject
、s3:DeleteObject
、s3:PutObject
の3つのアクションでアクセス可能と表示されています。
つまり、内部アクセス機能とSCP・RCPを併用する場合、SCP・RCPで制限していても内部アクセスの存在が通知されてしまうため、適切なアーカイブルールの設定が重要になります。
続いて、SCP・RCPで制限している範囲をアーカイブルールで除外できるか試してみました。
Service control policy (SCP) restriction
をフィルタキーとして、適用済み(Applied)
の値で検出結果をアーカイブする設定を作成しました。
結果として、18件すべての検出結果がアーカイブされてしまいました。
当初は「ルールに一致したアクセス権限だけをアーカイブし、不一致なアクセス権限だけが検出結果として残る」という動作を期待していましたが、期待通りにはいきませんでした。
アーカイブルールを不適切に設定してしまうと、重要な検知を見逃す可能性があるため、運用上十分な注意が必要です。
さいごに
IAM Access Analyzerの内部アクセス機能とSCP・RCP・Permission Boundaryの関係について検証してみました。
今回の検証で明らかになった重要なポイントは以下の通りです。
まず、内部アクセス機能は Permission Boundaryによる制限は検知結果に反映する が、 SCP・RCPによる制限は検知結果に反映されない ということです。SCP・RCPが「Applied」ステータスで表示されていても、実際のアクセス権限の評価結果は検知結果に反映されません。
そのため、Organizations環境でSCP・RCPを活用している場合、内部アクセス機能による検知結果と実際のアクセス可能性にギャップが生じる可能性があります。
運用上の考慮事項として、SCP・RCPで制限されているアクセスについてはアーカイブルールで適切に除外する必要がありますが、今回の検証ではルール設定が思ったようにいかず、より詳細な検証が必要だと感じました。
内部アクセス機能は組織のガバナンス強化に非常に有用な機能ですが、既存のアクセス制限機能との関係を十分理解して運用することが重要ですね。
以上です。