diff --git a/.changeset/tame-pianos-hunt.md b/.changeset/tame-pianos-hunt.md new file mode 100644 index 0000000000..b19f69a8b9 --- /dev/null +++ b/.changeset/tame-pianos-hunt.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-common': minor +--- + +Allow to provide authentification which in turn allows usage of private registries diff --git a/packages/backend-common/src/util/ContainerRunner.ts b/packages/backend-common/src/util/ContainerRunner.ts index 7dc12919b3..11d75bcd8d 100644 --- a/packages/backend-common/src/util/ContainerRunner.ts +++ b/packages/backend-common/src/util/ContainerRunner.ts @@ -16,6 +16,21 @@ import { Writable } from 'stream'; +/** + * Allows defining access credentials for a registry + * Follows dockerode auth configuration: + * {@link https://github.com/apocas/dockerode?tab=readme-ov-file#pull-from-private-repos} + * + * @public + */ +export interface DockerAuthentication { + username?: string; + password?: string; + auth?: string; + email?: string; + serveraddress?: string; +} + /** * Options passed to the {@link ContainerRunner.runContainer} method. * @@ -31,6 +46,7 @@ export type RunContainerOptions = { envVars?: Record; pullImage?: boolean; defaultUser?: boolean; + authentication?: DockerAuthentication; }; /** diff --git a/packages/backend-common/src/util/DockerContainerRunner.test.ts b/packages/backend-common/src/util/DockerContainerRunner.test.ts index 737bf3d178..dde4e48113 100644 --- a/packages/backend-common/src/util/DockerContainerRunner.test.ts +++ b/packages/backend-common/src/util/DockerContainerRunner.test.ts @@ -83,6 +83,28 @@ describe('DockerContainerRunner', () => { expect(mockDocker.run).toHaveBeenCalled(); }); + it('should pull the docker container with authentication', async () => { + await containerTaskApi.runContainer({ + imageName, + args, + authentication: { + auth: 'aaaaaaaaa', + }, + }); + + expect(mockDocker.pull).toHaveBeenCalledWith( + imageName, + { + authconfig: { + auth: 'aaaaaaaaa', + }, + }, + expect.any(Function), + ); + + expect(mockDocker.run).toHaveBeenCalled(); + }); + it('should not pull the docker container when pullImage is false', async () => { await containerTaskApi.runContainer({ imageName, diff --git a/packages/backend-common/src/util/DockerContainerRunner.ts b/packages/backend-common/src/util/DockerContainerRunner.ts index 986470eb98..675b618cab 100644 --- a/packages/backend-common/src/util/DockerContainerRunner.ts +++ b/packages/backend-common/src/util/DockerContainerRunner.ts @@ -47,6 +47,7 @@ export class DockerContainerRunner implements ContainerRunner { envVars = {}, pullImage = true, defaultUser = false, + authentication, } = options; // Show a better error message when Docker is unavailable. @@ -61,13 +62,17 @@ export class DockerContainerRunner implements ContainerRunner { if (pullImage) { await new Promise((resolve, reject) => { - this.dockerClient.pull(imageName, {}, (err, stream) => { - if (err) return reject(err); - stream.pipe(logStream, { end: false }); - stream.on('end', () => resolve()); - stream.on('error', (error: Error) => reject(error)); - return undefined; - }); + this.dockerClient.pull( + imageName, + { authconfig: authentication }, + (err, stream) => { + if (err) return reject(err); + stream.pipe(logStream, { end: false }); + stream.on('end', () => resolve()); + stream.on('error', (error: Error) => reject(error)); + return undefined; + }, + ); }); }