Fix Docker Hub authentication and reject build-id tags as candidates

Docker Hub answers with both token and access_token, which made the
serde alias fail as a duplicate field, so every Hub image reported that
no token was returned. Candidates now also have to match the shape of
the running tag; cert-manager v1.14.5 was otherwise offered an upgrade
to the build id 608111629.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Dennis Nemec
2026-09-03 20:24:50 +02:00
parent 214cd1506b
commit b161bf9cbd
2 changed files with 59 additions and 3 deletions

View File

@ -56,6 +56,15 @@ pub fn parse_auth_challenge(headers: &str) -> Option<String> {
Some(url.trim_end_matches(['&', '?']).to_string())
}
/// Registries answer with `token`, `access_token`, or both (Docker Hub sends both).
pub fn parse_token(body: &str) -> Option<String> {
let value: serde_json::Value = serde_json::from_str(body).ok()?;
["token", "access_token"]
.iter()
.find_map(|k| value.get(k).and_then(|v| v.as_str()))
.map(|t| t.to_string())
}
/// `{"tags": ["1.0", "1.1"]}`; a missing or null list means no tags.
pub fn parse_tags(body: &str) -> Result<Vec<String>, DomainError> {
#[derive(serde::Deserialize)]
@ -217,6 +226,18 @@ mod tests {
assert_eq!(parse_next_link("HTTP/1.1 200 OK\r\n"), None);
}
#[test]
fn reads_the_token_whichever_field_carries_it() {
// Docker Hub sends both fields, which must not be treated as a duplicate
assert_eq!(
parse_token(r#"{"token":"a","access_token":"a","expires_in":300}"#).as_deref(),
Some("a")
);
assert_eq!(parse_token(r#"{"access_token":"b"}"#).as_deref(), Some("b"));
assert_eq!(parse_token(r#"{"errors":[]}"#), None);
assert_eq!(parse_token("not json"), None);
}
#[test]
fn reads_the_tag_list() {
assert_eq!(