Add ability to login to AWS ECR repositories (#24)

* Add ability to login to ECR repositories
This commit is contained in:
Philipp Trulson 2022-06-14 15:49:07 +02:00 committed by GitHub
parent 9088ccefea
commit 58898ff661
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 1156 additions and 7 deletions

View file

@ -85,5 +85,32 @@ jobs:
# Now you can push images, and pull private ones, from ghcr.io. # Now you can push images, and pull private ones, from ghcr.io.
``` ```
It is also possible to login to AWS ECR repositories:
```yaml
name: Log in to ECR
on:
push:
env:
REGISTRY_USER: ${{ secrets.AWS_ACCESS_KEY_ID }}
REGISTRY_PASSWORD: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
IMAGE_REGISTRY: 123456789012.dkr.ecr.eu-west-1.amazonaws.com
jobs:
login:
name: Log in to AWS ECR Registry
runs-on: ubuntu-20.04
steps:
- name: Log in to AWS ECR
uses: redhat-actions/podman-login@v1
with:
username: ${{ env.REGISTRY_USER }}
password: ${{ env.REGISTRY_PASSWORD }}
registry: ${{ env.IMAGE_REGISTRY }}
# Now you can push images, and pull private ones, from ECR.
```
Refer to the [GitHub documentation](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) <!-- markdown-link-check-disable-line --> Refer to the [GitHub documentation](https://docs.github.com/en/actions/reference/context-and-expression-syntax-for-github-actions#github-context) <!-- markdown-link-check-disable-line -->
for information about the `github` context object. for information about the `github` context object.

2
dist/index.js vendored

File diff suppressed because one or more lines are too long

2
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

1063
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -23,7 +23,8 @@
"dependencies": { "dependencies": {
"@actions/core": "^1.2.6", "@actions/core": "^1.2.6",
"@actions/exec": "^1.0.4", "@actions/exec": "^1.0.4",
"@actions/io": "^1.0.2" "@actions/io": "^1.0.2",
"@aws-sdk/client-ecr": "^3.100.0"
}, },
"devDependencies": { "devDependencies": {
"@redhat-actions/action-io-generator": "^1.5.0", "@redhat-actions/action-io-generator": "^1.5.0",

54
src/ecr.ts Normal file
View file

@ -0,0 +1,54 @@
import * as core from "@actions/core";
import { ECR } from "@aws-sdk/client-ecr";
const ecrRegistryRegex = /^(([0-9]{12})\.dkr\.ecr\.(.+)\.amazonaws\.com(.cn)?)(\/([^:]+)(:.+)?)?$/;
export interface ECRData {
username: string;
password: string;
}
export function isECR(registry: string): boolean {
return ecrRegistryRegex.test(registry);
}
function getRegion(registry: string): string {
const matches = registry.match(ecrRegistryRegex);
if (!matches) {
return "";
}
return matches[3];
}
function getAccountID(registry: string): string {
const matches = registry.match(ecrRegistryRegex);
if (!matches) {
return "";
}
return matches[2];
}
export async function getECRToken(registry: string, username: string, password: string): Promise<ECRData> {
const ecr = new ECR({
credentials: {
accessKeyId: username,
secretAccessKey: password,
},
region: getRegion(registry),
});
const response = await ecr.getAuthorizationToken({ registryIds: [ getAccountID(registry) ] });
if (!Array.isArray(response.authorizationData) || response.authorizationData.length === 0) {
throw new Error("Unable to fetch ECR credentials from AWS!");
}
const tokenString = Buffer.from(response.authorizationData[0].authorizationToken || "", "base64").toString("utf-8");
const ecrCredentials = tokenString.split(":", 2);
// Hide auth token in actions logs
core.setSecret(ecrCredentials[1]);
return {
username: ecrCredentials[0],
password: ecrCredentials[1],
};
}

View file

@ -8,6 +8,7 @@ import { promises as fs } from "fs";
import * as io from "@actions/io"; import * as io from "@actions/io";
import * as os from "os"; import * as os from "os";
import * as path from "path"; import * as path from "path";
import * as ecr from "./ecr";
import { execute, getDockerConfigJson } from "./utils"; import { execute, getDockerConfigJson } from "./utils";
import * as stateHelper from "./state-helper"; import * as stateHelper from "./state-helper";
import { Inputs } from "./generated/inputs-outputs"; import { Inputs } from "./generated/inputs-outputs";
@ -31,11 +32,18 @@ async function run(): Promise<void> {
} }
registry = core.getInput(Inputs.REGISTRY, { required: true }); registry = core.getInput(Inputs.REGISTRY, { required: true });
const username = core.getInput(Inputs.USERNAME, { required: true }); let username = core.getInput(Inputs.USERNAME, { required: true });
const password = core.getInput(Inputs.PASSWORD, { required: true }); let password = core.getInput(Inputs.PASSWORD, { required: true });
const logout = core.getInput(Inputs.LOGOUT) || "true"; const logout = core.getInput(Inputs.LOGOUT) || "true";
const authFilePath = core.getInput(Inputs.AUTH_FILE_PATH); const authFilePath = core.getInput(Inputs.AUTH_FILE_PATH);
if (ecr.isECR(registry)) {
core.info(`💡 Detected ${registry} as an ECR repository`);
const ECRData = await ecr.getECRToken(registry, username, password);
username = ECRData.username;
password = ECRData.password;
}
stateHelper.setRegistry(registry); stateHelper.setRegistry(registry);
stateHelper.setLogout(logout); stateHelper.setLogout(logout);