- Common to split environments into multiple AWS accounts; e.g.
sandbox:111111111111
andprod:222222222222
- Common to have multiple Kubernetes clusters in a given account; e.g.
dev
andsandbox
clusters insandbox:111111111111
andbeta
andprod
clusters inprod: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
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.)
$ 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": "*"
}
]
}
}
$ 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