From 698bec5b83d536e48d6b923eeeb2a518557973dd Mon Sep 17 00:00:00 2001 From: David Robson Date: Mon, 13 Jul 2020 11:42:11 -0700 Subject: [PATCH] Fix: Edgelet unable to pull using certain passwords - cherry-pick into 1.0.9. (#3206) (#3209) Some passwords (especially generated passwords) can be used by docker CLI, but not by Edgelet. There is a chance of this happening when passwords contain `?` or `~`. It's not explicitly stated in the [Docker API](https://docs.docker.com/engine/api/v1.40/#section/Authentication), but the [code](https://github.com/docker/cli/blob/master/cli/command/registry.go#L50) is written such that the `X-Registry-Auth` header is expected to be URL safe (RFC 4648) base64. --- edgelet/edgelet-docker/src/runtime.rs | 2 +- edgelet/edgelet-docker/tests/runtime.rs | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/edgelet/edgelet-docker/src/runtime.rs b/edgelet/edgelet-docker/src/runtime.rs index e2e4b21a003..a1cabc4774e 100644 --- a/edgelet/edgelet-docker/src/runtime.rs +++ b/edgelet/edgelet-docker/src/runtime.rs @@ -109,7 +109,7 @@ impl ModuleRegistry for DockerModuleRuntime { let json = serde_json::to_string(a).with_context(|_| { ErrorKind::RegistryOperation(RegistryOperation::PullImage(image.clone())) })?; - Ok(base64::encode(&json)) + Ok(base64::encode_config(&json, base64::URL_SAFE)) }, ); diff --git a/edgelet/edgelet-docker/tests/runtime.rs b/edgelet/edgelet-docker/tests/runtime.rs index 44f244790a9..c00f3312933 100644 --- a/edgelet/edgelet-docker/tests/runtime.rs +++ b/edgelet/edgelet-docker/tests/runtime.rs @@ -426,13 +426,13 @@ fn image_pull_with_invalid_creds_handler(req: Request) -> ResponseFuture { .headers() .get_all("X-Registry-Auth") .into_iter() - .map(|bytes| base64::decode(bytes).unwrap()) + .map(|bytes| base64::decode_config(bytes, base64::URL_SAFE).unwrap()) .map(|raw| str::from_utf8(&raw).unwrap().to_owned()) .collect::>() .join(""); let auth_config: AuthConfig = serde_json::from_str(&auth_str).unwrap(); - assert_eq!(auth_config.username(), Some("u1")); - assert_eq!(auth_config.password(), Some("wrong_password")); + assert_eq!(auth_config.username(), Some("us1")); + assert_eq!(auth_config.password(), Some("ac?ac~aaac???")); assert_eq!(auth_config.email(), Some("u1@bleh.com")); assert_eq!(auth_config.serveraddress(), Some("svr1")); @@ -485,9 +485,10 @@ fn image_pull_with_invalid_creds_fails() { let task = DockerModuleRuntime::make_runtime(settings, provisioning_result(), crypto()) .and_then(|runtime| { + // password is written to guarantee base64 encoding has '-' and/or '_' let auth = AuthConfig::new() - .with_username("u1".to_string()) - .with_password("wrong_password".to_string()) + .with_username("us1".to_string()) + .with_password("ac?ac~aaac???".to_string()) .with_email("u1@bleh.com".to_string()) .with_serveraddress("svr1".to_string()); let config = DockerConfig::new( @@ -628,7 +629,7 @@ fn image_pull_with_creds_handler(req: Request) -> ResponseFuture { .headers() .get_all("X-Registry-Auth") .into_iter() - .map(|bytes| base64::decode(bytes).unwrap()) + .map(|bytes| base64::decode_config(bytes, base64::URL_SAFE).unwrap()) .map(|raw| str::from_utf8(&raw).unwrap().to_owned()) .collect::>() .join("");