ECR リポジトリ
概要
IAM Access Analyzer が ECR プライベートリポジトリの外部アクセスをどのように検出するかを検証する。
ECR プライベートリポジトリはリポジトリポリシー(リソースベースポリシー)により外部アクセスを制御する。set-repository-policy で Principal に "*" を指定するとパブリックアクセス、特定のアカウント ID を指定するとクロスアカウントアクセスとなる。デフォルトではリポジトリポリシーが存在せず、作成したアカウントのみがアクセスできる。S3 や EBS のような Block Public Access の仕組みは存在しない。
ECR リポジトリの外部アクセス制御レイヤー
| レイヤー | ECR リポジトリの状況 |
|---|---|
| デフォルト保護 | なし(Block Public Access なし) |
| 予防(SCP / RCP) | Control Tower 予防コントロールなし |
| Security Hub CSPM | 外部アクセスチェックなし |
| IAM Access Analyzer | パブリック + クロスアカウントの到達可能性を分析 |
結果
- デフォルト保護: ECR にはアカウントレベルの Block Public Access やレジストリポリシーによるデフォルト保護が存在しない。リポジトリポリシーが設定されていない状態では組織外からのアクセスは
AccessDeniedExceptionで拒否される - パブリックアクセスの検出: リポジトリポリシーで
Principal: "*"を設定するとisPublic: trueの finding が生成された。組織外アカウントからのdescribe-imagesも成功した - クロスアカウントアクセスの検出: リポジトリポリシーで組織外アカウント ID を設定すると
isPublic: falseの finding が生成された。principalに組織外アカウント ID が特定された - resourceControlPolicyRestriction: ECR に対応する RCP 型予防コントロールは存在しないため、すべて
NOT_APPLICABLE - ポリシー削除による finding の解消:
delete-repository-policyでリポジトリポリシーを削除すると 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 の確認
テスト用リポジトリを作成する前に、既存の ECR リポジトリ 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::ECR::Repository"]}}' \
--query 'findings[].{id:id,resource:resource,status:status}' \
--region ap-northeast-1 \
--profile Audit[]2. デフォルト設定の確認
ECR にはアカウントレベルの Block Public Access やレジストリポリシーによるデフォルト保護が存在するか確認する。
レジストリポリシー
aws ecr get-registry-policyAn error occurred (RegistryPolicyNotFoundException) when calling the GetRegistryPolicy operation: Registry policy does not exist in the registry with id '<Workload アカウント ID>'レジストリポリシーは未設定。アカウントレベルでのアクセス制御は存在しない。
リポジトリ作成テンプレート
aws ecr describe-repository-creation-templates \
--query 'repositoryCreationTemplates'[]リポジトリ作成テンプレートも未設定。新規リポジトリにデフォルトで適用されるポリシーはない。
デフォルトのリポジトリポリシー
テスト用リポジトリを作成し、デフォルトではリポジトリポリシーが存在しないことを確認する。
aws ecr create-repository \
--repository-name iaa-ecr-public-test \
--query '{repositoryName:repository.repositoryName,repositoryUri:repository.repositoryUri}'{
"repositoryName": "iaa-ecr-public-test",
"repositoryUri": "<Workload アカウント ID>.dkr.ecr.ap-northeast-1.amazonaws.com/iaa-ecr-public-test"
}aws ecr get-repository-policy \
--repository-name iaa-ecr-public-testAn error occurred (RepositoryPolicyNotFoundException) when calling the GetRepositoryPolicy operation: Repository policy does not exist for the repository with name 'iaa-ecr-public-test' in the registry with id '<Workload アカウント ID>'デフォルトではリポジトリポリシーが存在しない。
デフォルト状態での組織外アクセス確認
リポジトリポリシーが存在しない状態で、組織外アカウントからアクセスを試みる。
aws ecr describe-images \
--registry-id <Workload アカウント ID> \
--repository-name iaa-ecr-public-test \
--query 'imageDetails' \
--profile <組織外プロファイル> \
--region ap-northeast-1An error occurred (AccessDeniedException) when calling the DescribeImages operation: User: arn:aws:iam::<組織外アカウント ID>:user/<組織外ユーザー名> is not authorized to perform: ecr:DescribeImages on resource: arn:aws:ecr:ap-northeast-1:<Workload アカウント ID>:repository/iaa-ecr-public-test because no resource-based policy allows the ecr:DescribeImages actionリポジトリポリシーがない状態では組織外からのアクセスは拒否される。
3. テスト用リポジトリの作成
ステップ 2 で作成した iaa-ecr-public-test に加え、クロスアカウント用のリポジトリを作成する。
aws ecr create-repository \
--repository-name iaa-ecr-crossaccount-test \
--query '{repositoryName:repository.repositoryName,repositoryUri:repository.repositoryUri}'{
"repositoryName": "iaa-ecr-crossaccount-test",
"repositoryUri": "<Workload アカウント ID>.dkr.ecr.ap-northeast-1.amazonaws.com/iaa-ecr-crossaccount-test"
}パブリックアクセスを許可するリポジトリポリシーを設定する。
aws ecr set-repository-policy \
--repository-name iaa-ecr-public-test \
--policy-text '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicAccess",
"Effect": "Allow",
"Principal": "*",
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:DescribeImages"
]
}
]
}'
(出力なし)クロスアカウントアクセスを許可するリポジトリポリシーを設定する。
aws ecr set-repository-policy \
--repository-name iaa-ecr-crossaccount-test \
--policy-text '{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CrossAccountAccess",
"Effect": "Allow",
"Principal": {"AWS": "<組織外アカウント ID>"},
"Action": [
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:DescribeImages"
]
}
]
}'
(出力なし)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": ["iaa-ecr-public-test"]}}' \
--query 'findings[].{id:id,resource:resource,resourceType:resourceType,status:status}' \
--region ap-northeast-1 \
--profile Audit[
{
"id": "<パブリックリポジトリ finding ID>",
"resource": "arn:aws:ecr:ap-northeast-1:<Workload アカウント ID>:repository/iaa-ecr-public-test",
"resourceType": "AWS::ECR::Repository",
"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": [
"ecr:BatchGetImage",
"ecr:DescribeImages",
"ecr:GetDownloadUrlForLayer"
],
"condition": {},
"isPublic": true,
"principal": {"AWS": "*"},
"resourceControlPolicyRestriction": "NOT_APPLICABLE"
}
}
],
"resource": "arn:aws:ecr:ap-northeast-1:<Workload アカウント ID>:repository/iaa-ecr-public-test",
"status": "ACTIVE",
"resourceType": "AWS::ECR::Repository",
"findingType": "ExternalAccess",
"resourceOwnerAccount": "<Workload アカウント ID>",
"id": "<パブリックリポジトリ finding ID>"
}以下を確認する。
isPublicがtrueprincipalが{"AWS": "*"}actionにecr:BatchGetImage等が含まれるresourceControlPolicyRestrictionがNOT_APPLICABLE
組織外アカウントからの実際のアクセス確認
組織外アカウントからパブリックリポジトリのイメージ一覧を取得できることを確認する。リポジトリポリシーが設定されていない場合は AccessDeniedException になるため、空配列が返ればアクセスが許可されていることを意味する。
aws ecr describe-images \
--registry-id <Workload アカウント ID> \
--repository-name iaa-ecr-public-test \
--query 'imageDetails' \
--profile <組織外プロファイル> \
--region ap-northeast-1[]5. クロスアカウントアクセスの検出
クロスアカウントリポジトリの 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": ["iaa-ecr-crossaccount-test"]}}' \
--query 'findings[].{id:id,resource:resource,resourceType:resourceType,status:status}' \
--region ap-northeast-1 \
--profile Audit[
{
"id": "<クロスアカウントリポジトリ finding ID>",
"resource": "arn:aws:ecr:ap-northeast-1:<Workload アカウント ID>:repository/iaa-ecr-crossaccount-test",
"resourceType": "AWS::ECR::Repository",
"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": [
"ecr:BatchGetImage",
"ecr:DescribeImages",
"ecr:GetDownloadUrlForLayer"
],
"condition": {},
"isPublic": false,
"principal": {"AWS": "<組織外アカウント ID>"},
"resourceControlPolicyRestriction": "NOT_APPLICABLE"
}
}
],
"resource": "arn:aws:ecr:ap-northeast-1:<Workload アカウント ID>:repository/iaa-ecr-crossaccount-test",
"status": "ACTIVE",
"resourceType": "AWS::ECR::Repository",
"findingType": "ExternalAccess",
"resourceOwnerAccount": "<Workload アカウント ID>",
"id": "<クロスアカウントリポジトリ finding ID>"
}以下を確認する。
isPublicがfalseprincipalに組織外アカウント ID が特定されているactionにecr:BatchGetImage等が含まれるresourceControlPolicyRestrictionがNOT_APPLICABLE
組織外アカウントからの実際のアクセス確認
組織外アカウントからクロスアカウントリポジトリのイメージ一覧を取得できることを確認する。リポジトリポリシーが設定されていない場合は AccessDeniedException になるため、空配列が返ればアクセスが許可されていることを意味する。
aws ecr describe-images \
--registry-id <Workload アカウント ID> \
--repository-name iaa-ecr-crossaccount-test \
--query 'imageDetails' \
--profile <組織外プロファイル> \
--region ap-northeast-1[]6. クリーンアップ
リポジトリポリシーの削除
aws ecr delete-repository-policy \
--repository-name iaa-ecr-public-test
(出力なし)aws ecr delete-repository-policy \
--repository-name iaa-ecr-crossaccount-test
(出力なし)finding の確認
ポリシー削除後、finding が RESOLVED になることを確認する。
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::ECR::Repository"]}}' \
--query 'findings[].{id:id,resource:resource,status:status}' \
--region ap-northeast-1 \
--profile Audit[]テスト用リポジトリの削除
aws ecr delete-repository \
--repository-name iaa-ecr-public-test \
--force
(出力なし)aws ecr delete-repository \
--repository-name iaa-ecr-crossaccount-test \
--force
(出力なし)