Skip to content

Commit

Permalink
tuftool: Remove KeySource enum, use tough-ssm and KeySource trait
Browse files Browse the repository at this point in the history
This is a decent set of changes to tuftool. It fully removes the
KeySource enum in source.rs and instead uses the KeySource trait
from tough.

This commit also removes all SSM related code in favor of the
tough-ssm crate (which is a copy of this code).

It also removes the deref.rs file, as it is no longer need because
these features have stabilized in upstream Rust. See:
rust-lang/rust#50264
and
rust-lang/rust#64708
  • Loading branch information
zmrow committed May 19, 2020
1 parent f58cc80 commit a7672e7
Show file tree
Hide file tree
Showing 12 changed files with 125 additions and 326 deletions.
8 changes: 4 additions & 4 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions tuftool/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ url = "2.1.0"
walkdir = "2.2.9"
tough = { version = "0.5.0", path = "../tough", features = ["http"] }
tokio = "0.2.21"
tough-ssm = { version = "0.1.0", path = "../tough-ssm" }

[dev-dependencies]
assert_cmd = "1.0"
7 changes: 4 additions & 3 deletions tuftool/src/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::error::{self, Result};
use crate::key::RootKeys;
use crate::metadata;
use crate::root_digest::RootDigest;
use crate::source::KeySource;
use crate::source::parse_key_source;
use chrono::{DateTime, Utc};
use maplit::hashmap;
use rayon::prelude::*;
Expand All @@ -20,6 +20,7 @@ use std::io::Read;
use std::num::{NonZeroU64, NonZeroUsize};
use std::path::{Path, PathBuf};
use structopt::StructOpt;
use tough::key_source::KeySource;
use tough::schema::{
decoded::Decoded, Hashes, Role, Snapshot, SnapshotMeta, Target, Targets, Timestamp,
TimestampMeta,
Expand All @@ -37,8 +38,8 @@ pub(crate) struct CreateArgs {
jobs: Option<NonZeroUsize>,

/// Key files to sign with
#[structopt(short = "k", long = "key", required = true)]
keys: Vec<KeySource>,
#[structopt(short = "k", long = "key", required = true, parse(try_from_str = parse_key_source))]
keys: Vec<Box<dyn KeySource>>,

/// Version of snapshot.json file
#[structopt(long = "snapshot-version")]
Expand Down
18 changes: 0 additions & 18 deletions tuftool/src/deref.rs

This file was deleted.

80 changes: 12 additions & 68 deletions tuftool/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
use snafu::{Backtrace, Snafu};
use std::path::PathBuf;

#[cfg(any(feature = "rusoto-native-tls", feature = "rusoto-rustls"))]
use crate::deref::OptionDeref;

pub(crate) type Result<T> = std::result::Result<T, Error>;

#[derive(Debug, Snafu)]
Expand Down Expand Up @@ -124,14 +121,6 @@ pub(crate) enum Error {
backtrace: Backtrace,
},

#[snafu(display("{}: {}", path.display(), source))]
Key {
path: PathBuf,
#[snafu(source(from(Error, Box::new)))]
#[snafu(backtrace)]
source: Box<Self>,
},

#[snafu(display("Duplicate key ID: {}", key_id))]
KeyDuplicate {
key_id: String,
Expand All @@ -150,6 +139,12 @@ pub(crate) enum Error {
backtrace: Backtrace,
},

#[snafu(display("Unable to parse keypair: {}", source))]
KeyPairFromKeySource {
source: Box<dyn std::error::Error + Send + Sync + 'static>,
backtrace: Backtrace,
},

#[snafu(display("Unable to match any of the provided keys with root.json"))]
KeysNotFoundInRoot { backtrace: Backtrace },

Expand Down Expand Up @@ -200,28 +195,6 @@ pub(crate) enum Error {
backtrace: Backtrace,
},

#[cfg(any(feature = "rusoto-native-tls", feature = "rusoto-rustls"))]
#[snafu(display("Error creating AWS credentials provider: {}", source))]
RusotoCreds {
source: rusoto_credential::CredentialsError,
backtrace: Backtrace,
},

#[cfg(any(feature = "rusoto-native-tls", feature = "rusoto-rustls"))]
#[snafu(display("Unknown AWS region \"{}\": {}", region, source))]
RusotoRegion {
region: String,
source: rusoto_core::region::ParseRegionError,
backtrace: Backtrace,
},

#[cfg(any(feature = "rusoto-native-tls", feature = "rusoto-rustls"))]
#[snafu(display("Error creating AWS request dispatcher: {}", source))]
RusotoTls {
source: rusoto_core::request::TlsError,
backtrace: Backtrace,
},

#[snafu(display("Failed to sign message"))]
Sign {
source: tough::error::Error,
Expand All @@ -234,41 +207,6 @@ pub(crate) enum Error {
backtrace: Backtrace,
},

#[cfg(any(feature = "rusoto-native-tls", feature = "rusoto-rustls"))]
#[snafu(display(
"Failed to get aws-ssm://{}{}: {}",
profile.deref_shim().unwrap_or(""),
parameter_name,
source,
))]
SsmGetParameter {
profile: Option<String>,
parameter_name: String,
source: rusoto_core::RusotoError<rusoto_ssm::GetParameterError>,
backtrace: Backtrace,
},

#[cfg(any(feature = "rusoto-native-tls", feature = "rusoto-rustls"))]
#[snafu(display(
"Failed to put aws-ssm://{}{}: {}",
profile.deref_shim().unwrap_or(""),
parameter_name,
source,
))]
SsmPutParameter {
profile: Option<String>,
parameter_name: String,
source: rusoto_core::RusotoError<rusoto_ssm::PutParameterError>,
backtrace: Backtrace,
},

#[cfg(any(feature = "rusoto-native-tls", feature = "rusoto-rustls"))]
#[snafu(display("Missing field in SSM response: {}", field))]
SsmMissingField {
field: &'static str,
backtrace: Backtrace,
},

#[snafu(display("Target not found: {}", target))]
TargetNotFound {
target: String,
Expand Down Expand Up @@ -309,6 +247,12 @@ pub(crate) enum Error {
backtrace: Backtrace,
},

#[snafu(display("Failed write: {}", source))]
WriteKeySource {
source: Box<dyn std::error::Error + Send + Sync + 'static>,
backtrace: Backtrace,
},

#[snafu(display("Failed writing target data to disk: {}", source))]
WriteTarget {
source: std::io::Error,
Expand Down
2 changes: 0 additions & 2 deletions tuftool/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

mod create;
mod datetime;
mod deref;
mod download;
mod error;
mod key;
Expand All @@ -23,7 +22,6 @@ mod root;
mod root_digest;
mod sign;
mod source;
mod ssm;

use crate::error::Result;
use snafu::{ErrorCompat, OptionExt, ResultExt};
Expand Down
7 changes: 4 additions & 3 deletions tuftool/src/refresh.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::datetime::parse_datetime;
use crate::error::{self, Result};
use crate::metadata;
use crate::root_digest::RootDigest;
use crate::source::KeySource;
use crate::source::parse_key_source;
use chrono::{DateTime, Utc};
use maplit::hashmap;
use ring::rand::SystemRandom;
Expand All @@ -15,6 +15,7 @@ use std::fs::File;
use std::num::{NonZeroU64, NonZeroUsize};
use std::path::PathBuf;
use structopt::StructOpt;
use tough::key_source::KeySource;
use tough::schema::{Hashes, Snapshot, SnapshotMeta, Targets, Timestamp, TimestampMeta};
use tough::{
ExpirationEnforcement, FilesystemTransport, HttpTransport, Limits, Repository, Transport,
Expand Down Expand Up @@ -44,8 +45,8 @@ pub(crate) struct RefreshArgs {
jobs: Option<NonZeroUsize>,

/// Key files to sign with
#[structopt(short = "k", long = "key", required = true)]
keys: Vec<KeySource>,
#[structopt(short = "k", long = "key", required = true, parse(try_from_str = parse_key_source))]
keys: Vec<Box<dyn KeySource>>,

/// Version of snapshot.json file
#[structopt(long = "snapshot-version")]
Expand Down
32 changes: 21 additions & 11 deletions tuftool/src/root.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use crate::datetime::parse_datetime;
use crate::error::{self, Result};
use crate::source::KeySource;
use crate::source::parse_key_source;
use crate::{load_file, write_file};
use chrono::{DateTime, Timelike, Utc};
use maplit::hashmap;
Expand All @@ -12,6 +12,7 @@ use std::collections::HashMap;
use std::num::NonZeroU64;
use std::path::PathBuf;
use structopt::StructOpt;
use tough::key_source::KeySource;
use tough::schema::decoded::{Decoded, Hex};
use tough::schema::{key::Key, RoleKeys, RoleType, Root, Signed};
use tough::sign::{parse_keypair, Sign};
Expand Down Expand Up @@ -51,7 +52,8 @@ pub(crate) enum Command {
/// Path to root.json
path: PathBuf,
/// The new key
key_path: KeySource,
#[structopt(parse(try_from_str = parse_key_source))]
key_source: Box<dyn KeySource>,
/// The role to add the key to
#[structopt(short = "r", long = "role")]
roles: Vec<RoleType>,
Expand All @@ -71,7 +73,8 @@ pub(crate) enum Command {
/// Path to root.json
path: PathBuf,
/// Where to write the new key
key_path: KeySource,
#[structopt(parse(try_from_str = parse_key_source))]
key_source: Box<dyn KeySource>,
/// Bit length of new key
#[structopt(short = "b", long = "bits", default_value = "2048")]
bits: u16,
Expand Down Expand Up @@ -113,16 +116,16 @@ impl Command {
Command::AddKey {
path,
roles,
key_path,
} => Command::add_key(path, roles, key_path),
key_source,
} => Command::add_key(path, roles, key_source),
Command::RemoveKey { path, key_id, role } => Command::remove_key(path, key_id, *role),
Command::GenRsaKey {
path,
roles,
key_path,
key_source,
bits,
exponent,
} => Command::gen_rsa_key(path, roles, key_path, *bits, *exponent),
} => Command::gen_rsa_key(path, roles, key_source, *bits, *exponent),
}
}

Expand Down Expand Up @@ -181,9 +184,13 @@ impl Command {
write_file(path, &root)
}

fn add_key(path: &PathBuf, roles: &[RoleType], key_path: &KeySource) -> Result<()> {
#[allow(clippy::borrowed_box)]
fn add_key(path: &PathBuf, roles: &[RoleType], key_source: &Box<dyn KeySource>) -> Result<()> {
let mut root: Signed<Root> = load_file(path)?;
let key_pair = key_path.as_public_key()?;
let key_pair = key_source
.as_sign()
.context(error::KeyPairFromKeySource)?
.tuf_key();
let key_id = hex::encode(add_key(&mut root.signed, roles, key_pair)?);
clear_sigs(&mut root);
println!("{}", key_id);
Expand Down Expand Up @@ -214,10 +221,11 @@ impl Command {
write_file(path, &root)
}

#[allow(clippy::borrowed_box)]
fn gen_rsa_key(
path: &PathBuf,
roles: &[RoleType],
key_path: &KeySource,
key_source: &Box<dyn KeySource>,
bits: u16,
exponent: u32,
) -> Result<()> {
Expand Down Expand Up @@ -247,7 +255,9 @@ impl Command {

let key_pair = parse_keypair(stdout.as_bytes()).context(error::KeyPairParse)?;
let key_id = hex::encode(add_key(&mut root.signed, roles, key_pair.tuf_key())?);
key_path.write(&stdout, &key_id)?;
key_source
.write(&stdout, &key_id)
.context(error::WriteKeySource)?;
clear_sigs(&mut root);
println!("{}", key_id);
write_file(path, &root)
Expand Down
6 changes: 3 additions & 3 deletions tuftool/src/root_digest.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
use crate::error;
use crate::error::Result;
use crate::key::RootKeys;
use crate::source::KeySource;
use ring::digest::{SHA256, SHA256_OUTPUT_LEN};
use snafu::ensure;
use snafu::ResultExt;
use std::collections::HashMap;
use std::path::PathBuf;
use tough::key_source::KeySource;
use tough::schema::{Root, Signed};

/// Represents a loaded root.json file along with its sha256 digest and size in bytes
Expand Down Expand Up @@ -56,10 +56,10 @@ impl RootDigest {
///
/// * An error can occur for io reasons
///
pub(crate) fn load_keys(&self, keys: &[KeySource]) -> Result<RootKeys> {
pub(crate) fn load_keys(&self, keys: &[Box<dyn KeySource>]) -> Result<RootKeys> {
let mut map = HashMap::new();
for source in keys {
let key_pair = source.as_sign()?;
let key_pair = source.as_sign().context(error::KeyPairFromKeySource)?;
if let Some((keyid, _)) = self
.root
.keys
Expand Down
7 changes: 4 additions & 3 deletions tuftool/src/sign.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,14 @@
use crate::error::Result;
use crate::key::sign_metadata;
use crate::root_digest::RootDigest;
use crate::source::KeySource;
use crate::source::parse_key_source;
use crate::{load_file, write_file};
use ring::rand::SystemRandom;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use std::path::PathBuf;
use structopt::StructOpt;
use tough::key_source::KeySource;
use tough::schema::{RoleType, Signed};

#[derive(Debug, StructOpt)]
Expand All @@ -20,8 +21,8 @@ pub(crate) struct SignArgs {
root: PathBuf,

/// Key files to sign with
#[structopt(short = "k", long = "key")]
keys: Vec<KeySource>,
#[structopt(short = "k", long = "key", parse(try_from_str = parse_key_source))]
keys: Vec<Box<dyn KeySource>>,

/// Metadata file to sign
metadata_file: PathBuf,
Expand Down
Loading

0 comments on commit a7672e7

Please sign in to comment.