Skip to content

credhelper: add static-Bearer mode#129

Merged
chrissmiller merged 1 commit into
mainfrom
chrismiller/static-bearer-credhelper
May 14, 2026
Merged

credhelper: add static-Bearer mode#129
chrissmiller merged 1 commit into
mainfrom
chrismiller/static-bearer-credhelper

Conversation

@chrissmiller
Copy link
Copy Markdown
Contributor

@chrissmiller chrissmiller commented May 11, 2026

Summary

Add a static-Bearer authentication mode to credhelper.RegistryHostsFromDockerConfig. When a docker-credential helper returns Username == "<static_bearer>", the helper's Secret is installed as a literal Authorization: Bearer <Secret> header on the RegistryHost, and the docker challenge-response auth flow is skipped entirely.

Motivation

Some registries authenticate the caller via a pre-minted bearer token rather than an OAuth2 realm exchange. Concretely: Datadog's Terrapin Forwarder accepts the calling sandbox's identity JWT directly as a bearer, with no token endpoint to exchange against. Today, RegistryHostsFromDockerConfig always wires up a docker.NewDockerAuthorizer that runs the WWW-Authenticate challenge flow — either Basic-auth or OAuth2 token exchange — neither of which matches "send this token verbatim."

The new path mirrors go-containerregistry's "<token>" username convention, but tighter: "<token>" still goes through an OAuth2 refresh_token exchange against the challenge realm. "<static_bearer>" skips that and just sets the header.

Behavior

  • If the docker-credential helper for a host returns Username: "<static_bearer>", the host is configured with:
    • Header = http.Header{"Authorization": []string{"Bearer <Secret>"}} — applied to every request via containerd's RegistryHost.Header merge (remotes/docker/resolver.go).
    • Authorizer = nil — challenge-response auth flow disabled.
  • All other helper outputs use the existing challenge-response flow unchanged.

Test plan

  • New unit test TestRegistryHostsStaticBearerSentinel covers the sentinel path: confirms the Authorization: Bearer … header is installed and the Authorizer is nil.
  • bazel run //:bootstrap && bazel test //...6/6 pass on this branch (buildifier_test, docs:update_test, go/cmd/ocitool:go_default_test, go/pkg/credhelper:credhelper_test, go/pkg/deb2layer:go_default_test, go/pkg/ociutil:go_default_test).
  • End-to-end verified by building a patched ocitool and pulling a multi-arch image (registry.ddbuild.io/images/compute-toolbox@sha256:d45510ad…) through our forwarder proxy from inside a sandbox: manifest list → platform manifests → config + layer blobs all 200 OK. Without the patch the same flow gets 401 Unauthorized because the forwarder's challenge isn't an OAuth2 token endpoint.

🤖 Generated with Claude Code

When a docker-credential helper returns Username "<static_bearer>", install
the Secret as a literal "Authorization: Bearer <Secret>" header on the
RegistryHost and skip the challenge-response auth flow. Used by callers
whose registry accepts a bearer token directly rather than via an OAuth2
realm exchange (e.g. the Datadog Terrapin Forwarder, which authenticates
the calling sandbox via a pre-minted identity JWT).

Adds a unit test covering the new sentinel path.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
@chrissmiller chrissmiller marked this pull request as ready for review May 12, 2026 01:59
@chrissmiller chrissmiller merged commit 9309415 into main May 14, 2026
2 checks passed
@chrissmiller chrissmiller deleted the chrismiller/static-bearer-credhelper branch May 14, 2026 14:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants