Skip to content

Commit

Permalink
tuftool: Add download_root module
Browse files Browse the repository at this point in the history
This change adds a `download_root` module, which abstracts the logic of
downloading `root.json` out of `download` (the subcommand).  It also
makes the HTTP request a bit more robust by handling the initial request
error as well as a bad response.  Additionally, it avoids creating the
file until after the request has succeeded to avoid creating cruft on
the user's system.
  • Loading branch information
zmrow committed Aug 17, 2021
1 parent 9dd9c3a commit f47cfbd
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 0 deletions.
51 changes: 51 additions & 0 deletions tuftool/src/download_root.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: MIT OR Apache-2.0
//! The `download_root` module owns the logic for downloading a given version of `root.json`.
use crate::error::{self, Result};
use snafu::ResultExt;
use std::fs::File;
use std::num::NonZeroU64;
use std::path::{Path, PathBuf};
use url::Url;

/// Download the given version of `root.json`
/// This is an unsafe operation, and doesn't establish trust. It should only be used for testing!
pub(crate) fn download_root<P>(
metadata_base_url: &Url,
version: NonZeroU64,
outdir: P,
) -> Result<PathBuf>
where
P: AsRef<Path>,
{
let name = format!("{}.root.json", version);

let path = outdir.as_ref().join(&name);
let url = metadata_base_url.join(&name).context(error::UrlParse {
url: format!("{}/{}", metadata_base_url.as_str(), name),
})?;
root_warning(&path);

let mut root_request = reqwest::blocking::get(url.as_str())
.context(error::ReqwestGet)?
.error_for_status()
.context(error::BadResponse { url })?;

let mut f = File::create(&path).context(error::OpenFile { path: &path })?;
root_request.copy_to(&mut f).context(error::ReqwestCopy)?;

Ok(path)
}

/// Print a very noticeable warning message about the unsafe nature of downloading `root.json`
/// without verification
fn root_warning<P: AsRef<Path>>(path: P) {
#[rustfmt::skip]
eprintln!("\
=================================================================
WARNING: Downloading root.json to {}
This is unsafe and will not establish trust, use only for testing
=================================================================",
path.as_ref().display());
}
16 changes: 16 additions & 0 deletions tuftool/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,13 @@ pub(crate) enum Error {
backtrace: Backtrace,
},

#[snafu(display("Response '{}' from '{}': {}", get_status_code(source), url, source))]
BadResponse {
url: String,
source: reqwest::Error,
backtrace: Backtrace,
},

#[snafu(display("Failed to sign repository: {}", source))]
SignRepo {
source: tough::error::Error,
Expand Down Expand Up @@ -357,3 +364,12 @@ pub(crate) enum Error {
backtrace: Backtrace,
},
}

// Extracts the status code from a reqwest::Error and converts it to a string to be displayed
fn get_status_code(source: &reqwest::Error) -> String {
source
.status()
.as_ref()
.map_or("Unknown", |i| i.as_str())
.to_string()
}

0 comments on commit f47cfbd

Please sign in to comment.