Setting permissions on Amazon EC2 Container Registry repositories

- By Devashish Meena on January 26, 2016


Setting up permissions for images on Docker Hub is pretty straightforward, given how it follows a simple GitHub-like model. Amazon EC2 Container Registry (or Amazon ECR) is a great service for storing images but setting correct permissions is slightly complicated. This is especially true when configuring user-specific permissions on the images. We’ll create a few users and repos and set up repo permissions. We’ll use the AWS command line tool to set the permissions. Using the cli makes it easier to script all the steps and automate the entire process. Everything we do using cli can be done using the web interface

The objective is to setup following rules for any image pushed on Amazon ECRSetting up permissions on Amazon EC2 Container Registry (ECR)

  • user usr1 should have push/pull permissions for Repo1 and Repo2
  • user usr2 should have push/pull permissions for Repo2 only
  • user usr3 should have only pull permissions for Repo1

Let's get started.

Step 0: Configure the local environment

We have to configure the local system to enable the AWS cli to talk to the account. Download and install the AWS cli which should have the Amazon ECR module available. Next, provide the Access Key Id, Secret Key and region for the following command:
 
$ aws configure --profile admin
The reason we’re setting up different profiles is that it will make it easier to test the changes by just switching user profiles before executing commands.  Once the keys are in right place, this command to list keys should return valid data:
 
$ aws --profile admin iam list-access-keys
{
  "AccessKeyMetadata": [
    {
      "UserName": "b-deva",
      "Status": "Active",
      "CreateDate": "2015-11-14T18:18:49Z",
      "AccessKeyId": "AKIAIRKI4PQD4N3JRVJA"
    }
  ]
}
It's ideal to have users permissions that are on a "need-to-know" basis, so by default the users do not have any permissions on AWS. We will create a policy that will allow users to just request authentication token from AWS.
Create a file called authPolicy.json and add this content:
 
$ cat << EOM > authPolicy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "ecr:GetAuthorizationToken"
      ],
      "Resource": "*"
    }
  ]
}
 
 
$ aws --profile admin iam create-policy --policy-name=authOnly --policy-document file://authPolicy.json
{
  "Policy": {
    "PolicyName": "authOnly",
    "CreateDate": "<date>",
    "AttachmentCount": 0,
    "IsAttachable": true,
    "PolicyId": "<policy id>",
    "DefaultVersionId": "v1",
    "Path": "/",
    "Arn": "arn:aws:iam::<account number>:policy/authOnly",
    "UpdateDate": "<date>"
  }
}
 
 So now that we have a policy in place, we can start creating users and assigning this policy to them.

Step 2: Create Users

All three users need permission to authenticate, so we’ll first create the users and attach the policy

 
Run both these commands for usr2 and usr3 also. Also, once the users are created, we need to configure local environment with their credentials
 

Step 3: Create a repository

An image should be stored (ideally) in a different Amazon ECR repository. One can potentially push multiple images in the same repository with different tags but it becomes difficult to manage all the tags this way.
 
Use this command to create a repository:
 
aws ecr create-repository --repository-name=repo1
{
  "repository": {
    "registryId": "<account id>",
    "repositoryName": "repo1",
    "repositoryArn": "arn:aws:ecr:us-east-1:<account-id>:repository/repo1"
  }
}
 
$ aws ecr create-repository --repository-name=repo2
{
  "repository": {
    "registryId": "<account id>",
    "repositoryName": "repo2",
    "repositoryArn": "arn:aws:ecr:us-east-1:<account-id>:repository/repo2"
  }
}

Step 4: Repository permissions

Almost there. The last step is give user-level permissions. For this, each repository will have a different policy document for each user. Create file usr1Policy.json and add following content in it:
 
$ cat << EOM > usr1Policy.json
{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "new statement",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<account id>:user/<usr1>"
      },
      "Action": [
        "ecr:GetDownloadUrlForLayer",
        "ecr:PutImage",
        "ecr:InitiateLayerUpload",
        "ecr:UploadLayerPart",
        "ecr:CompleteLayerUpload",
        "ecr:DescribeRepositories",
        "ecr:GetRepositoryPolicy",
        "ecr:ListImages",
        "ecr:DeleteRepository",
        "ecr:BatchDeleteImage",
        "ecr:SetRepositoryPolicy",
        "ecr:DeleteRepositoryPolicy",
        "ecr:GetAuthorizationToken",
        "ecr:BatchCheckLayerAvailability",
        "ecr:BatchGetImage"
      ]
    }
  ]
}
EOM
 
$ aws --profile admin ecr set-repository-policy --repository-name repo1 --policy-text file://usr1Policy.json
$ aws --profile admin ecr set-repository-policy --repository-name repo2 --policy-text file://usr1Policy.json

This command should now return an empty array:

$ aws --profile usr1 ecr list-images --repository-name=repo1
{
"imageIds": []
}
 
$ aws --profile usr1 ecr list-images --repository-name=repo2
{
"imageIds": []
}
Next is to give usr2 permissions on Img2 only. Create a file usr2Policy.json and add this content:
$ cat << EOM > usr2Policy.json
{
  "Version": "2008-10-17",
  "Statement": [
    {
      "Sid": "new statement",
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::<account id>:user/usr2"
      },
      "Action": [
        "ecr:GetDownloadUrlForLayer",
        "ecr:PutImage",
        "ecr:InitiateLayerUpload",
        "ecr:UploadLayerPart",
        "ecr:CompleteLayerUpload",
        "ecr:DescribeRepositories",
        "ecr:GetRepositoryPolicy",
        "ecr:ListImages",
        "ecr:DeleteRepository",
        "ecr:BatchDeleteImage",
        "ecr:SetRepositoryPolicy",
        "ecr:DeleteRepositoryPolicy",
        "ecr:GetAuthorizationToken",
        "ecr:BatchCheckLayerAvailability",
        "ecr:BatchGetImage"
      ]
    }
  ]
}
EOM
 
$ aws --profile admin ecr set-repository-policy --repository-name repo2 -- policy text file://usr2Policy.json
We should now be able to list images for repo2 using usr2 profile:
 
$ aws --profile usr1 ecr list-images --repository-name=repo1
{
"imageIds": []
}
Lastly, usr3 should have permissions to just pull images from repo 2. Create a new file usr3Policy.json and add following content

Step 5: Time to test

For pushing images to Amazon ECR we first need to enable the local docker daemon to authenticate with the registry:
 
This returns a “docker login ….” command with short-lived credentials. Once we’ve run that command, we should be able to push the image. Just pick any image and tag it as follows:
 
$ docker tag <local image id> <aws account id>.dkr.ecr.<aws region>.amazonaws.com/repo1:latest
That’s about it. Once the tagging is done, the following command should push an image to the Amazon ECR repo:
 

$ docker push <aws account id>.dkr.ecr.<aws region>.amazonaws.com/repo1:latest

Now let's push an image to repo1 with usr3 account:

And, now for the pull:

ECR permissions works as expected !!! 


Try Shippable

Topics: EC2 container services, Amazon ECS, Amazon ECR