fix(login): accept equivalent registry hosts in auth creds callback - #5128
fix(login): accept equivalent registry hosts in auth creds callback#5128xianyuwu wants to merge 2 commits into
Conversation
Parse() appends the standard HTTPS port to the registry address, but the containerd authorizer calls the credentials callback with the request URL host, which omits the default port (or uses the registry-1.docker.io alias for Docker Hub). The strict equality check then fails and login aborts. Replace the strict equality check with an equivalence check that accepts the same hostname with the default port omitted, and the Docker Hub index.docker.io/registry-1.docker.io alias pair. Callback hosts with an explicit non-standard port must still match exactly. Fixes containerd#3992 Refs containerd#3245 Signed-off-by: rainwu <xianyuwu@foxmail.com>
|
The failing Unfortunately I don't have permission to re-run the job. Could a maintainer re-run the failed check? A review would also be much appreciated. @AkihiroSuda PTAL when you have a moment, thanks! |
There was a problem hiding this comment.
Pull request overview
Fixes login credential callbacks for equivalent registry hosts and Docker Hub aliases.
Changes:
- Adds host-equivalence logic for omitted HTTPS ports and Docker Hub aliases.
- Adds table-driven credential callback tests.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
pkg/cmd/login/login.go |
Implements equivalent-host credential matching. |
pkg/cmd/login/login_test.go |
Tests accepted and rejected host variants. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| if registryURL.Hostname() == "index.docker.io" && acHost == "registry-1.docker.io" { | ||
| return true | ||
| } |
There was a problem hiding this comment.
Fixed in e604593 — the Docker Hub alias is now only honored when the login target uses the standard HTTPS port, and the index.docker.io:8443 rejection cases are covered in the test table.
| acHost, acPort, err := net.SplitHostPort(acArg) | ||
| if err != nil { | ||
| // acArg carries no port | ||
| acHost, acPort = acArg, "" | ||
| } |
There was a problem hiding this comment.
Fixed in e604593 — the port-less fallback now goes through url.URL.Hostname(), so [::1] matches ::1. Added [::1] and [::1]:443 cases to the test table.
Address review feedback on the equivalent-host check: - Only honor the index.docker.io -> registry-1.docker.io alias when the login target uses the standard HTTPS port, so a login to index.docker.io:<port> no longer leaks credentials to registry-1.docker.io. - Normalize port-less callback hosts through url.URL.Hostname so bracketed IPv6 literals (e.g. [::1]) can match registryURL.Hostname. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: rainwu <xianyuwu@foxmail.com>
71507f5 to
e604593
Compare
PR Title
fix(login): accept equivalent registry hosts in auth creds callback
PR Body
Summary
nerdctl loginfails against registries served on the default HTTPS port (443)with:
docker loginworks fine against the same registry.Fixes #3992
Refs #3245
Root cause
In
pkg/cmd/login/login.go, the credentials callback passed to the containerdauthorizer used a strict string equality check:
However, the two sides of the comparison are built differently:
hostcomes fromdockerconfigresolver.Parse(), which appends thestandard HTTPS port explicitly when the user did not specify one
(
registryurl.go), sohostisharbor.example.io:443.acArgis passed by containerd'sdockerAuthorizer.AddResponses()aslast.Request.URL.Host, i.e. the host of the actual request, which isharbor.example.io— without the default port.The same fragility produces #3245: logging in to
docker.ioresolves toindex.docker.io:443, while the actual registry endpoint calling back isregistry-1.docker.io.Fix
Replace the strict equality check with an equivalence check
(
isEquivalentRegistryHost) that additionally accepts:did not explicitly configure a non-default port.
index.docker.io(the addressdocker.ioresolves to)and
registry-1.docker.io(the actual registry endpoint).Callback hosts carrying an explicit non-standard port still must match
exactly, so credentials are never served to a different endpoint.
This mirrors the equivalence rules already encoded in
RegistryURL.AllIdentifiers()for credential lookup.Test plan
Added
pkg/cmd/login/login_test.gowith table-driven cases covering:registry-1.docker.iowith/without port against adocker.iologin —reproduces Login to docker.io failed. (
expected acArg to be "docker.io", got "registry-1.docker.io") #3245:8443) — not silently dropped or matchedThe failing scenarios from both issues were reproduced against a private Harbor
registry served on port 443 (
nerdctl login --insecure-registry); the unittest cases above encode exactly those mismatches.