Introduction to ECR Repository Policies Using CloudFormation
ECR repositories can be configured with resource-based policies.
This page aims to set repository policies to restrict image push/pull.
Environment
Create an ECR.
Set an ECR repository policy to restrict image push/pull to the repository.
Create three EC2 instances in a private subnet.
The instances will be the latest version of Amazon Linux 2.
The three units will be configured similarly, but the repository policy will allow the following actions
- EC2 instance 1: Allow image push
- EC2 instance 2: Allow image pull
- EC2 instance 3: Do not allow image push/pull
CloudFormation Template Files
The above configuration is built with CloudFormation.
The CloudFormation templates are located at the following URL
https://github.com/awstut-an-r/awstut-fa/tree/main/085
Point Explanation of Template Files
EC2
Resources:
Instance1:
Type: AWS::EC2::Instance
Properties:
IamInstanceProfile: !Ref InstanceProfile1
ImageId: !Ref ImageId
InstanceType: !Ref InstanceType
NetworkInterfaces:
- DeviceIndex: 0
SubnetId: !Ref InstanceSubnet
GroupSet:
- !Ref InstanceSecurityGroup
UserData: !Ref UserData
Instance2:
Type: AWS::EC2::Instance
Properties:
...
Instance3:
Type: AWS::EC2::Instance
Properties:
...
Code language: YAML (yaml)
Create three EC2 instances.
Configure all of them in the same way.
When creating the instances, perform the initialization process using the user data.
This time, execute the following process.
#!/bin/bash -xe
yum update -y
amazon-linux-extras install docker
systemctl start docker
usermod -a -G docker ec2-user
Code language: Bash (bash)
After installing Docker, start it so that you can execute Docker commands with the privileges of ec2-user.
Here are the IAM roles for the instance
Resources:
InstanceRole1:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service:
- ec2.amazonaws.com
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
- arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryFullAccess
InstanceRole2:
Type: AWS::IAM::Role
Properties:
...
InstanceRole3:
Type: AWS::IAM::Role
Properties:
...
Code language: YAML (yaml)
Create an IAM role for each instance.
Configure all the same settings.
The point is to attach the AWS management policy “AmazonEC2ContainerRegistryFullAccess”.
This means that by attaching these IAM roles, the three instances will be authorized to push/pull images to/from the ECR repository.
Resources:
ECRRepository:
Type: AWS::ECR::Repository
Properties:
RepositoryName: !Ref Prefix
RepositoryPolicyText:
Version: 2012-10-17
Statement:
- Effect: Deny
Principal: "*"
NotAction:
- ecr:BatchCheckLayerAvailability
- ecr:CompleteLayerUpload
- ecr:InitiateLayerUpload
- ecr:PutImage
- ecr:UploadLayerPart
Condition:
ArnEquals:
aws:PrincipalArn: !Ref InstanceRoleArn1
- Effect: Deny
Principal: "*"
NotAction:
- ecr:BatchGetImage
- ecr:GetDownloadUrlForLayer
Condition:
ArnEquals:
aws:PrincipalArn: !Ref InstanceRoleArn2
- Effect: Deny
Principal: "*"
Action: "*"
Condition:
ArnNotEquals:
aws:PrincipalArn:
- !Ref InstanceRoleArn1
- !Ref InstanceRoleArn2
Code language: YAML (yaml)
The RepositoryPolicyText property sets the repository policy.
The repository policy consists of three statements.
The first statement is for EC2 instance 1.
Use ArnEquals and aws:PrincipalArn in the Condition element to specify the ARN of the IAM role attached to EC2 instance 1.
By specifying “Deny” in the Effect element and then using the NotAction element, you are rejecting actions other than those specified in NotAction.
Since we specified the action required for image push in NotAction, it means that instance 1 will be denied any action other than push.
The second statement is for EC2 instance 2.
It uses the same notation as the first one to deny any action other than an image pull to EC2 instance 2.
The third statement is for access from resources other than those listed above.
Use ArnNotEquals and aws:PrincipalArn in the Condition element to specify the ARNs of the two IAM roles above and target resources other than these.
By specifying “Deny” for the Effect element and “*” for the Action, all actions will be denied.
This means that all accesses other than those to the two EC2 instances will be denied.
Architecting
Using CloudFormation, we will build this environment and check the actual behavior.
Create CloudFormation stacks and check resources in stacks
Create CloudFormation stacks.
For information on how to create stacks and check each stack, please refer to the following page
After checking the resources in each stack, information on the main resources created this time is as follows
- ECR repository: fa-085
- EC2 instance 1: i-0bde1cc6fc498a208
- EC2 instance 2: i-0296e9a1b5f70b522
- EC2 instance 3: i-0d0cc36a5186db23b
Confirm the created resource from the AWS Management Console.
Check the ECR.
The ECR repository has been successfully created.
Next, check the ECR repository policy.
You can see that the repository policy has been created as defined in the CloudFormation template.
Check the command to push the image to the ECR.
Execute this command on the three EC2 instances to try to push the image.
Check Action
EC2 instance 1
Now that everything is ready, access EC2 instance 1.
Use SSM Session Manager to access the instances.
% aws ssm start-session --target i-0bde1cc6fc498a208
Starting session with SessionId: root-0c908f28046ae77b1
sh-4.2$
Code language: Bash (bash)
For more information on SSM Session Manager, please refer to the following page.
Change the user to operate.
sh-4.2$ sudo su --login ec2-user
[ec2-user@ip-10-0-2-38 ~]$
Code language: Bash (bash)
We have switched from ssm-user, the default user for SSM Session Manager, to ec2-user.
Now you can execute Docker commands with the authority of ec2-user.
After creating the Dockerfile for verification, run the command to push the image to the ECR repository.
[ec2-user@ip-10-0-2-38 ~]$ echo "FROM amazonlinux" > Dockerfile
[ec2-user@ip-10-0-2-38 ~]$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin [account-id].dkr.ecr.ap-northeast-1.amazonaws.com
...
Login Succeeded
[ec2-user@ip-10-0-2-38 ~]$ docker build -t fa-085 .
Sending build context to Docker daemon 11.26kB
Step 1/1 : FROM amazonlinux
latest: Pulling from library/amazonlinux
12df598bc31e: Pull complete
Digest: sha256:cb8a67164376ecca3b9993e6bb7d81dd868b7836d2631582becd140c8edf27bf
Status: Downloaded newer image for amazonlinux:latest
---> 06c59c262be8
Successfully built 06c59c262be8
Successfully tagged fa-085:latest
[ec2-user@ip-10-0-2-38 ~]$ docker tag fa-085:latest [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest
[ec2-user@ip-10-0-2-38 ~]$ docker push [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest
The push refers to repository [[account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085]
bb99a8750875: Pushed
latest: digest: sha256:ab12022e1a7cd318058af138291d638b1024dcb9844799e8014e6e37d0b35831 size: 529
Code language: Bash (bash)
We were able to push the image.
You can see that the image has indeed been pushed.
As you can see, we were able to push the image from EC2 instance 1 according to the repository policy.
Next, try to pull the image.
[ec2-user@ip-10-0-2-38 ~]$ docker pull [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest
Error response from daemon: pull access denied for [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085, repository does not exist or may require 'docker login': denied: User: arn:aws:sts::[account-id]:assumed-role/fa-085-EC2Stack-16BBODB5DWYO1-InstanceRole1-YILWRMUJ51EE/i-0bde1cc6fc498a208 is not authorized to perform: ecr:BatchGetImage on resource: arn:aws:ecr:ap-northeast-1:[account-id]:repository/fa-085 with an explicit deny in a resource-based policy
Code language: Bash (bash)
Image pull failed.
The IAM role attached to EC2 instance 1 allows full access to the ECR.
However, the repository policy means that actions other than push were denied.
EC2 instance 2
Checking the Action of instance 2 in the same way.
First, pull the image.
% aws ssm start-session --target i-0296e9a1b5f70b522
Starting session with SessionId: root-0ce11bf400c04ba6d
sh-4.2$
sh-4.2$ sudo su --login ec2-user
[ec2-user@ip-10-0-2-59 ~]$
[ec2-user@ip-10-0-2-59 ~]$ docker pull [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest
latest: Pulling from fa-085
12df598bc31e: Pull complete
Digest: sha256:ab12022e1a7cd318058af138291d638b1024dcb9844799e8014e6e37d0b35831
Status: Downloaded newer image for [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest
[account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest
[ec2-user@ip-10-0-2-59 ~]$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
[account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085 latest 06c59c262be8 3 weeks ago 194MB
Code language: Bash (bash)
We were able to pull the image.
Next, try to push the image.
[ec2-user@ip-10-0-2-59 ~]$ echo "FROM amazonlinux" > Dockerfile
[ec2-user@ip-10-0-2-59 ~]$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin [account-id].dkr.ecr.ap-northeast-1.amazonaws.com
...
Login Succeeded
[ec2-user@ip-10-0-2-59 ~]$ docker build -t fa-085 .
Sending build context to Docker daemon 11.26kB
Step 1/1 : FROM amazonlinux
latest: Pulling from library/amazonlinux
Digest: sha256:cb8a67164376ecca3b9993e6bb7d81dd868b7836d2631582becd140c8edf27bf
Status: Downloaded newer image for amazonlinux:latest
---> 06c59c262be8
Successfully built 06c59c262be8
Successfully tagged fa-085:latest
[ec2-user@ip-10-0-2-59 ~]$ docker tag fa-085:latest [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest
[ec2-user@ip-10-0-2-59 ~]$ docker push [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest
The push refers to repository [[account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085]
bb99a8750875: Retrying in 1 second
EOF
Code language: Bash (bash)
The command to push an image to the ECR repository failed because it timed out during the push.
The IAM role attached to EC2 instance 2 also allows full access to the ECR.
However, the repository policy means that actions other than pull were denied.
EC2 instance 3
Finally, instance 3 is also checked the Action.
First, try to push the image.
% aws ssm start-session --target i-0d0cc36a5186db23b
Starting session with SessionId: root-0dbc2ca03d6941d57
sh-4.2$
sh-4.2$ sudo su --login ec2-user
[ec2-user@ip-10-0-2-67 ~]$
[ec2-user@ip-10-0-2-67 ~]$ echo "FROM amazonlinux" > Dockerfile
[ec2-user@ip-10-0-2-67 ~]$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin [account-id].dkr.ecr.ap-northeast-1.amazonaws.com
...
Login Succeeded
[ec2-user@ip-10-0-2-67 ~]$ docker build -t fa-085 .
Sending build context to Docker daemon 11.26kB
Step 1/1 : FROM amazonlinux
latest: Pulling from library/amazonlinux
12df598bc31e: Pull complete
Digest: sha256:cb8a67164376ecca3b9993e6bb7d81dd868b7836d2631582becd140c8edf27bf
Status: Downloaded newer image for amazonlinux:latest
---> 06c59c262be8
Successfully built 06c59c262be8
Successfully tagged fa-085:latest
[ec2-user@ip-10-0-2-67 ~]$ docker tag fa-085:latest [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest
[ec2-user@ip-10-0-2-67 ~]$ docker push [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest
The push refers to repository [[account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085]
bb99a8750875: Retrying in 1 second
EOF
Code language: Bash (bash)
Push failed.
Then attempt to pull the image.
[ec2-user@ip-10-0-2-67 ~]$ docker pull [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085:latest
Error response from daemon: pull access denied for [account-id].dkr.ecr.ap-northeast-1.amazonaws.com/fa-085, repository does not exist or may require 'docker login': denied: User: arn:aws:sts::[account-id]:assumed-role/fa-085-EC2Stack-16BBODB5DWYO1-InstanceRole3-12LD37CD8F85G/i-0d0cc36a5186db23b is not authorized to perform: ecr:BatchGetImage on resource: arn:aws:ecr:ap-northeast-1:[account-id]:repository/fa-085 with an explicit deny in a resource-based policy
Code language: Bash (bash)
The pull also failed.
The IAM role attached to EC2 instance 3 also allows full access to the ECR.
However, the repository policy means that the push/pull action was denied.
Summary
We have reviewed how to configure the ECR repository policy.