Skip to content

Commit

Permalink
feat: added ECR Public Registry support
Browse files Browse the repository at this point in the history
  • Loading branch information
arjraman committed Jun 15, 2022
1 parent 3d4e073 commit b4f084e
Show file tree
Hide file tree
Showing 8 changed files with 680 additions and 216 deletions.
246 changes: 180 additions & 66 deletions README.md
@@ -1,130 +1,244 @@
## Amazon ECR "Login" Action for GitHub Actions

Logs in the local Docker client to one or more Amazon ECR registries.
Logs in the local Docker client to one or more Amazon ECR Private registries or an Amazon ECR Public registry.

**Table of Contents**

<!-- toc -->

- [Usage](#usage)
- [Example of Usage](#example-of-usage)
- [Credentials and Region](#credentials-and-region)
- [Permissions](#permissions)
- [License Summary](#license-summary)
- [Security Disclosures](#security-disclosures)

<!-- tocstop -->

## Usage
## Example of Usage

Logging in to Amazon ECR Private, then building and pushing a Docker image:
```yaml
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

- name: Build, tag, and push image to Amazon ECR
- name: Build, tag, and push docker image to Amazon ECR
env:
ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
ECR_REPOSITORY: my-ecr-repo
REGISTRY: ${{ steps.login-ecr.outputs.registry }}
REPOSITORY: my-ecr-repo
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
docker build -t $REGISTRY/$REPOSITORY:$IMAGE_TAG .
docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG
```

Logging in to Amazon ECR Public, then building and pushing a Docker image:
```yaml
- name: Login to Amazon ECR Public
id: login-ecr-public
uses: aws-actions/amazon-ecr-login@v1
with:
registry-type: 'public'

- name: Build, tag, and push docker image to Amazon ECR Public
env:
REGISTRY: ${{ steps.login-ecr-public.outputs.registry }}
REGISTRY_ALIAS: my-ecr-public-registry-alias
REPOSITORY: my-ecr-public-repo
IMAGE_TAG: ${{ github.sha }}
run: |
docker build -t $REGISTRY/$REGISTRY_ALIAS/$REPOSITORY:$IMAGE_TAG .
docker push $REGISTRY/$REGISTRY_ALIAS/$REPOSITORY:$IMAGE_TAG
```

Logging in to Amazon ECR Private, then packaging and pushing a Helm chart:
```yaml
- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1

- name: Package and push helm chart to Amazon ECR
env:
REGISTRY: ${{ steps.login-ecr.outputs.registry }}
REPOSITORY: my-ecr-repo
run: |
helm package $REPOSITORY
helm push $REPOSITORY-0.1.0.tgz oci://$REGISTRY
```

Logging in to Amazon ECR Public, then packaging and pushing a Helm chart:
```yaml
- name: Login to Amazon ECR Public
id: login-ecr-public
uses: aws-actions/amazon-ecr-login@v1
with:
registry-type: 'public'

- name: Package and push helm chart to Amazon ECR Public
env:
REGISTRY: ${{ steps.login-ecr-public.outputs.registry }}
REGISTRY_ALIAS: my-ecr-public-registry-alias
REPOSITORY: my-ecr-public-repo
run: |
helm package $REPOSITORY
helm push $REPOSITORY-0.1.0.tgz oci://$REGISTRY/$REGISTRY_ALIAS
```

Helm uses the same credential store as Docker. So Helm can authenticate with the same credentials that you use for Docker.

See [action.yml](action.yml) for the full documentation for this action's inputs and outputs.

## Credentials and Region

This action relies on the [default behavior of the AWS SDK for Javascript](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-node.html) to determine AWS credentials and region. Use [the `aws-actions/configure-aws-credentials` action](https://github.com/aws-actions/configure-aws-credentials) to configure the GitHub Actions environment with environment variables containing AWS credentials and your desired region.
### AWS Credentials

This action relies on the [default behavior of the AWS SDK for Javascript](https://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/setting-credentials-node.html) to determine AWS credentials and region. Use [the `aws-actions/configure-aws-credentials` action](https://github.com/aws-actions/configure-aws-credentials) to configure the GitHub Actions environment with a role using GitHub's OIDC provider and your desired region.

```yaml
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: us-east-2
role-to-assume: arn:aws:iam::123456789012:role/my-github-actions-role
aws-region: us-east-1

- name: Login to Amazon ECR
id: login-ecr
uses: aws-actions/amazon-ecr-login@v1
```

We recommend following [Amazon IAM best practices](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html) for the AWS credentials used in GitHub Actions workflows, including:
* Do not store credentials in your repository's code. You may use [GitHub Actions secrets](https://help.github.com/en/actions/automating-your-workflow-with-github-actions/creating-and-using-encrypted-secrets) to store credentials and redact credentials from GitHub Actions workflow logs.
* [Create an individual IAM user](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#create-iam-users) with an access key for use in GitHub Actions workflows, preferably one per repository. Do not use the AWS account root user access key.
* [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege) to the credentials used in GitHub Actions workflows. Grant only the permissions required to perform the actions in your GitHub Actions workflows. See the Permissions section below for the permissions required by this action.
* [Rotate the credentials](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#rotate-credentials) used in GitHub Actions workflows regularly.
* [Monitor the activity](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#keep-a-log) of the credentials used in GitHub Actions workflows.
We recommend following [Amazon IAM best practices](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html) when using AWS services in GitHub Actions workflows, including:
* [Assume an IAM role](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#delegate-using-roles) to receive temporary credentials. See the [Sample IAM Role CloudFormation Template](https://github.com/aws-actions/configure-aws-credentials#sample-iam-role-cloudformation-template) in the `aws-actions/configure-aws-credentials` action to get an example.
* [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege) to the IAM role used in GitHub Actions workflows. Grant only the permissions required to perform the actions in your GitHub Actions workflows. See the Permissions section below for the permissions required by this action.
* [Monitor the activity](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#keep-a-log) of the IAM role used in GitHub Actions workflows.

### Docker credentials
### Docker Credentials
After the authentication, you can access the docker username and password via Action outputs using the following format:
- Registry URL: `111111111111.dkr.ecr.aws-region-1.amazonaws.com`
- Docker username output: `docker_username_111111111111_dkr_ecr_aws_region_1_amazonaws_com`
- Docker password output: `docker_password_111111111111_dkr_ecr_aws_region_1_amazonaws_com`
- Registry URI for ECR Private: `123456789012.dkr.ecr.aws-region-1.amazonaws.com`
- Registry URI for ECR Public: `public.ecr.aws`

If using ECR Private:
- Docker username output: `docker_username_123456789012_dkr_ecr_aws_region_1_amazonaws_com`
- Docker password output: `docker_password_123456789012_dkr_ecr_aws_region_1_amazonaws_com`

If using ECR Public:
- Docker username output: `docker_username_public_ecr_aws`
- Docker password output: `docker_password_public_ecr_aws`

To push Helm charts, you can also login through Docker. By default, Helm can authenticate with the same credentials that you use for Docker.

## Permissions

This action requires the following minimum set of permissions:
### ECR Private

To see how and where to implement the permissions below, see the [IAM section in the Amazon ECR User Guide](https://docs.aws.amazon.com/AmazonECR/latest/userguide/security-iam.html).

This action requires the following minimum set of permissions to login to ECR Private:

```json
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"GetAuthorizationToken",
"Effect":"Allow",
"Action":[
"ecr:GetAuthorizationToken"
],
"Resource":"*"
}
]
"Version": "2012-10-17",
"Statement": [
{
"Sid": "GetAuthorizationToken",
"Effect": "Allow",
"Action": [
"ecr:GetAuthorizationToken"
],
"Resource": "*"
}
]
}
```

Docker commands in your GitHub Actions workflow, like `docker pull` and `docker push`, may require additional permissions attached to the credentials used by this action.
The following minimum permissions are required for pulling an image from an ECR repository:

The following minimum permissions are required for pulling an image from an ECR Private repository:

```json
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"AllowPull",
"Effect":"Allow",
"Action":[
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability"
],
"Resource":"arn:aws:ecr:us-east-1:123456789012:repository/my-repo"
}
]
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowPull",
"Effect": "Allow",
"Action": [
"ecr:BatchGetImage",
"ecr:GetDownloadUrlForLayer"
],
"Resource": "arn:aws:ecr:us-east-1:123456789012:repository/my-ecr-repo"
}
]
}
```

The following minimum permissions are required for pushing and pulling images in an ECR repository:
The following minimum permissions are required for pushing and pulling images in an ECR Private repository:

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowPushPull",
"Effect": "Allow",
"Action": [
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability",
"ecr:CompleteLayerUpload",
"ecr:GetDownloadUrlForLayer",
"ecr:InitiateLayerUpload",
"ecr:PutImage",
"ecr:UploadLayerPart"
],
"Resource": "arn:aws:ecr:us-east-1:123456789012:repository/my-ecr-repo"
}
]
}
```

### ECR Public

To see how and where to implement the permissions below, see the [IAM section in the Amazon ECR Public User Guide](https://docs.aws.amazon.com/AmazonECR/latest/public/security-iam.html).


This action requires the following minimum set of permissions to login to ECR Public:

```json
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "GetAuthorizationToken",
"Effect": "Allow",
"Action": [
"ecr-public:GetAuthorizationToken"
],
"Resource": "*"
}
]
}
```

Docker commands in your GitHub Actions workflow, like `docker push`, may require additional permissions attached to the credentials used by this action. There are no permissions needed for pulling images from ECR Public.

The following minimum permissions are required for pushing an image to an ECR Public repository:

```json
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"AllowPush",
"Effect":"Allow",
"Action":[
"ecr:GetDownloadUrlForLayer",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability",
"ecr:PutImage",
"ecr:InitiateLayerUpload",
"ecr:UploadLayerPart",
"ecr:CompleteLayerUpload"
],
"Resource":"arn:aws:ecr:us-east-1:123456789012:repository/my-repo"
}
]
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowPush",
"Effect": "Allow",
"Action": [
"ecr-public:BatchCheckLayerAvailability",
"ecr-public:CompleteLayerUpload",
"ecr-public:InitiateLayerUpload",
"ecr-public:PutImage",
"ecr-public:UploadLayerPart"
],
"Resource": "arn:aws:ecr-public:us-east-1:123456789012:repository/my-ecr-public-repo"
}
]
}
```

Expand Down
22 changes: 18 additions & 4 deletions action.yml
@@ -1,19 +1,33 @@
name: 'Amazon ECR "Login" Action for GitHub Actions'
description: 'Logs in the local Docker client to one or more ECR registries'
description: 'Logs in the local Docker client to one or more Amazon ECR Private registries or an Amazon ECR Public registry'
branding:
icon: 'cloud'
color: 'orange'
inputs:
registries:
description: 'A comma-delimited list of AWS account IDs that are associated with the ECR registries. If you do not specify a registry, the default ECR registry is assumed.'
description: >-
A comma-delimited list of AWS account IDs that are associated with the ECR Private registries.
If you do not specify a registry, the default ECR Private registry is assumed.
If 'public' is given as input to 'registry-type', this input is ignored.
required: false
skip-logout:
description: 'Whether to skip explicit logout of the registries during post-job cleanup. Exists for backward compatibility on self-hosted runners. Not recommended.'
description: >-
Whether to skip explicit logout of the registries during post-job cleanup.
Exists for backward compatibility on self-hosted runners.
Not recommended.
required: false
default: 'false'
registry-type:
description: >-
Which ECR registry type to log into.
Options: 'private', 'public'
required: false
default: 'private'
outputs:
registry:
description: 'The URI of the ECR registry i.e. aws_account_id.dkr.ecr.region.amazonaws.com. If multiple registries are provided as inputs, this output will not be set.'
description: >-
The URI of the ECR Private or ECR Public registry.
If logging into multiple registries on ECR Private, this output will not be set.
runs:
using: 'node12'
main: 'dist/index.js'
Expand Down
13 changes: 8 additions & 5 deletions cleanup.js
Expand Up @@ -2,21 +2,24 @@ const core = require('@actions/core');
const exec = require('@actions/exec');

/**
* When the GitHub Actions job is done, remove saved ECR credentials from the
* local Docker engine in the job's environment.
* When the GitHub Actions job is done, logout of ECR Private/Public.
*/

const STATES = {
registries: 'registries'
};

async function cleanup() {
try {
const registriesState = core.getState('registries');
const registriesState = core.getState(STATES.registries);

if (registriesState) {
const registries = registriesState.split(',');
const failedLogouts = [];

// Logout of each registry
for (const registry of registries) {
core.debug(`Logging out of registry ${registry}`);
core.info(`Logging out of registry ${registry}`);

// Execute the docker logout command
let doLogoutStdout = '';
Expand All @@ -35,7 +38,7 @@ async function cleanup() {
});
if (exitCode !== 0) {
core.debug(doLogoutStdout);
core.error(`Could not logout registry ${registry}: ${doLogoutStderr}`);
core.error(`Could not logout of registry ${registry}: ${doLogoutStderr}`);
failedLogouts.push(registry);
}
}
Expand Down

0 comments on commit b4f084e

Please sign in to comment.