Skip to content

Commit

Permalink
rpc: replace hyper::Client with reqwest::Client (informalsystems#…
Browse files Browse the repository at this point in the history
…1362)

* rpc: replace hyper::Client with reqwest::Client

In hyper, the high-level Client implementation is going to be removed
in the next major release. The current client lacks built-in support for
HTTP proxies, and we want to ditch hyper-proxy as it is unmaintained
and its webpki dependency has known security issues.

* Remove the proxy_client example

Oops, this was temporary and not meant to be commited.
The CLI can be used to test the proxy support.

* Bump async-tungstenite version to 0.23

* rpc: fix proxy configuration in http::Builder

* rpc: use argument type to select the dialog

Remove ugly turbofish syntax. The changes only affect internal methods,
so these stylistics do not matter a lot.

* rpc: restore LatestDialog as re-export

This solves the problem with using type alias as a constructor.

* Changelog entries for informalsystems#1362

* rpc: prune dependencies for http-client feature

* rpc: demote http to dev-dependencies

* Small rewording in changelog for informalsystems#1342 (informalsystems#1362)

Co-authored-by: Romain Ruetschi <[email protected]>

---------

Co-authored-by: Romain Ruetschi <[email protected]>
  • Loading branch information
2 people authored and SuperFluffy committed Oct 12, 2023
1 parent 4d81b67 commit 7e4d10d
Show file tree
Hide file tree
Showing 10 changed files with 168 additions and 301 deletions.
10 changes: 10 additions & 0 deletions .changelog/unreleased/breaking-changes/1362-rpc-by-reqwest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
- `[tendermint-rpc]` Changed `ErrorDetail` variants
([\#1362](https://github.com/informalsystems/tendermint-rs/pull/1362)):
* Removed the `Hyper` and `InvalidUri` variants.
* The `Http` variant now has `Error` from `reqwest` as the source.
* Added the `InvalidProxy` variant.
* The `tungstenite` dependency exposed through its `Error` type in
WebSocket-related variants has been updated to version 0.20.x.
- `[tendermint-rpc]` Removed a `TryFrom<HttpClientUrl>` conversion for
`hyper::Uri` as hyper is no longer a direct dependency
([\#1362](https://github.com/informalsystems/tendermint-rs/pull/1362)).
3 changes: 3 additions & 0 deletions .changelog/unreleased/security/1342-rpc-by-reqwest.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- `[tendermint-rpc]` Address the RUSTSEC-2023-0052 vulnerability by dropping
dependency on `hyper-proxy` and changing the HTTP client to use `reqwest`
([\#1342](https://github.com/informalsystems/tendermint-rs/issues/1342)).
15 changes: 4 additions & 11 deletions rpc/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,19 +38,14 @@ cli = [
]
http-client = [
"futures",
"http",
"hyper",
"hyper-proxy",
"hyper-rustls",
"tokio/fs",
"reqwest",
"tokio/macros",
"tracing"
]
secp256k1 = [ "tendermint/secp256k1" ]
websocket-client = [
"async-tungstenite",
"futures",
"http",
"tokio/rt-multi-thread",
"tokio/fs",
"tokio/macros",
Expand Down Expand Up @@ -83,17 +78,15 @@ subtle = { version = "2", default-features = false }
semver = { version = "1.0", default-features = false }

# Optional dependencies
async-tungstenite = { version = "0.20", default-features = false, features = ["tokio-runtime", "tokio-rustls-native-certs"], optional = true }
async-tungstenite = { version = "0.23", default-features = false, features = ["tokio-runtime", "tokio-rustls-native-certs"], optional = true }
futures = { version = "0.3", optional = true, default-features = false }
http = { version = "0.2", optional = true, default-features = false }
hyper = { version = "0.14", optional = true, default-features = false, features = ["client", "http1", "http2"] }
hyper-proxy = { version = "0.9.1", optional = true, default-features = false, features = ["rustls"] }
hyper-rustls = { version = "0.22.1", optional = true, default-features = false, features = ["rustls-native-certs", "webpki-roots", "tokio-runtime"] }
reqwest = { version = "0.11.20", optional = true, default-features = false, features = ["rustls-tls-native-roots"] }
structopt = { version = "0.3", optional = true, default-features = false }
tokio = { version = "1.0", optional = true, default-features = false, features = ["rt-multi-thread"] }
tracing = { version = "0.1", optional = true, default-features = false }
tracing-subscriber = { version = "0.2", optional = true, default-features = false, features = ["fmt"] }

[dev-dependencies]
http = { version = "0.2", default-features = false }
lazy_static = { version = "1.4.0", default-features = false }
tokio-test = { version = "0.4", default-features = false }
12 changes: 10 additions & 2 deletions rpc/src/client/transport.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,16 @@ macro_rules! perform_with_compat {
($self:expr, $request:expr) => {{
let request = $request;
match $self.compat {
CompatMode::V0_37 => $self.perform(request).await,
CompatMode::V0_34 => $self.perform_v0_34(request).await,
CompatMode::V0_37 => {
$self
.perform_with_dialect(request, crate::dialect::v0_37::Dialect)
.await
},
CompatMode::V0_34 => {
$self
.perform_with_dialect(request, crate::dialect::v0_34::Dialect)
.await
},
}
}};
}
Expand Down
18 changes: 7 additions & 11 deletions rpc/src/client/transport/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
use alloc::string::{String, ToString};
use core::fmt;

use http::Uri;
use subtle_encoding::base64;
use url::Url;

/// An HTTP authorization.
///
Expand All @@ -28,10 +28,10 @@ impl fmt::Display for Authorization {
///
/// This authorization can then be supplied to the RPC server via
/// the `Authorization` HTTP header.
pub fn authorize(uri: &Uri) -> Option<Authorization> {
let authority = uri.authority()?;
pub fn authorize(url: &Url) -> Option<Authorization> {
let authority = url.authority();

if let Some((userpass, _)) = authority.as_str().split_once('@') {
if let Some((userpass, _)) = authority.split_once('@') {
let bytes = base64::encode(userpass);
let credentials = String::from_utf8_lossy(bytes.as_slice());
Some(Authorization::Basic(credentials.to_string()))
Expand All @@ -42,28 +42,24 @@ pub fn authorize(uri: &Uri) -> Option<Authorization> {

#[cfg(test)]
mod tests {
use core::str::FromStr;

use http::Uri;

use super::*;

#[test]
fn extract_auth_absent() {
let uri = Uri::from_str("http://example.com").unwrap();
let uri = "http://example.com".parse().unwrap();
assert_eq!(authorize(&uri), None);
}

#[test]
fn extract_auth_username_only() {
let uri = Uri::from_str("http://[email protected]").unwrap();
let uri = "http://[email protected]".parse().unwrap();
let base64 = "dG90bw==".to_string();
assert_eq!(authorize(&uri), Some(Authorization::Basic(base64)));
}

#[test]
fn extract_auth_username_password() {
let uri = Uri::from_str("http://toto:[email protected]").unwrap();
let uri = "http://toto:[email protected]".parse().unwrap();
let base64 = "dG90bzp0YXRh".to_string();
assert_eq!(authorize(&uri), Some(Authorization::Basic(base64)));
}
Expand Down
Loading

0 comments on commit 7e4d10d

Please sign in to comment.