blob: 850d7eb1274958fa7f2f8df37fba5507add4a49d [file] [log] [blame]
use chrono::DateTime;
use chrono::offset::Utc;
use data_encoding::BASE64URL;
use std::collections::{HashMap, HashSet};
use Result;
use crypto;
use error::Error;
use metadata;
#[derive(Debug, Serialize, Deserialize)]
pub struct RootMetadata {
#[serde(rename = "type")]
typ: metadata::Role,
version: u32,
consistent_snapshot: bool,
expires: DateTime<Utc>,
keys: HashMap<crypto::KeyId, crypto::PublicKey>,
roles: HashMap<metadata::Role, metadata::RoleDefinition>,
}
impl RootMetadata {
pub fn from(meta: &metadata::RootMetadata) -> Result<Self> {
let mut roles = HashMap::new();
let _ = roles.insert(metadata::Role::Root, meta.root().clone());
let _ = roles.insert(metadata::Role::Snapshot, meta.snapshot().clone());
let _ = roles.insert(metadata::Role::Targets, meta.targets().clone());
let _ = roles.insert(metadata::Role::Timestamp, meta.timestamp().clone());
Ok(RootMetadata {
typ: metadata::Role::Root,
version: meta.version(),
expires: meta.expires().clone(),
consistent_snapshot: meta.consistent_snapshot(),
keys: meta.keys().clone(),
roles: roles,
})
}
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 {:?}",
self.typ
)));
}
let mut keys = Vec::new();
for (key_id, value) in self.keys.drain() {
if &key_id != value.key_id() {
warn!(
"Received key with ID {:?} but calculated it's value as {:?}. \
Refusing to add it to the set of trusted keys.",
key_id,
value.key_id()
);
} else {
debug!(
"Found key with good ID {:?}. Adding it to the set of trusted keys.",
key_id
);
keys.push(value);
}
}
let root = self.roles.remove(&metadata::Role::Root).ok_or_else(|| {
Error::Encoding("Missing root role definition".into())
})?;
let snapshot = self.roles.remove(&metadata::Role::Snapshot).ok_or_else(
|| {
Error::Encoding("Missing snapshot role definition".into())
},
)?;
let targets = self.roles.remove(&metadata::Role::Targets).ok_or_else(|| {
Error::Encoding("Missing targets role definition".into())
})?;
let timestamp = self.roles.remove(&metadata::Role::Timestamp).ok_or_else(
|| {
Error::Encoding("Missing timestamp role definition".into())
},
)?;
metadata::RootMetadata::new(
self.version,
self.expires,
self.consistent_snapshot,
keys,
root,
snapshot,
targets,
timestamp,
)
}
}
#[derive(Serialize, Deserialize)]
pub struct RoleDefinition {
threshold: u32,
key_ids: Vec<crypto::KeyId>,
}
impl RoleDefinition {
pub fn from(role: &metadata::RoleDefinition) -> Result<Self> {
let mut key_ids = role.key_ids()
.iter()
.cloned()
.collect::<Vec<crypto::KeyId>>();
key_ids.sort();
Ok(RoleDefinition {
threshold: role.threshold(),
key_ids: key_ids,
})
}
pub fn try_into(mut self) -> Result<metadata::RoleDefinition> {
let vec_len = self.key_ids.len();
if vec_len < 1 {
return Err(Error::Encoding(
"Role defined with no assoiciated key IDs.".into(),
));
}
let key_ids = self.key_ids.drain(0..).collect::<HashSet<crypto::KeyId>>();
let dupes = vec_len - key_ids.len();
if dupes != 0 {
return Err(Error::Encoding(
format!("Found {} duplicate key IDs.", dupes),
));
}
Ok(metadata::RoleDefinition::new(self.threshold, key_ids)?)
}
}
#[derive(Serialize, Deserialize)]
pub struct TimestampMetadata {
#[serde(rename = "type")]
typ: metadata::Role,
version: u32,
expires: DateTime<Utc>,
meta: HashMap<metadata::MetadataPath, metadata::MetadataDescription>,
}
impl TimestampMetadata {
pub fn from(metadata: &metadata::TimestampMetadata) -> Result<Self> {
Ok(TimestampMetadata {
typ: metadata::Role::Timestamp,
version: metadata.version(),
expires: metadata.expires().clone(),
meta: metadata.meta().clone(),
})
}
pub fn try_into(self) -> Result<metadata::TimestampMetadata> {
if self.typ != metadata::Role::Timestamp {
return Err(Error::Encoding(format!(
"Attempted to decode timestamp metdata labeled as {:?}",
self.typ
)));
}
metadata::TimestampMetadata::new(self.version, self.expires, self.meta)
}
}
#[derive(Serialize, Deserialize)]
pub struct SnapshotMetadata {
#[serde(rename = "type")]
typ: metadata::Role,
version: u32,
expires: DateTime<Utc>,
meta: HashMap<metadata::MetadataPath, metadata::MetadataDescription>,
}
impl SnapshotMetadata {
pub fn from(metadata: &metadata::SnapshotMetadata) -> Result<Self> {
Ok(SnapshotMetadata {
typ: metadata::Role::Snapshot,
version: metadata.version(),
expires: metadata.expires().clone(),
meta: metadata.meta().clone(),
})
}
pub fn try_into(self) -> Result<metadata::SnapshotMetadata> {
if self.typ != metadata::Role::Snapshot {
return Err(Error::Encoding(format!(
"Attempted to decode snapshot metdata labeled as {:?}",
self.typ
)));
}
metadata::SnapshotMetadata::new(self.version, self.expires, self.meta)
}
}
#[derive(Serialize, Deserialize)]
pub struct TargetsMetadata {
#[serde(rename = "type")]
typ: metadata::Role,
version: u32,
expires: DateTime<Utc>,
targets: HashMap<metadata::TargetPath, metadata::TargetDescription>,
}
impl TargetsMetadata {
pub fn from(metadata: &metadata::TargetsMetadata) -> Result<Self> {
Ok(TargetsMetadata {
typ: metadata::Role::Targets,
version: metadata.version(),
expires: metadata.expires().clone(),
targets: metadata.targets().clone(),
})
}
pub fn try_into(self) -> Result<metadata::TargetsMetadata> {
if self.typ != metadata::Role::Targets {
return Err(Error::Encoding(format!(
"Attempted to decode targets metdata labeled as {:?}",
self.typ
)));
}
metadata::TargetsMetadata::new(self.version, self.expires, self.targets)
}
}
#[derive(Serialize, Deserialize)]
pub struct PublicKey {
#[serde(rename = "type")]
typ: crypto::KeyType,
public_key: String,
}
impl PublicKey {
pub fn new(typ: crypto::KeyType, public_key_bytes: &[u8]) -> Self {
PublicKey {
typ: typ,
public_key: BASE64URL.encode(public_key_bytes),
}
}
pub fn public_key(&self) -> &String {
&self.public_key
}
}