EBS スナップショット
概要
IAM Access Analyzer が EBS スナップショットの外部アクセスをどのように検出するかを検証する。
EBS スナップショットは modify-snapshot-attribute により外部アカウントへの共有やパブリック共有を設定できる。S3 の Block Public Access とは異なり、EBS の Block Public Access for Snapshots はデフォルトでは無効(unblocked)である(公式ドキュメント)。また、S3 の BPA がアカウントレベルとバケットレベルの 2 階層で設定できるのに対し、EBS の Block Public Access はアカウントレベルのみであり、スナップショット個別の設定はできない。--group-names all でパブリック共有を設定するとパブリックアクセスとして検出され、--user-ids で特定の外部アカウントを設定するとクロスアカウントアクセスとして検出される。
EBS スナップショットの外部アクセス制御レイヤー
| レイヤー | EBS スナップショットの状況 |
|---|---|
| デフォルト保護 | Block Public Access for Snapshots(デフォルトでは無効) |
| 予防(SCP) | CT.EC2.PV.3(パブリック共有をブロック。クロスアカウント共有はブロックしない) |
| 予防(Declarative) | CT.EC2.PV.7(Block Public Access を強制。クロスアカウント共有はブロックしない) |
| Security Hub CSPM | EC2.1(パブリック共有のチェック) |
| IAM Access Analyzer | パブリック + クロスアカウントの到達可能性を分析 |
結果
- Block Public Access のデフォルト状態: EBS の Block Public Access for Snapshots はデフォルトでは無効(
unblocked)。S3 の BPA(2023年4月以降デフォルト有効)とは異なる - パブリックアクセスの検出:
modify-snapshot-attribute --group-names allでパブリック共有を設定すると、isPublic: trueの finding が生成された。action はec2:CopySnapshot,ec2:CreateVolume等 7 つ - クロスアカウントアクセスの検出:
--user-idsで組織外アカウントを設定すると、isPublic: falseの finding が生成された。principal に組織外アカウント ID が特定された - 予防コントロール(CT.EC2.PV.3)との連動: CT.EC2.PV.3 は SCP 型であり、パブリック共有の設定操作(
--group-names all)のみをブロックする。既存の共有には遡及せず、クロスアカウント共有(--user-ids)もブロックしない。resourceControlPolicyRestrictionはNOT_APPLICABLEのまま変わらない - クリーンアップ: 共有を解除(
modify-snapshot-attribute --operation-type remove)すると finding は RESOLVED になる
検証環境
本記事のコマンドは、--profile 指定がない場合は Workload アカウントで実行する。IAM Access Analyzer の finding 確認は Audit アカウントで実行する。
検証の流れ
flowchart LR
A[1. 既存 finding の<br>確認] --> B[2. テスト用<br>スナップショット作成]
B --> C[3. パブリックアクセス<br>検出の確認]
C --> D[4. クロスアカウント<br>アクセス検出]
D --> E[5. 予防コントロール<br>との連動]
E --> F[6. クリーンアップ]
1. 既存 finding の確認
テスト用スナップショットを作成する前に、Block Public Access の状態と既存の EBS スナップショット finding を確認する。
Block Public Access の状態確認
aws ec2 get-snapshot-block-public-access-state{
"State": "unblocked",
"ManagedBy": "account"
}Block Public Access がデフォルトで無効(unblocked)であることを確認する。
既存 finding の確認
aws accessanalyzer list-findings-v2 \
--analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
--filter '{"status": {"eq": ["ACTIVE"]}, "resourceType": {"eq": ["AWS::EC2::Snapshot"]}}' \
--query 'findings[].{id:id,resource:resource,status:status}' \
--region ap-northeast-1 \
--profile Audit[]2. テスト用スナップショットの作成
テスト用ボリュームを作成し、2 つのスナップショットを取得する。
aws ec2 create-volume \
--availability-zone ap-northeast-1a \
--size 1 \
--volume-type gp3 \
--query '{VolumeId:VolumeId}'{
"VolumeId": "<テスト用ボリューム ID>"
}パブリック共有用スナップショット
aws ec2 create-snapshot \
--volume-id <テスト用ボリューム ID> \
--description "iaa-ebs-public-test" \
--query '{SnapshotId:SnapshotId,State:State}'{
"SnapshotId": "<パブリックスナップショット ID>",
"State": "pending"
}パブリック共有を設定する。
aws ec2 modify-snapshot-attribute \
--snapshot-id <パブリックスナップショット ID> \
--attribute createVolumePermission \
--operation-type add \
--group-names all
(出力なし)クロスアカウント共有用スナップショット
aws ec2 create-snapshot \
--volume-id <テスト用ボリューム ID> \
--description "iaa-ebs-crossaccount-test" \
--query '{SnapshotId:SnapshotId,State:State}'{
"SnapshotId": "<クロスアカウントスナップショット ID>",
"State": "pending"
}クロスアカウント共有を設定する。
aws ec2 modify-snapshot-attribute \
--snapshot-id <クロスアカウントスナップショット ID> \
--attribute createVolumePermission \
--operation-type add \
--user-ids <組織外アカウント ID>
(出力なし)3. パブリックアクセスの検出
パブリック共有スナップショットの finding を確認する。
aws accessanalyzer list-findings-v2 \
--analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
--filter '{"status": {"eq": ["ACTIVE"]}, "resource": {"contains": ["<パブリックスナップショット ID>"]}}' \
--query 'findings[].{id:id,resource:resource,resourceType:resourceType,status:status}' \
--region ap-northeast-1 \
--profile Audit[
{
"id": "<パブリックスナップショット finding ID>",
"resource": "arn:aws:ec2:ap-northeast-1::snapshot/<パブリックスナップショット ID>",
"resourceType": "AWS::EC2::Snapshot",
"status": "ACTIVE"
}
]finding の詳細を確認する。
aws accessanalyzer get-finding-v2 \
--analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
--id <パブリックスナップショット finding ID> \
--region ap-northeast-1 \
--profile Audit{
"findingDetails": [
{
"externalAccessDetails": {
"action": [
"ec2:CopySnapshot",
"ec2:CreateVolume",
"ec2:DescribeFastSnapshotRestores",
"ec2:DescribeSnapshotAttribute",
"ec2:DescribeSnapshots",
"ec2:DisableFastSnapshotRestores",
"ec2:EnableFastSnapshotRestores"
],
"condition": {},
"isPublic": true,
"principal": {"AWS": "*"},
"resourceControlPolicyRestriction": "NOT_APPLICABLE"
}
}
],
"resource": "arn:aws:ec2:ap-northeast-1::snapshot/<パブリックスナップショット ID>",
"status": "ACTIVE",
"resourceType": "AWS::EC2::Snapshot",
"findingType": "ExternalAccess",
"resourceOwnerAccount": "<Workload アカウント ID>",
"id": "<パブリックスナップショット finding ID>"
}以下を確認する。
isPublicがtrueprincipalが{"AWS": "*"}actionにec2:CreateVolume等が含まれるresourceControlPolicyRestrictionがNOT_APPLICABLE
組織外アカウントからの実際のアクセス確認
組織外アカウントからパブリックスナップショットを使ってボリュームを作成できることを確認する。
aws ec2 create-volume \
--availability-zone ap-northeast-1a \
--snapshot-id <パブリックスナップショット ID> \
--volume-type gp3 \
--query '{VolumeId:VolumeId,State:State}' \
--profile <組織外プロファイル> \
--region ap-northeast-1{
"VolumeId": "<組織外ボリューム ID>",
"State": "creating"
}確認後、組織外アカウントで作成したボリュームを削除する。
aws ec2 delete-volume \
--volume-id <組織外ボリューム ID> \
--profile <組織外プロファイル> \
--region ap-northeast-1
(出力なし)4. クロスアカウントアクセスの検出
クロスアカウント共有スナップショットの finding を確認する。
aws accessanalyzer list-findings-v2 \
--analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
--filter '{"status": {"eq": ["ACTIVE"]}, "resource": {"contains": ["<クロスアカウントスナップショット ID>"]}}' \
--query 'findings[].{id:id,resource:resource,resourceType:resourceType,status:status}' \
--region ap-northeast-1 \
--profile Audit[
{
"id": "<クロスアカウントスナップショット finding ID>",
"resource": "arn:aws:ec2:ap-northeast-1::snapshot/<クロスアカウントスナップショット ID>",
"resourceType": "AWS::EC2::Snapshot",
"status": "ACTIVE"
}
]finding の詳細を確認する。
aws accessanalyzer get-finding-v2 \
--analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
--id <クロスアカウントスナップショット finding ID> \
--region ap-northeast-1 \
--profile Audit{
"findingDetails": [
{
"externalAccessDetails": {
"action": [
"ec2:CopySnapshot",
"ec2:CreateVolume",
"ec2:DescribeFastSnapshotRestores",
"ec2:DescribeSnapshotAttribute",
"ec2:DescribeSnapshots",
"ec2:DisableFastSnapshotRestores",
"ec2:EnableFastSnapshotRestores"
],
"condition": {},
"isPublic": false,
"principal": {"AWS": "<組織外アカウント ID>"},
"resourceControlPolicyRestriction": "NOT_APPLICABLE"
}
}
],
"resource": "arn:aws:ec2:ap-northeast-1::snapshot/<クロスアカウントスナップショット ID>",
"status": "ACTIVE",
"resourceType": "AWS::EC2::Snapshot",
"findingType": "ExternalAccess",
"resourceOwnerAccount": "<Workload アカウント ID>",
"id": "<クロスアカウントスナップショット finding ID>"
}以下を確認する。
isPublicがfalseprincipalに組織外アカウント ID が特定されているactionにec2:CreateVolume等が含まれるresourceControlPolicyRestrictionがNOT_APPLICABLE
組織外アカウントからの実際のアクセス確認
組織外アカウントからクロスアカウントスナップショットを使ってボリュームを作成できることを確認する。
aws ec2 create-volume \
--availability-zone ap-northeast-1a \
--snapshot-id <クロスアカウントスナップショット ID> \
--volume-type gp3 \
--query '{VolumeId:VolumeId,State:State}' \
--profile <組織外プロファイル> \
--region ap-northeast-1{
"VolumeId": "<組織外ボリューム ID>",
"State": "creating"
}確認後、組織外アカウントで作成したボリュームを削除する。
aws ec2 delete-volume \
--volume-id <組織外ボリューム ID> \
--profile <組織外プロファイル> \
--region ap-northeast-1
(出力なし)5. 予防コントロール(CT.EC2.PV.3)との連動
--group-names all)の新規設定のみをブロックする。既存のパブリック共有には遡及せず、クロスアカウント共有(--user-ids)もブロックしない。そのため、resourceControlPolicyRestriction は NOT_APPLICABLE のまま変わらない。CT.EC2.PV.3 の有効化確認
CT.EC2.PV.3 が有効であることを確認する。
aws controltower list-enabled-controls \
--target-identifier <対象 OU ARN> \
--query "enabledControls[?controlIdentifier=='arn:aws:controlcatalog:::control/chlzfpsllhs3knp1ixr773wa6'].{controlIdentifier:controlIdentifier,statusSummary:statusSummary}" \
--profile Master[]無効の場合は有効化する。
aws controltower enable-control \
--control-identifier arn:aws:controlcatalog:::control/chlzfpsllhs3knp1ixr773wa6 \
--target-identifier <対象 OU ARN> \
--profile Master{
"operationIdentifier": "<オペレーション ID>"
}既存のパブリック共有がブロックされないことの確認
CT.EC2.PV.3 が有効な状態でも、既存のパブリック共有スナップショットからのボリューム作成はブロックされないことを確認する。
aws ec2 create-volume \
--availability-zone ap-northeast-1a \
--snapshot-id <パブリックスナップショット ID> \
--volume-type gp3 \
--query '{VolumeId:VolumeId,State:State}' \
--profile <組織外プロファイル> \
--region ap-northeast-1{
"VolumeId": "<組織外ボリューム ID>",
"State": "creating"
}SCP は modify-snapshot-attribute API をブロックするだけで、既存の共有設定によるアクセスには遡及しない。確認後、ボリュームを削除する。
aws ec2 delete-volume \
--volume-id <組織外ボリューム ID> \
--profile <組織外プロファイル> \
--region ap-northeast-1
(出力なし)既存のクロスアカウント共有スナップショットからのボリューム作成も同様にブロックされないことを確認する。
aws ec2 create-volume \
--availability-zone ap-northeast-1a \
--snapshot-id <クロスアカウントスナップショット ID> \
--volume-type gp3 \
--query '{VolumeId:VolumeId,State:State}' \
--profile <組織外プロファイル> \
--region ap-northeast-1{
"VolumeId": "<組織外ボリューム ID>",
"State": "creating"
}確認後、ボリュームを削除する。
aws ec2 delete-volume \
--volume-id <組織外ボリューム ID> \
--profile <組織外プロファイル> \
--region ap-northeast-1
(出力なし)パブリック共有の設定がブロックされることの確認
CT.EC2.PV.3 が有効な状態で、クロスアカウント用スナップショットへのパブリック共有の設定がブロックされることを確認する。
aws ec2 modify-snapshot-attribute \
--snapshot-id <クロスアカウントスナップショット ID> \
--attribute createVolumePermission \
--operation-type add \
--group-names allAn error occurred (UnauthorizedOperation) when calling the ModifySnapshotAttribute operation: ...
with an explicit deny in a service control policy: ...resourceControlPolicyRestriction の確認
再スキャンを実行し、SCP 型では resourceControlPolicyRestriction が変わらないことを確認する。
aws accessanalyzer start-resource-scan \
--analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
--resource-arn arn:aws:ec2:ap-northeast-1::snapshot/<パブリックスナップショット ID> \
--resource-owner-account <Workload アカウント ID> \
--region ap-northeast-1 \
--profile Audit
(出力なし)aws accessanalyzer get-finding-v2 \
--analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
--id <パブリックスナップショット finding ID> \
--region ap-northeast-1 \
--profile AuditresourceControlPolicyRestriction が NOT_APPLICABLE のまま変わらないことを確認する。SCP 型のコントロールは IAM Access Analyzer の resourceControlPolicyRestriction には反映されない。また、RCP 型では再スキャンにより旧 finding が RESOLVED になり新しい finding ID で再生成されたが、SCP 型では finding ID も変わらない。
6. クリーンアップ
CT.EC2.PV.3 の無効化
aws controltower disable-control \
--control-identifier arn:aws:controlcatalog:::control/chlzfpsllhs3knp1ixr773wa6 \
--target-identifier <対象 OU ARN> \
--profile Master{
"operationIdentifier": "<オペレーション ID>"
}共有の解除
aws ec2 modify-snapshot-attribute \
--snapshot-id <パブリックスナップショット ID> \
--attribute createVolumePermission \
--operation-type remove \
--group-names all
(出力なし)aws ec2 modify-snapshot-attribute \
--snapshot-id <クロスアカウントスナップショット ID> \
--attribute createVolumePermission \
--operation-type remove \
--user-ids <組織外アカウント ID>
(出力なし)finding の確認
共有解除後、finding が RESOLVED になることを確認する。
aws accessanalyzer list-findings-v2 \
--analyzer-arn arn:aws:access-analyzer:ap-northeast-1:<Audit アカウント ID>:analyzer/org-access-analyzer \
--filter '{"resourceType": {"eq": ["AWS::EC2::Snapshot"]}}' \
--query 'findings[].{id:id,resource:resource,status:status}' \
--region ap-northeast-1 \
--profile Audit[]テスト用リソースの削除
aws ec2 delete-snapshot \
--snapshot-id <パブリックスナップショット ID>
(出力なし)aws ec2 delete-snapshot \
--snapshot-id <クロスアカウントスナップショット ID>
(出力なし)aws ec2 delete-volume \
--volume-id <テスト用ボリューム ID>
(出力なし)