From cdbad097dd4cffa02f4a8193c97ccf7b2d616fb4 Mon Sep 17 00:00:00 2001 From: iliana destroyer of worlds Date: Tue, 5 Nov 2019 18:49:40 +0000 Subject: [PATCH 1/5] tough: Swap reqwest::Url for url::Url Signed-off-by: iliana destroyer of worlds --- workspaces/Cargo.lock | 1 + workspaces/updater/tough/Cargo.toml | 1 + workspaces/updater/tough/src/error.rs | 10 +++++----- workspaces/updater/tough/src/fetch.rs | 3 ++- workspaces/updater/tough/src/io.rs | 4 ++-- workspaces/updater/tough/src/lib.rs | 2 +- workspaces/updater/tough/tests/interop.rs | 2 +- 7 files changed, 13 insertions(+), 10 deletions(-) diff --git a/workspaces/Cargo.lock b/workspaces/Cargo.lock index 9444438ba25..3d0efee21c8 100644 --- a/workspaces/Cargo.lock +++ b/workspaces/Cargo.lock @@ -2979,6 +2979,7 @@ dependencies = [ "snafu 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tough_schema 0.1.0", + "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] diff --git a/workspaces/updater/tough/Cargo.toml b/workspaces/updater/tough/Cargo.toml index 38c6cdfd34d..ca66f48f7fa 100644 --- a/workspaces/updater/tough/Cargo.toml +++ b/workspaces/updater/tough/Cargo.toml @@ -14,6 +14,7 @@ serde_json = "1.0.39" sha2 = "0.8.0" snafu = "0.5.0" tough_schema = { path = "../tough_schema" } +url = "1.7.2" [dev-dependencies] hex-literal = "0.2.0" diff --git a/workspaces/updater/tough/src/error.rs b/workspaces/updater/tough/src/error.rs index b7099b45f95..519e8972e56 100644 --- a/workspaces/updater/tough/src/error.rs +++ b/workspaces/updater/tough/src/error.rs @@ -72,8 +72,8 @@ pub enum Error { #[snafu(display("Failed to join \"{}\" to URL \"{}\": {}", path, url, source))] JoinUrl { path: String, - url: reqwest::Url, - source: reqwest::UrlError, + url: url::Url, + source: url::ParseError, backtrace: Backtrace, }, @@ -152,14 +152,14 @@ pub enum Error { #[snafu(display("Failed to parse URL {:?}: {}", url, source))] ParseUrl { url: String, - source: reqwest::UrlError, + source: url::ParseError, backtrace: Backtrace, }, /// An HTTP request failed. #[snafu(display("Failed to request \"{}\": {}", url, source))] Request { - url: reqwest::Url, + url: url::Url, source: reqwest::Error, backtrace: Backtrace, }, @@ -168,7 +168,7 @@ pub enum Error { #[snafu(display("Status {} {} in response for \"{}\"", code.as_u16(), code.as_str(), url))] ResponseStatus { code: reqwest::StatusCode, - url: reqwest::Url, + url: url::Url, backtrace: Backtrace, }, diff --git a/workspaces/updater/tough/src/fetch.rs b/workspaces/updater/tough/src/fetch.rs index f85d1425d46..1f6636897ac 100644 --- a/workspaces/updater/tough/src/fetch.rs +++ b/workspaces/updater/tough/src/fetch.rs @@ -1,10 +1,11 @@ use crate::error::Result; use crate::io::{DigestAdapter, MaxSizeAdapter}; -use reqwest::{Client, Url}; +use reqwest::Client; use snafu::ensure; use std::fs::File; use std::io::Read; use std::path::PathBuf; +use url::Url; fn fetch(client: &Client, url: Url) -> Result> { use crate::error; diff --git a/workspaces/updater/tough/src/io.rs b/workspaces/updater/tough/src/io.rs index aacea08f6f7..f3d6fc2bb85 100644 --- a/workspaces/updater/tough/src/io.rs +++ b/workspaces/updater/tough/src/io.rs @@ -1,7 +1,7 @@ use crate::error; -use reqwest::Url; use sha2::{Digest, Sha256}; use std::io::{self, Read}; +use url::Url; pub(crate) struct DigestAdapter { url: Url, @@ -86,8 +86,8 @@ impl Read for MaxSizeAdapter { mod tests { use crate::io::{DigestAdapter, MaxSizeAdapter}; use hex_literal::hex; - use reqwest::Url; use std::io::{Cursor, Read}; + use url::Url; #[test] fn test_max_size_adapter() { diff --git a/workspaces/updater/tough/src/lib.rs b/workspaces/updater/tough/src/lib.rs index 93bbc4d2da6..eaf0c13695d 100644 --- a/workspaces/updater/tough/src/lib.rs +++ b/workspaces/updater/tough/src/lib.rs @@ -22,13 +22,13 @@ use crate::error::Result; use crate::fetch::{fetch_max_size, fetch_sha256}; use chrono::{DateTime, Utc}; use reqwest::Client; -use reqwest::Url; use snafu::{ensure, OptionExt, ResultExt}; use std::borrow::Cow; use std::collections::HashMap; use std::io::Read; use std::path::Path; use tough_schema::{Role, RoleType, Root, Signed, Snapshot, Timestamp}; +use url::Url; /// Repository fetch settings, provided to [`Repository::load`]. #[derive(Debug, Clone)] diff --git a/workspaces/updater/tough/tests/interop.rs b/workspaces/updater/tough/tests/interop.rs index c79eb078b38..20b26c63410 100644 --- a/workspaces/updater/tough/tests/interop.rs +++ b/workspaces/updater/tough/tests/interop.rs @@ -1,9 +1,9 @@ -use reqwest::Url; use std::fs::File; use std::io::Read; use std::path::{Path, PathBuf}; use tempfile::TempDir; use tough::{Limits, Repository, Settings}; +use url::Url; fn test_data() -> PathBuf { PathBuf::from(env!("CARGO_MANIFEST_DIR")) From 96cbf2a85354cfc77e349e30a20a1b496f5b2f98 Mon Sep 17 00:00:00 2001 From: iliana destroyer of worlds Date: Tue, 5 Nov 2019 20:01:46 +0000 Subject: [PATCH 2/5] tough: Genericize file transport This allows users of tough to add additional functionality when making requests, such as authenticating requests or adding additional HTTP headers. Signed-off-by: iliana destroyer of worlds --- workspaces/tuftool/src/download.rs | 21 ++++---- workspaces/updater/tough/src/error.rs | 32 ++++--------- workspaces/updater/tough/src/fetch.rs | 54 ++++++++------------- workspaces/updater/tough/src/lib.rs | 58 +++++++++++++---------- workspaces/updater/tough/src/transport.rs | 40 ++++++++++++++++ workspaces/updater/tough/tests/interop.rs | 17 ++++--- workspaces/updater/updog/src/main.rs | 41 ++++++++-------- 7 files changed, 143 insertions(+), 120 deletions(-) create mode 100644 workspaces/updater/tough/src/transport.rs diff --git a/workspaces/tuftool/src/download.rs b/workspaces/tuftool/src/download.rs index 32eee215335..f60ccd7da4c 100644 --- a/workspaces/tuftool/src/download.rs +++ b/workspaces/tuftool/src/download.rs @@ -6,7 +6,7 @@ use std::num::NonZeroU64; use std::path::{Path, PathBuf}; use structopt::StructOpt; use tempdir::TempDir; -use tough::{Limits, Repository, Settings}; +use tough::{HttpTransport, Limits, Repository, Settings}; use url::Url; #[derive(Debug, StructOpt)] @@ -87,15 +87,18 @@ impl DownloadArgs { // load repository let repo_dir = TempDir::new("tuf").context(error::TempDir)?; - let repository = Repository::load(Settings { - root: File::open(&root_path).context(error::OpenRoot { path: &root_path })?, - datastore: repo_dir.path(), - metadata_base_url: &self.metadata_base_url, - target_base_url: &self.target_base_url, - limits: Limits { - ..tough::Limits::default() + let repository = Repository::load( + HttpTransport::new(), + Settings { + root: File::open(&root_path).context(error::OpenRoot { path: &root_path })?, + datastore: repo_dir.path(), + metadata_base_url: &self.metadata_base_url, + target_base_url: &self.target_base_url, + limits: Limits { + ..tough::Limits::default() + }, }, - }) + ) .context(error::Metadata)?; // copy all available targets diff --git a/workspaces/updater/tough/src/error.rs b/workspaces/updater/tough/src/error.rs index 519e8972e56..6000eaa8c9d 100644 --- a/workspaces/updater/tough/src/error.rs +++ b/workspaces/updater/tough/src/error.rs @@ -45,14 +45,6 @@ pub enum Error { backtrace: Backtrace, }, - /// A file from a `file:///` URL could not be opened. - #[snafu(display("Failed to read {}: {}", path.display(), source))] - FileRead { - path: PathBuf, - source: std::io::Error, - backtrace: Backtrace, - }, - /// A downloaded target's checksum does not match the checksum listed in the repository /// metadata. #[snafu(display( @@ -156,22 +148,6 @@ pub enum Error { backtrace: Backtrace, }, - /// An HTTP request failed. - #[snafu(display("Failed to request \"{}\": {}", url, source))] - Request { - url: url::Url, - source: reqwest::Error, - backtrace: Backtrace, - }, - - /// A response to an HTTP request was in the 4xx or 5xx range. - #[snafu(display("Status {} {} in response for \"{}\"", code.as_u16(), code.as_str(), url))] - ResponseStatus { - code: reqwest::StatusCode, - url: url::Url, - backtrace: Backtrace, - }, - /// System time is behaving irrationally, went back in time #[snafu(display( "System time stepped backward: system time '{}', last known time '{}'", @@ -183,6 +159,14 @@ pub enum Error { latest_known_time: DateTime, }, + /// A transport error occurred while fetching a URL. + #[snafu(display("Failed to fetch {}: {}", url, source))] + Transport { + url: url::Url, + source: Box, + backtrace: Backtrace, + }, + /// A metadata file could not be verified. #[snafu(display("Failed to verify {} metadata: {}", role, source))] VerifyMetadata { diff --git a/workspaces/updater/tough/src/fetch.rs b/workspaces/updater/tough/src/fetch.rs index 1f6636897ac..2f78da1a073 100644 --- a/workspaces/updater/tough/src/fetch.rs +++ b/workspaces/updater/tough/src/fetch.rs @@ -1,58 +1,42 @@ -use crate::error::Result; +use crate::error::{self, Result}; use crate::io::{DigestAdapter, MaxSizeAdapter}; -use reqwest::Client; -use snafu::ensure; -use std::fs::File; +use crate::transport::Transport; +use snafu::ResultExt; use std::io::Read; -use std::path::PathBuf; use url::Url; -fn fetch(client: &Client, url: Url) -> Result> { - use crate::error; - use snafu::ResultExt; - - if url.scheme() == "file" { - let path = PathBuf::from(url.path()); - let file = File::open(&path).context(error::FileRead { path })?; - Ok(Box::new(file) as Box) - } else { - let response = client - .get(url.clone()) - .send() - .context(error::Request { url: url.clone() })?; - ensure!( - !response.status().is_client_error() && !response.status().is_server_error(), - error::ResponseStatus { - code: response.status(), - url - } - ); - Ok(Box::new(response)) - } -} - -pub(crate) fn fetch_max_size( - client: &Client, +pub(crate) fn fetch_max_size( + transport: &T, url: Url, max_size: u64, specifier: &'static str, ) -> Result { Ok(MaxSizeAdapter::new( - fetch(client, url)?, + transport + .fetch(url.clone()) + .map_err(|e| Box::new(e) as Box) + .context(error::Transport { url })?, specifier, max_size, )) } -pub(crate) fn fetch_sha256( - client: &Client, +pub(crate) fn fetch_sha256( + transport: &T, url: Url, size: u64, specifier: &'static str, sha256: &[u8], ) -> Result { Ok(DigestAdapter::sha256( - MaxSizeAdapter::new(fetch(client, url.clone())?, specifier, size), + MaxSizeAdapter::new( + transport + .fetch(url.clone()) + .map_err(|e| Box::new(e) as Box) + .context(error::Transport { url: url.clone() })?, + specifier, + size, + ), sha256, url, )) diff --git a/workspaces/updater/tough/src/lib.rs b/workspaces/updater/tough/src/lib.rs index eaf0c13695d..604732993f1 100644 --- a/workspaces/updater/tough/src/lib.rs +++ b/workspaces/updater/tough/src/lib.rs @@ -16,12 +16,14 @@ mod datastore; pub mod error; mod fetch; mod io; +mod transport; + +pub use crate::transport::{FilesystemTransport, HttpTransport, Transport}; use crate::datastore::Datastore; use crate::error::Result; use crate::fetch::{fetch_max_size, fetch_sha256}; use chrono::{DateTime, Utc}; -use reqwest::Client; use snafu::{ensure, OptionExt, ResultExt}; use std::borrow::Cow; use std::collections::HashMap; @@ -101,8 +103,8 @@ impl Default for Limits { /// /// You can create a `Repository` using the `load` method. #[derive(Debug, Clone)] -pub struct Repository<'a> { - client: Client, +pub struct Repository<'a, T: Transport> { + transport: T, consistent_snapshot: bool, datastore: Datastore<'a>, earliest_expiration: DateTime, @@ -111,7 +113,7 @@ pub struct Repository<'a> { targets: HashMap, } -impl<'a> Repository<'a> { +impl<'a, T: Transport> Repository<'a, T> { /// Load and verify TUF repository metadata. /// /// `root` is a [`Read`]er for the trusted root metadata file, which you must ship with your @@ -132,9 +134,7 @@ impl<'a> Repository<'a> { /// /// `metadata_base_url` and `target_base_url` are the HTTP(S) base URLs for where the client /// can find metadata (such as root.json) and targets (as listed in targets.json). - pub fn load(settings: Settings<'a, R>) -> Result { - let client = Client::new(); - + pub fn load(transport: T, settings: Settings<'a, R>) -> Result { let metadata_base_url = parse_url(settings.metadata_base_url)?; let target_base_url = parse_url(settings.target_base_url)?; @@ -142,7 +142,7 @@ impl<'a> Repository<'a> { // 0. Load the trusted root metadata file + 1. Update the root metadata file let root = load_root( - &client, + &transport, settings.root, &datastore, settings.limits.max_root_size, @@ -152,7 +152,7 @@ impl<'a> Repository<'a> { // 2. Download the timestamp metadata file let timestamp = load_timestamp( - &client, + &transport, &root, &datastore, settings.limits.max_timestamp_size, @@ -160,11 +160,17 @@ impl<'a> Repository<'a> { )?; // 3. Download the snapshot metadata file - let snapshot = load_snapshot(&client, &root, ×tamp, &datastore, &metadata_base_url)?; + let snapshot = load_snapshot( + &transport, + &root, + ×tamp, + &datastore, + &metadata_base_url, + )?; // 4. Download the targets metadata file let targets = load_targets( - &client, + &transport, &root, &snapshot, &datastore, @@ -182,7 +188,7 @@ impl<'a> Repository<'a> { expires_iter.iter().min_by_key(|tup| tup.0).unwrap(); Ok(Self { - client, + transport, consistent_snapshot: root.signed.consistent_snapshot, datastore, earliest_expiration: earliest_expiration.to_owned(), @@ -247,7 +253,7 @@ impl<'a> Repository<'a> { }; Some(fetch_sha256( - &self.client, + &self.transport, self.target_base_url.join(&file).context(error::JoinUrl { path: file, url: self.target_base_url.to_owned(), @@ -327,8 +333,8 @@ fn parse_url(url: &str) -> Result { /// Steps 0 and 1 of the client application, which load the current root metadata file based on a /// trusted root metadata file. -fn load_root( - client: &Client, +fn load_root( + transport: &T, root: R, datastore: &Datastore<'_>, max_root_size: u64, @@ -382,7 +388,7 @@ fn load_root( ); let path = format!("{}.root.json", root.signed.version.get() + 1); match fetch_max_size( - client, + transport, metadata_base_url.join(&path).context(error::JoinUrl { path, url: metadata_base_url.to_owned(), @@ -490,8 +496,8 @@ fn load_root( } /// Step 2 of the client application, which loads the timestamp metadata file. -fn load_timestamp( - client: &Client, +fn load_timestamp( + transport: &T, root: &Signed, datastore: &Datastore<'_>, max_timestamp_size: u64, @@ -503,7 +509,7 @@ fn load_timestamp( // file is of the fixed form FILENAME.EXT (e.g., timestamp.json). let path = "timestamp.json"; let reader = fetch_max_size( - client, + transport, metadata_base_url.join(path).context(error::JoinUrl { path, url: metadata_base_url.to_owned(), @@ -558,8 +564,8 @@ fn load_timestamp( } /// Step 3 of the client application, which loads the snapshot metadata file. -fn load_snapshot( - client: &Client, +fn load_snapshot( + transport: &T, root: &Signed, timestamp: &Signed, datastore: &Datastore<'_>, @@ -586,7 +592,7 @@ fn load_snapshot( "snapshot.json".to_owned() }; let reader = fetch_sha256( - client, + transport, metadata_base_url.join(&path).context(error::JoinUrl { path, url: metadata_base_url.to_owned(), @@ -689,8 +695,8 @@ fn load_snapshot( } /// Step 4 of the client application, which loads the targets metadata file. -fn load_targets( - client: &Client, +fn load_targets( + transport: &T, root: &Signed, snapshot: &Signed, datastore: &Datastore<'_>, @@ -729,7 +735,7 @@ fn load_targets( }; let reader = if let Some(hashes) = &targets_meta.hashes { Box::new(fetch_sha256( - client, + transport, targets_url, max_targets_size, specifier, @@ -737,7 +743,7 @@ fn load_targets( )?) as Box } else { Box::new(fetch_max_size( - client, + transport, targets_url, max_targets_size, specifier, diff --git a/workspaces/updater/tough/src/transport.rs b/workspaces/updater/tough/src/transport.rs new file mode 100644 index 00000000000..2378a26d650 --- /dev/null +++ b/workspaces/updater/tough/src/transport.rs @@ -0,0 +1,40 @@ +use std::io::Read; +use url::Url; + +pub trait Transport { + type Stream: Read; + type Error: std::error::Error + Send + Sync + 'static; + + fn fetch(&self, url: Url) -> Result; +} + +pub struct FilesystemTransport; + +impl Transport for FilesystemTransport { + type Stream = std::fs::File; + type Error = std::io::Error; + + fn fetch(&self, url: Url) -> Result { + use std::io::{Error, ErrorKind}; + + if url.scheme() == "file" { + std::fs::File::open(url.path()) + } else { + Err(Error::new( + ErrorKind::InvalidInput, + format!("unexpected URL scheme: {}", url.scheme()), + )) + } + } +} + +pub type HttpTransport = reqwest::Client; + +impl Transport for reqwest::Client { + type Stream = reqwest::Response; + type Error = reqwest::Error; + + fn fetch(&self, url: Url) -> Result { + self.get(url).send()?.error_for_status() + } +} diff --git a/workspaces/updater/tough/tests/interop.rs b/workspaces/updater/tough/tests/interop.rs index 20b26c63410..88e17736fcc 100644 --- a/workspaces/updater/tough/tests/interop.rs +++ b/workspaces/updater/tough/tests/interop.rs @@ -33,13 +33,16 @@ fn test_tuf_reference_impl() { let metadata_base_url = &dir_url(base.join("metadata")); let target_base_url = &dir_url(base.join("targets")); - let repo = Repository::load(Settings { - root: File::open(base.join("metadata").join("1.root.json")).unwrap(), - datastore: datastore.as_ref(), - metadata_base_url, - target_base_url, - limits: Limits::default(), - }) + let repo = Repository::load( + tough::FilesystemTransport, + Settings { + root: File::open(base.join("metadata").join("1.root.json")).unwrap(), + datastore: datastore.as_ref(), + metadata_base_url, + target_base_url, + limits: Limits::default(), + }, + ) .unwrap(); assert_eq!( diff --git a/workspaces/updater/updog/src/main.rs b/workspaces/updater/updog/src/main.rs index 337bd46a626..2e16628a0ac 100644 --- a/workspaces/updater/updog/src/main.rs +++ b/workspaces/updater/updog/src/main.rs @@ -16,7 +16,7 @@ use std::io::{self, BufRead, BufReader}; use std::path::Path; use std::process; use std::str::FromStr; -use tough::{Limits, Repository, Settings}; +use tough::{HttpTransport, Limits, Repository, Settings}; use update_metadata::{Manifest, Update}; #[cfg(target_arch = "x86_64")] @@ -93,26 +93,29 @@ fn load_config() -> Result { Ok(config) } -fn load_repository(config: &Config) -> Result> { +fn load_repository(config: &Config) -> Result> { fs::create_dir_all("/var/lib/thar/updog").context(error::CreateMetadataCache)?; - Repository::load(Settings { - root: File::open(TRUSTED_ROOT_PATH).context(error::OpenRoot { - path: TRUSTED_ROOT_PATH, - })?, - datastore: Path::new("/var/lib/thar/updog"), - metadata_base_url: &config.metadata_base_url, - target_base_url: &config.target_base_url, - limits: Limits { - max_root_size: 1024 * 1024, // 1 MiB - max_targets_size: 1024 * 1024 * 10, // 10 MiB - max_timestamp_size: 1024 * 1024, // 1 MiB - max_root_updates: 1024, + Repository::load( + HttpTransport::new(), + Settings { + root: File::open(TRUSTED_ROOT_PATH).context(error::OpenRoot { + path: TRUSTED_ROOT_PATH, + })?, + datastore: Path::new("/var/lib/thar/updog"), + metadata_base_url: &config.metadata_base_url, + target_base_url: &config.target_base_url, + limits: Limits { + max_root_size: 1024 * 1024, // 1 MiB + max_targets_size: 1024 * 1024 * 10, // 10 MiB + max_timestamp_size: 1024 * 1024, // 1 MiB + max_root_updates: 1024, + }, }, - }) + ) .context(error::Metadata) } -fn load_manifest(repository: &Repository<'_>) -> Result { +fn load_manifest(repository: &Repository<'_, HttpTransport>) -> Result { let target = "manifest.json"; serde_json::from_reader( repository @@ -195,7 +198,7 @@ fn update_required<'a>( } fn write_target_to_disk>( - repository: &Repository<'_>, + repository: &Repository<'_, HttpTransport>, target: &str, disk_path: P, ) -> Result<()> { @@ -255,7 +258,7 @@ fn migration_targets( /// storage. All intermediate migrations between the current version and the /// target version must be retrieved. fn retrieve_migrations( - repository: &Repository<'_>, + repository: &Repository<'_, HttpTransport>, manifest: &Manifest, update: &Update, ) -> Result<()> { @@ -296,7 +299,7 @@ fn retrieve_migrations( Ok(()) } -fn update_image(update: &Update, repository: &Repository<'_>) -> Result<()> { +fn update_image(update: &Update, repository: &Repository<'_, HttpTransport>) -> Result<()> { let mut gpt_state = State::load().context(error::PartitionTableRead)?; gpt_state.clear_inactive(); // Write out the clearing of the inactive partition immediately, because we're about to From 08bae3b05a9fc0d9babe0b16051b05b5044e85a2 Mon Sep 17 00:00:00 2001 From: iliana destroyer of worlds Date: Thu, 7 Nov 2019 17:10:34 +0000 Subject: [PATCH 3/5] tough: Make reqwest an optional dependency Signed-off-by: iliana destroyer of worlds --- workspaces/Cargo.lock | 15 ++------------- workspaces/tuftool/Cargo.toml | 2 +- workspaces/updater/tough/Cargo.toml | 9 +++------ workspaces/updater/tough/src/lib.rs | 4 +++- workspaces/updater/tough/src/transport.rs | 4 +++- workspaces/updater/updog/Cargo.toml | 3 ++- 6 files changed, 14 insertions(+), 23 deletions(-) diff --git a/workspaces/Cargo.lock b/workspaces/Cargo.lock index 3d0efee21c8..cb507b40988 100644 --- a/workspaces/Cargo.lock +++ b/workspaces/Cargo.lock @@ -1650,14 +1650,6 @@ name = "openssl-probe" version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "openssl-src" -version = "111.6.0+1.1.1d" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "openssl-sys" version = "0.9.51" @@ -1666,7 +1658,6 @@ dependencies = [ "autocfg 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", - "openssl-src 111.6.0+1.1.1d (registry+https://github.com/rust-lang/crates.io-index)", "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", "vcpkg 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2082,11 +2073,9 @@ dependencies = [ "http 0.1.18 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.12.35 (registry+https://github.com/rust-lang/crates.io-index)", "hyper-rustls 0.17.1 (registry+https://github.com/rust-lang/crates.io-index)", - "hyper-tls 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)", "mime 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", "rustls 0.16.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2979,7 +2968,7 @@ dependencies = [ "snafu 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)", "tempfile 3.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "tough_schema 0.1.0", - "url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)", + "url 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -3167,6 +3156,7 @@ dependencies = [ "lz4 1.23.1 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", "regex 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "reqwest 0.9.22 (registry+https://github.com/rust-lang/crates.io-index)", "semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 1.0.41 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3594,7 +3584,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum opaque-debug 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2839e79665f131bdb5782e51f2c6c9599c133c6098982a54c794358bf432529c" "checksum openssl 0.10.25 (registry+https://github.com/rust-lang/crates.io-index)" = "2f372b2b53ce10fb823a337aaa674e3a7d072b957c6264d0f4ff0bd86e657449" "checksum openssl-probe 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "77af24da69f9d9341038eba93a073b1fdaaa1b788221b00a69bce9e762cb32de" -"checksum openssl-src 111.6.0+1.1.1d (registry+https://github.com/rust-lang/crates.io-index)" = "b9c2da1de8a7a3f860919c01540b03a6db16de042405a8a07a5e9d0b4b825d9c" "checksum openssl-sys 0.9.51 (registry+https://github.com/rust-lang/crates.io-index)" = "ba24190c8f0805d3bd2ce028f439fe5af1d55882bbe6261bed1dbc93b50dd6b1" "checksum parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f842b1982eb6c2fe34036a4fbfb06dd185a3f5c8edfaacdf7d1ea10b07de6252" "checksum parking_lot_core 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b876b1b9e7ac6e1a74a6da34d25c42e17e8862aa409cbbbdcfc8d86c6f3bc62b" diff --git a/workspaces/tuftool/Cargo.toml b/workspaces/tuftool/Cargo.toml index f4e3a10c143..794a9868ad7 100644 --- a/workspaces/tuftool/Cargo.toml +++ b/workspaces/tuftool/Cargo.toml @@ -34,4 +34,4 @@ tough_schema = { path = "../updater/tough_schema" } url = "2.1.0" walkdir = "2.2.9" tempdir = "0.3.7" -tough = { path = "../updater/tough" } +tough = { path = "../updater/tough", features = ["http"] } diff --git a/workspaces/updater/tough/Cargo.toml b/workspaces/updater/tough/Cargo.toml index ca66f48f7fa..7e1e578742e 100644 --- a/workspaces/updater/tough/Cargo.toml +++ b/workspaces/updater/tough/Cargo.toml @@ -8,20 +8,17 @@ publish = false [dependencies] chrono = { version = "0.4.6", features = ["serde"] } hex = "0.4.0" -reqwest = { version = "0.9.17", default-features = false } +reqwest = { version = "0.9.17", optional = true, default-features = false } serde = "1.0.92" serde_json = "1.0.39" sha2 = "0.8.0" snafu = "0.5.0" tough_schema = { path = "../tough_schema" } -url = "1.7.2" +url = "2.1.0" [dev-dependencies] hex-literal = "0.2.0" tempfile = "3.1.0" [features] -default = ["rustls-tls"] -default-tls = ["reqwest/default-tls"] -default-tls-vendored = ["reqwest/default-tls-vendored"] -rustls-tls = ["reqwest/rustls-tls"] +http = ["reqwest"] diff --git a/workspaces/updater/tough/src/lib.rs b/workspaces/updater/tough/src/lib.rs index 604732993f1..8564e368589 100644 --- a/workspaces/updater/tough/src/lib.rs +++ b/workspaces/updater/tough/src/lib.rs @@ -18,7 +18,9 @@ mod fetch; mod io; mod transport; -pub use crate::transport::{FilesystemTransport, HttpTransport, Transport}; +#[cfg(feature = "http")] +pub use crate::transport::HttpTransport; +pub use crate::transport::{FilesystemTransport, Transport}; use crate::datastore::Datastore; use crate::error::Result; diff --git a/workspaces/updater/tough/src/transport.rs b/workspaces/updater/tough/src/transport.rs index 2378a26d650..612b79d244a 100644 --- a/workspaces/updater/tough/src/transport.rs +++ b/workspaces/updater/tough/src/transport.rs @@ -28,13 +28,15 @@ impl Transport for FilesystemTransport { } } +#[cfg(feature = "http")] pub type HttpTransport = reqwest::Client; +#[cfg(feature = "http")] impl Transport for reqwest::Client { type Stream = reqwest::Response; type Error = reqwest::Error; fn fetch(&self, url: Url) -> Result { - self.get(url).send()?.error_for_status() + self.get(url.as_str()).send()?.error_for_status() } } diff --git a/workspaces/updater/updog/Cargo.toml b/workspaces/updater/updog/Cargo.toml index c99819292db..0f5fa9add18 100644 --- a/workspaces/updater/updog/Cargo.toml +++ b/workspaces/updater/updog/Cargo.toml @@ -12,6 +12,7 @@ log = "0.4" lz4 = "1.23.1" rand = "0.7.0" regex = "1.1" +reqwest = { version = "0.9.17", default-features = false, features = ["rustls-tls"] } semver = "0.9.0" serde = { version = "1.0.100", features = ["derive"] } serde_json = "1.0.40" @@ -21,7 +22,7 @@ simplelog = "0.7" snafu = "0.5.0" time = "0.1" toml = "0.5.1" -tough = { path = "../tough" } +tough = { path = "../tough", features = ["http"] } update_metadata = { path = "../update_metadata" } structopt = "0.3" From 82a368d20fdd2353c8d10aa85abbee84a2e4ef0e Mon Sep 17 00:00:00 2001 From: iliana destroyer of worlds Date: Thu, 7 Nov 2019 23:32:22 +0000 Subject: [PATCH 4/5] updog: Use a type alias for Repository Signed-off-by: iliana destroyer of worlds --- workspaces/updater/updog/src/main.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/workspaces/updater/updog/src/main.rs b/workspaces/updater/updog/src/main.rs index 2e16628a0ac..8be07891636 100644 --- a/workspaces/updater/updog/src/main.rs +++ b/workspaces/updater/updog/src/main.rs @@ -19,6 +19,8 @@ use std::str::FromStr; use tough::{HttpTransport, Limits, Repository, Settings}; use update_metadata::{Manifest, Update}; +type HttpRepo<'a> = Repository<'a, HttpTransport>; + #[cfg(target_arch = "x86_64")] const TARGET_ARCH: &str = "x86_64"; #[cfg(target_arch = "aarch64")] @@ -93,7 +95,7 @@ fn load_config() -> Result { Ok(config) } -fn load_repository(config: &Config) -> Result> { +fn load_repository(config: &Config) -> Result> { fs::create_dir_all("/var/lib/thar/updog").context(error::CreateMetadataCache)?; Repository::load( HttpTransport::new(), @@ -115,7 +117,7 @@ fn load_repository(config: &Config) -> Result> { .context(error::Metadata) } -fn load_manifest(repository: &Repository<'_, HttpTransport>) -> Result { +fn load_manifest(repository: &HttpRepo<'_>) -> Result { let target = "manifest.json"; serde_json::from_reader( repository @@ -198,7 +200,7 @@ fn update_required<'a>( } fn write_target_to_disk>( - repository: &Repository<'_, HttpTransport>, + repository: &HttpRepo<'_>, target: &str, disk_path: P, ) -> Result<()> { @@ -258,7 +260,7 @@ fn migration_targets( /// storage. All intermediate migrations between the current version and the /// target version must be retrieved. fn retrieve_migrations( - repository: &Repository<'_, HttpTransport>, + repository: &HttpRepo<'_>, manifest: &Manifest, update: &Update, ) -> Result<()> { @@ -299,7 +301,7 @@ fn retrieve_migrations( Ok(()) } -fn update_image(update: &Update, repository: &Repository<'_, HttpTransport>) -> Result<()> { +fn update_image(update: &Update, repository: &HttpRepo<'_>) -> Result<()> { let mut gpt_state = State::load().context(error::PartitionTableRead)?; gpt_state.clear_inactive(); // Write out the clearing of the inactive partition immediately, because we're about to From 558487e3a0ff144aab099f5ac3d5c042197dcbdd Mon Sep 17 00:00:00 2001 From: iliana destroyer of worlds Date: Thu, 7 Nov 2019 23:38:40 +0000 Subject: [PATCH 5/5] tough: Use transports by reference Signed-off-by: iliana destroyer of worlds --- workspaces/tuftool/src/download.rs | 3 ++- workspaces/updater/tough/src/lib.rs | 20 +++++++------------- workspaces/updater/tough/tests/interop.rs | 2 +- workspaces/updater/updog/src/main.rs | 7 ++++--- 4 files changed, 14 insertions(+), 18 deletions(-) diff --git a/workspaces/tuftool/src/download.rs b/workspaces/tuftool/src/download.rs index f60ccd7da4c..910e011134f 100644 --- a/workspaces/tuftool/src/download.rs +++ b/workspaces/tuftool/src/download.rs @@ -86,9 +86,10 @@ impl DownloadArgs { }; // load repository + let transport = HttpTransport::new(); let repo_dir = TempDir::new("tuf").context(error::TempDir)?; let repository = Repository::load( - HttpTransport::new(), + &transport, Settings { root: File::open(&root_path).context(error::OpenRoot { path: &root_path })?, datastore: repo_dir.path(), diff --git a/workspaces/updater/tough/src/lib.rs b/workspaces/updater/tough/src/lib.rs index 8564e368589..1e6e33770a4 100644 --- a/workspaces/updater/tough/src/lib.rs +++ b/workspaces/updater/tough/src/lib.rs @@ -106,7 +106,7 @@ impl Default for Limits { /// You can create a `Repository` using the `load` method. #[derive(Debug, Clone)] pub struct Repository<'a, T: Transport> { - transport: T, + transport: &'a T, consistent_snapshot: bool, datastore: Datastore<'a>, earliest_expiration: DateTime, @@ -136,7 +136,7 @@ impl<'a, T: Transport> Repository<'a, T> { /// /// `metadata_base_url` and `target_base_url` are the HTTP(S) base URLs for where the client /// can find metadata (such as root.json) and targets (as listed in targets.json). - pub fn load(transport: T, settings: Settings<'a, R>) -> Result { + pub fn load(transport: &'a T, settings: Settings<'a, R>) -> Result { let metadata_base_url = parse_url(settings.metadata_base_url)?; let target_base_url = parse_url(settings.target_base_url)?; @@ -144,7 +144,7 @@ impl<'a, T: Transport> Repository<'a, T> { // 0. Load the trusted root metadata file + 1. Update the root metadata file let root = load_root( - &transport, + transport, settings.root, &datastore, settings.limits.max_root_size, @@ -154,7 +154,7 @@ impl<'a, T: Transport> Repository<'a, T> { // 2. Download the timestamp metadata file let timestamp = load_timestamp( - &transport, + transport, &root, &datastore, settings.limits.max_timestamp_size, @@ -162,17 +162,11 @@ impl<'a, T: Transport> Repository<'a, T> { )?; // 3. Download the snapshot metadata file - let snapshot = load_snapshot( - &transport, - &root, - ×tamp, - &datastore, - &metadata_base_url, - )?; + let snapshot = load_snapshot(transport, &root, ×tamp, &datastore, &metadata_base_url)?; // 4. Download the targets metadata file let targets = load_targets( - &transport, + transport, &root, &snapshot, &datastore, @@ -255,7 +249,7 @@ impl<'a, T: Transport> Repository<'a, T> { }; Some(fetch_sha256( - &self.transport, + self.transport, self.target_base_url.join(&file).context(error::JoinUrl { path: file, url: self.target_base_url.to_owned(), diff --git a/workspaces/updater/tough/tests/interop.rs b/workspaces/updater/tough/tests/interop.rs index 88e17736fcc..ec07d817184 100644 --- a/workspaces/updater/tough/tests/interop.rs +++ b/workspaces/updater/tough/tests/interop.rs @@ -34,7 +34,7 @@ fn test_tuf_reference_impl() { let target_base_url = &dir_url(base.join("targets")); let repo = Repository::load( - tough::FilesystemTransport, + &tough::FilesystemTransport, Settings { root: File::open(base.join("metadata").join("1.root.json")).unwrap(), datastore: datastore.as_ref(), diff --git a/workspaces/updater/updog/src/main.rs b/workspaces/updater/updog/src/main.rs index 8be07891636..0d9ac84c71f 100644 --- a/workspaces/updater/updog/src/main.rs +++ b/workspaces/updater/updog/src/main.rs @@ -95,10 +95,10 @@ fn load_config() -> Result { Ok(config) } -fn load_repository(config: &Config) -> Result> { +fn load_repository<'a>(transport: &'a HttpTransport, config: &'a Config) -> Result> { fs::create_dir_all("/var/lib/thar/updog").context(error::CreateMetadataCache)?; Repository::load( - HttpTransport::new(), + transport, Settings { root: File::open(TRUSTED_ROOT_PATH).context(error::OpenRoot { path: TRUSTED_ROOT_PATH, @@ -436,7 +436,8 @@ fn main_inner() -> Result<()> { serde_plain::from_str::(&arguments.subcommand).unwrap_or_else(|_| usage()); let config = load_config()?; - let repository = load_repository(&config)?; + let transport = HttpTransport::new(); + let repository = load_repository(&transport, &config)?; let manifest = load_manifest(&repository)?; let (current_version, flavor) = running_version().unwrap();