diff --git a/docs/reference/docker_auth.md b/docs/reference/docker_auth.md index b94e018..74f42fc 100644 --- a/docs/reference/docker_auth.md +++ b/docs/reference/docker_auth.md @@ -21,7 +21,7 @@ docker_auth: password: "${REGISTRY_PASSWORD}" ``` -On each `up` run, dokku-compose runs `dokku registry:login ` for every entry. Docker stores credentials in `~/.docker/config.json` and overwrites in place, so re-running is idempotent and rotation is just an `up` away. +On each `up` run, dokku-compose runs `dokku registry:login --global ` for every entry. Docker stores credentials in `~/.docker/config.json` and overwrites in place, so re-running is idempotent and rotation is just an `up` away. | Field | Required | Description | |-------|----------|-------------| @@ -34,7 +34,7 @@ This top-level `docker_auth:` is host-global pull authentication. It is **not** ## Removal Semantics -Removing an entry from `docker_auth:` does **not** automatically log out — host credentials persist. To revoke, run `dokku registry:logout ` manually on the host. Same posture as `plugins:` (installed plugins aren't auto-removed). +Removing an entry from `docker_auth:` does **not** automatically log out — host credentials persist. To revoke, run `dokku registry:logout --global ` manually on the host. Same posture as `plugins:` (installed plugins aren't auto-removed). ## Secrets diff --git a/src/core/mask.test.ts b/src/core/mask.test.ts index 220bba2..4663df3 100644 --- a/src/core/mask.test.ts +++ b/src/core/mask.test.ts @@ -66,14 +66,19 @@ describe('maskSensitiveArgs', () => { .toBe('apps:create myapp') }) - it('masks positional password in registry:login', () => { - expect(maskSensitiveArgs('registry:login ghcr.io octocat ghp_abcdefgh')) - .toBe('registry:login ghcr.io octocat ****efgh') + it('masks positional password in registry:login --global', () => { + expect(maskSensitiveArgs('registry:login --global ghcr.io octocat ghp_abcdefgh')) + .toBe('registry:login --global ghcr.io octocat ****efgh') + }) + + it('masks short positional password in registry:login --global', () => { + expect(maskSensitiveArgs('registry:login --global ghcr.io octocat pw')) + .toBe('registry:login --global ghcr.io octocat ****') }) - it('masks short positional password in registry:login', () => { - expect(maskSensitiveArgs('registry:login ghcr.io octocat pw')) - .toBe('registry:login ghcr.io octocat ****') + it('masks positional password in registry:login without --global', () => { + expect(maskSensitiveArgs('registry:login ghcr.io octocat ghp_abcdefgh')) + .toBe('registry:login ghcr.io octocat ****efgh') }) it('does not affect other registry: subcommands', () => { diff --git a/src/core/mask.ts b/src/core/mask.ts index 1a30239..c5f9cef 100644 --- a/src/core/mask.ts +++ b/src/core/mask.ts @@ -11,10 +11,10 @@ export function maskSensitiveArgs(cmd: string): string { return `${key}=${maskValue(value)}` }) - // Special-case `registry:login ` — password is - // a positional arg, not KEY=VALUE, so the regex above can't catch it. + // Special-case `registry:login [--global] ` — + // password is a positional arg, not KEY=VALUE, so the regex above can't catch it. masked = masked.replace( - /^(registry:login\s+\S+\s+\S+\s+)(\S+)/, + /^(registry:login\s+(?:--global\s+)?\S+\s+\S+\s+)(\S+)/, (_, prefix, password) => `${prefix}${maskValue(password)}` ) diff --git a/src/modules/docker-auth.test.ts b/src/modules/docker-auth.test.ts index 5637cc1..a277f3d 100644 --- a/src/modules/docker-auth.test.ts +++ b/src/modules/docker-auth.test.ts @@ -13,10 +13,10 @@ describe('ensureDockerAuth', () => { 'registry.example.com': { username: 'svc', password: 'pw' }, }) expect(runner.run).toHaveBeenCalledWith( - 'registry:login', 'ghcr.io', 'octocat', 'ghp_secret' + 'registry:login', '--global', 'ghcr.io', 'octocat', 'ghp_secret' ) expect(runner.run).toHaveBeenCalledWith( - 'registry:login', 'registry.example.com', 'svc', 'pw' + 'registry:login', '--global', 'registry.example.com', 'svc', 'pw' ) expect(runner.run).toHaveBeenCalledTimes(2) }) diff --git a/src/modules/docker-auth.ts b/src/modules/docker-auth.ts index 022e86e..017c8d6 100644 --- a/src/modules/docker-auth.ts +++ b/src/modules/docker-auth.ts @@ -8,7 +8,7 @@ export async function ensureDockerAuth( ): Promise { for (const [server, creds] of Object.entries(config)) { logAction('docker-auth', `Logging in to ${server} as ${creds.username}`) - await ctx.run('registry:login', server, creds.username, creds.password) + await ctx.run('registry:login', '--global', server, creds.username, creds.password) logDone() } }