如何从另一个账户的 EC2 实例访问 AWS ECR?

How to access AWS ECR from another account's EC2 instance?

我有两个帐户,a1a2

我在 a1 中有一个 EC2 实例,a1.ec2。它在该帐户中承担了一些角色,a1.r。此角色对所有 ECR 操作具有完全访问权限。

现在,我在 a2 中有一个映像注册表 (ECR),并且希望能够从 a1.ec2 访问它。

所以,我 ssh 进入那个实例,为了测试访问权限,我 运行

aws ecr describe-repositories --region <my-region> --registry-id <id of a2>

但是我得到了错误

An error occurred (AccessDeniedException) when calling the DescribeRepositories operation: User: arn:aws:sts::<id of a1>:assumed-role/a1.r/i-075fad654b998275c is not authorized to perform: ecr:DescribeRepositories on resource: arn:aws:ecr:*:*:repository/*

但是,这个权限确实授予了角色a1.r。我通过能够在 a1 中访问 ECR 来验证这一点。

另外,我喜欢访问的ECR有以下权限策略,所以我确定问题不是由a2的ECR引起的:

    {
      "Sid": "new statement",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<id of a1>:root"
      },
      "Action": "*"
    },
    {
      "Sid": "new statement",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<id of a1>:role/a1.r"
      },
      "Action": "*"
    }

我查看了 https://serverfault.com/questions/897392/ecr-cross-account-pull-permissions,其中的解决方案似乎是创建跨账户角色。尽管我可以创建这样的角色 a2.cross-acc-r,但我无法弄清楚如何为 aws ecr cli 命令承担该角色。我不希望 EC2 实例担任该角色,因为它驻留在不同的帐户中(甚至不确定这是否可能)。

我是否缺乏有关 AWS IAM 工作原理的基本知识?

I had a look at https://serverfault.com/questions/897392/ecr-cross-account-pull-permissions where the solution appears to be to create cross-account roles. Although I could create such a role a2.cross-acc-r, I cannot figure out how I can assume that role for the aws ecr CLI commands. I do not want the EC2 instance to assume that role, as it resides in a different account (not even sure if that is possible at all).

您可以按照以下步骤进行操作:

  1. 账户A中,我创建了一个角色(例如RoleForB)来信任账户B ,并将 IAM 策略 附加到之前创建的角色,以允许它在 账户 A 中执行一些读取操作。 e.g ReadOnlyAccess
  2. 帐户 B 中,我创建了一个 角色 (例如 AssumeRoleInA)并附加了一个 政策 允许它承担在 帐户 A.
  3. 中创建的角色
  4. 账户 B 关联到您的 EC2 实例 ec2-profile 在步骤 2 中创建的 IAM 角色 (AssumeRoleInA)。
  5. 账户 B 中登录此 EC2 实例以账户 A 中担任角色使用命令 aws sts assume-role --role-arn "arn:aws:iam::Account_A_ID:role/RoleForB" --role-session-name "EC2FromB".
  6. account BEC2终端下命令step 4.完成后,可以看到access key ID、秘密访问密钥和会话令牌 来自您路由它的任何地方,在我们的例子中 stdout 手动或使用脚本。然后,您可以将这些值分配给环境变量 (AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYAWS_SESSION_TOKEN)

所以让我们逐步检查上面提到的配置,但有一些模式细节:

  1. 如前所述,在 账户 A 中,它通过创建名为 RoleForB 的角色来建立对 账户 B 的信任,并且附加 ReadOnlyAccess 许可。
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Principal": {"AWS": "arn:aws:iam::Account_B_ID:root"},
        "Action": "sts:AssumeRole"
    }
}
  1. 账户B中,创建一个名为AssumeRoleInA角色然后附上相应的policy以允许它在 帐户 A.
  2. 中担任名为 RoleForB 的角色
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": [
        "arn:aws:iam::Account_A_ID:role/RoleForB"
      ]
    }
  ]
}
  1. 账户B中,创建一个新的EC2实例(如果它还不存在),并将其关联到ec2-profileIAM 角色 命名为 AssumeRoleInA.
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Principal": {"Service": "ec2.amazonaws.com"},
        "Action": "sts:AssumeRole"
    }
}
  1. 账户 B 中登录此 EC2 实例以账户 A 中担任角色使用命令:
aws sts assume-role --role-arn "arn:aws:iam::Account_A_ID:role/RoleForB" --role-session-name "EC2FromB"`

您需要在您的帐户 a1a2 之间建立信任关系。

从您的 a2 控制台,转到 IAM 服务,创建一个新角色:

1) 可信实体:另一个 AWS 账户(输入账户 a1 的 ID)

2) 策略:AmazonEC2ContainerRegistryPowerUser(或满足您要求的其他策略)

从您的 a2 控制台,转到 ECR 服务,您需要编辑您的权限:

{
      "Sid": "new statement",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<id of a1>:root"
      },
      "Action": "*"
    },
    {
      "Sid": "new statement",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<id of a2>:role/a2.r"
      },
      "Action": "*"
    }
}

如果你想从一个账户的 EC2 实例中拉取和推送镜像到另一个账户的 ECR,并且不需要完整的 aws ecr CLI 功能,你可以通过 docker 来实现。 例如,如果您希望 Jenkins 根据驻留在不同 AWS 账户中的目标环境(生产、暂存)将构建的图像推送到 ECR。

通过 docker 执行此操作记录在 https://aws.amazon.com/premiumsupport/knowledge-center/secondary-account-access-ecr/

简单地说,在 ECR 存储库中,您授予其他帐户所需的权限。

然后您将获得一个临时身份验证令牌,通过以下方式授权 docker 进行 ECR:

$(aws ecr get-login --registry-ids <account ID> --region <your region> --no-include-email)

之后,您可以使用docker pulldocker push访问它。