diff --git a/tuf/src/client.rs b/tuf/src/client.rs index 8e01e01..b1577e0 100644 --- a/tuf/src/client.rs +++ b/tuf/src/client.rs @@ -1014,7 +1014,7 @@ where } } - let role_meta = match snapshot.meta().get(delegation.role()) { + let role_meta = match snapshot.meta().get(delegation.name()) { Some(m) => m, None if delegation.terminating() => { return (true, Err(Error::TargetNotFound(target.clone()))); @@ -1053,12 +1053,12 @@ where let raw_signed_meta = match self .remote - .fetch_metadata(delegation.role(), version, role_length, role_hashes) + .fetch_metadata(delegation.name(), version, role_length, role_hashes) .await { Ok(m) => m, Err(e) => { - warn!("Failed to fetch metadata {:?}: {:?}", delegation.role(), e); + warn!("Failed to fetch metadata {:?}: {:?}", delegation.name(), e); if delegation.terminating() { return (true, Err(e)); } else { @@ -1070,7 +1070,7 @@ where match self.tuf.update_delegated_targets( start_time, &targets_role, - delegation.role(), + delegation.name(), &raw_signed_meta, ) { Ok(_) => { @@ -1082,14 +1082,14 @@ where match self .local - .store_metadata(delegation.role(), MetadataVersion::None, &raw_signed_meta) + .store_metadata(delegation.name(), MetadataVersion::None, &raw_signed_meta) .await { Ok(_) => (), Err(e) => { warn!( "Error storing metadata {:?} locally: {:?}", - delegation.role(), + delegation.name(), e ) } @@ -1098,7 +1098,7 @@ where let meta = self .tuf .trusted_delegations() - .get(delegation.role()) + .get(delegation.name()) .unwrap() .clone(); let f: Pin>> = @@ -1108,7 +1108,7 @@ where current_depth + 1, target, snapshot, - Some((&meta, delegation.role().clone())), + Some((&meta, delegation.name().clone())), )); let (term, res) = f.await; diff --git a/tuf/src/database.rs b/tuf/src/database.rs index 74e7c7c..45c41de 100644 --- a/tuf/src/database.rs +++ b/tuf/src/database.rs @@ -850,7 +850,7 @@ impl Database { }; for trusted_delegation in trusted_delegations.roles() { - if trusted_delegation.role() != role { + if trusted_delegation.name() != role { continue; } @@ -898,21 +898,21 @@ impl Database { return Ok(d.clone()); } - fn lookup( + fn lookup<'a, D: DataInterchange>( start_time: &DateTime, - tuf: &Database, + tuf: &'a Database, default_terminate: bool, current_depth: u32, target_path: &TargetPath, - delegations: &Delegations, + delegations: &'a Delegations, parents: &[HashSet], - visited: &mut HashSet, + visited: &mut HashSet<&'a MetadataPath>, ) -> (bool, Option) { for delegation in delegations.roles() { - if visited.contains(delegation.role()) { + if visited.contains(delegation.name()) { return (delegation.terminating(), None); } - let _ = visited.insert(delegation.role().clone()); + let _ = visited.insert(delegation.name()); let mut new_parents = parents.to_owned(); new_parents.push(delegation.paths().clone()); @@ -921,7 +921,7 @@ impl Database { return (delegation.terminating(), None); } - let trusted_delegation = match tuf.trusted_delegations.get(delegation.role()) { + let trusted_delegation = match tuf.trusted_delegations.get(delegation.name()) { Some(trusted_delegation) => trusted_delegation, None => return (delegation.terminating(), None), }; diff --git a/tuf/src/interchange/cjson/shims.rs b/tuf/src/interchange/cjson/shims.rs index a3f10a2..f8d4407 100644 --- a/tuf/src/interchange/cjson/shims.rs +++ b/tuf/src/interchange/cjson/shims.rs @@ -368,7 +368,7 @@ pub struct PublicKeyValue { #[derive(Serialize, Deserialize)] pub struct Delegation { - role: metadata::MetadataPath, + name: metadata::MetadataPath, terminating: bool, threshold: u32, #[serde(rename = "keyids")] @@ -376,15 +376,16 @@ pub struct Delegation { paths: Vec, } -impl Delegation { - pub fn from(meta: &metadata::Delegation) -> Self { - let mut paths = meta +impl From<&metadata::Delegation> for Delegation { + fn from(delegation: &metadata::Delegation) -> Self { + let mut paths = delegation .paths() .iter() .cloned() .collect::>(); paths.sort(); - let mut key_ids = meta + + let mut key_ids = delegation .key_ids() .iter() .cloned() @@ -392,34 +393,40 @@ impl Delegation { key_ids.sort(); Delegation { - role: meta.role().clone(), - terminating: meta.terminating(), - threshold: meta.threshold(), + name: delegation.name().clone(), + terminating: delegation.terminating(), + threshold: delegation.threshold(), key_ids, paths, } } +} - pub fn try_into(self) -> Result { - let paths = self - .paths - .iter() - .cloned() - .collect::>(); - if paths.len() != self.paths.len() { - return Err(Error::Encoding("Non-unique delegation paths.".into())); - } +impl TryFrom for metadata::Delegation { + type Error = Error; - let key_ids = self - .key_ids - .iter() - .cloned() - .collect::>(); - if key_ids.len() != self.key_ids.len() { + fn try_from(delegation: Delegation) -> Result { + let delegation_key_ids_len = delegation.key_ids.len(); + let key_ids = delegation.key_ids.into_iter().collect::>(); + + if key_ids.len() != delegation_key_ids_len { return Err(Error::Encoding("Non-unique delegation key IDs.".into())); } - metadata::Delegation::new(self.role, self.terminating, self.threshold, key_ids, paths) + let delegation_paths_len = delegation.paths.len(); + let paths = delegation.paths.into_iter().collect::>(); + + if paths.len() != delegation_paths_len { + return Err(Error::Encoding("Non-unique delegation paths.".into())); + } + + metadata::Delegation::new( + delegation.name, + delegation.terminating, + delegation.threshold, + key_ids, + paths, + ) } } @@ -427,23 +434,43 @@ impl Delegation { pub struct Delegations { #[serde(deserialize_with = "deserialize_reject_duplicates::deserialize")] keys: BTreeMap, - roles: Vec, + roles: Vec, } -impl Delegations { - pub fn from(delegations: &metadata::Delegations) -> Delegations { +impl From<&metadata::Delegations> for Delegations { + fn from(delegations: &metadata::Delegations) -> Delegations { + let mut roles = delegations + .roles() + .iter() + .map(Delegation::from) + .collect::>(); + + // We want our roles in a consistent order. + roles.sort_by(|lhs, rhs| lhs.name.cmp(&rhs.name)); + Delegations { keys: delegations .keys() .iter() .map(|(id, key)| (id.clone(), key.clone())) .collect(), - roles: delegations.roles().clone(), + roles, } } +} + +impl TryFrom for metadata::Delegations { + type Error = Error; - pub fn try_into(self) -> Result { - metadata::Delegations::new(self.keys.into_iter().collect(), self.roles) + fn try_from(delegations: Delegations) -> Result { + metadata::Delegations::new( + delegations.keys.into_iter().collect(), + delegations + .roles + .into_iter() + .map(|delegation| delegation.try_into()) + .collect::>>()?, + ) } } diff --git a/tuf/src/metadata.rs b/tuf/src/metadata.rs index e2135d6..bdbf0bf 100644 --- a/tuf/src/metadata.rs +++ b/tuf/src/metadata.rs @@ -2043,7 +2043,7 @@ impl Delegations { if roles.len() != roles .iter() - .map(|r| &r.role) + .map(|r| &r.name) .collect::>() .len() { @@ -2087,7 +2087,7 @@ impl<'de> Deserialize<'de> for Delegations { /// A delegated targets role. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Delegation { - role: MetadataPath, + name: MetadataPath, terminating: bool, threshold: u32, key_ids: HashSet, @@ -2097,7 +2097,7 @@ pub struct Delegation { impl Delegation { /// Create a new delegation. pub fn new( - role: MetadataPath, + name: MetadataPath, terminating: bool, threshold: u32, key_ids: HashSet, @@ -2122,7 +2122,7 @@ impl Delegation { } Ok(Delegation { - role, + name, terminating, threshold, key_ids, @@ -2131,8 +2131,8 @@ impl Delegation { } /// An immutable reference to the delegations's metadata path (role). - pub fn role(&self) -> &MetadataPath { - &self.role + pub fn name(&self) -> &MetadataPath { + &self.name } /// Whether or not this delegation is terminating. @@ -3002,7 +3002,7 @@ mod test { }, "roles": [ { - "role": "foo/bar", + "name": "foo/bar", "terminating": false, "threshold": 1, "keyids": ["a9f3ebc9b138762563a9c27b6edd439959e559709babd123e8d449ba2c18c61a"],