Skip to content

Instantly share code, notes, and snippets.

@dhermes
Last active January 30, 2024 21:45
Show Gist options
  • Save dhermes/02b83c4e0ada735f80896d332b5b80fa to your computer and use it in GitHub Desktop.
Save dhermes/02b83c4e0ada735f80896d332b5b80fa to your computer and use it in GitHub Desktop.
Understanding Cross-Account ECR Options

Understanding Cross-Account ECR Options

Executive Summary

  • Common to split environments into multiple AWS accounts; e.g. sandbox:111111111111 and prod:222222222222
  • Common to have multiple Kubernetes clusters in a given account; e.g. dev and sandbox clusters in sandbox:111111111111 and beta and prod clusters in prod:222222222222
  • Centralize ECR images in a dedicated registry (one registry per AWS region); use "new" registry:333333333333 account for this
  • Cross-account ECR access requires two IAM policies, one in each account (source, example):

    To enable cross-account access, you can specify an entire account or IAM entities in another account as the principal in a resource-based policy. Adding a cross-account principal to a resource-based policy is only half of establishing the trust relationship. When the principal and the resource are in different AWS accounts, you must also grant the principal entity permission to access the resource.

  • Desired use case: allow cross-account access to every Docker repository in the registry:333333333333 ECR registry for a set of IAM roles (e.g. each the node IAM role for every Kubernetes cluster in the same AWS region)
  • Pain point: since cross-account access is per-Docker-repository, updating the set of roles (e.g. list of Kubernetes clusters) is error prone and requires bespoke tooling
  • Minor concern: if the number of principals in a given cluster becomes large, the policy document on each ECR Docker repository may become too large

Question: Are Registry-Wide Settings Possible?

Note the available subcommands in the AWS CLI:

$ aws --version
aws-cli/2.2.5 Python/3.9.5 Darwin/20.4.0 source/x86_64 prompt/off
$ aws ecr help | grep policy
       o delete-lifecycle-policy
       o delete-registry-policy
       o delete-repository-policy
       o get-lifecycle-policy
       o get-lifecycle-policy-preview
       o get-registry-policy
       o get-repository-policy
       o put-lifecycle-policy
       o put-registry-policy
       o set-repository-policy
       o start-lifecycle-policy-preview

In particular notice delete-registry-policy, get-registry-policy and put-registry-policy. Does this indicate registry-wide settings exist? (See relevant GitHub issue aws/containers-roadmap#799.)

IAM Policy for the "Pull" Account

$ aws-vault exec sandbox-Admin  # 111111111111
(sandbox-Admin) $ aws iam list-role-policies --role-name nodes.sandbox.k8s.invalid
{
    "PolicyNames": [
        "nodes.sandbox.k8s.invalid"
    ]
}
(sandbox-Admin) $
(sandbox-Admin) $ aws iam get-role-policy \
>   --role-name   nodes.sandbox.k8s.invalid \
>   --policy-name nodes.sandbox.k8s.invalid
{
    "RoleName": "nodes.sandbox.k8s.invalid",
    "PolicyName": "nodes.sandbox.k8s.invalid",
    "PolicyDocument": {
        "Version": "2012-10-17",
        "Statement": [
            ...
            {
                "Sid": "",
                "Effect": "Allow",
                "Action": [
                    "ecr:BatchCheckLayerAvailability",
                    "ecr:BatchGetImage",
                    "ecr:DescribeRepositories",
                    "ecr:GetAuthorizationToken",
                    "ecr:GetDownloadUrlForLayer",
                    "ecr:GetRepositoryPolicy",
                    "ecr:ListImages"
                ],
                "Resource": "*"
            }
        ]
    }
}

Policy for the Docker Repository in the Registry Account

$ aws-vault exec registry-Admin  # 333333333333
(registry-Admin) $ aws ecr get-repository-policy --repository-name microservice > tmp.json
(registry-Admin) $ cat tmp.json
{
    "registryId": "333333333333",
    "repositoryName": "microservice",
    "policyText": "{\n  \"Version\" : \"2008-10-17\",\n  ..."
}
(registry-Admin) $
(registry-Admin) $ cat tmp.json | jq '.policyText' -r | jq
{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "cross-account",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::111111111111:role/nodes.sandbox.k8s.invalid"
      },
      "Action": [
        "ecr:BatchCheckLayerAvailability",
        "ecr:BatchGetImage",
        "ecr:DescribeImages",
        "ecr:DescribeRepositories",
        "ecr:GetDownloadUrlForLayer",
        "ecr:GetLifecyclePolicy",
        "ecr:GetLifecyclePolicyPreview",
        "ecr:GetRepositoryPolicy",
        "ecr:ListImages"
      ]
    }
  ]
}
(registry-Admin) $ rm -f tmp.json
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment