From 06349b9ac760082dd9ee86f0bb019b75411a7615 Mon Sep 17 00:00:00 2001 From: super-mcgin <103895120+super-mcgin@users.noreply.github.com> Date: Sun, 7 Jul 2024 10:20:44 +0100 Subject: [PATCH] feat(datasource/docker): Enable additional authentication mechansim for private ECR repositories (#30053) --- docs/usage/docker.md | 23 ++++++++++++++++++ lib/modules/datasource/docker/ecr.ts | 10 +++++++- lib/modules/datasource/docker/index.spec.ts | 27 +++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/docs/usage/docker.md b/docs/usage/docker.md index 4044921c9ca090..43b0113102ce8b 100644 --- a/docs/usage/docker.md +++ b/docs/usage/docker.md @@ -237,6 +237,8 @@ module.exports = { #### AWS ECR (Amazon Web Services Elastic Container Registry) +#### Using access key id & secret + Renovate can authenticate with AWS ECR using AWS access key id & secret as the username & password, for example: ```json @@ -254,6 +256,27 @@ Renovate can authenticate with AWS ECR using AWS access key id & secret as the u } ``` +##### Using `get-login-password` + +Renovate can also authenticate with AWS ECR using the output from the `aws ecr get-login-password` command as outlined in +the [AWS documentation](https://docs.aws.amazon.com/AmazonECR/latest/userguide/registry_auth.html#registry-auth-token). +To make use of this authentication mechanism, specify the username as `AWS`: + +```json +{ + "hostRules": [ + { + "hostType": "docker", + "matchHost": "12345612312.dkr.ecr.us-east-1.amazonaws.com", + "username": "AWS", + "encrypted": { + "password": "w...A" + } + } + ] +} +``` + #### Google Container Registry / Google Artifact Registry ##### Using Application Default Credentials / Workload Identity (Self-Hosted only) diff --git a/lib/modules/datasource/docker/ecr.ts b/lib/modules/datasource/docker/ecr.ts index f90a6608495a5b..4a2d1be216f777 100644 --- a/lib/modules/datasource/docker/ecr.ts +++ b/lib/modules/datasource/docker/ecr.ts @@ -16,7 +16,15 @@ export async function getECRAuthToken( opts: HostRule, ): Promise { const config: ECRClientConfig = { region }; - if (opts.username && opts.password) { + if (opts.username === `AWS` && opts.password) { + logger.trace( + `AWS user specified, encoding basic auth credentials for ECR registry`, + ); + return Buffer.from(`AWS:${opts.password}`).toString('base64'); + } else if (opts.username && opts.password) { + logger.trace( + `Using AWS accessKey to get Authorization token for ECR registry`, + ); config.credentials = { accessKeyId: opts.username, secretAccessKey: opts.password, diff --git a/lib/modules/datasource/docker/index.spec.ts b/lib/modules/datasource/docker/index.spec.ts index 52a8fef2588ac2..96e576aa07a261 100644 --- a/lib/modules/datasource/docker/index.spec.ts +++ b/lib/modules/datasource/docker/index.spec.ts @@ -358,6 +358,33 @@ describe('modules/datasource/docker/index', () => { expect(res).toBeNull(); }); + it('supports ECR authentication for private repositories', async () => { + httpMock + .scope(amazonUrl) + .get('/') + .reply(401, '', { + 'www-authenticate': 'Basic realm="My Private Docker Registry Server"', + }) + .head('/node/manifests/some-tag') + .matchHeader('authorization', 'Basic QVdTOnNvbWUtcGFzc3dvcmQ=') + .reply(200, '', { 'docker-content-digest': 'some-digest' }); + + hostRules.find.mockReturnValue({ + username: 'AWS', + password: 'some-password', + }); + + const res = await getDigest( + { + datasource: 'docker', + packageName: '123456789.dkr.ecr.us-east-1.amazonaws.com/node', + }, + 'some-tag', + ); + + expect(res).toBe('some-digest'); + }); + it('supports Google ADC authentication for gcr', async () => { httpMock .scope(gcrUrl)