Skip to content

docker-credential-forge: credential helper for Docker, Podman, containerd and Helm OCI #163

Open

Description

@schmitch

Part of #44. Builds on the shared client crate (#162). Depends on #39's Docker token service and device-flow endpoints.

Protocol

This implements the docker credential helper protocol: the action is the first argument, input comes on stdin and output goes as JSON to stdout.

  • get
    • Reads the server URL and returns {"ServerURL", "Username", "Secret"} from the keychain cache, renewing the token silently if needed.
    • When nothing usable is cached, it fails with exactly credentials not found in native keychain. Clients treat that as "no credentials", so anonymous pulls still work.
  • store / erase: what docker login / docker logout call.
  • list: the Forge hosts with cached tokens.
  • version.

Login

get runs non-interactively. Clients capture stdout and don't reliably show the helper's stderr, so a docker pull must never hang waiting for a browser login. Users sign in with forge login (#167). With no cached token, get only prints "run forge login <host>" to stderr.

To decide: what does get return?

  • A username and a short-lived token as the password. The client then does Basic auth against /v2/token, which Client login for every format: Nexus-style logins, UI-minted tokens, browser/OAuth login #39 already handles.
  • <token> as the username and a refresh token as the secret.
    • Docker treats this as an identity token and runs the OAuth2 refresh-token grant against the token endpoint itself, so the helper never has to know per-repository scopes.
    • It needs POST /v2/token with grant_type=refresh_token on the server.

Clients

  • Docker and BuildKit: credHelpers in ~/.docker/config.json.
  • Podman, Buildah, Skopeo: credHelpers in containers-auth.json.
  • containerd / nerdctl: Docker's config file.
  • Helm OCI: check which file Helm reads (its own registry/config.json or Docker's) and that credHelpers there are honoured.

forge configure docker (#167) writes these entries. Kubernetes kubelet image credential providers use a different protocol and are out of scope.

Acceptance criteria

  • e2e, extending .github/scripts/oci-e2e.sh: forge login approved through the mock IdP harness, then docker push / pull against Forge with only the helper configured and no docker login.
  • podman pull and helm push / pull oci:// work the same way.
  • With no cached token, get returns "not found" within a second, and anonymous pulls from a public repository still work.
  • An expired token is renewed without user interaction while the refresh token is valid.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions