Add RootMetadataBuilder to simplify making RootMetadata
diff --git a/src/client.rs b/src/client.rs
index b596472..67c62cf 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -743,10 +743,9 @@
#[cfg(test)]
mod test {
use super::*;
- use chrono::prelude::*;
use crypto::{PrivateKey, SignatureScheme};
use interchange::Json;
- use metadata::{MetadataPath, MetadataVersion, RoleDefinition, RootMetadata, SignedMetadata};
+ use metadata::{MetadataPath, MetadataVersion, RootMetadataBuilder};
use repository::EphemeralRepository;
lazy_static! {
@@ -768,18 +767,14 @@
#[test]
fn root_chain_update() {
let repo = EphemeralRepository::new();
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![KEYS[0].public().clone()],
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- ).unwrap();
- let root: SignedMetadata<Json, _> =
- SignedMetadata::new(root, &KEYS[0]).unwrap();
+ let root = RootMetadataBuilder::new()
+ .version(1)
+ .root_key(KEYS[0].public().clone())
+ .snapshot_key(KEYS[0].public().clone())
+ .targets_key(KEYS[0].public().clone())
+ .timestamp_key(KEYS[0].public().clone())
+ .signed::<Json>(&KEYS[0])
+ .unwrap();
repo.store_metadata(
&MetadataPath::from_role(&Role::Root),
@@ -787,18 +782,14 @@
&root,
).unwrap();
- let root = RootMetadata::new(
- 2,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![KEYS[1].public().clone()],
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- ).unwrap();
- let mut root: SignedMetadata<Json, _> =
- SignedMetadata::new(root, &KEYS[1]).unwrap();
+ let mut root = RootMetadataBuilder::new()
+ .version(2)
+ .root_key(KEYS[1].public().clone())
+ .snapshot_key(KEYS[1].public().clone())
+ .targets_key(KEYS[1].public().clone())
+ .timestamp_key(KEYS[1].public().clone())
+ .signed::<Json>(&KEYS[1])
+ .unwrap();
root.add_signature(&KEYS[0]).unwrap();
@@ -808,18 +799,14 @@
&root,
).unwrap();
- let root = RootMetadata::new(
- 3,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![KEYS[2].public().clone()],
- RoleDefinition::new(1, hashset!(KEYS[2].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[2].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[2].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[2].key_id().clone())).unwrap(),
- ).unwrap();
- let mut root: SignedMetadata<Json, _> =
- SignedMetadata::new(root, &KEYS[2]).unwrap();
+ let mut root = RootMetadataBuilder::new()
+ .version(3)
+ .root_key(KEYS[2].public().clone())
+ .snapshot_key(KEYS[2].public().clone())
+ .targets_key(KEYS[2].public().clone())
+ .timestamp_key(KEYS[2].public().clone())
+ .signed::<Json>(&KEYS[2])
+ .unwrap();
root.add_signature(&KEYS[1]).unwrap();
diff --git a/src/metadata.rs b/src/metadata.rs
index 4854ba7..99315c5 100644
--- a/src/metadata.rs
+++ b/src/metadata.rs
@@ -1,13 +1,12 @@
//! TUF metadata.
use chrono::offset::Utc;
-use chrono::DateTime;
+use chrono::{DateTime, Duration};
use serde::de::{Deserialize, DeserializeOwned, Deserializer, Error as DeserializeError};
use serde::ser::{Error as SerializeError, Serialize, Serializer};
use std::collections::{HashMap, HashSet};
use std::fmt::{self, Debug, Display};
use std::io::Read;
-use std::iter::FromIterator;
use std::marker::PhantomData;
use crypto::{self, HashAlgorithm, HashValue, KeyId, PrivateKey, PublicKey, Signature};
@@ -499,6 +498,173 @@
}
}
+/// Helper to construct `RootMetadata`.
+pub struct RootMetadataBuilder {
+ version: u32,
+ expires: DateTime<Utc>,
+ consistent_snapshot: bool,
+ keys: HashMap<KeyId, PublicKey>,
+ root_threshold: u32,
+ root_key_ids: HashSet<KeyId>,
+ snapshot_threshold: u32,
+ snapshot_key_ids: HashSet<KeyId>,
+ targets_threshold: u32,
+ targets_key_ids: HashSet<KeyId>,
+ timestamp_threshold: u32,
+ timestamp_key_ids: HashSet<KeyId>,
+}
+
+impl RootMetadataBuilder {
+ /// Create a new `RootMetadataBuilder`. It defaults to:
+ ///
+ /// * version: 1,
+ /// * expires: 365 days from the current time.
+ /// * consistent snapshot: false
+ /// * role thresholds: 1
+ pub fn new() -> Self {
+ RootMetadataBuilder {
+ version: 1,
+ expires: Utc::now() + Duration::days(365),
+ consistent_snapshot: false,
+ keys: HashMap::new(),
+ root_threshold: 1,
+ root_key_ids: HashSet::new(),
+ snapshot_threshold: 1,
+ snapshot_key_ids: HashSet::new(),
+ targets_threshold: 1,
+ targets_key_ids: HashSet::new(),
+ timestamp_threshold: 1,
+ timestamp_key_ids: HashSet::new(),
+ }
+ }
+
+ /// Set the version number for this metadata.
+ pub fn version(mut self, version: u32) -> Self {
+ self.version = version;
+ self
+ }
+
+ /// Set the time this metadata expires.
+ pub fn expires(mut self, expires: DateTime<Utc>) -> Self {
+ self.expires = expires;
+ self
+ }
+
+ /// Set this metadata to have a consistent snapshot.
+ pub fn consistent_snapshot(mut self, consistent_snapshot: bool) -> Self {
+ self.consistent_snapshot = consistent_snapshot;
+ self
+ }
+
+ /// Set the root threshold.
+ pub fn root_threshold(mut self, threshold: u32) -> Self {
+ self.root_threshold = threshold;
+ self
+ }
+
+ /// Add a root public key.
+ pub fn root_key(mut self, public_key: PublicKey) -> Self {
+ let key_id = public_key.key_id().clone();
+ self.keys.insert(key_id.clone(), public_key);
+ self.root_key_ids.insert(key_id);
+ self
+ }
+
+ /// Set the snapshot threshold.
+ pub fn snapshot_threshold(mut self, threshold: u32) -> Self {
+ self.snapshot_threshold = threshold;
+ self
+ }
+
+ /// Add a snapshot public key.
+ pub fn snapshot_key(mut self, public_key: PublicKey) -> Self {
+ let key_id = public_key.key_id().clone();
+ self.keys.insert(key_id.clone(), public_key);
+ self.snapshot_key_ids.insert(key_id);
+ self
+ }
+
+ /// Set the targets threshold.
+ pub fn targets_threshold(mut self, threshold: u32) -> Self {
+ self.targets_threshold = threshold;
+ self
+ }
+
+ /// Add a targets public key.
+ pub fn targets_key(mut self, public_key: PublicKey) -> Self {
+ let key_id = public_key.key_id().clone();
+ self.keys.insert(key_id.clone(), public_key);
+ self.targets_key_ids.insert(key_id);
+ self
+ }
+
+ /// Set the timestamp threshold.
+ pub fn timestamp_threshold(mut self, threshold: u32) -> Self {
+ self.timestamp_threshold = threshold;
+ self
+ }
+
+ /// Add a timestamp public key.
+ pub fn timestamp_key(mut self, public_key: PublicKey) -> Self {
+ let key_id = public_key.key_id().clone();
+ self.keys.insert(key_id.clone(), public_key);
+ self.timestamp_key_ids.insert(key_id);
+ self
+ }
+
+ /// Construct a new `RootMetadata`.
+ pub fn build(self) -> Result<RootMetadata> {
+ RootMetadata::new(
+ self.version,
+ self.expires,
+ self.consistent_snapshot,
+ self.keys,
+ RoleDefinition::new(
+ self.root_threshold,
+ self.root_key_ids,
+ )?,
+ RoleDefinition::new(
+ self.snapshot_threshold,
+ self.snapshot_key_ids,
+ )?,
+ RoleDefinition::new(
+ self.targets_threshold,
+ self.targets_key_ids,
+ )?,
+ RoleDefinition::new(
+ self.timestamp_threshold,
+ self.timestamp_key_ids,
+ )?,
+ )
+ }
+
+ /// Construct a new `SignedMetadata<D, RootMetadata>`.
+ pub fn signed<D>(self, private_key: &PrivateKey) -> Result<SignedMetadata<D, RootMetadata>>
+ where D: DataInterchange,
+ {
+ Ok(SignedMetadata::new(self.build()?, private_key)?)
+ }
+}
+
+impl From<RootMetadata> for RootMetadataBuilder {
+ fn from(metadata: RootMetadata) -> Self {
+ RootMetadataBuilder {
+ version: metadata.version,
+ expires: metadata.expires,
+ consistent_snapshot: metadata.consistent_snapshot,
+ keys: metadata.keys,
+ root_threshold: metadata.root.threshold,
+ root_key_ids: metadata.root.key_ids,
+ snapshot_threshold: metadata.snapshot.threshold,
+ snapshot_key_ids: metadata.snapshot.key_ids,
+ targets_threshold: metadata.targets.threshold,
+ targets_key_ids: metadata.targets.key_ids,
+ timestamp_threshold: metadata.timestamp.threshold,
+ timestamp_key_ids: metadata.timestamp.key_ids,
+ }
+ }
+}
+
/// Metadata for the root role.
#[derive(Debug, Clone, PartialEq)]
pub struct RootMetadata {
@@ -518,7 +684,7 @@
version: u32,
expires: DateTime<Utc>,
consistent_snapshot: bool,
- mut keys: Vec<PublicKey>,
+ keys: HashMap<KeyId, PublicKey>,
root: RoleDefinition,
snapshot: RoleDefinition,
targets: RoleDefinition,
@@ -531,13 +697,6 @@
)));
}
- let keys_len = keys.len();
- let keys = HashMap::from_iter(keys.drain(..).map(|k| (k.key_id().clone(), k)));
-
- if keys.len() != keys_len {
- return Err(Error::IllegalArgument("Cannot have duplicate keys".into()));
- }
-
Ok(RootMetadata {
version,
expires,
@@ -1604,29 +1763,14 @@
let timestamp_key =
PrivateKey::from_pkcs8(ED25519_4_PK8, SignatureScheme::Ed25519).unwrap();
- let keys = vec![
- root_key.public().clone(),
- snapshot_key.public().clone(),
- targets_key.public().clone(),
- timestamp_key.public().clone(),
- ];
-
- let root_def = RoleDefinition::new(1, hashset!(root_key.key_id().clone())).unwrap();
- let snapshot_def = RoleDefinition::new(1, hashset!(snapshot_key.key_id().clone())).unwrap();
- let targets_def = RoleDefinition::new(1, hashset!(targets_key.key_id().clone())).unwrap();
- let timestamp_def =
- RoleDefinition::new(1, hashset!(timestamp_key.key_id().clone())).unwrap();
-
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2017, 1, 1).and_hms(0, 0, 0),
- false,
- keys,
- root_def,
- snapshot_def,
- targets_def,
- timestamp_def,
- ).unwrap();
+ let root = RootMetadataBuilder::new()
+ .expires(Utc.ymd(2017, 1, 1).and_hms(0, 0, 0))
+ .root_key(root_key.public().clone())
+ .snapshot_key(snapshot_key.public().clone())
+ .targets_key(targets_key.public().clone())
+ .timestamp_key(timestamp_key.public().clone())
+ .build()
+ .unwrap();
let jsn = json!({
"type": "root",
@@ -1884,7 +2028,7 @@
});
let encoded = json::to_value(&signed).unwrap();
- assert_eq!(encoded, jsn);
+ assert_eq!(encoded, jsn, "{:#?} != {:#?}", encoded, jsn);
let decoded: SignedMetadata<Json, SnapshotMetadata> = json::from_value(encoded).unwrap();
assert_eq!(decoded, signed);
}
@@ -1913,73 +2057,25 @@
// TODO test for mismatched ed25519/rsa keys/schemes
fn make_root() -> json::Value {
- let root_def = RoleDefinition::new(
- 1,
- hashset!(
- PrivateKey::from_pkcs8(ED25519_1_PK8, SignatureScheme::Ed25519)
- .unwrap()
- .key_id()
- .clone()
- ),
- ).unwrap();
+ let root_key = PrivateKey::from_pkcs8(ED25519_1_PK8, SignatureScheme::Ed25519)
+ .unwrap();
+ let snapshot_key = PrivateKey::from_pkcs8(ED25519_2_PK8, SignatureScheme::Ed25519)
+ .unwrap();
+ let targets_key = PrivateKey::from_pkcs8(ED25519_3_PK8, SignatureScheme::Ed25519)
+ .unwrap();
+ let timestamp_key = PrivateKey::from_pkcs8(ED25519_4_PK8, SignatureScheme::Ed25519)
+ .unwrap();
- let snapshot_def = RoleDefinition::new(
- 1,
- hashset!(
- PrivateKey::from_pkcs8(ED25519_2_PK8, SignatureScheme::Ed25519)
- .unwrap()
- .key_id()
- .clone()
- ),
- ).unwrap();
-
- let targets_def = RoleDefinition::new(
- 1,
- hashset!(
- PrivateKey::from_pkcs8(ED25519_3_PK8, SignatureScheme::Ed25519)
- .unwrap()
- .key_id()
- .clone()
- ),
- ).unwrap();
-
- let timestamp_def = RoleDefinition::new(
- 1,
- hashset!(
- PrivateKey::from_pkcs8(ED25519_4_PK8, SignatureScheme::Ed25519)
- .unwrap()
- .key_id()
- .clone()
- ),
- ).unwrap();
-
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![
- PrivateKey::from_pkcs8(ED25519_1_PK8, SignatureScheme::Ed25519)
- .unwrap()
- .public()
- .clone(),
- PrivateKey::from_pkcs8(ED25519_2_PK8, SignatureScheme::Ed25519)
- .unwrap()
- .public()
- .clone(),
- PrivateKey::from_pkcs8(ED25519_3_PK8, SignatureScheme::Ed25519)
- .unwrap()
- .public()
- .clone(),
- PrivateKey::from_pkcs8(ED25519_4_PK8, SignatureScheme::Ed25519)
- .unwrap()
- .public()
- .clone(),
- ],
- root_def,
- snapshot_def,
- targets_def,
- timestamp_def,
- ).unwrap();
+ let root = RootMetadataBuilder::new()
+ .expires(Utc.ymd(2038, 1, 1).and_hms(0, 0, 0))
+ .root_key(
+ root_key.public().clone()
+ )
+ .snapshot_key(snapshot_key.public().clone())
+ .targets_key(targets_key.public().clone())
+ .timestamp_key(timestamp_key.public().clone())
+ .build()
+ .unwrap();
json::to_value(&root).unwrap()
}
diff --git a/src/shims.rs b/src/shims.rs
index 324b2f9..890c0b8 100644
--- a/src/shims.rs
+++ b/src/shims.rs
@@ -2,6 +2,7 @@
use chrono::prelude::*;
use data_encoding::BASE64URL;
use std::collections::{HashMap, HashSet};
+use std::iter::FromIterator;
use crypto;
use error::Error;
@@ -60,7 +61,7 @@
})
}
- pub fn try_into(self) -> Result<metadata::RootMetadata> {
+ pub fn try_into(mut self) -> Result<metadata::RootMetadata> {
if self.typ != metadata::Role::Root {
return Err(Error::Encoding(format!(
"Attempted to decode root metdata labeled as {:?}",
@@ -68,11 +69,18 @@
)));
}
+ let keys_len = self.keys.len();
+ let keys = HashMap::from_iter(self.keys.drain(..).map(|k| (k.key_id().clone(), k)));
+
+ if keys.len() != keys_len {
+ return Err(Error::IllegalArgument("Cannot have duplicate keys".into()));
+ }
+
metadata::RootMetadata::new(
self.version,
parse_datetime(&self.expires)?,
self.consistent_snapshot,
- self.keys,
+ keys,
self.root,
self.snapshot,
self.targets,
diff --git a/src/tuf.rs b/src/tuf.rs
index 5a2cf68..c6c7b5e 100644
--- a/src/tuf.rs
+++ b/src/tuf.rs
@@ -616,7 +616,7 @@
use chrono::prelude::*;
use crypto::{HashAlgorithm, PrivateKey, SignatureScheme};
use interchange::Json;
- use metadata::{MetadataDescription, RoleDefinition};
+ use metadata::{MetadataDescription, RootMetadataBuilder};
lazy_static! {
static ref KEYS: Vec<PrivateKey> = {
@@ -637,69 +637,50 @@
#[test]
fn root_pinned_success() {
let root_key = &KEYS[0];
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![KEYS[0].public().clone()],
- RoleDefinition::new(1, hashset!(root_key.key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- ).unwrap();
- let root: SignedMetadata<Json, RootMetadata> =
- SignedMetadata::new(root, &root_key).unwrap();
+ let root = RootMetadataBuilder::new()
+ .root_key(KEYS[0].public().clone())
+ .snapshot_key(KEYS[0].public().clone())
+ .targets_key(KEYS[0].public().clone())
+ .timestamp_key(KEYS[0].public().clone())
+ .signed::<Json>(&root_key)
+ .unwrap();
assert!(Tuf::from_root_pinned(root, &[root_key.key_id().clone()]).is_ok());
}
#[test]
fn root_pinned_failure() {
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![KEYS[0].public().clone()],
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- ).unwrap();
- let root: SignedMetadata<Json, RootMetadata> =
- SignedMetadata::new(root, &KEYS[0]).unwrap();
+ let root = RootMetadataBuilder::new()
+ .root_key(KEYS[0].public().clone())
+ .snapshot_key(KEYS[0].public().clone())
+ .targets_key(KEYS[0].public().clone())
+ .timestamp_key(KEYS[0].public().clone())
+ .signed::<Json>(&KEYS[0])
+ .unwrap();
assert!(Tuf::from_root_pinned(root, &[KEYS[1].key_id().clone()]).is_err());
}
#[test]
fn good_root_rotation() {
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![KEYS[0].public().clone()],
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- ).unwrap();
- let root: SignedMetadata<Json, RootMetadata> =
- SignedMetadata::new(root, &KEYS[0]).unwrap();
+ let root = RootMetadataBuilder::new()
+ .root_key(KEYS[0].public().clone())
+ .snapshot_key(KEYS[0].public().clone())
+ .targets_key(KEYS[0].public().clone())
+ .timestamp_key(KEYS[0].public().clone())
+ .signed::<Json>(&KEYS[0])
+ .unwrap();
let mut tuf = Tuf::from_root(root).unwrap();
- let root = RootMetadata::new(
- 2,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![KEYS[1].public().clone()],
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- ).unwrap();
- let mut root: SignedMetadata<Json, RootMetadata> =
- SignedMetadata::new(root, &KEYS[1]).unwrap();
+ let mut root = RootMetadataBuilder::new()
+ .version(2)
+ .root_key(KEYS[1].public().clone())
+ .snapshot_key(KEYS[1].public().clone())
+ .targets_key(KEYS[1].public().clone())
+ .timestamp_key(KEYS[1].public().clone())
+ .signed::<Json>(&KEYS[1])
+ .unwrap();
// add the original key's signature to make it cross signed
root.add_signature(&KEYS[0]).unwrap();
@@ -712,52 +693,36 @@
#[test]
fn no_cross_sign_root_rotation() {
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![KEYS[0].public().clone()],
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- ).unwrap();
- let root: SignedMetadata<Json, RootMetadata> =
- SignedMetadata::new(root, &KEYS[0]).unwrap();
+ let root = RootMetadataBuilder::new()
+ .root_key(KEYS[0].public().clone())
+ .snapshot_key(KEYS[0].public().clone())
+ .targets_key(KEYS[0].public().clone())
+ .timestamp_key(KEYS[0].public().clone())
+ .signed::<Json>(&KEYS[0])
+ .unwrap();
let mut tuf = Tuf::from_root(root).unwrap();
- let root = RootMetadata::new(
- 2,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- // include the old key to prevent short circuiting the verify logic
- vec![KEYS[0].public().clone(), KEYS[1].public().clone()],
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- ).unwrap();
- let root: SignedMetadata<Json, RootMetadata> =
- SignedMetadata::new(root, &KEYS[1]).unwrap();
+ let root = RootMetadataBuilder::new()
+ .root_key(KEYS[1].public().clone())
+ .snapshot_key(KEYS[1].public().clone())
+ .targets_key(KEYS[1].public().clone())
+ .timestamp_key(KEYS[1].public().clone())
+ .signed::<Json>(&KEYS[1])
+ .unwrap();
assert!(tuf.update_root(root).is_err());
}
#[test]
fn good_timestamp_update() {
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![KEYS[0].public().clone(), KEYS[1].public().clone()],
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- ).unwrap();
- let root: SignedMetadata<Json, RootMetadata> =
- SignedMetadata::new(root, &KEYS[0]).unwrap();
+ let root = RootMetadataBuilder::new()
+ .root_key(KEYS[0].public().clone())
+ .snapshot_key(KEYS[1].public().clone())
+ .targets_key(KEYS[1].public().clone())
+ .timestamp_key(KEYS[1].public().clone())
+ .signed::<Json>(&KEYS[0])
+ .unwrap();
let mut tuf = Tuf::from_root(root).unwrap();
@@ -777,18 +742,13 @@
#[test]
fn bad_timestamp_update_wrong_key() {
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![KEYS[0].public().clone(), KEYS[1].public().clone()],
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- ).unwrap();
- let root: SignedMetadata<Json, RootMetadata> =
- SignedMetadata::new(root, &KEYS[0]).unwrap();
+ let root = RootMetadataBuilder::new()
+ .root_key(KEYS[0].public().clone())
+ .snapshot_key(KEYS[1].public().clone())
+ .targets_key(KEYS[1].public().clone())
+ .timestamp_key(KEYS[1].public().clone())
+ .signed::<Json>(&KEYS[0])
+ .unwrap();
let mut tuf = Tuf::from_root(root).unwrap();
@@ -807,22 +767,13 @@
#[test]
fn good_snapshot_update() {
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![
- KEYS[0].public().clone(),
- KEYS[1].public().clone(),
- KEYS[2].public().clone(),
- ],
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[2].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[2].key_id().clone())).unwrap(),
- ).unwrap();
- let root: SignedMetadata<Json, RootMetadata> =
- SignedMetadata::new(root, &KEYS[0]).unwrap();
+ let root = RootMetadataBuilder::new()
+ .root_key(KEYS[0].public().clone())
+ .snapshot_key(KEYS[1].public().clone())
+ .targets_key(KEYS[2].public().clone())
+ .timestamp_key(KEYS[2].public().clone())
+ .signed::<Json>(&KEYS[0])
+ .unwrap();
let mut tuf = Tuf::from_root(root).unwrap();
@@ -849,22 +800,13 @@
#[test]
fn bad_snapshot_update_wrong_key() {
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![
- KEYS[0].public().clone(),
- KEYS[1].public().clone(),
- KEYS[2].public().clone(),
- ],
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[2].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[2].key_id().clone())).unwrap(),
- ).unwrap();
- let root: SignedMetadata<Json, RootMetadata> =
- SignedMetadata::new(root, &KEYS[0]).unwrap();
+ let root = RootMetadataBuilder::new()
+ .root_key(KEYS[0].public().clone())
+ .snapshot_key(KEYS[1].public().clone())
+ .targets_key(KEYS[2].public().clone())
+ .timestamp_key(KEYS[2].public().clone())
+ .signed::<Json>(&KEYS[0])
+ .unwrap();
let mut tuf = Tuf::from_root(root).unwrap();
@@ -888,22 +830,13 @@
#[test]
fn bad_snapshot_update_wrong_version() {
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![
- KEYS[0].public().clone(),
- KEYS[1].public().clone(),
- KEYS[2].public().clone(),
- ],
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[2].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[2].key_id().clone())).unwrap(),
- ).unwrap();
- let root: SignedMetadata<Json, RootMetadata> =
- SignedMetadata::new(root, &KEYS[0]).unwrap();
+ let root = RootMetadataBuilder::new()
+ .root_key(KEYS[0].public().clone())
+ .snapshot_key(KEYS[1].public().clone())
+ .targets_key(KEYS[2].public().clone())
+ .timestamp_key(KEYS[2].public().clone())
+ .signed::<Json>(&KEYS[0])
+ .unwrap();
let mut tuf = Tuf::from_root(root).unwrap();
@@ -927,23 +860,13 @@
#[test]
fn good_targets_update() {
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![
- KEYS[0].public().clone(),
- KEYS[1].public().clone(),
- KEYS[2].public().clone(),
- KEYS[3].public().clone(),
- ],
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[2].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[3].key_id().clone())).unwrap(),
- ).unwrap();
- let root: SignedMetadata<Json, _> =
- SignedMetadata::new(root, &KEYS[0]).unwrap();
+ let root = RootMetadataBuilder::new()
+ .root_key(KEYS[0].public().clone())
+ .snapshot_key(KEYS[1].public().clone())
+ .targets_key(KEYS[2].public().clone())
+ .timestamp_key(KEYS[3].public().clone())
+ .signed::<Json>(&KEYS[0])
+ .unwrap();
let mut tuf = Tuf::from_root(root).unwrap();
@@ -982,23 +905,13 @@
#[test]
fn bad_targets_update_wrong_key() {
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![
- KEYS[0].public().clone(),
- KEYS[1].public().clone(),
- KEYS[2].public().clone(),
- KEYS[3].public().clone(),
- ],
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[2].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[3].key_id().clone())).unwrap(),
- ).unwrap();
- let root: SignedMetadata<Json, RootMetadata> =
- SignedMetadata::new(root, &KEYS[0]).unwrap();
+ let root = RootMetadataBuilder::new()
+ .root_key(KEYS[0].public().clone())
+ .snapshot_key(KEYS[1].public().clone())
+ .targets_key(KEYS[2].public().clone())
+ .timestamp_key(KEYS[3].public().clone())
+ .signed::<Json>(&KEYS[0])
+ .unwrap();
let mut tuf = Tuf::from_root(root).unwrap();
@@ -1034,23 +947,13 @@
#[test]
fn bad_targets_update_wrong_version() {
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- vec![
- KEYS[0].public().clone(),
- KEYS[1].public().clone(),
- KEYS[2].public().clone(),
- KEYS[3].public().clone(),
- ],
- RoleDefinition::new(1, hashset!(KEYS[0].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[1].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[2].key_id().clone())).unwrap(),
- RoleDefinition::new(1, hashset!(KEYS[3].key_id().clone())).unwrap(),
- ).unwrap();
- let root: SignedMetadata<Json, RootMetadata> =
- SignedMetadata::new(root, &KEYS[0]).unwrap();
+ let root = RootMetadataBuilder::new()
+ .root_key(KEYS[0].public().clone())
+ .snapshot_key(KEYS[1].public().clone())
+ .targets_key(KEYS[2].public().clone())
+ .timestamp_key(KEYS[3].public().clone())
+ .signed::<Json>(&KEYS[0])
+ .unwrap();
let mut tuf = Tuf::from_root(root).unwrap();
diff --git a/tests/integration.rs b/tests/integration.rs
index 37e1ad1..f732a73 100644
--- a/tests/integration.rs
+++ b/tests/integration.rs
@@ -9,7 +9,7 @@
use tuf::crypto::{HashAlgorithm, PrivateKey, SignatureScheme};
use tuf::interchange::Json;
use tuf::metadata::{
- Delegation, Delegations, MetadataDescription, MetadataPath, RoleDefinition, RootMetadata,
+ Delegation, Delegations, MetadataDescription, MetadataPath, RootMetadataBuilder,
SignedMetadata, SnapshotMetadata, TargetDescription, TargetsMetadata, TimestampMetadata,
VirtualTargetPath,
};
@@ -31,30 +31,14 @@
let delegation_key = PrivateKey::from_pkcs8(ED25519_5_PK8, SignatureScheme::Ed25519).unwrap();
//// build the root ////
- let keys = vec![
- root_key.public().clone(),
- snapshot_key.public().clone(),
- targets_key.public().clone(),
- timestamp_key.public().clone(),
- ];
- let root_def = RoleDefinition::new(1, hashset!(root_key.key_id().clone())).unwrap();
- let snapshot_def = RoleDefinition::new(1, hashset!(snapshot_key.key_id().clone())).unwrap();
- let targets_def = RoleDefinition::new(1, hashset!(targets_key.key_id().clone())).unwrap();
- let timestamp_def = RoleDefinition::new(1, hashset!(timestamp_key.key_id().clone())).unwrap();
-
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- keys,
- root_def,
- snapshot_def,
- targets_def,
- timestamp_def,
- ).unwrap();
-
- let signed = SignedMetadata::<Json, _>::new(root, &root_key).unwrap();
+ let signed = RootMetadataBuilder::new()
+ .root_key(root_key.public().clone())
+ .snapshot_key(snapshot_key.public().clone())
+ .targets_key(targets_key.public().clone())
+ .timestamp_key(timestamp_key.public().clone())
+ .signed::<Json>(&root_key)
+ .unwrap();
let mut tuf = Tuf::<Json>::from_root_pinned(signed, &[root_key.key_id().clone()]).unwrap();
@@ -142,30 +126,14 @@
let delegation_b_key = PrivateKey::from_pkcs8(ED25519_6_PK8, SignatureScheme::Ed25519).unwrap();
//// build the root ////
- let keys = vec![
- root_key.public().clone(),
- snapshot_key.public().clone(),
- targets_key.public().clone(),
- timestamp_key.public().clone(),
- ];
- let root_def = RoleDefinition::new(1, hashset!(root_key.key_id().clone())).unwrap();
- let snapshot_def = RoleDefinition::new(1, hashset!(snapshot_key.key_id().clone())).unwrap();
- let targets_def = RoleDefinition::new(1, hashset!(targets_key.key_id().clone())).unwrap();
- let timestamp_def = RoleDefinition::new(1, hashset!(timestamp_key.key_id().clone())).unwrap();
-
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- keys,
- root_def,
- snapshot_def,
- targets_def,
- timestamp_def,
- ).unwrap();
-
- let signed = SignedMetadata::<Json, _>::new(root, &root_key).unwrap();
+ let signed = RootMetadataBuilder::new()
+ .root_key(root_key.public().clone())
+ .snapshot_key(snapshot_key.public().clone())
+ .targets_key(targets_key.public().clone())
+ .timestamp_key(timestamp_key.public().clone())
+ .signed::<Json>(&root_key)
+ .unwrap();
let mut tuf = Tuf::<Json>::from_root_pinned(signed, &[root_key.key_id().clone()]).unwrap();
diff --git a/tests/simple_example.rs b/tests/simple_example.rs
index 1381958..f264d1b 100644
--- a/tests/simple_example.rs
+++ b/tests/simple_example.rs
@@ -9,9 +9,9 @@
use tuf::crypto::{HashAlgorithm, KeyId, PrivateKey, SignatureScheme};
use tuf::interchange::{DataInterchange, Json};
use tuf::metadata::{
- MetadataDescription, MetadataPath, MetadataVersion, RoleDefinition, RootMetadata,
- SignedMetadata, SnapshotMetadata, TargetDescription, TargetPath, TargetsMetadata,
- TimestampMetadata, VirtualTargetPath,
+ MetadataDescription, MetadataPath, MetadataVersion, RootMetadataBuilder, SignedMetadata,
+ SnapshotMetadata, TargetDescription, TargetPath, TargetsMetadata, TimestampMetadata,
+ VirtualTargetPath,
};
use tuf::repository::{EphemeralRepository, Repository};
use tuf::Result;
@@ -84,30 +84,13 @@
//// build the root ////
- let keys = vec![
- root_key.public().clone(),
- snapshot_key.public().clone(),
- targets_key.public().clone(),
- timestamp_key.public().clone(),
- ];
-
- let root_def = RoleDefinition::new(1, hashset!(root_key.key_id().clone()))?;
- let snapshot_def = RoleDefinition::new(1, hashset!(snapshot_key.key_id().clone()))?;
- let targets_def = RoleDefinition::new(1, hashset!(targets_key.key_id().clone()))?;
- let timestamp_def = RoleDefinition::new(1, hashset!(timestamp_key.key_id().clone()))?;
-
- let root = RootMetadata::new(
- 1,
- Utc.ymd(2038, 1, 1).and_hms(0, 0, 0),
- false,
- keys,
- root_def,
- snapshot_def,
- targets_def,
- timestamp_def,
- )?;
-
- let signed = SignedMetadata::<Json, _>::new(root, &root_key)?;
+ let signed = RootMetadataBuilder::new()
+ .root_key(root_key.public().clone())
+ .snapshot_key(snapshot_key.public().clone())
+ .targets_key(targets_key.public().clone())
+ .timestamp_key(timestamp_key.public().clone())
+ .signed::<Json>(&root_key)
+ .unwrap();
remote.store_metadata(
&MetadataPath::new("root".into())?,