From 892843e8877df58e38ffb70bc49757a8230474c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=BAeen?= <3han5chou7@gmail.com> Date: Wed, 20 Jul 2022 18:52:10 +0900 Subject: [PATCH 01/10] initial patch of rustls-support --- Cargo.lock | 296 ++++++++++++++++++++++++++++++++++++-------- Cargo.toml | 5 + rust-toolchain | 2 +- src/docker.rs | 4 +- src/errors.rs | 6 + src/hyper_client.rs | 40 ++++++ 6 files changed, 299 insertions(+), 54 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 03799abf..8c080f0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "aho-corasick" version = "0.7.18" @@ -38,6 +40,12 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bumpalo" +version = "3.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" + [[package]] name = "byteorder" version = "1.4.3" @@ -46,9 +54,9 @@ checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" [[package]] name = "bytes" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" +checksum = "f0b3de4a0c5e67e16066a0715723abd91edc2f9001d09c46e1dca929351e130e" [[package]] name = "cc" @@ -129,6 +137,7 @@ dependencies = [ "futures", "http", "hyper", + "hyper-rustls", "hyper-tls", "hyperlocal", "log", @@ -138,6 +147,7 @@ dependencies = [ "nix", "openssl", "rand", + "rustls", "serde", "serde_json", "tar", @@ -145,6 +155,7 @@ dependencies = [ "tokio", "unix_socket", "url", + "webpki", ] [[package]] @@ -171,14 +182,14 @@ dependencies = [ [[package]] name = "filetime" -version = "0.2.16" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0408e2626025178a6a7f7ffc05a25bc47103229f19c113755de7bf63816290c" +checksum = "e94a7bbaa59354bc20dd75b67f23e2797b4490e9d6928203fb105c79e448c86c" dependencies = [ "cfg-if 1.0.0", "libc", "redox_syscall", - "winapi", + "windows-sys", ] [[package]] @@ -369,9 +380,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.19" +version = "0.14.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42dc3c131584288d375f2d07f822b0cb012d8c6fb899a5b9fdb3cb7eb9b6004f" +checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac" dependencies = [ "bytes", "futures-channel", @@ -390,6 +401,21 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d87c48c02e0dc5e3b849a2041db3029fd066650f8f717c07bf8ed78ccb895cac" +dependencies = [ + "http", + "hyper", + "log", + "rustls", + "rustls-native-certs", + "tokio", + "tokio-rustls", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -442,6 +468,15 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "112c678d4050afce233f4f2852bb2eb519230b3cf12f33585275537d7e41578d" +[[package]] +name = "js-sys" +version = "0.3.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3fac17f7123a73ca62df411b1bf727ccc805daa070338fda671c86dac1bdc27" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "lazy_static" version = "1.4.0" @@ -502,9 +537,9 @@ checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" [[package]] name = "mio" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713d550d9b44d89174e066b7a6217ae06234c10cb47819a88290d2b353c31799" +checksum = "57ee1c23c7c63b0c9250c339ffdc69255f110b298b901b9f6c82547b7b87caaf" dependencies = [ "libc", "log", @@ -541,9 +576,9 @@ dependencies = [ [[package]] name = "nix" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f17df307904acd05aa8e32e97bb20f2a0df1728bbc2d771ae8f9a90463441e9" +checksum = "195cdbc1741b8134346d515b3a56a1c94b0912758009cfd53f99ea0f57b065fc" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -582,15 +617,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" +checksum = "18a6dbe30758c9f83eb00cbea4ac95966305f5a7772f3f42ebfc7fc7eddbd8e1" [[package]] name = "openssl" -version = "0.10.40" +version = "0.10.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb81a6430ac911acb25fe5ac8f1d2af1b4ea8a4fdfda0f1ee4292af2e2d8eb0e" +checksum = "618febf65336490dfcf20b73f885f5651a0c89c64c2d4a8c3662585a70bf5bd0" dependencies = [ "bitflags", "cfg-if 1.0.0", @@ -620,9 +655,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.74" +version = "0.9.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "835363342df5fba8354c5b453325b110ffd54044e588c539cf2f20a8014e4cb1" +checksum = "e5f9bd0c2710541a3cda73d6f9ac4f1b240de4ae261065d309dbe73d9dceb42f" dependencies = [ "autocfg", "cc", @@ -662,18 +697,18 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pin-project" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58ad3879ad3baf4e44784bc6a718a8698867bb991f8ce24d1bcbe2cfb4c3a75e" +checksum = "78203e83c48cffbe01e4a2d35d566ca4de445d79a85372fc64e378bfc812a260" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744b6f092ba29c3650faf274db506afd39944f48420f6c86b17cfe0ee1cb36bb" +checksum = "710faf75e1b33345361201d36d04e98ac1ed8909151a017ed384700836104c74" dependencies = [ "proc-macro2", "quote", @@ -706,18 +741,18 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872" [[package]] name = "proc-macro2" -version = "1.0.39" +version = "1.0.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +checksum = "dd96a1e8ed2596c337f8eae5f24924ec83f5ad5ab21ea8e455d3566c69fbcaf7" dependencies = [ "unicode-ident", ] [[package]] name = "quote" -version = "1.0.18" +version = "1.0.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +checksum = "3bcdf212e9776fbcb2d23ab029360416bb1706b1aea2d1a5ba002727cbcab804" dependencies = [ "proc-macro2", ] @@ -774,9 +809,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.5.6" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d83f127d94bdbcda4c8cc2e50f6f84f4b611f69c902699ca385a39c3a75f9ff1" +checksum = "4c4eb3267174b8c6c2f654116623910a0fef09c4753f8dd83db29c48a0df988b" dependencies = [ "aho-corasick", "memchr", @@ -785,9 +820,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.6.26" +version = "0.6.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b3de9ec5dc0a3417da371aab17d729997c15010e7fd24ff707773a33bddb64" +checksum = "a3f87b73ce11b1619a3c6332f45341e0047173771e8b8b73f87bfeefb7b56244" [[package]] name = "remove_dir_all" @@ -798,6 +833,54 @@ dependencies = [ "winapi", ] +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rustls" +version = "0.20.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aab8ee6c7097ed6057f43c187a62418d0c05a4bd5f18b3571db50ee0f9ce033" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustls-native-certs" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0167bac7a9f490495f3c33013e7722b53cb087ecbe082fb0c6387c96f634ea50" +dependencies = [ + "openssl-probe", + "rustls-pemfile", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7522c9de787ff061458fe9a829dc790a3f5b22dc571694fc5883f448b94d9a9" +dependencies = [ + "base64", +] + [[package]] name = "ryu" version = "1.0.10" @@ -820,6 +903,16 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "security-framework" version = "2.6.1" @@ -845,18 +938,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.137" +version = "1.0.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61ea8d54c77f8315140a05f4c7237403bf38b72704d031543aa1d16abbf517d1" +checksum = "0171ebb889e45aa68b44aee0859b3eede84c6f5f5c228e6f140c0b2a0a46cad6" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.137" +version = "1.0.139" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f26faba0c3959972377d3b2d306ee9f71faee9714294e41bb777f83f88578be" +checksum = "dc1d3230c1de7932af58ad8ffbe1d784bd55efd5a9d84ac24f69c72d83543dfb" dependencies = [ "proc-macro2", "quote", @@ -865,9 +958,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.81" +version = "1.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b7ce2b32a1aed03c558dc61a5cd328f15aff2dbc17daad8fb8af04d2100e15c" +checksum = "82c2c1fdcd807d1098552c5b9a36e425e42e9fbd7c6a37a8425f390f781f7fa7" dependencies = [ "itoa", "ryu", @@ -885,15 +978,18 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb703cfe953bccee95685111adeedb76fabe4e97549a58d16f03ea7b9367bb32" +checksum = "4614a76b2a8be0058caa9dbbaf66d988527d86d003c11a94fbd335d7661edcef" +dependencies = [ + "autocfg", +] [[package]] name = "smallvec" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2dd574626839106c320a323308629dcb1acfc96e32a8cba364ddc61ac23ee83" +checksum = "2fd0db749597d91ff862fd1d55ea87f7855a744a8425a64695b6fca237d1dad1" [[package]] name = "socket2" @@ -905,11 +1001,17 @@ dependencies = [ "winapi", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "syn" -version = "1.0.96" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0748dd251e24453cb8717f0354206b91557e4ec8703673a4b30208f2abaf1ebf" +checksum = "c50aef8a904de4c23c788f104b7dddc7d6f79c647c7c8ce4cc8f73eb0ca773dd" dependencies = [ "proc-macro2", "quote", @@ -998,10 +1100,11 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.19.2" +version = "1.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c51a52ed6686dd62c320f9b89299e9dfb46f730c7a48e635c19f21d116cb1439" +checksum = "57aec3cfa4c296db7255446efb4928a6be304b431a806216105542a67b6ca82e" dependencies = [ + "autocfg", "bytes", "libc", "memchr", @@ -1037,11 +1140,22 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls", + "tokio", + "webpki", +] + [[package]] name = "tower-service" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" @@ -1056,9 +1170,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.27" +version = "0.1.28" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7709595b8878a4965ce5e87ebf880a7d39c9afc6837721b21a5a816a8117d921" +checksum = "7b7358be39f2f274f322d2aaed611acc57f382e8eb1e5b48cb9ae30933495ce7" dependencies = [ "once_cell", ] @@ -1077,15 +1191,15 @@ checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" [[package]] name = "unicode-ident" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bd2fe26506023ed7b5e1e315add59d6f584c621d037f9368fea9cfb988f368c" +checksum = "15c61ba63f9235225a22310255a29b806b907c9b8c964bcbd0a2c70f3f2deea7" [[package]] name = "unicode-normalization" -version = "0.1.19" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" +checksum = "854cbdc4f7bc6ae19c820d44abdc3277ac3e1b2b93db20a636825d9322fb60e6" dependencies = [ "tinyvec", ] @@ -1100,6 +1214,12 @@ dependencies = [ "libc", ] +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + [[package]] name = "url" version = "2.2.2" @@ -1140,6 +1260,80 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasm-bindgen" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c53b543413a17a202f4be280a7e5c62a1c69345f5de525ee64f8cfdbc954994" +dependencies = [ + "cfg-if 1.0.0", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5491a68ab4500fa6b4d726bd67408630c3dbe9c4fe7bda16d5c82a1fd8c7340a" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c441e177922bc58f1e12c022624b6216378e5febc2f0533e41ba443d505b80aa" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d94ac45fcf608c1f45ef53e748d35660f168490c10b23704c7779ab8f5c3048" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a89911bd99e5f3659ec4acf9c4d93b0a90fe4a2a11f15328472058edc5261be" + +[[package]] +name = "web-sys" +version = "0.3.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2fed94beee57daf8dd7d51f2b15dc2bcde92d7a72304cdf662a4371008b71b90" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 3e2481b5..935145de 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,6 +24,8 @@ experimental = [] # Enable OpenSSL both directly and for Hyper. ssl = ["openssl", "native-tls", "hyper-tls"] +# Enable TLS via Rustls +ssl-rustls = ["rustls", "hyper-rustls", "webpki"] [dependencies] chrono = "0.4" @@ -32,6 +34,9 @@ http = "0.2" hyper = { version = "0.14", features = ["client", "http1", "stream", "tcp"] } openssl = { version = "0.10", optional = true } hyper-tls = { version = "0.5", optional = true } +hyper-rustls = { version = "0.23", optional = true } +rustls = { version = "0.20.1", optional = true } +webpki = { version = "0.22.0", optional = true } serde = { version = "1", features = ["derive"] } serde_json = "1" url = "2" diff --git a/rust-toolchain b/rust-toolchain index 7f3a46a8..3ebf789f 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1 +1 @@ -1.49.0 +1.56.0 diff --git a/src/docker.rs b/src/docker.rs index 12066298..14043d02 100644 --- a/src/docker.rs +++ b/src/docker.rs @@ -216,7 +216,7 @@ impl Docker { .into()) } - #[cfg(feature = "openssl")] + #[cfg(any(feature = "openssl", feature = "ssl-rustls"))] pub fn connect_with_ssl(addr: &str, key: &Path, cert: &Path, ca: &Path) -> Result { let client = HyperClient::connect_with_ssl(addr, key, cert, ca).map_err(|err| { Error::CouldNotConnect { @@ -227,7 +227,7 @@ impl Docker { Ok(Docker::new(client, Protocol::Tcp)) } - #[cfg(not(feature = "openssl"))] + #[cfg(not(any(feature = "openssl", feature = "rustls")))] pub fn connect_with_ssl(_addr: &str, _key: &Path, _cert: &Path, _ca: &Path) -> Result { Err(Error::SslDisabled.into()) } diff --git a/src/errors.rs b/src/errors.rs index f80b5a66..b66ec01a 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -33,6 +33,12 @@ pub enum Error { #[cfg(feature = "openssl")] #[error("ssl error")] OpenSsl(#[from] openssl::error::ErrorStack), + #[cfg(feature = "ssl-rustls")] + #[error("tls error")] + Rustls(#[from] rustls::Error), + #[cfg(feature = "ssl-rustls")] + #[error("certificate error")] + Webpki(#[from] webpki::Error), #[error("could not connect: {}", addr)] CouldNotConnect { addr: String, source: Box }, #[error("could not find DOCKER_CERT_PATH")] diff --git a/src/hyper_client.rs b/src/hyper_client.rs index 2b4864c5..ee5c83f2 100644 --- a/src/hyper_client.rs +++ b/src/hyper_client.rs @@ -15,6 +15,8 @@ enum Client { HttpClient(hyper::Client), #[cfg(feature = "openssl")] HttpsClient(hyper::Client>), + #[cfg(feature = "ssl-rustls")] + HttpsClient(hyper::Client>), #[cfg(unix)] UnixClient(hyper::Client), } @@ -25,6 +27,8 @@ impl Client { Client::HttpClient(http_client) => http_client.request(req), #[cfg(feature = "openssl")] Client::HttpsClient(https_client) => https_client.request(req), + #[cfg(feature = "ssl-rustls")] + Client::HttpsClient(https_client) => https_client.request(req), #[cfg(unix)] Client::UnixClient(unix_client) => unix_client.request(req), } @@ -288,6 +292,42 @@ impl HyperClient { Ok(Self::new(Client::HttpsClient(client), url)) } + #[cfg(feature = "ssl-rustls")] + pub fn connect_with_ssl( + addr: &str, + key: &Path, + cert: &Path, + ca: &Path, + ) -> result::Result { + use rustls::{Certificate, PrivateKey}; + use std::fs; + let addr_https = addr.clone().replacen("tcp://", "https://", 1); + let url = Uri::from_str(&addr_https).map_err(|err| Error::InvalidUri { + var: addr_https, + source: err, + })?; + let private_key = PrivateKey(fs::read(key)?); + let cert = Certificate(fs::read(cert)?); + let ca = Certificate(fs::read(ca)?); + let mut root_certs = rustls::RootCertStore::empty(); + root_certs.add(&ca)?; + let config = rustls::ClientConfig::builder() + .with_safe_default_cipher_suites() + .with_safe_default_kx_groups() + .with_safe_default_protocol_versions() + .unwrap() + .with_root_certificates(root_certs) + .with_single_cert(vec![cert], private_key) + .expect("bad certificate/key"); + let https = hyper_rustls::HttpsConnectorBuilder::new() + .with_tls_config(config) + .https_only() + .enable_http1() + .build(); + let client = hyper::Client::builder().build::<_, hyper::Body>(https); + Ok(Self::new(Client::HttpsClient(client), url)) + } + pub fn connect_with_http(addr: &str) -> result::Result { // This ensures that using docker-machine-esque addresses work with Hyper. let addr_https = addr.clone().replace("tcp://", "http://"); From 0523dee4779a193e49b01040fa01c95d81f82b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=BAeen?= <3han5chou7@gmail.com> Date: Wed, 20 Jul 2022 18:56:11 +0900 Subject: [PATCH 02/10] CI setup --- .circleci/config.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6ecb94e2..53494586 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -22,7 +22,7 @@ jobs: build: working_directory: /tmp/dockworker docker: - - image: rust:1.49.0 + - image: rust:1.56.0 environment: DOCKER_VERSION: 18.03.1-ce steps: @@ -63,11 +63,21 @@ jobs: RUST_BACKTRACE=1 cargo build --verbose --features ssl RUST_BACKTRACE=1 cargo build --examples -j 8 - run: - name: Unit testing + name: Unit testing with ssl feature command: | RUST_BACKTRACE=1 cargo test -j 8 --verbose --features ssl - run: - name: More unit testing + name: Unit testing with ssl-rustls feature + command: | + RUST_BACKTRACE=1 cargo test -j 8 --verbose --features ssl + - run: + name: More unit testing with ssl feature + command: | + docker load -i test-iostream + docker load -i test-signal + RUST_BACKTRACE=1 cargo test --verbose --features ssl -- --ignored + - run: + name: More unit testing with ssl-rustls feature command: | docker load -i test-iostream docker load -i test-signal From bf1f2c9d5a7f459450599e8c846e59a7804ea702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=BAeen?= <3han5chou7@gmail.com> Date: Thu, 21 Jul 2022 14:27:59 +0900 Subject: [PATCH 03/10] fix typo --- .circleci/config.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index 53494586..61ae48e5 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -69,7 +69,7 @@ jobs: - run: name: Unit testing with ssl-rustls feature command: | - RUST_BACKTRACE=1 cargo test -j 8 --verbose --features ssl + RUST_BACKTRACE=1 cargo test -j 8 --verbose --features ssl-rustls - run: name: More unit testing with ssl feature command: | @@ -81,7 +81,7 @@ jobs: command: | docker load -i test-iostream docker load -i test-signal - RUST_BACKTRACE=1 cargo test --verbose --features ssl -- --ignored + RUST_BACKTRACE=1 cargo test --verbose --features ssl-rustls -- --ignored - save_cache: key: cache-cargo-target-{{ .Environment.CIRCLE_JOB }}-{{ .Environment.CIRCLECI_CACHE_VERSION }}-{{ checksum "/tmp/build-dep" }} paths: From 55dbd10929ad4b687af321ae196cc8fc3c9eaa03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=BAeen?= <3han5chou7@gmail.com> Date: Thu, 21 Jul 2022 15:14:20 +0900 Subject: [PATCH 04/10] use pem parser --- Cargo.lock | 9 +++++---- Cargo.toml | 3 ++- src/hyper_client.rs | 33 +++++++++++++++++++++++++++------ 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8c080f0c..999ae44b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -148,6 +148,7 @@ dependencies = [ "openssl", "rand", "rustls", + "rustls-pemfile", "serde", "serde_json", "tar", @@ -938,18 +939,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.139" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0171ebb889e45aa68b44aee0859b3eede84c6f5f5c228e6f140c0b2a0a46cad6" +checksum = "fc855a42c7967b7c369eb5860f7164ef1f6f81c20c7cc1141f2a604e18723b03" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.139" +version = "1.0.140" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1d3230c1de7932af58ad8ffbe1d784bd55efd5a9d84ac24f69c72d83543dfb" +checksum = "6f2122636b9fe3b81f1cb25099fcf2d3f542cdb1d45940d56c713158884a05da" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 935145de..80f4aa0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ experimental = [] # Enable OpenSSL both directly and for Hyper. ssl = ["openssl", "native-tls", "hyper-tls"] # Enable TLS via Rustls -ssl-rustls = ["rustls", "hyper-rustls", "webpki"] +ssl-rustls = ["rustls", "hyper-rustls", "webpki", "rustls-pemfile"] [dependencies] chrono = "0.4" @@ -36,6 +36,7 @@ openssl = { version = "0.10", optional = true } hyper-tls = { version = "0.5", optional = true } hyper-rustls = { version = "0.23", optional = true } rustls = { version = "0.20.1", optional = true } +rustls-pemfile = { version = "1.0.0", optional = true } webpki = { version = "0.22.0", optional = true } serde = { version = "1", features = ["derive"] } serde_json = "1" diff --git a/src/hyper_client.rs b/src/hyper_client.rs index ee5c83f2..9f81b3b4 100644 --- a/src/hyper_client.rs +++ b/src/hyper_client.rs @@ -4,6 +4,7 @@ use futures::prelude::*; use futures::stream::FusedStream; use http::{HeaderMap, Request, StatusCode}; use hyper::Uri; +use log::warn; use std::fs::File; use std::io::Read; use std::path::Path; @@ -300,24 +301,44 @@ impl HyperClient { ca: &Path, ) -> result::Result { use rustls::{Certificate, PrivateKey}; - use std::fs; + use rustls_pemfile::pkcs8_private_keys; + use std::io::BufReader; + let addr_https = addr.clone().replacen("tcp://", "https://", 1); let url = Uri::from_str(&addr_https).map_err(|err| Error::InvalidUri { var: addr_https, source: err, })?; - let private_key = PrivateKey(fs::read(key)?); - let cert = Certificate(fs::read(cert)?); - let ca = Certificate(fs::read(ca)?); + + let mut key_buf = BufReader::new(File::open(key)?); + let mut cert_buf = BufReader::new(File::open(cert)?); + let mut ca_buf = BufReader::new(File::open(ca)?); + + let private_key = match pkcs8_private_keys(&mut key_buf)? { + keys if keys.is_empty() => return Err(rustls::Error::NoCertificatesPresented.into()), + mut keys if keys.len() == 1 => PrivateKey(keys.remove(0)), + mut keys => { + // if keys.len() > 1 + warn!("Private key file contains multiple keys. Using only first one."); + PrivateKey(keys.remove(0)) + } + }; + let certs = rustls_pemfile::certs(&mut cert_buf)? + .into_iter() + .map(Certificate) + .collect(); let mut root_certs = rustls::RootCertStore::empty(); - root_certs.add(&ca)?; + for c in rustls_pemfile::certs(&mut ca_buf)? { + root_certs.add(&Certificate(c))?; + } + let config = rustls::ClientConfig::builder() .with_safe_default_cipher_suites() .with_safe_default_kx_groups() .with_safe_default_protocol_versions() .unwrap() .with_root_certificates(root_certs) - .with_single_cert(vec![cert], private_key) + .with_single_cert(certs, private_key) .expect("bad certificate/key"); let https = hyper_rustls::HttpsConnectorBuilder::new() .with_tls_config(config) From 0e08e6892895021e9ca5b25a650410922065ade4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=BAeen?= <3han5chou7@gmail.com> Date: Thu, 21 Jul 2022 19:26:47 +0900 Subject: [PATCH 05/10] read rsa private key --- src/hyper_client.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hyper_client.rs b/src/hyper_client.rs index 9f81b3b4..4c19fad7 100644 --- a/src/hyper_client.rs +++ b/src/hyper_client.rs @@ -301,7 +301,6 @@ impl HyperClient { ca: &Path, ) -> result::Result { use rustls::{Certificate, PrivateKey}; - use rustls_pemfile::pkcs8_private_keys; use std::io::BufReader; let addr_https = addr.clone().replacen("tcp://", "https://", 1); @@ -314,7 +313,7 @@ impl HyperClient { let mut cert_buf = BufReader::new(File::open(cert)?); let mut ca_buf = BufReader::new(File::open(ca)?); - let private_key = match pkcs8_private_keys(&mut key_buf)? { + let private_key = match rustls_pemfile::rsa_private_keys(&mut key_buf)? { keys if keys.is_empty() => return Err(rustls::Error::NoCertificatesPresented.into()), mut keys if keys.len() == 1 => PrivateKey(keys.remove(0)), mut keys => { From a4aa4649516187864c4e4f771601e3a40ae7250c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=BAeen?= <3han5chou7@gmail.com> Date: Thu, 21 Jul 2022 19:42:24 +0900 Subject: [PATCH 06/10] read pkcs8 private keys --- src/hyper_client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hyper_client.rs b/src/hyper_client.rs index 4c19fad7..abde2d2b 100644 --- a/src/hyper_client.rs +++ b/src/hyper_client.rs @@ -322,7 +322,7 @@ impl HyperClient { PrivateKey(keys.remove(0)) } }; - let certs = rustls_pemfile::certs(&mut cert_buf)? + let certs = rustls_pemfile::pkcs8_private_keys(&mut cert_buf)? .into_iter() .map(Certificate) .collect(); From df958e8acc1530ece5a39f356f129766daae68f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=BAeen?= <3han5chou7@gmail.com> Date: Thu, 21 Jul 2022 19:53:40 +0900 Subject: [PATCH 07/10] debug --- src/docker.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/docker.rs b/src/docker.rs index 14043d02..5b5edb92 100644 --- a/src/docker.rs +++ b/src/docker.rs @@ -1538,9 +1538,8 @@ mod tests { assert_eq!(res.linkTarget, "/bin/busybox"); assert_eq!(res.mode, 134218239); assert!(chrono::DateTime::parse_from_rfc3339(&res.mtime).is_ok()); - assert!(docker - .remove_container(&container.id, None, None, None) - .is_ok()); + let ret = docker.remove_container(&container.id, None, None, None); + assert!(ret.is_ok(), "result is not Ok: {:?}", ret); }) } From 4fee31aa3fc9632e10e2bb6d9176feea1e166c5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=BAeen?= <3han5chou7@gmail.com> Date: Thu, 21 Jul 2022 19:56:03 +0900 Subject: [PATCH 08/10] move import to silence warning --- src/hyper_client.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hyper_client.rs b/src/hyper_client.rs index abde2d2b..a99e1b00 100644 --- a/src/hyper_client.rs +++ b/src/hyper_client.rs @@ -4,7 +4,6 @@ use futures::prelude::*; use futures::stream::FusedStream; use http::{HeaderMap, Request, StatusCode}; use hyper::Uri; -use log::warn; use std::fs::File; use std::io::Read; use std::path::Path; @@ -300,6 +299,7 @@ impl HyperClient { cert: &Path, ca: &Path, ) -> result::Result { + use log::warn; use rustls::{Certificate, PrivateKey}; use std::io::BufReader; From 38596bb498330a84e6279b27d4efbf88562a7a37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=BAeen?= <3han5chou7@gmail.com> Date: Thu, 21 Jul 2022 20:07:18 +0900 Subject: [PATCH 09/10] debug --- src/docker.rs | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/docker.rs b/src/docker.rs index 5b5edb92..c37a9f67 100644 --- a/src/docker.rs +++ b/src/docker.rs @@ -1538,8 +1538,9 @@ mod tests { assert_eq!(res.linkTarget, "/bin/busybox"); assert_eq!(res.mode, 134218239); assert!(chrono::DateTime::parse_from_rfc3339(&res.mtime).is_ok()); - let ret = docker.remove_container(&container.id, None, None, None); - assert!(ret.is_ok(), "result is not Ok: {:?}", ret); + assert!(docker + .remove_container(&container.id, None, None, None) + .is_ok()); }) } @@ -1572,10 +1573,10 @@ mod tests { } fn pull_image(docker: &Docker, name: &str, tag: &str) { - assert!(docker + let ret = docker .create_image(name, tag) - .map(|sts| sts.for_each(|st| println!("{:?}", st))) - .is_ok()); + .map(|sts| sts.for_each(|st| println!("{:?}", st))); + assert!(ret.is_ok(), "create image failed {:?}", ret); } #[test] From 8f3d114010885f4a660bee02f30d5344f4624094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=BAeen?= <3han5chou7@gmail.com> Date: Thu, 21 Jul 2022 20:46:09 +0900 Subject: [PATCH 10/10] tweak --- Cargo.lock | 50 +++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 2 +- src/hyper_client.rs | 12 +++++++---- 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 999ae44b..dd26a158 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -324,6 +324,31 @@ dependencies = [ "wasi 0.11.0+wasi-snapshot-preview1", ] +[[package]] +name = "h2" +version = "0.3.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37a82c6d637fc9515a4694bbf1cb2457b79d81ce52b3108bdeea58b07dd34a57" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hermit-abi" version = "0.1.19" @@ -389,6 +414,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-util", + "h2", "http", "http-body", "httparse", @@ -454,6 +480,16 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "indexmap" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10a35a97730320ffe8e2d410b5d3b69279b98d2c14bdb8b70ea89ecf7888d41e" +dependencies = [ + "autocfg", + "hashbrown", +] + [[package]] name = "instant" version = "0.1.12" @@ -1152,6 +1188,20 @@ dependencies = [ "webpki", ] +[[package]] +name = "tokio-util" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc463cd8deddc3770d20f9852143d50bf6094e640b485cb2e189a2099085ff45" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + [[package]] name = "tower-service" version = "0.3.2" diff --git a/Cargo.toml b/Cargo.toml index 80f4aa0b..fe728f45 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -34,7 +34,7 @@ http = "0.2" hyper = { version = "0.14", features = ["client", "http1", "stream", "tcp"] } openssl = { version = "0.10", optional = true } hyper-tls = { version = "0.5", optional = true } -hyper-rustls = { version = "0.23", optional = true } +hyper-rustls = { version = "0.23", optional = true, features = ["http2"] } rustls = { version = "0.20.1", optional = true } rustls-pemfile = { version = "1.0.0", optional = true } webpki = { version = "0.22.0", optional = true } diff --git a/src/hyper_client.rs b/src/hyper_client.rs index a99e1b00..81ee5f88 100644 --- a/src/hyper_client.rs +++ b/src/hyper_client.rs @@ -301,6 +301,7 @@ impl HyperClient { ) -> result::Result { use log::warn; use rustls::{Certificate, PrivateKey}; + use rustls_pemfile::Item; use std::io::BufReader; let addr_https = addr.clone().replacen("tcp://", "https://", 1); @@ -322,9 +323,12 @@ impl HyperClient { PrivateKey(keys.remove(0)) } }; - let certs = rustls_pemfile::pkcs8_private_keys(&mut cert_buf)? + let certs = rustls_pemfile::read_all(&mut cert_buf)? .into_iter() - .map(Certificate) + .filter_map(|item| match item { + Item::X509Certificate(c) => Some(Certificate(c)), + _ => None, + }) .collect(); let mut root_certs = rustls::RootCertStore::empty(); for c in rustls_pemfile::certs(&mut ca_buf)? { @@ -341,8 +345,8 @@ impl HyperClient { .expect("bad certificate/key"); let https = hyper_rustls::HttpsConnectorBuilder::new() .with_tls_config(config) - .https_only() - .enable_http1() + .https_or_http() + .enable_http2() .build(); let client = hyper::Client::builder().build::<_, hyper::Body>(https); Ok(Self::new(Client::HttpsClient(client), url))