Is there a way to share my ECR repository across my organization or across different accounts?

Viewed 3301

I want to achieve this without having to push it individually in the accounts with cross account policy enabled. Is there a way to just mention the image uri path in my lambda function of other accounts so that it picks up my docker image from the origin account.

My image already resides in one of the account, lets call it ACC A. Now i want to use the same repo in ACC B, without having to push that image again in ACC B.

4 Answers

Cross Account Method

First add ecr:GetAuthorizationToken permission in your Account B Lambda IAM role for authenticating to ECR repository.

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecr:GetAuthorizationToken"
                ],
            "Resource": "*"
        }
    ]
}

Then, in Account A, add a policy similar to the following in your ECR repository (in Permissions). The below policy allows AWS account 111111111111 to push and pull image from/to your ECR repository. Replace 111111111111 with your Account B AWS account number

{
    "Version": "2008-10-17",
    "Statement": [
        {
            "Sid": "AllowCrossAccountPush",
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::111111111111:root"
            },
            "Action": [
                "ecr:BatchCheckLayerAvailability",
                "ecr:BatchGetImage",
                "ecr:CompleteLayerUpload",
                "ecr:GetDownloadUrlForLayer",
                "ecr:InitiateLayerUpload",
                "ecr:BatchCheckLayerAvailability",
                "ecr:PutImage",
                "ecr:UploadLayerPart"
            ]
        }
    ]
}

I normally use resource based policies for services like ECR or S3 when I need to allow access for all the accounts within the organization.

This is achieved by using the "AWS:PrincipalOrgID" IAM condition, here is a read-only access example for it.

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "ReadonlyAccess",
            "Effect": "Allow",
            "Principal": "*",
            "Action": [
                "ecr:BatchCheckLayerAvailability",
                "ecr:BatchGetImage",
                "ecr:DescribeImageScanFindings",
                "ecr:DescribeImages",
                "ecr:DescribeRepositories",
                "ecr:GetAuthorizationToken",
                "ecr:GetDownloadUrlForLayer",
                "ecr:GetRepositoryPolicy",
                "ecr:ListImages"
            ],
            "Condition": {
                "StringLike": {
                    "aws:PrincipalOrgID": "<YOUR-ORGANIZATION-ID>"
                }
            }
        }
    ]
}

And here is the full Terraform equivalent of how to use achieve this

resource "aws_ecr_repository" "example" {
  name = "example"
}

data "aws_iam_policy_document" "ecr_readonly_access" {
  statement {
    sid    = "ReadonlyAccess"
    effect = "Allow"

    principals {
      type        = "*"
      identifiers = ["*"]
    }

    condition {
      test     = "StringLike"
      variable = "aws:PrincipalOrgID"
      # This is our organization-wide identifier which can be found after
      # log-in to AWS: <https://console.aws.amazon.com/organizations/home>
      values = [aws_organizations_organization.this.id]
    }

    actions = [
      "ecr:GetAuthorizationToken",
      "ecr:BatchCheckLayerAvailability",
      "ecr:GetDownloadUrlForLayer",
      "ecr:GetRepositoryPolicy",
      "ecr:DescribeRepositories",
      "ecr:ListImages",
      "ecr:DescribeImages",
      "ecr:BatchGetImage",
      "ecr:DescribeImageScanFindings",
    ]
  }
}

resource "aws_ecr_repository_policy" "ecr" {
  repository = aws_ecr_repository.example.name
  policy     = data.aws_iam_policy_document.ecr_readonly_access.json
}

I followed the blog post in the other answer, and found that it is just as simple as adding

{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "share_dev",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "ecr:DescribeImages",
      "Condition": {
        "ForAnyValue:StringLike": {
          "aws:PrincipalOrgPaths": [
            "o-<org-id>/r-<root-ou-id>/ou-<sub-ou-id>/*"
          ]
        }
      }
    }
  ]
}

In the permission set of you repository.

Now any account/role that is in the sub-ou-id organization can describe images.

This blog post walks you through the setup (it focuses on ECS as the consumption service for the image but the same concepts would apply to Lambda)

Related