From 3a464de616af0c4c14f49296f16ee3660d7ff2b0 Mon Sep 17 00:00:00 2001 From: Erick Tryzelaar Date: Fri, 22 Nov 2019 21:13:12 -0800 Subject: [PATCH] Add new Client constructors This patch changes how Clients are created. It adds the following functions: * `Client::from_local` - use the specified root version from the local repository as our initial trusted root. * `Client::from_pinned_root_keyids` - use the specified root version, threshold, and keyids to trust a root fetched from the local or remote repository. * `Client::from_pinned_root_keys` - use the specified root version, threshold, and public keys to trust a root fetched from the local or remote repository. * `Client::from_pinned_root` - use the specified root metadata as the initial trusted root. This deprecates the old constructors: * `Client::new` * `Client::with_root_pinned` Closes: #229 --- src/client.rs | 557 ++++++++++++++++++++++++++++++++++++---- src/crypto.rs | 2 +- src/repository.rs | 1 + src/tuf.rs | 44 +++- tests/integration.rs | 6 +- tests/interop/main.rs | 14 +- tests/simple_example.rs | 10 +- 7 files changed, 566 insertions(+), 68 deletions(-) diff --git a/src/client.rs b/src/client.rs index cdd2d7c0..febd6b82 100644 --- a/src/client.rs +++ b/src/client.rs @@ -36,12 +36,13 @@ //! .user_agent("rustup/1.4.0") //! .build(); //! -//! let mut client = Client::with_root_pinned( -//! &key_ids, +//! let mut client = Client::from_pinned_root_keyids( //! Config::default(), +//! &MetadataVersion::Number(1), +//! 1, +//! &key_ids, //! local, //! remote, -//! 1, //! ).await?; //! //! let _ = client.update().await?; @@ -57,11 +58,11 @@ use log::{error, warn}; use std::future::Future; use std::pin::Pin; -use crate::crypto::{self, KeyId}; +use crate::crypto::{self, KeyId, PublicKey}; use crate::error::Error; use crate::interchange::DataInterchange; use crate::metadata::{ - Metadata, MetadataPath, MetadataVersion, Role, SignedMetadata, SnapshotMetadata, + Metadata, MetadataPath, MetadataVersion, Role, RootMetadata, SignedMetadata, SnapshotMetadata, TargetDescription, TargetPath, TargetsMetadata, VirtualTargetPath, }; use crate::repository::Repository; @@ -93,7 +94,7 @@ pub trait PathTranslator { } /// A `PathTranslator` that does nothing. -#[derive(Clone, Default)] +#[derive(Clone, Debug, Default)] pub struct DefaultTranslator; impl DefaultTranslator { @@ -114,6 +115,7 @@ impl PathTranslator for DefaultTranslator { } /// A client that interacts with TUF repositories. +#[derive(Debug)] pub struct Client where D: DataInterchange + Sync, @@ -139,12 +141,101 @@ where /// /// **WARNING**: This method offers weaker security guarantees than the related method /// `with_root_pinned`. + /// + /// **DEPRECATED**: This has been replaced with [Client::from_local]. + #[deprecated(note = "use Client::from_local method instead")] pub async fn new(config: Config, local: L, remote: R) -> Result { + Client::from_local(config, &MetadataVersion::Number(1), local, remote).await + } + + /// Create a new TUF client. It will attempt to load initial root metadata the local and remote + /// repositories using the provided key IDs to pin the verification. + /// + /// **DEPRECATED**: This has been replaced with [Client::from_root_pinned_keyids]. + #[deprecated(note = "use Client::from_root_pinned_keyids method instead")] + pub async fn with_root_keyids_pinned( + trusted_root_keys: &[KeyId], + config: Config, + local: L, + remote: R, + version: u32, + ) -> Result { + Client::from_pinned_root_keyids( + config, + &MetadataVersion::Number(version), + 1, + trusted_root_keys, + local, + remote, + ) + .await + } + + /// Create a new TUF client. It will attempt to load the latest root metadata from the local + /// repo and use it as the initial trusted root metadata, or it will return an error if it + /// cannot do so. + /// + /// **WARNING**: This method offers weaker security guarantees than the related method + /// `from_pinned_root_keys`. + /// + /// # Examples + /// + /// ``` + /// # use chrono::offset::{Utc, TimeZone}; + /// # use futures_executor::block_on; + /// # use tuf::{ + /// # Error, + /// # interchange::Json, + /// # client::{Client, Config}, + /// # crypto::{KeyType, PrivateKey, SignatureScheme}, + /// # metadata::{MetadataPath, MetadataVersion, Role, RootMetadataBuilder}, + /// # repository::{EphemeralRepository, Repository}, + /// # }; + /// # fn main() -> Result<(), Error> { + /// # block_on(async { + /// # let private_key = PrivateKey::from_pkcs8( + /// # &PrivateKey::new(KeyType::Ed25519)?, + /// # SignatureScheme::Ed25519, + /// # )?; + /// # let public_key = private_key.public().clone(); + /// let local = EphemeralRepository::new(); + /// let remote = EphemeralRepository::new(); + /// + /// let root_version = 1; + /// let root = RootMetadataBuilder::new() + /// .version(root_version) + /// .expires(Utc.ymd(2038, 1, 1).and_hms(0, 0, 0)) + /// .root_key(public_key.clone()) + /// .snapshot_key(public_key.clone()) + /// .targets_key(public_key.clone()) + /// .timestamp_key(public_key.clone()) + /// .signed::(&private_key)?; + /// + /// let root_path = MetadataPath::from_role(&Role::Root); + /// let root_version = MetadataVersion::Number(root_version); + /// + /// local.store_metadata(&root_path, &root_version, &root).await?; + /// + /// let client = Client::from_local( + /// Config::default(), + /// &root_version, + /// local, + /// remote, + /// ).await?; + /// # Ok(()) + /// # }) + /// # } + /// ``` + pub async fn from_local( + config: Config, + root_version: &MetadataVersion, + local: L, + remote: R, + ) -> Result { let root_path = MetadataPath::from_role(&Role::Root); - let root_version = MetadataVersion::Number(1); let root = local - .fetch_metadata(&root_path, &root_version, config.max_root_length, None) + .fetch_metadata(&root_path, root_version, config.max_root_length, None) .await?; let tuf = Tuf::from_root(root)?; @@ -160,38 +251,272 @@ where /// Create a new TUF client. It will attempt to load initial root metadata the local and remote /// repositories using the provided key IDs to pin the verification. /// - /// This is the preferred method of creating a client. - pub async fn with_root_pinned( - trusted_root_keys: &[KeyId], + /// # Examples + /// + /// ``` + /// # use chrono::offset::{Utc, TimeZone}; + /// # use futures_executor::block_on; + /// # use std::iter::once; + /// # use tuf::{ + /// # Error, + /// # interchange::Json, + /// # client::{Client, Config}, + /// # crypto::{KeyType, PrivateKey, SignatureScheme}, + /// # metadata::{MetadataPath, MetadataVersion, Role, RootMetadataBuilder}, + /// # repository::{EphemeralRepository, Repository}, + /// # }; + /// # fn main() -> Result<(), Error> { + /// # block_on(async { + /// # let private_key = PrivateKey::from_pkcs8( + /// # &PrivateKey::new(KeyType::Ed25519)?, + /// # SignatureScheme::Ed25519, + /// # )?; + /// # let public_key = private_key.public().clone(); + /// let local = EphemeralRepository::new(); + /// let remote = EphemeralRepository::new(); + /// + /// let root_version = 1; + /// let root_threshold = 1; + /// let root = RootMetadataBuilder::new() + /// .version(root_version) + /// .expires(Utc.ymd(2038, 1, 1).and_hms(0, 0, 0)) + /// .root_key(public_key.clone()) + /// .root_threshold(root_threshold) + /// .snapshot_key(public_key.clone()) + /// .targets_key(public_key.clone()) + /// .timestamp_key(public_key.clone()) + /// .signed::(&private_key)?; + /// + /// let root_path = MetadataPath::from_role(&Role::Root); + /// let root_version = MetadataVersion::Number(root_version); + /// + /// remote.store_metadata(&root_path, &root_version, &root).await?; + /// + /// let client = Client::from_pinned_root_keyids( + /// Config::default(), + /// &root_version, + /// root_threshold, + /// once(public_key.key_id()), + /// local, + /// remote, + /// ).await?; + /// # Ok(()) + /// # }) + /// # } + /// ``` + pub async fn from_pinned_root_keyids<'a, I>( config: Config, + root_version: &MetadataVersion, + root_threshold: u32, + trusted_root_keyids: I, local: L, remote: R, - version: u32, - ) -> Result { + ) -> Result + where + I: IntoIterator, + { let root_path = MetadataPath::from_role(&Role::Root); - let root_version = MetadataVersion::Number(version); - let root = match local - .fetch_metadata(&root_path, &root_version, config.max_root_length, None) - .await - { - Ok(root) => root, - Err(_) => { - let root = remote - .fetch_metadata(&root_path, &root_version, config.max_root_length, None) - .await?; + let (fetched, root) = fetch_metadata_from_local_then_remote( + &root_path, + &root_version, + config.max_root_length, + &local, + &remote, + ) + .await?; - local - .store_metadata(&root_path, &root_version, &root) - .await?; + let tuf = Tuf::from_root_keyids_pinned(root.clone(), root_threshold, trusted_root_keyids)?; - // FIXME: should we also the root as `MetadataVersion::None`? + // Only store the metadata after we have validated it. + if fetched { + let root_version = MetadataVersion::Number(root.version()); + local + .store_metadata(&root_path, &root_version, &root) + .await?; - root - } - }; + // Also store this root metadata as the latest version. + local + .store_metadata(&root_path, &MetadataVersion::None, &root) + .await?; + } + + Ok(Client { + tuf, + config, + local, + remote, + }) + } - let tuf = Tuf::from_root_pinned(root, trusted_root_keys)?; + /// Create a new TUF client. It will attempt to load initial root metadata from the local and remote + /// repositories using the provided keys to pin the verification. + /// + /// # Examples + /// + /// ``` + /// # use chrono::offset::{Utc, TimeZone}; + /// # use futures_executor::block_on; + /// # use std::iter::once; + /// # use tuf::{ + /// # Error, + /// # interchange::Json, + /// # client::{Client, Config}, + /// # crypto::{KeyType, PrivateKey, SignatureScheme}, + /// # metadata::{MetadataPath, MetadataVersion, Role, RootMetadataBuilder}, + /// # repository::{EphemeralRepository, Repository}, + /// # }; + /// # fn main() -> Result<(), Error> { + /// # block_on(async { + /// # let private_key = PrivateKey::from_pkcs8( + /// # &PrivateKey::new(KeyType::Ed25519)?, + /// # SignatureScheme::Ed25519, + /// # )?; + /// # let public_key = private_key.public().clone(); + /// let local = EphemeralRepository::new(); + /// let remote = EphemeralRepository::new(); + /// + /// let root_version = 1; + /// let root_threshold = 1; + /// let root = RootMetadataBuilder::new() + /// .version(root_version) + /// .expires(Utc.ymd(2038, 1, 1).and_hms(0, 0, 0)) + /// .root_key(public_key.clone()) + /// .root_threshold(root_threshold) + /// .snapshot_key(public_key.clone()) + /// .targets_key(public_key.clone()) + /// .timestamp_key(public_key.clone()) + /// .signed::(&private_key)?; + /// + /// let root_path = MetadataPath::from_role(&Role::Root); + /// let root_version = MetadataVersion::Number(root_version); + /// + /// remote.store_metadata(&root_path, &root_version, &root).await?; + /// + /// let client = Client::from_pinned_root_keys( + /// Config::default(), + /// &root_version, + /// root_threshold, + /// once(&public_key), + /// local, + /// remote, + /// ).await?; + /// # Ok(()) + /// # }) + /// # } + /// ``` + pub async fn from_pinned_root_keys<'a, I>( + config: Config, + root_version: &MetadataVersion, + root_threshold: u32, + trusted_root_keys: I, + local: L, + remote: R, + ) -> Result + where + I: IntoIterator, + { + let root_path = MetadataPath::from_role(&Role::Root); + + let (fetched, root) = fetch_metadata_from_local_then_remote( + &root_path, + root_version, + config.max_root_length, + &local, + &remote, + ) + .await?; + + let tuf = Tuf::from_root_keys_pinned(root.clone(), root_threshold, trusted_root_keys)?; + + // Only store the metadata after we have validated it. + if fetched { + let root_version = MetadataVersion::Number(root.version()); + local + .store_metadata(&root_path, &root_version, &root) + .await?; + + // Also store this root metadata as the latest version. + local + .store_metadata(&root_path, &MetadataVersion::None, &root) + .await?; + } + + Ok(Client { + tuf, + config, + local, + remote, + }) + } + + /// Create a new TUF client. It will use trust this initial root metadata. + /// + /// # Examples + /// + /// ``` + /// # use chrono::offset::{Utc, TimeZone}; + /// # use futures_executor::block_on; + /// # use tuf::{ + /// # Error, + /// # interchange::Json, + /// # client::{Client, Config}, + /// # crypto::{KeyType, PrivateKey, SignatureScheme}, + /// # metadata::{MetadataPath, MetadataVersion, Role, RootMetadataBuilder}, + /// # repository::{EphemeralRepository, Repository}, + /// # }; + /// # fn main() -> Result<(), Error> { + /// # block_on(async { + /// # let private_key = PrivateKey::from_pkcs8( + /// # &PrivateKey::new(KeyType::Ed25519)?, + /// # SignatureScheme::Ed25519, + /// # )?; + /// # let public_key = private_key.public().clone(); + /// let local = EphemeralRepository::new(); + /// let remote = EphemeralRepository::new(); + /// + /// let root_version = 1; + /// let root_threshold = 1; + /// let root = RootMetadataBuilder::new() + /// .version(root_version) + /// .expires(Utc.ymd(2038, 1, 1).and_hms(0, 0, 0)) + /// .root_key(public_key.clone()) + /// .root_threshold(root_threshold) + /// .snapshot_key(public_key.clone()) + /// .targets_key(public_key.clone()) + /// .timestamp_key(public_key.clone()) + /// .signed::(&private_key) + /// .unwrap(); + /// + /// let client = Client::from_pinned_root( + /// Config::default(), + /// root, + /// local, + /// remote, + /// ).await?; + /// # Ok(()) + /// # }) + /// # } + /// ``` + pub async fn from_pinned_root( + config: Config, + trusted_root: SignedMetadata, + local: L, + remote: R, + ) -> Result { + let tuf = Tuf::from_root(trusted_root.clone())?; + + let root_path = MetadataPath::from_role(&Role::Root); + let root_version = MetadataVersion::Number(trusted_root.version()); + + local + .store_metadata(&root_path, &root_version, &trusted_root) + .await?; + + // Also store this root metadata as the latest version. + local + .store_metadata(&root_path, &MetadataVersion::None, &trusted_root) + .await?; Ok(Client { tuf, @@ -633,6 +958,32 @@ where } } +/// Helper function that first tries to fetch the metadata from the local store, and if it doesn't +/// exist, try fetching it from the remote store. +async fn fetch_metadata_from_local_then_remote( + path: &MetadataPath, + version: &MetadataVersion, + max_length: Option, + local: &L, + remote: &R, +) -> Result<(bool, SignedMetadata)> +where + D: DataInterchange + Sync, + L: Repository, + R: Repository, +{ + match local.fetch_metadata(path, version, max_length, None).await { + Ok(meta) => Ok((false, meta)), + Err(Error::NotFound) => { + let meta = remote + .fetch_metadata(path, version, max_length, None) + .await?; + Ok((true, meta)) + } + Err(err) => Err(err), + } +} + /// Configuration for a TUF `Client`. /// /// # Defaults @@ -776,7 +1127,7 @@ impl Default for ConfigBuilder { #[cfg(test)] mod test { use super::*; - use crate::crypto::{HashAlgorithm, PrivateKey, SignatureScheme}; + use crate::crypto::{HashAlgorithm, KeyType, PrivateKey, SignatureScheme}; use crate::interchange::Json; use crate::metadata::{ MetadataPath, MetadataVersion, RootMetadata, RootMetadataBuilder, SnapshotMetadataBuilder, @@ -787,7 +1138,9 @@ mod test { use futures_executor::block_on; use lazy_static::lazy_static; use maplit::hashmap; + use matches::assert_matches; use serde_json::json; + use std::iter::once; lazy_static! { static ref KEYS: Vec = { @@ -805,6 +1158,118 @@ mod test { }; } + #[test] + fn client_constructors_err_with_not_found() { + block_on(async { + let local = EphemeralRepository::::new(); + let remote = EphemeralRepository::::new(); + + let private_key = PrivateKey::from_pkcs8( + &PrivateKey::new(KeyType::Ed25519).unwrap(), + SignatureScheme::Ed25519, + ).unwrap(); + let public_key = private_key.public().clone(); + + assert_matches!( + Client::from_local( + Config::default(), + &MetadataVersion::Number(1), + &local, + &remote, + ).await, + Err(Error::NotFound) + ); + + assert_matches!( + Client::from_pinned_root_keys( + Config::default(), + &MetadataVersion::Number(1), + 1, + once(&public_key), + &local, + &remote, + ).await, + Err(Error::NotFound) + ); + + assert_matches!( + Client::from_pinned_root_keyids( + Config::default(), + &MetadataVersion::Number(1), + 1, + once(public_key.key_id()), + &local, + &remote, + ).await, + Err(Error::NotFound) + ); + }) + } + + #[test] + fn client_constructors_err_with_invalid_keys() { + block_on(async { + let local = EphemeralRepository::::new(); + let remote = EphemeralRepository::::new(); + + let good_private_key = PrivateKey::from_pkcs8( + &PrivateKey::new(KeyType::Ed25519).unwrap(), + SignatureScheme::Ed25519, + ).unwrap(); + let good_public_key = good_private_key.public().clone(); + + let root_version = 1; + let root = RootMetadataBuilder::new() + .version(root_version) + .expires(Utc.ymd(2038, 1, 1).and_hms(0, 0, 0)) + .root_key(good_public_key.clone()) + .snapshot_key(good_public_key.clone()) + .targets_key(good_public_key.clone()) + .timestamp_key(good_public_key.clone()) + .signed::(&good_private_key) + .unwrap(); + + let root_path = MetadataPath::from_role(&Role::Root); + let root_version = MetadataVersion::Number(root_version); + + remote.store_metadata( + &root_path, + &root_version, + &root, + ).await.unwrap(); + + let bad_private_key = PrivateKey::from_pkcs8( + &PrivateKey::new(KeyType::Ed25519).unwrap(), + SignatureScheme::Ed25519, + ).unwrap(); + let bad_public_key = bad_private_key.public().clone(); + + assert_matches!( + Client::from_pinned_root_keys( + Config::default(), + &root_version, + 1, + once(&bad_public_key), + &local, + &remote, + ).await, + Err(Error::VerificationFailure(_)) + ); + + assert_matches!( + Client::from_pinned_root_keyids( + Config::default(), + &root_version, + 1, + once(bad_public_key.key_id()), + &local, + &remote, + ).await, + Err(Error::VerificationFailure(_)) + ); + }) + } + #[test] fn root_chain_update() { block_on(async { @@ -917,12 +1382,13 @@ mod test { //// // Now, make sure that the local metadata got version 1. let key_ids = [KEYS[0].public().key_id().clone()]; - let mut client = Client::with_root_pinned( + let mut client = Client::from_pinned_root_keyids( + Config::default(), + &MetadataVersion::Number(1), + 1, &key_ids, - Config::build().finish().unwrap(), EphemeralRepository::new(), repo, - 1, ) .await .unwrap(); @@ -1101,12 +1567,13 @@ mod test { KEYS[0].public().key_id().clone(), KEYS[1].public().key_id().clone(), ]; - let mut client = Client::with_root_pinned( - &key_ids, + let mut client = Client::from_pinned_root_keyids( Config::build().finish().unwrap(), + &MetadataVersion::Number(2), + 1, + &key_ids, EphemeralRepository::new(), repo, - 2, ) .await .unwrap(); @@ -1233,16 +1700,10 @@ mod test { .unwrap(); // Initialize and update client. - let key_ids = [KEYS[0].public().key_id().clone()]; - let mut client = Client::with_root_pinned( - &key_ids, - Config::build().finish().unwrap(), - EphemeralRepository::new(), - repo, - 1, - ) - .await - .unwrap(); + let mut client = + Client::from_pinned_root(Config::default(), root, EphemeralRepository::new(), repo) + .await + .unwrap(); assert_eq!(client.update().await, Ok(true)); diff --git a/src/crypto.rs b/src/crypto.rs index 9d45a125..82f99a9e 100644 --- a/src/crypto.rs +++ b/src/crypto.rs @@ -354,7 +354,7 @@ pub struct PrivateKey { } impl PrivateKey { - /// Generate a new `PrivateKey`. + /// Generate a new `PrivateKey` bytes in pkcs8 format. /// /// Note: For RSA keys, `openssl` needs to the on the `$PATH`. pub fn new(key_type: KeyType) -> Result> { diff --git a/src/repository.rs b/src/repository.rs index 3c210583..56dadd8e 100644 --- a/src/repository.rs +++ b/src/repository.rs @@ -615,6 +615,7 @@ where type ArcHashMap = Arc>>; /// An ephemeral repository contained solely in memory. +#[derive(Debug)] pub struct EphemeralRepository where D: DataInterchange, diff --git a/src/tuf.rs b/src/tuf.rs index 08d61f74..9600a21b 100644 --- a/src/tuf.rs +++ b/src/tuf.rs @@ -5,7 +5,7 @@ use log::info; use std::collections::{HashMap, HashSet}; use std::marker::PhantomData; -use crate::crypto::KeyId; +use crate::crypto::{KeyId, PublicKey}; use crate::error::Error; use crate::interchange::DataInterchange; use crate::metadata::{ @@ -26,27 +26,47 @@ pub struct Tuf { } impl Tuf { - /// Create a new `TUF` struct from a known set of pinned root keys that are used to verify the - /// signed metadata. - pub fn from_root_pinned<'a, I>( - mut signed_root: SignedMetadata, + /// Create a new `TUF` struct from a known set of pinned root key ids that are used to verify + /// the signed metadata. + pub fn from_root_keyids_pinned<'a, I>( + signed_root: SignedMetadata, + threshold: u32, root_key_ids: I, ) -> Result where I: IntoIterator, { - let root_key_ids = root_key_ids.into_iter().collect::>(); + { + let root = signed_root.as_ref(); + signed_root.verify( + threshold, + root_key_ids + .into_iter() + .filter_map(|key_id| root.keys().get(key_id)), + )? + } + + Self::from_root(signed_root) + } - signed_root - .signatures_mut() - .retain(|s| root_key_ids.contains(s.key_id())); + /// Create a new `TUF` struct from a known set of pinned root keys that are used to verify the + /// signed metadata. + pub fn from_root_keys_pinned<'a, I>( + signed_root: SignedMetadata, + threshold: u32, + root_keys: I, + ) -> Result + where + I: IntoIterator, + { + signed_root.verify(threshold, root_keys)?; Self::from_root(signed_root) } /// Create a new `TUF` struct from a piece of metadata that is assumed to be trusted. /// /// **WARNING**: This is trust-on-first-use (TOFU) and offers weaker security guarantees than - /// the related method `from_root_pinned`. + /// the related method `from_root_keys_pinned` and `from_root_keyids_pinned`. pub fn from_root(signed_root: SignedMetadata) -> Result { { let root = signed_root.as_ref(); @@ -658,7 +678,7 @@ mod test { .signed::(&root_key) .unwrap(); - assert!(Tuf::from_root_pinned(root, &[root_key.key_id().clone()]).is_ok()); + assert!(Tuf::from_root_keyids_pinned(root, 1, &[root_key.key_id().clone()]).is_ok()); } #[test] @@ -671,7 +691,7 @@ mod test { .signed::(&KEYS[0]) .unwrap(); - assert!(Tuf::from_root_pinned(root, &[KEYS[1].key_id().clone()]).is_err()); + assert!(Tuf::from_root_keyids_pinned(root, 1, &[KEYS[1].key_id().clone()]).is_err()); } #[test] diff --git a/tests/integration.rs b/tests/integration.rs index a79ee2bc..ae276fe7 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -32,7 +32,8 @@ fn simple_delegation() { .signed::(&root_key) .unwrap(); - let mut tuf = Tuf::::from_root_pinned(root, &[root_key.key_id().clone()]).unwrap(); + let mut tuf = + Tuf::::from_root_keyids_pinned(root, 1, &[root_key.key_id().clone()]).unwrap(); //// build the snapshot and timestamp //// @@ -121,7 +122,8 @@ fn nested_delegation() { .signed::(&root_key) .unwrap(); - let mut tuf = Tuf::::from_root_pinned(root, &[root_key.key_id().clone()]).unwrap(); + let mut tuf = + Tuf::::from_root_keyids_pinned(root, 1, &[root_key.key_id().clone()]).unwrap(); //// build the snapshot and timestamp //// diff --git a/tests/interop/main.rs b/tests/interop/main.rs index 0864573e..d5be57e4 100644 --- a/tests/interop/main.rs +++ b/tests/interop/main.rs @@ -149,10 +149,16 @@ impl TestKeyRotation { let remote = init_remote(&dir).unwrap(); // Connect to the client with our initial keys. - let mut client = - Client::with_root_pinned(&key_ids, Config::default(), &self.local, remote, 1) - .await - .expect("client to open"); + let mut client = Client::from_pinned_root_keyids( + Config::default(), + &MetadataVersion::Number(1), + 1, + key_ids, + &self.local, + remote, + ) + .await + .expect("client to open"); // Update our TUF metadata. The first time should report there is new metadata, the second // time should not. diff --git a/tests/simple_example.rs b/tests/simple_example.rs index f68f1a5d..408ca1bc 100644 --- a/tests/simple_example.rs +++ b/tests/simple_example.rs @@ -90,7 +90,15 @@ where T: PathTranslator, { let local = EphemeralRepository::::new(); - let mut client = Client::with_root_pinned(&root_key_ids, config, local, remote, 1).await?; + let mut client = Client::from_pinned_root_keyids( + config, + &MetadataVersion::Number(1), + 1, + root_key_ids, + local, + remote, + ) + .await?; let _ = client.update().await?; let target_path = TargetPath::new("foo-bar".into())?; client.fetch_target(&target_path).await