文章

ECR 跨 AWS 帳號存取教學:Repository Policy 與 IAM 權限設定

示範如何透過 ECR Repository Policy 與 IAM Policy,授予指定跨帳號 IAM Role 拉取私有映像檔的權限,並使用 AWS CLI 與 Docker 驗證。

ECR 跨 AWS 帳號存取教學:Repository Policy 與 IAM 權限設定

讓來源帳號的 IAM Role 拉取另一個 AWS 帳號的 ECR 私有映像檔,需要在目標 Repository Policy 授權來源身分,並在來源 Role 的 IAM Policy 授予相應 ECR 操作。 此外,來源 Role 必須有 ecr:GetAuthorizationToken 權限,才能向 ECR 登入。即使登入成功,若 Repository 沒有授權,拉取映像檔仍會失敗。ECR Repository Policy 官方說明

本文以「帳號 A 的應用程式,需要唯讀拉取帳號 B 的私有 Repository」為例,示範如何設定最小權限、登入目標 Registry、拉取映像檔,以及排查常見錯誤。若要了解另一種跨帳號儲存服務授權,可參考S3 跨帳號存取教學。

Repository Policy 與 IAM Policy 的分工

ECR 使用 Repository Policy(資源型政策)控制個別 Repository 接受哪些身分的操作;IAM Policy(身分型政策)則附加在來源帳號的 Role 上,授予該身分可執行的操作。跨帳號存取時,目標帳號必須透過 Repository Policy 授權來源帳號;來源 Role 也需具有相應的身分權限。兩邊的 Allow 都不能被適用的明確 Deny 覆蓋。ECR IAM 整合說明

設定位置Policy本文用途
帳號 A 的 IAM RoleIAM Policy允許登入 ECR,並拉取帳號 B 指定 Repository 的映像檔
帳號 B 的 ECR RepositoryRepository Policy允許帳號 A 指定 Role 存取該 Repository

範例與前置條件

項目範例值
來源帳號 A111111111111
目標帳號 B222222222222
AWS Regionap-northeast-1
帳號 A 的 RoleAppPullImageRole
帳號 B 的 Repositorybackend-api
映像 Tag2026.10.12
CLI Profileaccount-a-app

請將範例值換成實際帳號、Region、Repository 與 Tag。本文假設目標 Repository 已存在,Role 也已建立,且操作環境已安裝並設定 AWS CLI、Docker。ECR Registry URI 的格式為 <account-id>.dkr.ecr.<region>.amazonaws.com;Repository URI 則再加上 Repository 名稱。

本文僅設定拉取既有映像檔的權限,不授予推送、建立或刪除 Repository 的權限。ECR 的跨帳號與跨 Region replication 是另一種將映像複製到目的地的方式;若需要共用同一份來源映像並由消費端直接拉取,可採用本文的 Repository Policy。ECR 跨帳號與跨 Region 複製

步驟一:在帳號 A 授予 Role 必要權限

在帳號 A 的 IAM 中,將以下 Policy 附加到 AppPullImageRole。其中 ecr:GetAuthorizationToken 必須使用 Resource: "*";其餘拉取操作限制在帳號 B 的指定 Repository ARN。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "GetECRAuthorizationToken",
      "Effect": "Allow",
      "Action": "ecr:GetAuthorizationToken",
      "Resource": "*"
    },
    {
      "Sid": "PullFromAccountBRepository",
      "Effect": "Allow",
      "Action": [
        "ecr:BatchCheckLayerAvailability",
        "ecr:BatchGetImage",
        "ecr:GetDownloadUrlForLayer"
      ],
      "Resource": "arn:aws:ecr:ap-northeast-1:222222222222:repository/backend-api"
    }
  ]
}

GetAuthorizationToken 是登入 Registry 所需的權限,不能只放在目標 Repository Policy。三個 Repository 操作則用於檢查 Layer、取得映像 Manifest 與下載 Layer。若工具還會列出映像或讀取 Repository 資訊,再依需求加入 ecr:ListImages、ecr:DescribeImages 或 ecr:DescribeRepositories;本文的 docker pull 範例不需要因此擴大權限。ECR IAM 權限與推拉映像範例

Terraform:來源 Role 的 IAM Policy

下列 Terraform 範例建立 GitLab Runner 拉取 dockerdind 與 devtool 兩個 Repository 所需的身分政策;請將建立的 Policy 附加至帳號 A 的 Runner Role。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
resource "aws_iam_policy" "pull_ecr_from_other_account_policy" {
  name = "PullECRFromOtherAccountPolicy"

  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "PullCrossAccountRunnerImages"
        Effect = "Allow"
        Action = [
          "ecr:BatchCheckLayerAvailability",
          "ecr:GetDownloadUrlForLayer",
          "ecr:BatchGetImage"
        ]
        Resource = [
          "arn:aws:ecr:ap-northeast-1:222222222222:repository/dockerdind",
          "arn:aws:ecr:ap-northeast-1:222222222222:repository/devtool"
        ]
      }
    ]
  })
}

步驟二:在帳號 B 設定 Repository Policy

切換到帳號 B 與 ap-northeast-1 Region,開啟 ECR Repository backend-api 的 Permissions,新增以下 Repository Policy。若已有 Policy,請合併 Statement,不要覆蓋仍需要的規則。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "AllowAccountARoleToPull",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:role/AppPullImageRole"
      },
      "Action": [
        "ecr:BatchCheckLayerAvailability",
        "ecr:BatchGetImage",
        "ecr:GetDownloadUrlForLayer"
      ],
      "Resource": "*"
    }
  ]
}

Principal 使用來源 IAM Role ARN。若 Role 設有 Path,請填入完整 ARN,例如 arn:aws:iam::111111111111:role/team/AppPullImageRole。本文授權單一 Role;若改為授權整個帳號,Principal 可指定 arn:aws:iam::111111111111:root,但此時來源帳號仍須透過 IAM Policy 決定哪些身分可以使用這項跨帳號授權。請避免在不需要時直接授權整個帳號或使用萬用 Principal。ECR Repository Policy 範例

Terraform:目標帳號的 Repository Policy

以下設定會將跨帳號拉取權限加入帳號 B 的 devtool 與 dockerdind Repository。請依實際 Repository 名稱與來源 Role ARN 調整。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
resource "aws_ecr_repository_policy" "devtool" {
  repository = aws_ecr_repository.devtool.name
  policy     = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "AllowCrossAccountGitLabRunnerPull"
        Effect = "Allow"
        Principal = {
          AWS = "arn:aws:iam::111111111111:role/DummyRole"
        }
        Action = [
          "ecr:BatchCheckLayerAvailability",
          "ecr:GetDownloadUrlForLayer",
          "ecr:BatchGetImage"
        ]
        Resource = "*"
      }
    ]
  })
}

resource "aws_ecr_repository_policy" "dockerdind" {
  repository = aws_ecr_repository.dockerdind.name
  policy     = jsonencode({
    Version = "2012-10-17"
    Statement = [
      {
        Sid    = "AllowCrossAccountGitLabRunnerPull"
        Effect = "Allow"
        Principal = {
          AWS = "arn:aws:iam::111111111111:role/DummyRole"
        }
        Action = [
          "ecr:BatchCheckLayerAvailability",
          "ecr:GetDownloadUrlForLayer",
          "ecr:BatchGetImage"
        ]
        Resource = "*"
      }
    ]
  })
}

步驟三:驗證來源身分並登入 ECR

先確認 AWS CLI 使用的是帳號 A 的預期 Role:

1
aws sts get-caller-identity --profile account-a-app

輸出的 Account 應為 111111111111,ARN 類似:

1
arn:aws:sts::111111111111:assumed-role/AppPullImageRole/example-session

接著使用該 Profile 取得登入密碼,並登入帳號 B 位於 ap-northeast-1 的 Registry:

1
aws ecr get-login-password --region ap-northeast-1 --profile account-a-app | docker login --username AWS --password-stdin 222222222222.dkr.ecr.ap-northeast-1.amazonaws.com

成功時 Docker 會回報 Login Succeeded。ECR 登入憑證有時效;遇到授權權杖過期時,重新執行登入命令即可。AWS CLI get-login-password 文件

步驟四:拉取映像檔

登入成功後,使用完整 Repository URI 與 Tag 拉取映像:

1
docker pull 222222222222.dkr.ecr.ap-northeast-1.amazonaws.com/backend-api:2026.10.12

URI 中的帳號 ID 與 Region 必須對應目標帳號 B 的 Registry 和 Repository 所在 Region,Repository 名稱及 Tag 也必須存在。跨 Region 時,請以映像實際所在的 Region 登入並拉取。

遇到拒絕存取時的檢查方式

現象或錯誤檢查方向
get-login-password 回傳 AccessDeniedException檢查來源 Role 的 IAM Policy 是否允許 ecr:GetAuthorizationToken,以及 SCP、Permissions Boundary、Session Policy 等限制
Docker 登入失敗或 no basic auth credentials確認登入的 Registry URI、Region 與帳號 ID 一致,並確認 docker login 使用 AWS 作為帳號名稱
登入成功但 docker pull 回傳 denied檢查來源 IAM Policy 與目標 Repository Policy 的 Pull Actions、Repository ARN、Principal Role ARN 是否正確
找不到映像或 Tag確認 Repository 名稱、Tag 是否存在,以及完整 URI 指向正確 Registry 與 Region
Policy 看似正確仍被拒絕檢查明確 Deny、SCP、Resource Control Policy、VPC Endpoint Policy

來源 Role 的 IAM Policy 中,Resource ARN 必須精確對應 Repository;Repository Policy 的 Resource 使用 "*",並以 Principal 指定來源 IAM Role ARN,而不是 get-caller-identity 顯示的 STS assumed-role session ARN。新增 Allow 不會排除其他政策中的明確拒絕。ECR 設定 Repository Policy

常見問題

只設定 Repository Policy 可以嗎?

跨帳號情況下,請同時檢查目標 Repository Policy 與來源 Role 的 IAM Policy。無論如何,ecr:GetAuthorizationToken 都需要來源身分的 IAM 權限,Repository Policy 無法代替這項登入權限。

這樣會授予推送映像檔的權限嗎?

不會。本文只允許拉取所需操作。推送需要另外授予 ecr:CompleteLayerUpload、ecr:InitiateLayerUpload、ecr:PutImage、ecr:UploadLayerPart 等操作,請依需求另行設計並限制 Repository 範圍。ECR Repository Policy 推送範例

一定要使用 IAM Role 嗎?

本文使用 Role,讓應用程式透過臨時憑證取得權限。其他 IAM 身分也能依需求授權,但應避免將長期 Access Key 寫入映像、原始碼或部署設定;在 AWS 運算環境中,優先使用其執行 Role 或工作負載身分機制。


設定完成後,帳號 A 的 AppPullImageRole 可以登入帳號 B 的 ECR Registry,並拉取 backend-api 中指定的映像。若要讓其他 Role 使用,請在兩端 Policy 明確加入對應身分與 Repository 權限,再以實際 AWS 環境驗證。

參考文件

本文章以 CC BY 4.0 授權

熱門標籤