Skip to content

Commit 29dc8ec

Browse files
Fricounetimeoer
authored andcommitted
[registry] Accept empty scope during token auth challenge
The distribution spec (https://distribution.github.io/distribution/spec/auth/scope/#authorization-server-use) mentions that the access token provided during auth challenge "may include a scope" which means that it's not necessary to have one either to comply with the spec. Additionally, this is something that is already accepted by containerd which will simply log a warning when no scope is specified: https://github.com/containerd/containerd/blob/main/core/remotes/docker/auth/fetch.go#L64 To match with what containerd and the spec suggest, the commit modifies the `parse_auth` logic to accept an empty `scope` field. It also logs the same warning as containerd. Signed-off-by: Baptiste Girard-Carrabin <baptiste.girardcarrabin@datadoghq.com>
1 parent 7886e18 commit 29dc8ec

1 file changed

Lines changed: 23 additions & 6 deletions

File tree

storage/src/backend/registry.rs

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -432,17 +432,21 @@ impl RegistryState {
432432
Some(Auth::Basic(BasicAuth { realm }))
433433
}
434434
"Bearer" => {
435-
if !paras.contains_key("realm")
436-
|| !paras.contains_key("service")
437-
|| !paras.contains_key("scope")
438-
{
435+
if !paras.contains_key("realm") || !paras.contains_key("service") {
439436
return None;
440437
}
441438

439+
let scope = if let Some(scope) = paras.get("scope") {
440+
(*scope).to_string()
441+
} else {
442+
debug!("no scope specified for token auth challenge");
443+
String::new()
444+
};
445+
442446
Some(Auth::Bearer(BearerAuth {
443447
realm: (*paras.get("realm").unwrap()).to_string(),
444448
service: (*paras.get("service").unwrap()).to_string(),
445-
scope: (*paras.get("scope").unwrap()).to_string(),
449+
scope,
446450
}))
447451
}
448452
_ => None,
@@ -1112,12 +1116,25 @@ mod tests {
11121116
_ => panic!("failed to parse `Bearer` authentication header"),
11131117
}
11141118

1119+
// No scope is accetpable
1120+
let str = "Bearer realm=\"https://auth.my-registry.com/token\",service=\"my-registry.com\"";
1121+
let header = HeaderValue::from_str(str).unwrap();
1122+
let auth = RegistryState::parse_auth(&header).unwrap();
1123+
match auth {
1124+
Auth::Bearer(auth) => {
1125+
assert_eq!(&auth.realm, "https://auth.my-registry.com/token");
1126+
assert_eq!(&auth.service, "my-registry.com");
1127+
assert_eq!(&auth.scope, "");
1128+
}
1129+
_ => panic!("failed to parse `Bearer` authentication header without scope"),
1130+
}
1131+
11151132
let str = "Basic realm=\"https://auth.my-registry.com/token\"";
11161133
let header = HeaderValue::from_str(str).unwrap();
11171134
let auth = RegistryState::parse_auth(&header).unwrap();
11181135
match auth {
11191136
Auth::Basic(auth) => assert_eq!(&auth.realm, "https://auth.my-registry.com/token"),
1120-
_ => panic!("failed to parse `Bearer` authentication header"),
1137+
_ => panic!("failed to parse `Basic` authentication header"),
11211138
}
11221139

11231140
let str = "Base realm=\"https://auth.my-registry.com/token\"";

0 commit comments

Comments
 (0)