コンテンツにスキップ

ECR リポジトリ

検証日: 2026-04-05 / リージョン: ap-northeast-1

概要

IAM Access Analyzer が ECR プライベートリポジトリの外部アクセスをどのように検出するかを検証する。

ECR プライベートリポジトリはリポジトリポリシー(リソースベースポリシー)により外部アクセスを制御する。set-repository-policyPrincipal"*" を指定するとパブリックアクセス、特定のアカウント 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-policy
An 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-test
An 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-1
An 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. テスト用リポジトリの作成

外部アカウントやパブリックへのアクセスを許可するリポジトリポリシーを設定する。検証目的のみで行い、ステップ 6 で削除する。

ステップ 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. パブリックアクセスの検出

ポリシー変更後、IAM Access Analyzer が finding を生成・更新するまで最大 30 分かかる場合がある。

パブリックリポジトリの 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>"
}

以下を確認する。

  • isPublictrue
  • principal{"AWS": "*"}
  • actionecr:BatchGetImage 等が含まれる
  • resourceControlPolicyRestrictionNOT_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>"
}

以下を確認する。

  • isPublicfalse
  • principal に組織外アカウント ID が特定されている
  • actionecr:BatchGetImage 等が含まれる
  • resourceControlPolicyRestrictionNOT_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
(出力なし)

Amazonアソシエイトリンク