diff --git a/client/src/bin/krill_admin.rs b/client/src/bin/krill_admin.rs index 1599efc9..4fa20c1d 100644 --- a/client/src/bin/krill_admin.rs +++ b/client/src/bin/krill_admin.rs @@ -1,8 +1,8 @@ extern crate krill_client; -use krill_client::KrillClient; use krill_client::options::Options; use krill_client::report::ReportFormat; +use krill_client::KrillClient; fn main() { match Options::from_args() { @@ -17,10 +17,10 @@ fn main() { ::std::process::exit(1); } } - }, + } Err(e) => { eprintln!("{}", e); ::std::process::exit(1); } } -} \ No newline at end of file +} diff --git a/client/src/client.rs b/client/src/client.rs index 6ccc0bbf..9c872a65 100644 --- a/client/src/client.rs +++ b/client/src/client.rs @@ -1,37 +1,22 @@ -use std::io; use rpki::uri; +use std::io; use serde::de::DeserializeOwned; -use krill_commons::util::file; -use krill_commons::util::httpclient; use krill_commons::api::admin::{ - ParentCaContact, - PublisherDetails, - PublisherList, - PublisherRequest, - Token, -}; -use krill_commons::api::ca::{TrustAnchorInfo}; -use krill_commons::remote::api::{ - ClientAuth, - ClientInfo, + ParentCaContact, PublisherDetails, PublisherList, PublisherRequest, Token, }; +use krill_commons::api::ca::TrustAnchorInfo; +use krill_commons::remote::api::{ClientAuth, ClientInfo}; use krill_commons::remote::rfc8183; use krill_commons::remote::rfc8183::RepositoryResponse; +use krill_commons::util::file; +use krill_commons::util::httpclient; -use crate::report::{ - ApiResponse, - ReportError -}; use crate::options::{ - Options, - CaCommand, - Command, - PublishersCommand, - Rfc8181Command, - TrustAnchorCommand + CaCommand, Command, Options, PublishersCommand, Rfc8181Command, TrustAnchorCommand, }; +use crate::report::{ApiResponse, ReportError}; /// Command line tool for Krill admin tasks pub struct KrillClient { @@ -40,7 +25,6 @@ pub struct KrillClient { } impl KrillClient { - /// Delegates the options to be processed, and reports the response /// back to the user. Note that error reporting is handled by CLI. pub fn report(options: Options) -> Result<(), Error> { @@ -58,8 +42,8 @@ impl KrillClient { /// and client. pub fn process(options: Options) -> Result { let client = KrillClient { - server: options.server, - token: options.token, + server: options.server, + token: options.token, }; match options.command { Command::Health => client.health(), @@ -67,15 +51,12 @@ impl KrillClient { Command::CertAuth(cmd) => client.certauth(cmd), Command::Publishers(cmd) => client.publishers(cmd), Command::Rfc8181(cmd) => client.rfc8181(cmd), - Command::NotSet => Err(Error::MissingCommand) + Command::NotSet => Err(Error::MissingCommand), } } fn health(&self) -> Result { - httpclient::get_ok( - &self.resolve_uri("api/v1/health"), - Some(&self.token) - )?; + httpclient::get_ok(&self.resolve_uri("api/v1/health"), Some(&self.token))?; Ok(ApiResponse::Health) } @@ -85,22 +66,21 @@ impl KrillClient { let uri = self.resolve_uri("api/v1/trustanchor"); httpclient::post_empty(&uri, Some(&self.token))?; Ok(ApiResponse::Empty) - }, + } TrustAnchorCommand::Show => { let uri = self.resolve_uri("api/v1/trustanchor"); - let ta: TrustAnchorInfo = self.get_json(&uri)?; + let ta: TrustAnchorInfo = self.get_json(&uri)?; Ok(ApiResponse::TrustAnchorInfo(ta)) - }, + } TrustAnchorCommand::Publish => { let uri = self.resolve_uri("api/v1/republish"); httpclient::post_empty(&uri, Some(&self.token))?; Ok(ApiResponse::Empty) - }, + } TrustAnchorCommand::AddChild(req) => { let uri = self.resolve_uri("api/v1/trustanchor/children"); - let info: ParentCaContact = httpclient::post_json_with_response( - &uri, req, Some(&self.token) - )?; + let info: ParentCaContact = + httpclient::post_json_with_response(&uri, req, Some(&self.token))?; Ok(ApiResponse::ParentCaInfo(info)) } } @@ -113,29 +93,25 @@ impl KrillClient { let uri = self.resolve_uri(&uri); httpclient::post_json(&uri, parent, Some(&self.token))?; Ok(ApiResponse::Empty) - }, + } CaCommand::ChildRequest(handle) => { let uri = format!("api/v1/cas/{}/child_request", handle); let uri = self.resolve_uri(&uri); - let xml = httpclient::get_text( - &uri, - "application/xml", - Some(&self.token) - )?; + let xml = httpclient::get_text(&uri, "application/xml", Some(&self.token))?; let req = rfc8183::ChildRequest::validate(xml.as_bytes())?; Ok(ApiResponse::Rfc8183ChildRequest(req)) - }, + } CaCommand::Init(init) => { let uri = self.resolve_uri("api/v1/cas"); httpclient::post_json(&uri, init, Some(&self.token))?; Ok(ApiResponse::Empty) - }, + } CaCommand::List => { let uri = self.resolve_uri("api/v1/cas"); let cas = self.get_json(&uri)?; Ok(ApiResponse::CertAuths(cas)) - }, + } CaCommand::Show(handle) => { let uri = format!("api/v1/cas/{}", handle); let uri = self.resolve_uri(&uri); @@ -146,36 +122,29 @@ impl KrillClient { } } - fn publishers( - &self, - command: PublishersCommand, - ) -> Result { + fn publishers(&self, command: PublishersCommand) -> Result { match command { PublishersCommand::List => { let list: PublisherList = self.get_json(&self.resolve_uri("api/v1/publishers"))?; Ok(ApiResponse::PublisherList(list)) - }, + } PublishersCommand::Add(add) => { - let pbl = PublisherRequest::new( - add.handle, - add.token, - add.base_uri - ); + let pbl = PublisherRequest::new(add.handle, add.token, add.base_uri); self.add_publisher(pbl) - }, + } PublishersCommand::Deactivate(handle) => { let uri = format!("api/v1/publishers/{}", handle); let uri = self.resolve_uri(&uri); httpclient::delete(&uri, Some(&self.token))?; Ok(ApiResponse::Empty) - }, + } PublishersCommand::Details(handle) => { let uri = format!("api/v1/publishers/{}", handle); let uri = self.resolve_uri(&uri); let details: PublisherDetails = self.get_json(&uri)?; Ok(ApiResponse::PublisherDetails(details)) - }, + } } } @@ -183,7 +152,7 @@ impl KrillClient { httpclient::post_json( &self.resolve_uri("api/v1/publishers"), pbl, - Some(&self.token) + Some(&self.token), )?; Ok(ApiResponse::Empty) @@ -196,7 +165,7 @@ impl KrillClient { let list: Vec = self.get_json(&uri)?; Ok(ApiResponse::Rfc8181ClientList(list)) - }, + } Rfc8181Command::RepoRes(handle) => { let uri = format!("api/v1/rfc8181/{}/response.xml", handle); let uri = self.resolve_uri(&uri); @@ -206,9 +175,8 @@ impl KrillClient { let res = RepositoryResponse::validate(xml.as_bytes())?; Ok(ApiResponse::Rfc8183RepositoryResponse(res)) - }, + } Rfc8181Command::Add(details) => { - let xml = file::read(&details.xml)?; let pr = rfc8183::PublisherRequest::validate(xml.as_ref())?; @@ -222,7 +190,7 @@ impl KrillClient { httpclient::post_json( &self.resolve_uri("api/v1/rfc8181/clients"), info, - Some(&self.token) + Some(&self.token), )?; Ok(ApiResponse::Empty) @@ -234,14 +202,8 @@ impl KrillClient { format!("{}{}", &self.server, path) } - fn get_json( - &self, - uri: &str, - ) -> Result { - httpclient::get_json( - &uri, - Some(&self.token) - ).map_err(Error::HttpClientError) + fn get_json(&self, uri: &str) -> Result { + httpclient::get_json(&uri, Some(&self.token)).map_err(Error::HttpClientError) } } @@ -249,30 +211,32 @@ impl KrillClient { #[derive(Debug, Display)] pub enum Error { - #[display(fmt="No valid command given, see --help")] + #[display(fmt = "No valid command given, see --help")] MissingCommand, - #[display(fmt="Server is not available.")] + #[display(fmt = "Server is not available.")] ServerDown, - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] HttpClientError(httpclient::Error), - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] ReportError(ReportError), - #[display(fmt="Can't read file: {}", _0)] + #[display(fmt = "Can't read file: {}", _0)] IoError(io::Error), - #[display(fmt="Empty response received from server")] + #[display(fmt = "Empty response received from server")] EmptyResponse, - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] Rfc8183(rfc8183::Error), } impl From for Error { - fn from(e: httpclient::Error) -> Self { Error::HttpClientError(e) } + fn from(e: httpclient::Error) -> Self { + Error::HttpClientError(e) + } } impl From for Error { @@ -291,4 +255,4 @@ impl From for Error { fn from(e: rfc8183::Error) -> Error { Error::Rfc8183(e) } -} \ No newline at end of file +} diff --git a/client/src/lib.rs b/client/src/lib.rs index 4b42f5bc..601ec9ca 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -1,5 +1,6 @@ extern crate clap; -#[macro_use] extern crate derive_more; +#[macro_use] +extern crate derive_more; extern crate krill_commons; extern crate rpki; extern crate serde; @@ -8,5 +9,5 @@ pub mod options; pub mod report; mod client; -pub use client::KrillClient; pub use client::Error; +pub use client::KrillClient; diff --git a/client/src/options.rs b/client/src/options.rs index 53cbb6fc..ee27fb72 100644 --- a/client/src/options.rs +++ b/client/src/options.rs @@ -1,17 +1,17 @@ -use std::path::PathBuf; -use std::str::FromStr; use clap::{App, Arg, SubCommand}; use rpki::uri; +use std::path::PathBuf; +use std::str::FromStr; -use krill_commons::api::admin::{AddChildRequest, CertAuthInit, CertAuthPubMode, Handle, AddParentRequest, ParentCaContact, Token, ChildAuthRequest}; +use krill_commons::api::admin::{ + AddChildRequest, AddParentRequest, CertAuthInit, CertAuthPubMode, ChildAuthRequest, Handle, + ParentCaContact, Token, +}; use krill_commons::api::ca::ResourceSet; -use crate::report::{ - ReportFormat, - ReportError -}; -use krill_commons::util::file; +use crate::report::{ReportError, ReportFormat}; use krill_commons::remote::rfc8183; +use krill_commons::util::file; use std::io; /// This type holds all the necessary data to connect to a Krill daemon, and @@ -22,7 +22,7 @@ pub struct Options { pub server: uri::Https, pub token: Token, pub format: ReportFormat, - pub command: Command + pub command: Command, } impl Options { @@ -31,13 +31,13 @@ impl Options { } /// Creates a new Options explicitly (useful for testing) - pub fn new( - server: uri::Https, - token: &str, - format: ReportFormat, - command: Command - ) -> Self { - Options { server, token: Token::from(token), format, command } + pub fn new(server: uri::Https, token: &str, format: ReportFormat, command: Command) -> Self { + Options { + server, + token: Token::from(token), + format, + command, + } } /// Creates a new Options from command line args (useful for cli) @@ -344,7 +344,6 @@ impl Options { } if let Some(m) = m.subcommand_matches("children") { if let Some(m) = m.subcommand_matches("add") { - let asn = m.value_of("asn").unwrap_or(""); let ipv4 = m.value_of("ipv4").unwrap_or(""); let ipv6 = m.value_of("ipv6").unwrap_or(""); @@ -356,9 +355,7 @@ impl Options { let auth = ChildAuthRequest::Embedded(token); - let req = AddChildRequest::new( - handle, res, auth - ); + let req = AddChildRequest::new(handle, res, auth); command = Command::TrustAnchor(TrustAnchorCommand::AddChild(req)) } @@ -380,16 +377,11 @@ impl Options { let auth = ChildAuthRequest::Rfc8183(cr); - let req = AddChildRequest::new( - handle, res, auth - ); + let req = AddChildRequest::new(handle, res, auth); command = Command::TrustAnchor(TrustAnchorCommand::AddChild(req)) } - - } } - } if let Some(m) = matches.subcommand_matches("cas") { @@ -421,13 +413,11 @@ impl Options { if let Some(m) = m.subcommand_matches("embedded") { let token = Token::from(m.value_of("token").unwrap()); - let contact = ParentCaContact::Embedded(parent.clone(), - token); + let contact = ParentCaContact::Embedded(parent.clone(), token); let req = AddParentRequest::new(parent, contact); - command = Command::CertAuth( - CaCommand::AddParent(handle, req)) + command = Command::CertAuth(CaCommand::AddParent(handle, req)) } else if let Some(m) = m.subcommand_matches("rfc6492") { let xml_path = m.value_of("xml").unwrap(); let xml = PathBuf::from(xml_path); @@ -437,13 +427,8 @@ impl Options { let contact = ParentCaContact::Rfc6492(pr); let req = AddParentRequest::new(parent, contact); - command = Command::CertAuth( - CaCommand::AddParent(handle, req) - ) - + command = Command::CertAuth(CaCommand::AddParent(handle, req)) } - - } } } @@ -457,10 +442,12 @@ impl Options { let base_uri = uri::Rsync::from_str(m.value_of("uri").unwrap())?; let token = Token::from(m.value_of("token").unwrap()); - let add = AddPublisher { handle, base_uri, token }; - command = Command::Publishers( - PublishersCommand::Add(add) - ); + let add = AddPublisher { + handle, + base_uri, + token, + }; + command = Command::Publishers(PublishersCommand::Add(add)); } if let Some(m) = m.subcommand_matches("details") { let handle = m.value_of("handle").unwrap(); @@ -481,15 +468,12 @@ impl Options { let xml_path = m.value_of("xml").unwrap(); let xml = PathBuf::from(xml_path); - command = Command::Rfc8181( - Rfc8181Command::Add(AddRfc8181Client{ xml }) - ) + command = Command::Rfc8181(Rfc8181Command::Add(AddRfc8181Client { xml })) } if let Some(m) = m.subcommand_matches("repo-res") { - let handle = Handle::from(m.value_of("handle").unwrap()); + let handle = Handle::from(m.value_of("handle").unwrap()); command = Command::Rfc8181(Rfc8181Command::RepoRes(handle)); } - } let server = matches.value_of("server").unwrap(); // required @@ -502,7 +486,12 @@ impl Options { format = ReportFormat::from_str(fmt)?; } - Ok(Options { server, token, format, command }) + Ok(Options { + server, + token, + format, + command, + }) } } @@ -514,7 +503,7 @@ pub enum Command { TrustAnchor(TrustAnchorCommand), CertAuth(CaCommand), Publishers(PublishersCommand), - Rfc8181(Rfc8181Command) + Rfc8181(Rfc8181Command), } #[derive(Clone, Debug, Eq, PartialEq)] @@ -523,7 +512,7 @@ pub enum TrustAnchorCommand { Init, Show, Publish, - AddChild(AddChildRequest) + AddChild(AddChildRequest), } #[derive(Clone, Debug, Eq, PartialEq)] @@ -536,48 +525,47 @@ pub enum CaCommand { Show(Handle), } - #[derive(Clone, Debug, Eq, PartialEq)] pub enum PublishersCommand { Add(AddPublisher), Details(String), Deactivate(String), - List + List, } #[derive(Clone, Debug, Eq, PartialEq)] pub struct AddPublisher { - pub handle: Handle, + pub handle: Handle, pub base_uri: uri::Rsync, - pub token: Token + pub token: Token, } #[derive(Clone, Debug, Eq, PartialEq)] pub enum Rfc8181Command { List, Add(AddRfc8181Client), - RepoRes(Handle) + RepoRes(Handle), } #[derive(Clone, Debug, Eq, PartialEq)] pub struct AddRfc8181Client { - pub xml: PathBuf + pub xml: PathBuf, } //------------ Error --------------------------------------------------------- #[derive(Debug, Display)] pub enum Error { - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] UriError(uri::Error), - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] IoError(io::Error), - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] ReportError(ReportError), - #[display(fmt="Invalid RFC8183 XML: {}", _0)] + #[display(fmt = "Invalid RFC8183 XML: {}", _0)] Rfc8183(rfc8183::Error), } @@ -603,4 +591,4 @@ impl From for Error { fn from(e: ReportError) -> Self { Error::ReportError(e) } -} \ No newline at end of file +} diff --git a/client/src/report.rs b/client/src/report.rs index 7cdb41f6..5ceeb58a 100644 --- a/client/src/report.rs +++ b/client/src/report.rs @@ -1,10 +1,11 @@ -use std::str::{FromStr, from_utf8_unchecked}; -use krill_commons::api::admin::{PublisherDetails, PublisherList, ParentCaContact}; -use krill_commons::api::ca::{TrustAnchorInfo, CertAuthList, CertAuthInfo, CaParentsInfo, CurrentObjects}; +use krill_commons::api::admin::{ParentCaContact, PublisherDetails, PublisherList}; +use krill_commons::api::ca::{ + CaParentsInfo, CertAuthInfo, CertAuthList, CurrentObjects, TrustAnchorInfo, +}; use krill_commons::remote::api::ClientInfo; -use krill_commons::remote::rfc8183::RepositoryResponse; use krill_commons::remote::rfc8183; - +use krill_commons::remote::rfc8183::RepositoryResponse; +use std::str::{from_utf8_unchecked, FromStr}; //------------ ApiResponse --------------------------------------------------- @@ -28,15 +29,12 @@ pub enum ApiResponse { Rfc8183RepositoryResponse(rfc8183::RepositoryResponse), Rfc8183ChildRequest(rfc8183::ChildRequest), - Empty, // Typically a successful post just gets an empty 200 response - GenericBody(String) // For when the server echos Json to a successful post + Empty, // Typically a successful post just gets an empty 200 response + GenericBody(String), // For when the server echos Json to a successful post } impl ApiResponse { - pub fn report( - &self, - fmt: ReportFormat - ) -> Result, ReportError> { + pub fn report(&self, fmt: ReportFormat) -> Result, ReportError> { if fmt == ReportFormat::None { Ok(None) } else { @@ -47,38 +45,18 @@ impl ApiResponse { } else { Err(ReportError::UnsupportedFormat) } - }, - ApiResponse::TrustAnchorInfo(ta) => { - Ok(Some(ta.report(fmt)?)) - }, - ApiResponse::CertAuths(list) => { - Ok(Some(list.report(fmt)?)) - }, - ApiResponse::CertAuthInfo(info) => { - Ok(Some(info.report(fmt)?)) - }, - ApiResponse::ParentCaInfo(info) => { - Ok(Some(info.report(fmt)?)) - }, - ApiResponse::PublisherList(list) => { - Ok(Some(list.report(fmt)?)) - }, - ApiResponse::PublisherDetails(details) => { - Ok(Some(details.report(fmt)?)) } - ApiResponse::Rfc8181ClientList(list) => { - Ok(Some(list.report(fmt)?)) - } - ApiResponse::Rfc8183ChildRequest(req) => { - Ok(Some(req.report(fmt)?)) - } - ApiResponse::Rfc8183RepositoryResponse(res) => { - Ok(Some(res.report(fmt)?)) - } - ApiResponse::GenericBody(body) => { - Ok(Some(body.clone())) - } - ApiResponse::Empty => Ok(None) + ApiResponse::TrustAnchorInfo(ta) => Ok(Some(ta.report(fmt)?)), + ApiResponse::CertAuths(list) => Ok(Some(list.report(fmt)?)), + ApiResponse::CertAuthInfo(info) => Ok(Some(info.report(fmt)?)), + ApiResponse::ParentCaInfo(info) => Ok(Some(info.report(fmt)?)), + ApiResponse::PublisherList(list) => Ok(Some(list.report(fmt)?)), + ApiResponse::PublisherDetails(details) => Ok(Some(details.report(fmt)?)), + ApiResponse::Rfc8181ClientList(list) => Ok(Some(list.report(fmt)?)), + ApiResponse::Rfc8183ChildRequest(req) => Ok(Some(req.report(fmt)?)), + ApiResponse::Rfc8183RepositoryResponse(res) => Ok(Some(res.report(fmt)?)), + ApiResponse::GenericBody(body) => Ok(Some(body.clone())), + ApiResponse::Empty => Ok(None), } } } @@ -93,7 +71,7 @@ pub enum ReportFormat { None, Json, Text, - Xml + Xml, } impl FromStr for ReportFormat { @@ -104,26 +82,24 @@ impl FromStr for ReportFormat { "none" => Ok(ReportFormat::None), "json" => Ok(ReportFormat::Json), "text" => Ok(ReportFormat::Text), - "xml" => Ok(ReportFormat::Xml), - _ => Err(ReportError::UnrecognisedFormat(s.to_string())) + "xml" => Ok(ReportFormat::Xml), + _ => Err(ReportError::UnrecognisedFormat(s.to_string())), } } } - //------------ ReportError --------------------------------------------------- /// This type defines possible Errors for KeyStore #[derive(Debug, Display)] pub enum ReportError { - #[display(fmt="This report format is not supported for this data")] + #[display(fmt = "This report format is not supported for this data")] UnsupportedFormat, - #[display(fmt="This report format is not recognised: {}", _0)] - UnrecognisedFormat(String) + #[display(fmt = "This report format is not recognised: {}", _0)] + UnrecognisedFormat(String), } - //------------ Report -------------------------------------------------------- /// This trait should be implemented by all api responses, so that the @@ -137,7 +113,7 @@ impl Report for TrustAnchorInfo { match format { ReportFormat::Default | ReportFormat::Json => { Ok(serde_json::to_string_pretty(self).unwrap()) - }, + } ReportFormat::Text => { let mut res = String::new(); @@ -168,16 +144,14 @@ impl Report for TrustAnchorInfo { res.push_str(&format!(" v6: {}\n", inrs.v6())); res.push_str("\n"); } - } } else { res.push_str(""); } - Ok(res) - }, - _ => Err(ReportError::UnsupportedFormat) + } + _ => Err(ReportError::UnsupportedFormat), } } } @@ -187,7 +161,7 @@ impl Report for CertAuthList { match format { ReportFormat::Default | ReportFormat::Json => { Ok(serde_json::to_string_pretty(self).unwrap()) - }, + } ReportFormat::Text => { let mut res = String::new(); for ca in self.cas() { @@ -195,8 +169,8 @@ impl Report for CertAuthList { } Ok(res) - }, - _ => Err(ReportError::UnsupportedFormat) + } + _ => Err(ReportError::UnsupportedFormat), } } } @@ -206,7 +180,7 @@ impl Report for CertAuthInfo { match format { ReportFormat::Default | ReportFormat::Json => { Ok(serde_json::to_string_pretty(self).unwrap()) - }, + } ReportFormat::Text => { let mut res = String::new(); @@ -236,7 +210,6 @@ impl Report for CertAuthInfo { res.push_str(&format!("IPv4: {}\n", inrs.v4())); res.push_str(&format!("IPv6: {}\n", inrs.v6())); - res.push_str("Current objects:\n"); print_objects(&mut res, key.current_set().objects()); res.push_str("\n"); @@ -254,7 +227,6 @@ impl Report for CertAuthInfo { res.push_str(&format!(" v6: {}\n", inrs.v6())); res.push_str("\n"); } - } } else { res.push_str(""); @@ -262,7 +234,7 @@ impl Report for CertAuthInfo { res.push_str("TAL:\n"); res.push_str(&format!("{}\n", tal)); - }, + } CaParentsInfo::Parents(map) => { for info in map.values() { res.push_str(&format!("Parent: {}\n", info.contact())); @@ -296,14 +268,13 @@ impl Report for CertAuthInfo { res.push_str(" OLD unrevoked key exists!\n"); res.push_str("\n"); } - } } } } Ok(res) - }, - _ => Err(ReportError::UnsupportedFormat) + } + _ => Err(ReportError::UnsupportedFormat), } } } @@ -313,11 +284,9 @@ impl Report for ParentCaContact { match format { ReportFormat::Default | ReportFormat::Json => { Ok(serde_json::to_string_pretty(self).unwrap()) - }, - ReportFormat::Text => { - Ok(self.to_string()) - }, - _ => Err(ReportError::UnsupportedFormat) + } + ReportFormat::Text => Ok(self.to_string()), + _ => Err(ReportError::UnsupportedFormat), } } } @@ -327,14 +296,14 @@ impl Report for PublisherList { match format { ReportFormat::Default | ReportFormat::Json => { Ok(serde_json::to_string_pretty(self).unwrap()) - }, + } ReportFormat::Text => { let mut res = String::new(); res.push_str("Publishers: "); let mut first = true; for p in self.publishers() { - if ! first { + if !first { res.push_str(", "); } else { first = false; @@ -342,8 +311,8 @@ impl Report for PublisherList { res.push_str(p.id()); } Ok(res) - }, - _ => Err(ReportError::UnsupportedFormat) + } + _ => Err(ReportError::UnsupportedFormat), } } } @@ -353,9 +322,8 @@ impl Report for PublisherDetails { match format { ReportFormat::Default | ReportFormat::Json => { Ok(serde_json::to_string_pretty(self).unwrap()) - }, + } ReportFormat::Text => { - let mut res = String::new(); res.push_str("handle: "); @@ -367,8 +335,8 @@ impl Report for PublisherDetails { res.push_str("\n"); Ok(res) - }, - _ => Err(ReportError::UnsupportedFormat) + } + _ => Err(ReportError::UnsupportedFormat), } } } @@ -378,7 +346,7 @@ impl Report for Vec { match format { ReportFormat::Default | ReportFormat::Json => { Ok(serde_json::to_string_pretty(self).unwrap()) - }, + } ReportFormat::Text => { let mut res = String::new(); @@ -388,13 +356,11 @@ impl Report for Vec { let auth = client.auth(); let ski = auth.cert().ski_hex(); - res.push_str( - &format!(" Handle: {}, Cert (ski): {}\n", handle, ski) - ); + res.push_str(&format!(" Handle: {}, Cert (ski): {}\n", handle, ski)); } Ok(res) - }, - _ => Err(ReportError::UnsupportedFormat) + } + _ => Err(ReportError::UnsupportedFormat), } } } @@ -404,13 +370,11 @@ impl Report for RepositoryResponse { match format { ReportFormat::Text | ReportFormat::Xml | ReportFormat::Default => { let bytes = self.encode_vec(); - let xml = unsafe { - from_utf8_unchecked(&bytes) - }; + let xml = unsafe { from_utf8_unchecked(&bytes) }; Ok(xml.to_string()) - }, - _ => Err(ReportError::UnsupportedFormat) + } + _ => Err(ReportError::UnsupportedFormat), } } } @@ -420,13 +384,11 @@ impl Report for rfc8183::ChildRequest { match format { ReportFormat::Text | ReportFormat::Xml | ReportFormat::Default => { let bytes = self.encode_vec(); - let xml = unsafe { - from_utf8_unchecked(&bytes) - }; + let xml = unsafe { from_utf8_unchecked(&bytes) }; Ok(xml.to_string()) - }, - _ => Err(ReportError::UnsupportedFormat) + } + _ => Err(ReportError::UnsupportedFormat), } } -} \ No newline at end of file +} diff --git a/commons/src/api/admin.rs b/commons/src/api/admin.rs index ac64e886..c68043be 100644 --- a/commons/src/api/admin.rs +++ b/commons/src/api/admin.rs @@ -2,15 +2,14 @@ use std::fmt; -use rpki::uri; use rpki::crypto::Signer; +use rpki::uri; use crate::api::Link; -use std::path::Path; use api::ca::ResourceSet; use remote::rfc8183; use remote::rfc8183::{ChildRequest, ServiceUri}; - +use std::path::Path; //------------ Handle -------------------------------------------------------- @@ -59,7 +58,6 @@ impl fmt::Display for Handle { } } - //------------ Token ------------------------------------------------------ #[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] @@ -98,24 +96,19 @@ impl fmt::Display for Token { } } - //------------ PublisherRequest ---------------------------------------------- /// This type defines request for a new Publisher (CA that is allowed to /// publish). #[derive(Clone, Debug, Deserialize, Serialize)] pub struct PublisherRequest { - handle: Handle, - token: Token, + handle: Handle, + token: Token, base_uri: uri::Rsync, } impl PublisherRequest { - pub fn new( - handle: Handle, - token: Token, - base_uri: uri::Rsync, - ) -> Self { + pub fn new(handle: Handle, token: Token, base_uri: uri::Rsync) -> Self { PublisherRequest { handle, token, @@ -145,14 +138,12 @@ impl PublisherRequest { impl PartialEq for PublisherRequest { fn eq(&self, other: &PublisherRequest) -> bool { - self.handle == other.handle && - self.base_uri == other.base_uri + self.handle == other.handle && self.base_uri == other.base_uri } } impl Eq for PublisherRequest {} - //------------ PublisherSummaryInfo ------------------------------------------ /// Defines a summary of publisher information to be used in the publisher @@ -160,51 +151,45 @@ impl Eq for PublisherRequest {} #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct PublisherSummary { id: String, - links: Vec + links: Vec, } impl PublisherSummary { - pub fn from( - handle: &Handle, - path_publishers: &str - ) -> PublisherSummary { + pub fn from(handle: &Handle, path_publishers: &str) -> PublisherSummary { let mut links = Vec::new(); let self_link = Link { rel: "self".to_string(), - link: format!("{}/{}", path_publishers, handle) + link: format!("{}/{}", path_publishers, handle), }; links.push(self_link); PublisherSummary { id: handle.to_string(), - links + links, } } - pub fn id(&self) -> &str { &self.id } + pub fn id(&self) -> &str { + &self.id + } } - //------------ PublisherList ------------------------------------------------- /// This type represents a list of (all) current publishers to show in the API #[derive(Clone, Eq, Debug, Deserialize, PartialEq, Serialize)] pub struct PublisherList { - publishers: Vec + publishers: Vec, } impl PublisherList { - pub fn build( - publishers: &[Handle], - path_publishers: &str - ) -> PublisherList { - let publishers: Vec = publishers.iter().map(|p| - PublisherSummary::from(&p, path_publishers) - ).collect(); + pub fn build(publishers: &[Handle], path_publishers: &str) -> PublisherList { + let publishers: Vec = publishers + .iter() + .map(|p| PublisherSummary::from(&p, path_publishers)) + .collect(); - PublisherList { - publishers - } + PublisherList { publishers } } pub fn publishers(&self) -> &Vec { @@ -212,7 +197,6 @@ impl PublisherList { } } - //------------ PublisherDetails ---------------------------------------------- /// This type defines the publisher details for: @@ -229,57 +213,64 @@ impl PublisherDetails { PublisherDetails { handle: handle.to_string(), deactivated, - base_uri: base_uri.clone() + base_uri: base_uri.clone(), } } - pub fn handle(&self) -> &str { &self.handle } - pub fn deactivated(&self) -> bool { self.deactivated } - pub fn base_uri(&self) -> &uri::Rsync { &self.base_uri } + pub fn handle(&self) -> &str { + &self.handle + } + pub fn deactivated(&self) -> bool { + self.deactivated + } + pub fn base_uri(&self) -> &uri::Rsync { + &self.base_uri + } } impl PartialEq for PublisherDetails { fn eq(&self, other: &PublisherDetails) -> bool { match (serde_json::to_string(self), serde_json::to_string(other)) { (Ok(ser_self), Ok(ser_other)) => ser_self == ser_other, - _ => false + _ => false, } } } impl Eq for PublisherDetails {} - - //------------ PublisherClientRequest ---------------------------------------- /// This type defines request for a new Publisher client, i.e. the proxy that /// is used by an embedded CA to do the actual publication. #[derive(Clone, Debug, Deserialize, Serialize)] pub struct PublisherClientRequest { - handle: Handle, - server_info: PubServerContact + handle: Handle, + server_info: PubServerContact, } impl PublisherClientRequest { pub fn new(handle: Handle, server_info: PubServerContact) -> Self { - PublisherClientRequest { handle, server_info } + PublisherClientRequest { + handle, + server_info, + } } - pub fn embedded( - handle: Handle - ) -> Self { + pub fn embedded(handle: Handle) -> Self { let server_info = PubServerContact::embedded(); - PublisherClientRequest { handle, server_info } + PublisherClientRequest { + handle, + server_info, + } } - pub fn krill( - handle: Handle, - service_uri: uri::Https, - token: Token - ) -> Self { + pub fn krill(handle: Handle, service_uri: uri::Https, token: Token) -> Self { let server_info = PubServerContact::for_krill(service_uri, token); - PublisherClientRequest { handle, server_info } + PublisherClientRequest { + handle, + server_info, + } } pub fn unwrap(self) -> (Handle, PubServerContact) { @@ -287,7 +278,6 @@ impl PublisherClientRequest { } } - //------------ PubServerInfo ------------------------------------------------- #[derive(Clone, Debug, Deserialize, Display, Serialize)] @@ -296,7 +286,7 @@ pub enum PubServerContact { Embedded, #[display(fmt = "Remote Krill at: {}, using token: {}", _0, _1)] - KrillServer(uri::Https, Token) + KrillServer(uri::Https, Token), } impl PubServerContact { @@ -309,21 +299,17 @@ impl PubServerContact { } } - //------------ ParentCaReq --------------------------------------------------- /// This type defines all parent ca details needed to add a parent to a CA #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct AddParentRequest { handle: Handle, // the local name the child gave to the parent - contact: ParentCaContact // where the parent can be contacted + contact: ParentCaContact, // where the parent can be contacted } impl AddParentRequest { - pub fn new( - handle: Handle, - contact: ParentCaContact - ) -> Self { + pub fn new(handle: Handle, contact: ParentCaContact) -> Self { AddParentRequest { handle, contact } } @@ -346,7 +332,7 @@ pub enum ParentCaContact { Embedded(Handle, Token), #[display(fmt = "RFC 6492 Parent")] - Rfc6492(rfc8183::ParentResponse) + Rfc6492(rfc8183::ParentResponse), } impl ParentCaContact { @@ -363,52 +349,50 @@ impl ParentCaContact { } } - //------------ CertAuthInit -------------------------------------------------- #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct CertAuthInit { - handle: Handle, - token: Token, - pub_mode: CertAuthPubMode + handle: Handle, + token: Token, + pub_mode: CertAuthPubMode, } impl CertAuthInit { - pub fn new( - handle: Handle, - token: Token, - pub_mode: CertAuthPubMode - ) -> Self { - CertAuthInit { handle, token, pub_mode } + pub fn new(handle: Handle, token: Token, pub_mode: CertAuthPubMode) -> Self { + CertAuthInit { + handle, + token, + pub_mode, + } } pub fn unwrap(self) -> (Handle, Token, CertAuthPubMode) { - ( self.handle, self.token, self.pub_mode ) + (self.handle, self.token, self.pub_mode) } } #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub enum CertAuthPubMode { - Embedded + Embedded, } - //------------ AddChildRequest ----------------------------------------------- #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct AddChildRequest { handle: Handle, resources: ResourceSet, - auth: ChildAuthRequest + auth: ChildAuthRequest, } impl AddChildRequest { - pub fn new( - handle: Handle, - resources: ResourceSet, - auth: ChildAuthRequest - ) -> Self { - AddChildRequest { handle, resources, auth } + pub fn new(handle: Handle, resources: ResourceSet, auth: ChildAuthRequest) -> Self { + AddChildRequest { + handle, + resources, + auth, + } } pub fn unwrap(self) -> (Handle, ResourceSet, ChildAuthRequest) { @@ -421,7 +405,5 @@ impl AddChildRequest { pub enum ChildAuthRequest { Embedded(Token), Remote(Token), - Rfc8183(ChildRequest) + Rfc8183(ChildRequest), } - - diff --git a/commons/src/api/ca.rs b/commons/src/api/ca.rs index 103b74a2..f6586cc7 100644 --- a/commons/src/api/ca.rs +++ b/commons/src/api/ca.rs @@ -11,45 +11,22 @@ use bytes::Bytes; use chrono::Duration; use rpki::cert::{Cert, Overclaim}; -use rpki::crypto::{PublicKey, KeyIdentifier}; -use rpki::resources::{ - AsBlocks, - AsResources, - IpBlocks, - IpResources, - Ipv4Resources, - Ipv6Resources, -}; +use rpki::crypto::{KeyIdentifier, PublicKey}; +use rpki::resources::{AsBlocks, AsResources, IpBlocks, IpResources, Ipv4Resources, Ipv6Resources}; use rpki::uri; -use rpki::x509::{ - Serial, - Time, -}; +use rpki::x509::{Serial, Time}; -use crate::api::{ - Base64, - EncodedHash, -}; -use crate::api::admin::{ - Handle, - Token -}; +use crate::api::admin::{Handle, Token}; use crate::api::publication; +use crate::api::{Base64, EncodedHash}; +use crate::rpki::crl::{Crl, CrlEntry}; +use crate::rpki::manifest::{FileAndHash, Manifest}; use crate::util::ext_serde; use crate::util::softsigner::SignerKeyId; -use crate::rpki::crl::{ - Crl, - CrlEntry, -}; -use crate::rpki::manifest::{ - FileAndHash, - Manifest, -}; use api::admin::ParentCaContact; -use api::{RequestResourceLimit, IssuanceRequest}; +use api::{IssuanceRequest, RequestResourceLimit}; use remote::id::IdCert; - //------------ ChildCa ------------------------------------------------------- /// This type defines a Child Certificate Authority under a parent @@ -57,7 +34,7 @@ use remote::id::IdCert; #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct ChildCa { handle: Handle, - details: ChildCaDetails + details: ChildCaDetails, } impl ChildCa { @@ -65,11 +42,7 @@ impl ChildCa { ChildCa { handle, details } } - pub fn without_resources( - handle: Handle, - token: Token, - id_cert: Option - ) -> Self { + pub fn without_resources(handle: Handle, token: Token, id_cert: Option) -> Self { let details = ChildCaDetails::new(token, id_cert); ChildCa { handle, details } } @@ -87,27 +60,34 @@ impl ChildCa { } pub fn unwrap(self) -> (Handle, ChildCaDetails) { - (self.handle, self.details ) + (self.handle, self.details) } } - //------------ ChildCaDetails ------------------------------------------------ #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct ChildCaDetails { token: Token, id_cert: Option, - resources: HashMap + resources: HashMap, } impl ChildCaDetails { pub fn new(token: Token, id_cert: Option) -> Self { - ChildCaDetails { token, id_cert, resources: HashMap::new() } + ChildCaDetails { + token, + id_cert, + resources: HashMap::new(), + } } - pub fn token(&self) -> &Token { &self.token } - pub fn id_cert(&self) -> Option<&IdCert> { self.id_cert.as_ref() } + pub fn token(&self) -> &Token { + &self.token + } + pub fn id_cert(&self) -> Option<&IdCert> { + self.id_cert.as_ref() + } pub fn resources(&self) -> &HashMap { &self.resources @@ -118,10 +98,8 @@ impl ChildCaDetails { } pub fn add_resources(&mut self, name: &str, resources: ResourceSet) { - self.resources.insert( - name.to_string(), - ChildResources::new(resources) - ); + self.resources + .insert(name.to_string(), ChildResources::new(resources)); } pub fn add_cert(&mut self, class_name: &str, cert: IssuedCert) { @@ -129,7 +107,6 @@ impl ChildCaDetails { // been issued to it. So, it's safe to unwrap here. self.resources.get_mut(class_name).unwrap().add_cert(cert) } - } /// This type defines a reference to PublicKey for easy storage and lookup. @@ -139,9 +116,7 @@ pub struct KeyRef(String); impl From<&KeyIdentifier> for KeyRef { fn from(ki: &KeyIdentifier) -> Self { let hex = ki.into_hex(); - let s = unsafe { - str::from_utf8_unchecked(&hex) - }; + let s = unsafe { str::from_utf8_unchecked(&hex) }; KeyRef(s.to_string()) } } @@ -152,7 +127,6 @@ impl From<&Cert> for KeyRef { } } - //------------ ChildResources ------------------------------------------------ /// This type defines the resource entitlements for a child CA within @@ -164,20 +138,21 @@ impl From<&Cert> for KeyRef { pub struct ChildResources { resources: ResourceSet, not_after: Time, - certs: HashMap + certs: HashMap, } impl ChildResources { - pub fn new(resources: ResourceSet) -> Self { ChildResources { resources, not_after: Time::next_year(), - certs: HashMap::new() + certs: HashMap::new(), } } - pub fn resources(&self) -> &ResourceSet { &self.resources } + pub fn resources(&self) -> &ResourceSet { + &self.resources + } /// Give back the not_after time that would be used on newly /// issued certificates. See `resource_set_notafter` in @@ -196,7 +171,7 @@ impl ChildResources { } } - pub fn certs(&self) -> impl Iterator { + pub fn certs(&self) -> impl Iterator { self.certs.values() } @@ -212,10 +187,8 @@ impl ChildResources { self.resources = ResourceSet::from(cert.cert()); self.certs.insert(key_ref, cert); } - } - //------------ IssuedCert ---------------------------------------------------- /// This type defines an issued certificate, including its publication @@ -230,10 +203,10 @@ impl ChildResources { // of the stored json structures. #[derive(Clone, Debug, Deserialize, Serialize)] pub struct IssuedCert { - uri: uri::Rsync, // where this cert is published + uri: uri::Rsync, // where this cert is published limit: RequestResourceLimit, // the limit on the request resource_set: ResourceSet, - cert: Cert + cert: Cert, } impl IssuedCert { @@ -241,33 +214,45 @@ impl IssuedCert { uri: uri::Rsync, limit: RequestResourceLimit, resource_set: ResourceSet, - cert: Cert + cert: Cert, ) -> Self { - IssuedCert { uri, limit, resource_set, cert } + IssuedCert { + uri, + limit, + resource_set, + cert, + } } pub fn unwrap(self) -> (uri::Rsync, RequestResourceLimit, ResourceSet, Cert) { (self.uri, self.limit, self.resource_set, self.cert) } - pub fn uri(&self) -> &uri::Rsync { &self.uri } - pub fn limit(&self) -> &RequestResourceLimit { &self.limit } - pub fn resource_set(&self) -> &ResourceSet { &self.resource_set } - pub fn cert(&self) -> &Cert { &self.cert } + pub fn uri(&self) -> &uri::Rsync { + &self.uri + } + pub fn limit(&self) -> &RequestResourceLimit { + &self.limit + } + pub fn resource_set(&self) -> &ResourceSet { + &self.resource_set + } + pub fn cert(&self) -> &Cert { + &self.cert + } } impl PartialEq for IssuedCert { fn eq(&self, other: &IssuedCert) -> bool { - self.uri == other.uri && - self.limit == other.limit && - self.resource_set == other.resource_set && - self.cert.to_captured().as_slice() == other.cert.to_captured().as_slice() + self.uri == other.uri + && self.limit == other.limit + && self.resource_set == other.resource_set + && self.cert.to_captured().as_slice() == other.cert.to_captured().as_slice() } } impl Eq for IssuedCert {} - //------------ RcvdCert ------------------------------------------------------ /// Contains a CA Certificate that has been issued to this CA, for some key. @@ -277,22 +262,27 @@ impl Eq for IssuedCert {} pub struct RcvdCert { cert: Cert, uri: uri::Rsync, - resources: ResourceSet + resources: ResourceSet, } impl RcvdCert { - pub fn new(cert: Cert, uri: uri::Rsync) -> Self { let resources = ResourceSet::from(&cert); - RcvdCert { cert, uri, resources } + RcvdCert { + cert, + uri, + resources, + } } - pub fn cert(&self) -> &Cert { &self.cert } - pub fn uri(&self) -> &uri::Rsync { &self.uri } + pub fn cert(&self) -> &Cert { + &self.cert + } + pub fn uri(&self) -> &uri::Rsync { + &self.uri + } pub fn crl_uri(&self) -> uri::Rsync { - self.uri_for_object( - ObjectName::new(&self.cert.subject_key_identifier(), "crl") - ) + self.uri_for_object(ObjectName::new(&self.cert.subject_key_identifier(), "crl")) } pub fn uri_for_object(&self, name: impl Into) -> uri::Rsync { @@ -300,7 +290,9 @@ impl RcvdCert { self.cert.ca_repository().unwrap().join(name.as_bytes()) } - pub fn resources(&self) -> &ResourceSet { &self.resources } + pub fn resources(&self) -> &ResourceSet { + &self.resources + } pub fn der_encoded(&self) -> Bytes { self.cert.to_captured().into_bytes() @@ -312,7 +304,7 @@ impl From for RcvdCert { RcvdCert { cert: issued.cert, uri: issued.uri, - resources: issued.resource_set + resources: issued.resource_set, } } } @@ -325,14 +317,13 @@ impl AsRef for RcvdCert { impl PartialEq for RcvdCert { fn eq(&self, other: &RcvdCert) -> bool { - self.cert.to_captured().into_bytes() == other.cert.to_captured().into_bytes() && - self.uri == other.uri + self.cert.to_captured().into_bytes() == other.cert.to_captured().into_bytes() + && self.uri == other.uri } } impl Eq for RcvdCert {} - //------------ TrustAnchorLocator -------------------------------------------- #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] @@ -341,7 +332,8 @@ pub struct TrustAnchorLocator { #[serde( deserialize_with = "ext_serde::de_bytes", - serialize_with = "ext_serde::ser_bytes")] + serialize_with = "ext_serde::ser_bytes" + )] encoded_ski: Bytes, } @@ -370,9 +362,9 @@ impl fmt::Display for TrustAnchorLocator { for i in 0..=(len / wrap) { if (i * wrap + wrap) < len { - writeln!(f, "{}", &base64[i * wrap .. i * wrap + wrap])?; + writeln!(f, "{}", &base64[i * wrap..i * wrap + wrap])?; } else { - write!(f, "{}", &base64[i * wrap .. ])?; + write!(f, "{}", &base64[i * wrap..])?; } } @@ -380,38 +372,38 @@ impl fmt::Display for TrustAnchorLocator { } } - //------------ RepoInfo ------------------------------------------------------ #[derive(Clone, Debug, Deserialize, Serialize)] pub struct RepoInfo { base_uri: uri::Rsync, - rpki_notify: uri::Https + rpki_notify: uri::Https, } impl RepoInfo { pub fn new(base_uri: uri::Rsync, rpki_notify: uri::Https) -> Self { - RepoInfo { base_uri, rpki_notify } + RepoInfo { + base_uri, + rpki_notify, + } } - pub fn base_uri(&self) -> &uri::Rsync { &self.base_uri } + pub fn base_uri(&self) -> &uri::Rsync { + &self.base_uri + } /// Returns the ca repository uri for this RepoInfo and a given namespace. /// If the namespace is an empty str, it is omitted from the path. pub fn ca_repository(&self, name_space: &str) -> uri::Rsync { match name_space { "" => self.base_uri.clone(), - _ => self.base_uri.join(name_space.as_ref()).join(b"/") + _ => self.base_uri.join(name_space.as_ref()).join(b"/"), } } /// Returns the rpki manifest uri for this RepoInfo and a given namespace. /// If the namespace is an empty str, it is omitted from the path. - pub fn rpki_manifest( - &self, - name_space: &str, - signing_key: &KeyIdentifier - ) -> uri::Rsync { + pub fn rpki_manifest(&self, name_space: &str, signing_key: &KeyIdentifier) -> uri::Rsync { self.resolve(name_space, &Self::mft_name(signing_key)) } @@ -436,14 +428,12 @@ impl RepoInfo { impl PartialEq for RepoInfo { fn eq(&self, other: &RepoInfo) -> bool { - self.base_uri == other.base_uri && - self.rpki_notify.as_str() == other.rpki_notify.as_str() + self.base_uri == other.base_uri && self.rpki_notify.as_str() == other.rpki_notify.as_str() } } impl Eq for RepoInfo {} - //------------ PendingKey ---------------------------------------------------- /// A Pending Key in a resource class. Should usually have an open @@ -452,24 +442,34 @@ impl Eq for RepoInfo {} #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct PendingKey { key_id: SignerKeyId, - request: Option + request: Option, } impl PendingKey { pub fn new(key_id: SignerKeyId) -> Self { - PendingKey { key_id, request: None} + PendingKey { + key_id, + request: None, + } } pub fn unwrap(self) -> (SignerKeyId, Option) { (self.key_id, self.request) } - pub fn key_id(&self) -> &SignerKeyId { &self.key_id } - pub fn request(&self) -> Option<&IssuanceRequest> { self.request.as_ref() } - pub fn add_request(&mut self, req: IssuanceRequest) { self.request = Some(req)} - pub fn clear_request(&mut self) { self.request = None } + pub fn key_id(&self) -> &SignerKeyId { + &self.key_id + } + pub fn request(&self) -> Option<&IssuanceRequest> { + self.request.as_ref() + } + pub fn add_request(&mut self, req: IssuanceRequest) { + self.request = Some(req) + } + pub fn clear_request(&mut self) { + self.request = None + } } - //------------ CertifiedKey -------------------------------------------------- #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] @@ -479,7 +479,7 @@ pub struct CertifiedKey { key_id: SignerKeyId, incoming_cert: RcvdCert, current_set: CurrentObjectSet, - request: Option + request: Option, } impl CertifiedKey { @@ -487,22 +487,39 @@ impl CertifiedKey { let current_set = CurrentObjectSet::default(); CertifiedKey { - key_id, incoming_cert, current_set, request: None + key_id, + incoming_cert, + current_set, + request: None, } } - pub fn key_id(&self) -> &SignerKeyId { &self.key_id } - pub fn incoming_cert(&self) -> &RcvdCert { &self.incoming_cert } - pub fn current_set(&self) -> &CurrentObjectSet { &self.current_set } - pub fn request(&self) -> Option<&IssuanceRequest> { self.request.as_ref() } - pub fn add_request(&mut self, req: IssuanceRequest) { self.request = Some(req)} - pub fn clear_request(&mut self) { self.request = None } + pub fn key_id(&self) -> &SignerKeyId { + &self.key_id + } + pub fn incoming_cert(&self) -> &RcvdCert { + &self.incoming_cert + } + pub fn current_set(&self) -> &CurrentObjectSet { + &self.current_set + } + pub fn request(&self) -> Option<&IssuanceRequest> { + self.request.as_ref() + } + pub fn add_request(&mut self, req: IssuanceRequest) { + self.request = Some(req) + } + pub fn clear_request(&mut self) { + self.request = None + } - pub fn resources(&self) -> &ResourceSet { &self.incoming_cert.resources } + pub fn resources(&self) -> &ResourceSet { + &self.incoming_cert.resources + } pub fn needs_publication(&self) -> bool { - self.current_set.number == 1 || - self.current_set.next_update < Time::now() + Duration::hours(8) + self.current_set.number == 1 + || self.current_set.next_update < Time::now() + Duration::hours(8) } pub fn with_new_cert(mut self, cert: RcvdCert) -> Self { @@ -515,20 +532,25 @@ impl CertifiedKey { } } - //------------ CurrentObject ------------------------------------------------- #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct CurrentObject { content: Base64, serial: Serial, - expires: Time + expires: Time, } impl CurrentObject { - pub fn content(&self) -> &Base64 { &self.content } - pub fn serial(&self) -> Serial { self.serial } - pub fn expires(&self) -> Time { self.expires } + pub fn content(&self) -> &Base64 { + &self.content + } + pub fn serial(&self) -> Serial { + self.serial + } + pub fn expires(&self) -> Time { + self.expires + } } impl From<&Cert> for CurrentObject { @@ -537,7 +559,9 @@ impl From<&Cert> for CurrentObject { let serial = cert.serial_number(); let expires = cert.validity().not_after(); CurrentObject { - content, serial, expires + content, + serial, + expires, } } } @@ -545,11 +569,13 @@ impl From<&Cert> for CurrentObject { impl From<&Crl> for CurrentObject { fn from(crl: &Crl) -> Self { let content = Base64::from(crl); - let serial = crl.crl_number(); // never revoked + let serial = crl.crl_number(); // never revoked let expires = crl.next_update(); CurrentObject { - content, serial, expires + content, + serial, + expires, } } } @@ -561,12 +587,13 @@ impl From<&Manifest> for CurrentObject { let expires = mft.content().next_update(); CurrentObject { - content, serial, expires + content, + serial, + expires, } } } - //------------ ObjectName ---------------------------------------------------- /// This type is used to represent the (deterministic) file names for @@ -618,7 +645,6 @@ impl Deref for ObjectName { } } - //------------ CurrentObjects ------------------------------------------------ #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] @@ -631,16 +657,11 @@ impl Default for CurrentObjects { } impl CurrentObjects { - pub fn insert( - &mut self, - name: ObjectName, - object: CurrentObject - ) -> Option { + pub fn insert(&mut self, name: ObjectName, object: CurrentObject) -> Option { self.0.insert(name, object) } pub fn apply_delta(&mut self, delta: ObjectsDelta) { - for add in delta.added.into_iter() { self.0.insert(add.name, add.object); } @@ -652,7 +673,7 @@ impl CurrentObjects { } } - pub fn names(&self) -> impl Iterator { + pub fn names(&self) -> impl Iterator { self.0.keys() } @@ -662,15 +683,18 @@ impl CurrentObjects { /// Returns Manifest Entries, i.e. excluding the manifest itself pub fn mft_entries(&self) -> Vec> { - self.0.keys().filter(|k| !k.as_ref().ends_with("mft")).map(|k| { - let name_bytes = Bytes::from(k.as_str()); - let hash_bytes = self.0[k].content.to_encoded_hash().into(); - FileAndHash::new(name_bytes, hash_bytes) - }).collect() + self.0 + .keys() + .filter(|k| !k.as_ref().ends_with("mft")) + .map(|k| { + let name_bytes = Bytes::from(k.as_str()); + let hash_bytes = self.0[k].content.to_encoded_hash().into(); + FileAndHash::new(name_bytes, hash_bytes) + }) + .collect() } } - //------------ AllCurrentObjects --------------------------------------------- /// This type contains a mapping of all name spaces for parent & resource @@ -682,25 +706,17 @@ impl<'a> AllCurrentObjects<'a> { AllCurrentObjects(HashMap::new()) } - pub fn for_name_space( - name_space: &'a str, - current_objects: &'a CurrentObjects - ) -> Self { + pub fn for_name_space(name_space: &'a str, current_objects: &'a CurrentObjects) -> Self { let mut res = Self::empty(); res.add_name_space(name_space, current_objects); res } - pub fn add_name_space( - &mut self, - name_space: &'a str, - current_objects: &'a CurrentObjects - ) { + pub fn add_name_space(&mut self, name_space: &'a str, current_objects: &'a CurrentObjects) { self.0.insert(name_space, current_objects); } } - //------------ Revocation ---------------------------------------------------- /// A Crl Revocation. Note that this type differs from CrlEntry in @@ -708,14 +724,14 @@ impl<'a> AllCurrentObjects<'a> { #[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct Revocation { serial: Serial, - revocation_date: Time + revocation_date: Time, } impl From<&CurrentObject> for Revocation { fn from(co: &CurrentObject) -> Self { Revocation { serial: co.serial, - revocation_date: Time::now() + revocation_date: Time::now(), } } } @@ -724,11 +740,13 @@ impl From<&Manifest> for Revocation { fn from(m: &Manifest) -> Self { let serial = m.cert().serial_number(); let revocation_date = Time::now(); - Revocation { serial, revocation_date } + Revocation { + serial, + revocation_date, + } } } - //------------ Revocations --------------------------------------------------- #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] @@ -736,17 +754,18 @@ pub struct Revocations(Vec); impl Revocations { pub fn to_crl_entries(&self) -> Vec { - self.0.iter() + self.0 + .iter() .map(|r| CrlEntry::new(r.serial, r.revocation_date)) .collect() } /// Purges all expired revocations, and returns them. pub fn purge(&mut self) -> Vec { - - let (relevant, expired) = self.0.iter().partition(|r| { - r.revocation_date.validate_not_after(Time::now()).is_ok() - }); + let (relevant, expired) = self + .0 + .iter() + .partition(|r| r.revocation_date.validate_not_after(Time::now()).is_ok()); self.0 = relevant; expired } @@ -769,20 +788,19 @@ impl Default for Revocations { } } - //------------ RevocationsDelta ---------------------------------------------- #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct RevocationsDelta { added: Vec, - dropped: Vec + dropped: Vec, } impl Default for RevocationsDelta { fn default() -> Self { RevocationsDelta { added: vec![], - dropped: vec![] + dropped: vec![], } } } @@ -805,7 +823,7 @@ pub struct CurrentObjectSet { next_update: Time, number: u64, revocations: Revocations, - objects: CurrentObjects + objects: CurrentObjects, } impl Default for CurrentObjectSet { @@ -815,7 +833,7 @@ impl Default for CurrentObjectSet { next_update: Time::tomorrow(), number: 1, revocations: Revocations::default(), - objects: CurrentObjects::default() + objects: CurrentObjects::default(), } } } @@ -840,7 +858,6 @@ impl CurrentObjectSet { } } - //------------ PublicationDelta ---------------------------------------------- /// This type describes a set up of objects published for a CA key. @@ -850,7 +867,7 @@ pub struct PublicationDelta { next_update: Time, number: u64, revocations: RevocationsDelta, - objects: ObjectsDelta + objects: ObjectsDelta, } impl PublicationDelta { @@ -859,10 +876,14 @@ impl PublicationDelta { next_update: Time, number: u64, revocations: RevocationsDelta, - objects: ObjectsDelta + objects: ObjectsDelta, ) -> Self { PublicationDelta { - this_update, next_update, number, revocations, objects + this_update, + next_update, + number, + revocations, + objects, } } @@ -887,7 +908,7 @@ pub struct ObjectsDelta { ca_repo: uri::Rsync, added: Vec, updated: Vec, - withdrawn: Vec + withdrawn: Vec, } impl ObjectsDelta { @@ -898,7 +919,7 @@ impl ObjectsDelta { ca_repo, added: vec![], updated: vec![], - withdrawn: vec![] + withdrawn: vec![], } } @@ -921,7 +942,7 @@ impl Into for ObjectsDelta { let publish = publication::Publish::new( None, self.ca_repo.join(a.name.as_bytes()), - a.object.content + a.object.content, ); builder.add_publish(publish); } @@ -930,37 +951,30 @@ impl Into for ObjectsDelta { None, self.ca_repo.join(u.name.as_bytes()), u.object.content, - u.old + u.old, ); builder.add_update(update); } for w in self.withdrawn.into_iter() { - let withdraw = publication::Withdraw::new( - None, - self.ca_repo.join(w.name.as_bytes()), - w.hash - ); + let withdraw = + publication::Withdraw::new(None, self.ca_repo.join(w.name.as_bytes()), w.hash); builder.add_withdraw(withdraw); } builder.finish() } } - //------------ AddedObject --------------------------------------------------- /// An object that is newly added to the repository. #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct AddedObject { name: ObjectName, - object: CurrentObject + object: CurrentObject, } impl AddedObject { - pub fn new( - name: ObjectName, - object: CurrentObject - ) -> Self { + pub fn new(name: ObjectName, object: CurrentObject) -> Self { AddedObject { name, object } } } @@ -972,39 +986,30 @@ impl AddedObject { pub struct UpdatedObject { name: ObjectName, object: CurrentObject, - old: EncodedHash + old: EncodedHash, } impl UpdatedObject { - pub fn new( - name: ObjectName, - object: CurrentObject, - old: EncodedHash - ) -> Self { + pub fn new(name: ObjectName, object: CurrentObject, old: EncodedHash) -> Self { UpdatedObject { name, object, old } } } - //------------ WithdrawnObject ----------------------------------------------- /// An object that is to be withdrawn from the repository. #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct WithdrawnObject { name: ObjectName, - hash: EncodedHash + hash: EncodedHash, } impl WithdrawnObject { - pub fn new( - name: ObjectName, - hash: EncodedHash - ) -> Self { - WithdrawnObject { name, hash} + pub fn new(name: ObjectName, hash: EncodedHash) -> Self { + WithdrawnObject { name, hash } } } - //------------ ResourceSet --------------------------------------------------- /// This type defines a set of Internet Number Resources. @@ -1015,15 +1020,11 @@ impl WithdrawnObject { pub struct ResourceSet { asn: AsResources, v4: Ipv4Resources, - v6: Ipv6Resources + v6: Ipv6Resources, } impl ResourceSet { - pub fn new( - asn: AsResources, - v4: Ipv4Resources, - v6: Ipv6Resources - ) -> Self { + pub fn new(asn: AsResources, v4: Ipv4Resources, v6: Ipv6Resources) -> Self { ResourceSet { asn, v4, v6 } } @@ -1031,7 +1032,7 @@ impl ResourceSet { let asn = AsResources::from_str(asn).map_err(|_| ResSetErr::Asn)?; let v4 = Ipv4Resources::from_str(v4).map_err(|_| ResSetErr::V4)?; let v6 = Ipv6Resources::from_str(v6).map_err(|_| ResSetErr::V6)?; - Ok(ResourceSet { asn , v4, v6 }) + Ok(ResourceSet { asn, v4, v6 }) } pub fn all_resources() -> Self { @@ -1062,37 +1063,36 @@ impl ResourceSet { /// resources in the other set will be considered to fall outside of /// this set. pub fn contains(&self, other: &ResourceSet) -> bool { - if (self.asn.is_inherited() && ! other.asn.is_inherited()) || - (self.v4.is_inherited() && ! other.v4.is_inherited())|| - (self.v6.is_inherited() && ! other.v6.is_inherited()) { + if (self.asn.is_inherited() && !other.asn.is_inherited()) + || (self.v4.is_inherited() && !other.v4.is_inherited()) + || (self.v6.is_inherited() && !other.v6.is_inherited()) + { return false; } if let Some(asn) = self.asn.as_blocks() { - - - if asn.validate_issued( - Some(&other.asn), - Overclaim::Refuse - ).is_err() { + if asn + .validate_issued(Some(&other.asn), Overclaim::Refuse) + .is_err() + { return false; } } if let Some(v4) = self.v4.as_blocks() { - if v4.validate_issued( - Some(&other.v4), - Overclaim::Refuse - ).is_err() { + if v4 + .validate_issued(Some(&other.v4), Overclaim::Refuse) + .is_err() + { return false; } } if let Some(v6) = self.v6.as_blocks() { - if v6.validate_issued( - Some(&other.v6), - Overclaim::Refuse - ).is_err() { + if v6 + .validate_issued(Some(&other.v6), Overclaim::Refuse) + .is_err() + { return false; } } @@ -1115,37 +1115,35 @@ impl From<&Cert> for ResourceSet { fn from(cert: &Cert) -> Self { let asn = match cert.as_resources() { None => AsResources::blocks(AsBlocks::empty()), - Some(set) => set.clone() + Some(set) => set.clone(), }; let v4 = { let v4 = match cert.v4_resources() { None => IpResources::blocks(IpBlocks::empty()), - Some(res) => res.clone() + Some(res) => res.clone(), }; match v4.to_blocks() { Ok(blocks) => Ipv4Resources::blocks(blocks), - Err(_) => Ipv4Resources::inherit() + Err(_) => Ipv4Resources::inherit(), } }; let v6 = { let v6 = match cert.v6_resources() { None => IpResources::blocks(IpBlocks::empty()), - Some(res) => res.clone() + Some(res) => res.clone(), }; match v6.to_blocks() { Ok(blocks) => Ipv6Resources::blocks(blocks), - Err(_) => Ipv6Resources::inherit() + Err(_) => Ipv6Resources::inherit(), } }; - ResourceSet { asn, v4, v6 } } } - //------------ TrustAnchorInfo ----------------------------------------------- /// This type represents the TrustAnchor details that need to be accessible @@ -1155,8 +1153,8 @@ pub struct TrustAnchorInfo { resources: ResourceSet, repo_info: RepoInfo, children: HashMap, - cert: RcvdCert, - tal: TrustAnchorLocator + cert: RcvdCert, + tal: TrustAnchorLocator, } impl TrustAnchorInfo { @@ -1164,16 +1162,15 @@ impl TrustAnchorInfo { resources: ResourceSet, repo_info: RepoInfo, children: HashMap, - cert: RcvdCert, - tal: TrustAnchorLocator + cert: RcvdCert, + tal: TrustAnchorLocator, ) -> Self { - TrustAnchorInfo { resources, repo_info, children, cert, - tal + tal, } } @@ -1201,7 +1198,7 @@ impl TrustAnchorInfo { //------------ CertAuthList -------------------------------------------------- #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct CertAuthList { - cas: Vec + cas: Vec, } impl CertAuthList { @@ -1209,13 +1206,14 @@ impl CertAuthList { CertAuthList { cas } } - pub fn cas(&self) -> &Vec { &self.cas } + pub fn cas(&self) -> &Vec { + &self.cas + } } - #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct CertAuthSummary { - name: Handle + name: Handle, } impl CertAuthSummary { @@ -1223,10 +1221,11 @@ impl CertAuthSummary { CertAuthSummary { name } } - pub fn name(&self) -> &Handle { &self.name } + pub fn name(&self) -> &Handle { + &self.name + } } - //------------ CertAuthInfo -------------------------------------------------- /// This type represents the details of a CertAuth that need @@ -1244,20 +1243,28 @@ impl CertAuthInfo { handle: Handle, base_repo: RepoInfo, parents: CaParentsInfo, - children: HashMap + children: HashMap, ) -> Self { CertAuthInfo { handle, base_repo, parents, - children + children, } } - pub fn handle(&self) -> &Handle { &self.handle } - pub fn base_repo(&self) -> &RepoInfo { &self.base_repo } - pub fn parents(&self) -> &CaParentsInfo { &self.parents } - pub fn children(&self) -> &HashMap { &self.children } + pub fn handle(&self) -> &Handle { + &self.handle + } + pub fn base_repo(&self) -> &RepoInfo { + &self.base_repo + } + pub fn parents(&self) -> &CaParentsInfo { + &self.parents + } + pub fn children(&self) -> &HashMap { + &self.children + } } /// This type contains public data about parents of a CA @@ -1265,28 +1272,26 @@ impl CertAuthInfo { #[allow(clippy::large_enum_variant)] pub enum CaParentsInfo { SelfSigned(CertifiedKey, TrustAnchorLocator), - Parents(HashMap) + Parents(HashMap), } #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct ParentCaInfo { contact: ParentCaContact, - resources: HashMap + resources: HashMap, } impl ParentCaInfo { - pub fn new( - contact: ParentCaContact, - resources: HashMap - ) -> Self { - ParentCaInfo { - contact, - resources - } + pub fn new(contact: ParentCaContact, resources: HashMap) -> Self { + ParentCaInfo { contact, resources } } - pub fn contact(&self) -> &ParentCaContact { &self.contact } - pub fn resources(&self) -> &HashMap { &self.resources } + pub fn contact(&self) -> &ParentCaContact { + &self.contact + } + pub fn resources(&self) -> &HashMap { + &self.resources + } } //------------ ResourceClassInfo --------------------------------------------- @@ -1297,7 +1302,7 @@ pub struct ResourceClassInfo { pending_key: Option, new_key: Option, current_key: Option, - revoke_key: Option + revoke_key: Option, } impl ResourceClassInfo { @@ -1306,18 +1311,20 @@ impl ResourceClassInfo { pending_key: Option, new_key: Option, current_key: Option, - revoke_key: Option + revoke_key: Option, ) -> Self { ResourceClassInfo { name_space, pending_key, new_key, current_key, - revoke_key + revoke_key, } } - pub fn name_space(&self) -> &str { &self.name_space } + pub fn name_space(&self) -> &str { + &self.name_space + } pub fn pending_key(&self) -> Option<&PendingKey> { self.pending_key.as_ref() @@ -1352,20 +1359,19 @@ impl ResourceClassInfo { #[derive(Clone, Debug, Display, Eq, PartialEq)] pub enum ResSetErr { - #[display(fmt="Cannot parse ASN resources")] + #[display(fmt = "Cannot parse ASN resources")] Asn, - #[display(fmt="Cannot parse IPv4 resources")] + #[display(fmt = "Cannot parse IPv4 resources")] V4, - #[display(fmt="Cannot parse IPv6 resources")] + #[display(fmt = "Cannot parse IPv6 resources")] V6, - #[display(fmt="Mixed Address Families in configured resource set")] + #[display(fmt = "Mixed Address Families in configured resource set")] Mix, } - //============ Tests ========================================================= #[cfg(test)] @@ -1374,10 +1380,10 @@ mod test { use super::*; use bytes::Bytes; + use crate::util::softsigner::OpenSslSigner; + use crate::util::test; use rpki::crypto::signer::Signer; use rpki::crypto::PublicKeyFormat; - use crate::util::test; - use crate::util::softsigner::OpenSslSigner; fn base_uri() -> uri::Rsync { test::rsync("rsync://localhost/repo/ta/") @@ -1388,7 +1394,10 @@ mod test { } fn info() -> RepoInfo { - RepoInfo { base_uri: base_uri(), rpki_notify: rrdp_uri() } + RepoInfo { + base_uri: base_uri(), + rpki_notify: rrdp_uri(), + } } #[test] @@ -1409,9 +1418,7 @@ mod test { unsafe { use std::str; - let mft_path = str::from_utf8_unchecked( - mft_uri.relative_to(&base_uri()).unwrap() - ); + let mft_path = str::from_utf8_unchecked(mft_uri.relative_to(&base_uri()).unwrap()); assert_eq!(44, mft_path.len()); @@ -1460,7 +1467,7 @@ mod test { fn serialize_deserialise_repo_info() { let info = RepoInfo::new( test::rsync("rsync://some/module/folder/"), - test::https("https://host/notification.xml") + test::https("https://host/notification.xml"), ); let json = serde_json::to_string(&info).unwrap(); @@ -1481,6 +1488,5 @@ mod test { let found_tal = tal.to_string(); assert_eq!(expected_tal, &found_tal); - } } diff --git a/commons/src/api/mod.rs b/commons/src/api/mod.rs index 82579b23..c3d424db 100644 --- a/commons/src/api/mod.rs +++ b/commons/src/api/mod.rs @@ -20,7 +20,6 @@ use rpki::manifest::Manifest; use crate::util::sha256; - //------------ Base64 -------------------------------------------------------- /// This type contains a base64 encoded structure. The publication protocol @@ -82,30 +81,29 @@ impl From<&Crl> for Base64 { impl ToString for Base64 { fn to_string(&self) -> String { - unsafe { - String::from_utf8_unchecked(self.0.to_vec()) - } + unsafe { String::from_utf8_unchecked(self.0.to_vec()) } } } impl Serialize for Base64 { - fn serialize( - &self, serializer: S - ) -> Result where S: Serializer { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { self.to_string().serialize(serializer) } } impl<'de> Deserialize<'de> for Base64 { - fn deserialize( - deserializer: D - ) -> Result where D: Deserializer<'de> { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { let string = String::deserialize(deserializer)?; Ok(Base64::from(string)) } } - //------------ EncodedHash --------------------------------------------------- /// This type contains a hex encoded sha256 hash. @@ -143,31 +141,29 @@ impl From for EncodedHash { impl ToString for EncodedHash { fn to_string(&self) -> String { - unsafe { - String::from_utf8_unchecked(self.0.to_vec()) - } + unsafe { String::from_utf8_unchecked(self.0.to_vec()) } } } impl Serialize for EncodedHash { - fn serialize( - &self, serializer: S - ) -> Result where S: Serializer { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { self.to_string().serialize(serializer) } } impl<'de> Deserialize<'de> for EncodedHash { - fn deserialize( - deserializer: D - ) -> Result where D: Deserializer<'de> { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { let string = String::deserialize(deserializer)?; Ok(EncodedHash::from(string)) } } - - //------------ Link ---------------------------------------------------------- /// Defines a link element to include as part of a links array in a Json @@ -175,10 +171,9 @@ impl<'de> Deserialize<'de> for EncodedHash { #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct Link { rel: String, - link: String + link: String, } - //------------ ErrorResponse -------------------------------------------------- /// Defines an error response. Codes are unique and documented here: @@ -186,13 +181,19 @@ pub struct Link { #[derive(Debug, Deserialize, Serialize)] pub struct ErrorResponse { code: usize, - msg: String + msg: String, } impl ErrorResponse { - pub fn new(code: usize, msg: String) -> Self { ErrorResponse { code, msg }} - pub fn code(&self) -> usize { self.code } - pub fn msg(&self) -> &str { &self.msg } + pub fn new(code: usize, msg: String) -> Self { + ErrorResponse { code, msg } + } + pub fn code(&self) -> usize { + self.code + } + pub fn msg(&self) -> &str { + &self.msg + } } impl fmt::Display for ErrorResponse { @@ -210,79 +211,79 @@ impl Into for ErrorResponse { /// This type defines externally visible errors that the API may return. #[derive(Clone, Debug, Display, Eq, PartialEq)] pub enum ErrorCode { - #[display(fmt="Submitted Json cannot be parsed")] + #[display(fmt = "Submitted Json cannot be parsed")] InvalidJson, - #[display(fmt="Invalid RFC8183 Publisher Request")] + #[display(fmt = "Invalid RFC8183 Publisher Request")] InvalidPublisherRequest, - #[display(fmt="Issue with submitted publication XML")] + #[display(fmt = "Issue with submitted publication XML")] InvalidPublicationXml, - #[display(fmt="Invalid handle name")] + #[display(fmt = "Invalid handle name")] InvalidHandle, - #[display(fmt="Submitted protocol CMS cannot be parsed")] + #[display(fmt = "Submitted protocol CMS cannot be parsed")] InvalidCms, - #[display(fmt="2001: Submitted protocol CMS does not validate")] + #[display(fmt = "2001: Submitted protocol CMS does not validate")] CmsValidation, - #[display(fmt="Out of sync with server, please send requests for instances sequentially")] + #[display(fmt = "Out of sync with server, please send requests for instances sequentially")] ConcurrentModification, - #[display(fmt="Unknown publisher")] + #[display(fmt = "Unknown publisher")] UnknownPublisher, - #[display(fmt="Handle already in use")] + #[display(fmt = "Handle already in use")] DuplicateHandle, - #[display(fmt="Base URI for publisher is outside of publisher base URI")] + #[display(fmt = "Base URI for publisher is outside of publisher base URI")] InvalidBaseUri, - #[display(fmt="Not allowed to publish outside of publisher jail")] + #[display(fmt = "Not allowed to publish outside of publisher jail")] UriOutsideJail, - #[display(fmt="File already exists for uri (use update!)")] + #[display(fmt = "File already exists for uri (use update!)")] ObjectAlreadyPresent, - #[display(fmt="No file found for hash at uri")] + #[display(fmt = "No file found for hash at uri")] NoObjectForHashAndOrUri, - #[display(fmt="Publisher has been deactivated")] + #[display(fmt = "Publisher has been deactivated")] PublisherDeactivated, // 2300s CA Admin Issues - #[display(fmt="Child with name exists")] + #[display(fmt = "Child with name exists")] DuplicateChild, - #[display(fmt="Child MUST have resources")] + #[display(fmt = "Child MUST have resources")] ChildNeedsResources, - #[display(fmt="Child cannot have resources not held by parent")] + #[display(fmt = "Child cannot have resources not held by parent")] ChildOverclaims, // 3000s General server errors - #[display(fmt="Cannot update internal state, issue with work_dir?")] + #[display(fmt = "Cannot update internal state, issue with work_dir?")] Persistence, - #[display(fmt="Cannot update repository, issue with repo_dir?")] + #[display(fmt = "Cannot update repository, issue with repo_dir?")] RepositoryUpdate, - #[display(fmt="Signing error, issue with openssl version or work_dir?")] + #[display(fmt = "Signing error, issue with openssl version or work_dir?")] SigningError, - #[display(fmt="Proxy server error.")] + #[display(fmt = "Proxy server error.")] ProxyError, - #[display(fmt="General CA Server issue.")] + #[display(fmt = "General CA Server issue.")] CaServerError, - #[display(fmt="Publication Client Server issue.")] + #[display(fmt = "Publication Client Server issue.")] PubClientServerError, - #[display(fmt="Unrecognised error (this is a bug)")] - Unknown + #[display(fmt = "Unrecognised error (this is a bug)")] + Unknown, } impl From for ErrorCode { @@ -323,7 +324,7 @@ impl From for ErrorCode { 3005 => ErrorCode::CaServerError, 3006 => ErrorCode::PubClientServerError, - _ => ErrorCode::Unknown + _ => ErrorCode::Unknown, } } } @@ -366,7 +367,7 @@ impl Into for ErrorCode { ErrorCode::CaServerError => 3005, ErrorCode::PubClientServerError => 3006, - ErrorCode::Unknown => 65535 + ErrorCode::Unknown => 65535, }; let msg = format!("{}", self); @@ -382,7 +383,6 @@ mod tests { #[test] fn should_convert_code_to_number_and_back() { - fn test_code(number_to_test: usize) { let code = ErrorCode::from(number_to_test); let response: ErrorResponse = code.into(); @@ -412,8 +412,5 @@ mod tests { for n in 3001..3007 { test_code(n) } - - } } - diff --git a/commons/src/api/provisioning.rs b/commons/src/api/provisioning.rs index e074c91f..62d8ea7e 100644 --- a/commons/src/api/provisioning.rs +++ b/commons/src/api/provisioning.rs @@ -1,10 +1,10 @@ -use api::ca::{ResourceSet, IssuedCert, RcvdCert}; -use rpki::x509::Time; +use api::ca::{IssuedCert, RcvdCert, ResourceSet}; use rpki::cert::{Cert, Overclaim}; +use rpki::crypto::{KeyIdentifier, PublicKey}; use rpki::csr::Csr; -use rpki::uri; use rpki::resources::{AsResources, Ipv4Resources, Ipv6Resources}; -use rpki::crypto::{PublicKey, KeyIdentifier}; +use rpki::uri; +use rpki::x509::Time; pub const DFLT_CLASS: &str = "all"; @@ -14,30 +14,32 @@ pub const DFLT_CLASS: &str = "all"; #[allow(clippy::large_enum_variant)] pub enum ProvisioningRequest { List, - Request(IssuanceRequest) + Request(IssuanceRequest), } impl ProvisioningRequest { - pub fn list() -> Self { ProvisioningRequest::List } - pub fn request(r: IssuanceRequest) -> Self { ProvisioningRequest::Request(r)} + pub fn list() -> Self { + ProvisioningRequest::List + } + pub fn request(r: IssuanceRequest) -> Self { + ProvisioningRequest::Request(r) + } } - //------------ ProvisioningResponse ----------------------------------------- #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub enum ProvisioningResponse { - List(Entitlements) + List(Entitlements), } - //------------ Entitlements ------------------------------------------------- /// This structure is what is called the "Resource Class List Response" /// in section 3.3.2 of RFC6492. #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct Entitlements { - classes: Vec + classes: Vec, } impl Entitlements { @@ -45,21 +47,28 @@ impl Entitlements { issuer: SigningCert, resource_set: ResourceSet, not_after: Time, - issued: Vec + issued: Vec, ) -> Self { let name = DFLT_CLASS.to_string(); - Entitlements { classes: vec![ - EntitlementClass { class_name: name, issuer, resource_set, not_after, issued } - ]} + Entitlements { + classes: vec![EntitlementClass { + class_name: name, + issuer, + resource_set, + not_after, + issued, + }], + } } pub fn new(classes: Vec) -> Self { Entitlements { classes } } - pub fn classes(&self) -> &Vec { &self.classes } + pub fn classes(&self) -> &Vec { + &self.classes + } } - //------------ EntitlementClass ---------------------------------------------- #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] @@ -68,7 +77,7 @@ pub struct EntitlementClass { issuer: SigningCert, resource_set: ResourceSet, not_after: Time, - issued: Vec + issued: Vec, } impl EntitlementClass { @@ -77,27 +86,41 @@ impl EntitlementClass { issuer: SigningCert, resource_set: ResourceSet, not_after: Time, - issued: Vec + issued: Vec, ) -> Self { - EntitlementClass { class_name, issuer, resource_set, not_after, issued } + EntitlementClass { + class_name, + issuer, + resource_set, + not_after, + issued, + } } - fn unwrap( - self - ) -> (String, SigningCert, ResourceSet, Time, Vec) { + fn unwrap(self) -> (String, SigningCert, ResourceSet, Time, Vec) { ( self.class_name, self.issuer, self.resource_set, self.not_after, - self.issued + self.issued, ) } - pub fn class_name(&self) -> &str { &self.class_name } - pub fn issuer(&self) -> &SigningCert { &self.issuer } - pub fn resource_set(&self) -> &ResourceSet { &self.resource_set } - pub fn not_after(&self) -> Time { self.not_after } - pub fn issued(&self) -> &Vec { &self.issued } + pub fn class_name(&self) -> &str { + &self.class_name + } + pub fn issuer(&self) -> &SigningCert { + &self.issuer + } + pub fn resource_set(&self) -> &ResourceSet { + &self.resource_set + } + pub fn not_after(&self) -> Time { + self.not_after + } + pub fn issued(&self) -> &Vec { + &self.issued + } /// Converts this into an IssuanceResponse for the given key. I.e. includes /// the issued certificate matching the given public key only. Returns a @@ -105,27 +128,21 @@ impl EntitlementClass { pub fn into_issuance_response(self, key: &PublicKey) -> Option { let (class_name, issuer, resource_set, not_after, issued) = self.unwrap(); - issued.into_iter() + issued + .into_iter() .find(|issued| issued.cert().subject_public_key_info() == key) .map(|issued| { - IssuanceResponse::new( - class_name, - issuer, - resource_set, - not_after, - issued - ) + IssuanceResponse::new(class_name, issuer, resource_set, not_after, issued) }) } } - //------------ SigningCert --------------------------------------------------- #[derive(Clone, Debug, Deserialize, Serialize)] pub struct SigningCert { uri: uri::Rsync, - cert: Cert + cert: Cert, } impl SigningCert { @@ -133,15 +150,18 @@ impl SigningCert { SigningCert { uri, cert } } - pub fn uri(&self) -> &uri::Rsync { &self.uri } - pub fn cert(&self) -> &Cert { &self.cert } + pub fn uri(&self) -> &uri::Rsync { + &self.uri + } + pub fn cert(&self) -> &Cert { + &self.cert + } } - impl PartialEq for SigningCert { fn eq(&self, other: &SigningCert) -> bool { - self.uri == other.uri && - self.cert.to_captured().as_slice() == other.cert.to_captured().as_slice() + self.uri == other.uri + && self.cert.to_captured().as_slice() == other.cert.to_captured().as_slice() } } @@ -151,12 +171,11 @@ impl From<&RcvdCert> for SigningCert { fn from(c: &RcvdCert) -> Self { SigningCert { uri: c.uri().clone(), - cert: c.cert().clone() + cert: c.cert().clone(), } } } - //------------ IssuanceRequest ----------------------------------------------- /// This type reflects the content of a Certificate Issuance Request @@ -165,38 +184,43 @@ impl From<&RcvdCert> for SigningCert { pub struct IssuanceRequest { class_name: String, limit: RequestResourceLimit, - csr: Csr + csr: Csr, } impl IssuanceRequest { - pub fn new( - class_name: String, - limit: RequestResourceLimit, - csr: Csr - ) -> Self { - IssuanceRequest { class_name, limit, csr } + pub fn new(class_name: String, limit: RequestResourceLimit, csr: Csr) -> Self { + IssuanceRequest { + class_name, + limit, + csr, + } } pub fn unwrap(self) -> (String, RequestResourceLimit, Csr) { (self.class_name, self.limit, self.csr) } - pub fn class_name(&self) -> &str { &self.class_name } - pub fn limit(&self) -> &RequestResourceLimit { &self.limit } - pub fn csr(&self) -> &Csr { &self.csr } + pub fn class_name(&self) -> &str { + &self.class_name + } + pub fn limit(&self) -> &RequestResourceLimit { + &self.limit + } + pub fn csr(&self) -> &Csr { + &self.csr + } } impl PartialEq for IssuanceRequest { fn eq(&self, other: &IssuanceRequest) -> bool { - self.class_name == other.class_name && - self.limit == other.limit && - self.csr.to_captured().as_slice() == other.csr.to_captured().as_slice() + self.class_name == other.class_name + && self.limit == other.limit + && self.csr.to_captured().as_slice() == other.csr.to_captured().as_slice() } } impl Eq for IssuanceRequest {} - //------------ IssuanceResponse ---------------------------------------------- /// A Certificate Issuance Response equivalent to the one defined in @@ -210,7 +234,7 @@ pub struct IssuanceResponse { issuer: SigningCert, resource_set: ResourceSet, // resources allowed on a cert not_after: Time, - issued: IssuedCert + issued: IssuedCert, } impl IssuanceResponse { @@ -219,23 +243,38 @@ impl IssuanceResponse { issuer: SigningCert, resource_set: ResourceSet, // resources allowed on a cert not_after: Time, - issued: IssuedCert + issued: IssuedCert, ) -> Self { - IssuanceResponse { class_name, issuer, resource_set, not_after, issued } + IssuanceResponse { + class_name, + issuer, + resource_set, + not_after, + issued, + } } pub fn unwrap(self) -> (String, SigningCert, ResourceSet, IssuedCert) { (self.class_name, self.issuer, self.resource_set, self.issued) } - pub fn class_name(&self) -> &str { &self.class_name } - pub fn issuer(&self) -> &SigningCert { &self.issuer } - pub fn resource_set(&self) -> &ResourceSet { &self.resource_set } - pub fn not_after(&self) -> Time { self.not_after } - pub fn issued(&self) -> &IssuedCert { &self.issued } + pub fn class_name(&self) -> &str { + &self.class_name + } + pub fn issuer(&self) -> &SigningCert { + &self.issuer + } + pub fn resource_set(&self) -> &ResourceSet { + &self.resource_set + } + pub fn not_after(&self) -> Time { + self.not_after + } + pub fn issued(&self) -> &IssuedCert { + &self.issued + } } - //------------ RequestResourceLimit ------------------------------------------ /// The scope of resources that a child CA wants to have certified. By default @@ -250,11 +289,13 @@ impl IssuanceResponse { pub struct RequestResourceLimit { asn: Option, v4: Option, - v6: Option + v6: Option, } impl RequestResourceLimit { - pub fn new() -> RequestResourceLimit { Self::default() } + pub fn new() -> RequestResourceLimit { + Self::default() + } pub fn is_empty(&self) -> bool { self.asn == None && self.v4 == None && self.v6 == None @@ -272,9 +313,15 @@ impl RequestResourceLimit { self.v6 = Some(ipv6); } - pub fn asn(&self) -> Option<&AsResources> { self.asn.as_ref() } - pub fn v4(&self) -> Option<&Ipv4Resources> { self.v4.as_ref() } - pub fn v6(&self) -> Option<&Ipv6Resources> { self.v6.as_ref() } + pub fn asn(&self) -> Option<&AsResources> { + self.asn.as_ref() + } + pub fn v4(&self) -> Option<&Ipv4Resources> { + self.v4.as_ref() + } + pub fn v6(&self) -> Option<&Ipv6Resources> { + self.v6.as_ref() + } /// Give back a ResourceSet based on the input set as limited by this. /// Note, if the limit exceeds the input set for any resource type @@ -289,14 +336,14 @@ impl RequestResourceLimit { // resources. This is unverifiable. As Krill // will never use the "inherit" type on CA certificates // it is safe to just return a None here. - return None - }, + return None; + } Some(parent_asn) => { - if parent_asn.validate_issued( - Some(asn), - Overclaim::Refuse - ).is_err() { - return None // Child is overclaiming + if parent_asn + .validate_issued(Some(asn), Overclaim::Refuse) + .is_err() + { + return None; // Child is overclaiming } asn.clone() // Child gets what they ask for } @@ -313,14 +360,14 @@ impl RequestResourceLimit { // resources. This is unverifiable. As Krill // will never use the "inherit" type on CA certificates // it is safe to just return a None here. - return None - }, + return None; + } Some(parent_v4) => { - if parent_v4.validate_issued( - Some(v4), - Overclaim::Refuse - ).is_err() { - return None // Child is overclaiming + if parent_v4 + .validate_issued(Some(v4), Overclaim::Refuse) + .is_err() + { + return None; // Child is overclaiming } v4.clone() // Child gets what they ask for } @@ -337,14 +384,14 @@ impl RequestResourceLimit { // resources. This is unverifiable. As Krill // will never use the "inherit" type on CA certificates // it is safe to just return a None here. - return None - }, + return None; + } Some(parent_v6) => { - if parent_v6.validate_issued( - Some(v6), - Overclaim::Refuse - ).is_err() { - return None // Child is overclaiming + if parent_v6 + .validate_issued(Some(v6), Overclaim::Refuse) + .is_err() + { + return None; // Child is overclaiming } v6.clone() // Child gets what they ask for } @@ -361,12 +408,11 @@ impl Default for RequestResourceLimit { RequestResourceLimit { asn: None, v4: None, - v6: None + v6: None, } } } - //------------ RevocationRequest --------------------------------------------- /// This type represents a Certificate Revocation Request as @@ -374,14 +420,18 @@ impl Default for RequestResourceLimit { #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct RevocationRequest { class_name: String, - key: KeyIdentifier + key: KeyIdentifier, } impl RevocationRequest { pub fn new(class_name: String, key: KeyIdentifier) -> Self { - RevocationRequest { class_name, key} + RevocationRequest { class_name, key } } - pub fn class_name(&self) -> &str { &self.class_name } - pub fn key(&self) -> &KeyIdentifier { &self.key } + pub fn class_name(&self) -> &str { + &self.class_name + } + pub fn key(&self) -> &KeyIdentifier { + &self.key + } } diff --git a/commons/src/api/publication.rs b/commons/src/api/publication.rs index d289ab61..e010ec0a 100644 --- a/commons/src/api/publication.rs +++ b/commons/src/api/publication.rs @@ -1,8 +1,7 @@ //! Support for requests sent to the Json API -use rpki::uri; -use crate::api::{ Base64, EncodedHash }; +use crate::api::{Base64, EncodedHash}; use crate::util::file::CurrentFile; - +use rpki::uri; //------------ PublishRequest ------------------------------------------------ @@ -11,10 +10,9 @@ use crate::util::file::CurrentFile; #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub enum PublishRequest { List, // See https://tools.ietf.org/html/rfc8181#section-2.3 - Delta(PublishDelta) + Delta(PublishDelta), } - //------------ PublishDelta ------------------------------------------------ /// This type represents a multi element query as described in @@ -23,16 +21,16 @@ pub enum PublishRequest { pub struct PublishDelta { publishes: Vec, updates: Vec, - withdraws: Vec + withdraws: Vec, } impl PublishDelta { - pub fn new( - publishes: Vec, - updates: Vec, - withdraws: Vec - ) -> Self { - PublishDelta { publishes, updates, withdraws } + pub fn new(publishes: Vec, updates: Vec, withdraws: Vec) -> Self { + PublishDelta { + publishes, + updates, + withdraws, + } } pub fn publishes(&self) -> &Vec { @@ -49,21 +47,22 @@ impl PublishDelta { self.publishes.len() + self.updates.len() + self.withdraws.len() } - pub fn is_empty(&self) -> bool { self.len() == 0 } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } pub fn unwrap(self) -> (Vec, Vec, Vec) { (self.publishes, self.updates, self.withdraws) } } - //------------ PublishDeltaBuilder ------------------------------------------- #[derive(Default)] pub struct PublishDeltaBuilder { publishes: Vec, updates: Vec, - withdraws: Vec + withdraws: Vec, } impl PublishDeltaBuilder { @@ -87,12 +86,11 @@ impl PublishDeltaBuilder { PublishDelta { publishes: self.publishes, updates: self.updates, - withdraws: self.withdraws + withdraws: self.withdraws, } } } - //------------ Publish ------------------------------------------------------ /// Type representing a json equivalent to the publish element, that does not @@ -102,7 +100,7 @@ impl PublishDeltaBuilder { pub struct Publish { tag: Option, uri: uri::Rsync, - content: Base64 + content: Base64, } impl Publish { @@ -114,22 +112,27 @@ impl Publish { Publish { tag, uri, content } } - pub fn tag(&self) -> &Option { &self.tag } + pub fn tag(&self) -> &Option { + &self.tag + } pub fn tag_for_xml(&self) -> String { match &self.tag { None => "".to_string(), - Some(t) => t.clone() + Some(t) => t.clone(), } } - pub fn uri(&self) -> &uri::Rsync{ &self.uri} - pub fn content(&self) -> &Base64{ &self.content } + pub fn uri(&self) -> &uri::Rsync { + &self.uri + } + pub fn content(&self) -> &Base64 { + &self.content + } pub fn unwrap(self) -> (Option, uri::Rsync, Base64) { (self.tag, self.uri, self.content) } } - //------------ Update -------------------------------------------------------- /// Type representing a json equivalent to the publish element, that updates @@ -148,36 +151,49 @@ impl Update { tag: Option, uri: uri::Rsync, content: Base64, - old_hash: EncodedHash + old_hash: EncodedHash, ) -> Self { - Update { tag, uri, content, hash: old_hash } + Update { + tag, + uri, + content, + hash: old_hash, + } } - pub fn with_hash_tag( - uri: uri::Rsync, - content: Base64, - old_hash: EncodedHash - ) -> Self { + pub fn with_hash_tag(uri: uri::Rsync, content: Base64, old_hash: EncodedHash) -> Self { let tag = Some(content.to_hex_hash()); - Update { tag, uri, content, hash: old_hash } + Update { + tag, + uri, + content, + hash: old_hash, + } } - pub fn tag(&self) -> &Option { &self.tag } + pub fn tag(&self) -> &Option { + &self.tag + } pub fn tag_for_xml(&self) -> String { match &self.tag { Some(t) => t.clone(), - None => "".to_string() + None => "".to_string(), } } - pub fn uri(&self) -> &uri::Rsync { &self.uri} - pub fn content(&self) -> &Base64 { &self.content } - pub fn hash(&self) -> &EncodedHash { &self.hash } + pub fn uri(&self) -> &uri::Rsync { + &self.uri + } + pub fn content(&self) -> &Base64 { + &self.content + } + pub fn hash(&self) -> &EncodedHash { + &self.hash + } pub fn unwrap(self) -> (Option, uri::Rsync, Base64, EncodedHash) { (self.tag, self.uri, self.content, self.hash) } } - //------------ Withdraw ------------------------------------------------------ /// Type representing a json equivalent to a withdraw element that removes an @@ -204,19 +220,25 @@ impl Withdraw { Withdraw { tag: None, uri: el.uri().clone(), - hash: el.hash().clone() + hash: el.hash().clone(), } } - pub fn tag(&self) -> &Option { &self.tag } + pub fn tag(&self) -> &Option { + &self.tag + } pub fn tag_for_xml(&self) -> String { match &self.tag { Some(t) => t.clone(), - None => "".to_string() + None => "".to_string(), } } - pub fn uri(&self) -> &uri::Rsync { &self.uri} - pub fn hash(&self) -> &EncodedHash { &self.hash } + pub fn uri(&self) -> &uri::Rsync { + &self.uri + } + pub fn hash(&self) -> &EncodedHash { + &self.hash + } pub fn unwrap(self) -> (Option, uri::Rsync, EncodedHash) { (self.tag, self.uri, self.hash) @@ -228,17 +250,16 @@ impl Withdraw { /// This type is used to wrap API responses for publication requests. pub enum PublishReply { Success, // See https://tools.ietf.org/html/rfc8181#section-3.4 - List(ListReply) + List(ListReply), } - //------------ ListReply ----------------------------------------------------- /// This type represents the list reply as described in /// https://tools.ietf.org/html/rfc8181#section-2.3 #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct ListReply { - elements: Vec + elements: Vec, } impl ListReply { @@ -247,7 +268,10 @@ impl ListReply { } pub fn from_files(files: Vec) -> Self { - let elements = files.into_iter().map(CurrentFile::into_list_element).collect(); + let elements = files + .into_iter() + .map(CurrentFile::into_list_element) + .collect(); ListReply { elements } } @@ -256,15 +280,14 @@ impl ListReply { } } - //------------ ListElement --------------------------------------------------- /// This type represents a single object that is published at a publication /// server. #[derive(Clone, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)] pub struct ListElement { - uri: uri::Rsync, - hash: EncodedHash + uri: uri::Rsync, + hash: EncodedHash, } impl ListElement { @@ -272,6 +295,10 @@ impl ListElement { ListElement { uri, hash } } - pub fn uri(&self) -> &uri::Rsync { &self.uri } - pub fn hash(&self) -> &EncodedHash { &self.hash } + pub fn uri(&self) -> &uri::Rsync { + &self.uri + } + pub fn hash(&self) -> &EncodedHash { + &self.hash + } } diff --git a/commons/src/api/rrdp.rs b/commons/src/api/rrdp.rs index 430a663a..453ed345 100644 --- a/commons/src/api/rrdp.rs +++ b/commons/src/api/rrdp.rs @@ -1,18 +1,17 @@ //! Data objects used in the (RRDP) repository. I.e. the publish, update, and //! withdraw elements, as well as the notification, snapshot and delta file //! definitions. -use std::collections::HashMap; -use std::io; -use std::path::PathBuf; -use bytes::Bytes; -use rpki::uri; use crate::api::publication; use crate::api::Base64; use crate::api::EncodedHash; use crate::util::file; -use crate::util::Time; use crate::util::xml::XmlWriter; - +use crate::util::Time; +use bytes::Bytes; +use rpki::uri; +use std::collections::HashMap; +use std::io; +use std::path::PathBuf; const VERSION: &str = "1"; const NS: &str = "http://www.ripe.net/rpki/rrdp"; @@ -26,7 +25,7 @@ const NS: &str = "http://www.ripe.net/rpki/rrdp"; #[derive(Clone, Debug, Deserialize, Serialize)] pub struct PublishElement { base64: Base64, - uri: uri::Rsync + uri: uri::Rsync, } impl PublishElement { @@ -34,8 +33,12 @@ impl PublishElement { PublishElement { base64, uri } } - pub fn base64(&self) -> &Base64 { &self.base64 } - pub fn uri(&self) -> &uri::Rsync { &self.uri } + pub fn base64(&self) -> &Base64 { + &self.base64 + } + pub fn uri(&self) -> &uri::Rsync { + &self.uri + } } impl From for PublishElement { @@ -45,7 +48,6 @@ impl From for PublishElement { } } - //------------ UpdateElement ------------------------------------------------- /// The updates as used in the RRDP protocol. @@ -56,13 +58,19 @@ impl From for PublishElement { pub struct UpdateElement { uri: uri::Rsync, hash: EncodedHash, - base64: Base64 + base64: Base64, } impl UpdateElement { - pub fn uri(&self) -> &uri::Rsync { &self.uri } - pub fn hash(&self) -> &EncodedHash { &self.hash } - pub fn base64(&self) -> &Base64 { &self.base64 } + pub fn uri(&self) -> &uri::Rsync { + &self.uri + } + pub fn hash(&self) -> &EncodedHash { + &self.hash + } + pub fn base64(&self) -> &Base64 { + &self.base64 + } } impl From for UpdateElement { @@ -74,11 +82,13 @@ impl From for UpdateElement { impl Into for UpdateElement { fn into(self) -> PublishElement { - PublishElement { uri: self.uri, base64: self.base64 } + PublishElement { + uri: self.uri, + base64: self.base64, + } } } - //------------ WithdrawElement ----------------------------------------------- /// The withdraws as used in the RRDP protocol. @@ -88,12 +98,16 @@ impl Into for UpdateElement { #[derive(Clone, Debug, Deserialize, Serialize)] pub struct WithdrawElement { uri: uri::Rsync, - hash: EncodedHash + hash: EncodedHash, } impl WithdrawElement { - pub fn uri(&self) -> &uri::Rsync { &self.uri } - pub fn hash(&self) -> &EncodedHash { &self.hash } + pub fn uri(&self) -> &uri::Rsync { + &self.uri + } + pub fn hash(&self) -> &EncodedHash { + &self.hash + } } impl From for WithdrawElement { @@ -103,25 +117,23 @@ impl From for WithdrawElement { } } - - #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Notification { - session: String, - serial: u64, - time: Time, - snapshot: SnapshotRef, - deltas: Vec, - old_refs: Vec<(Time, FileRef)> + session: String, + serial: u64, + time: Time, + snapshot: SnapshotRef, + deltas: Vec, + old_refs: Vec<(Time, FileRef)>, } #[derive(Clone, Debug, Deserialize, Serialize)] pub struct NotificationUpdate { - time: Time, - session: Option, - snapshot: SnapshotRef, - delta: DeltaRef, - last_delta: u64 + time: Time, + session: Option, + snapshot: SnapshotRef, + delta: DeltaRef, + last_delta: u64, } impl NotificationUpdate { @@ -130,21 +142,33 @@ impl NotificationUpdate { session: Option, snapshot: SnapshotRef, delta: DeltaRef, - last_delta: u64 + last_delta: u64, ) -> Self { - NotificationUpdate { time, session, snapshot, delta, last_delta } + NotificationUpdate { + time, + session, + snapshot, + delta, + last_delta, + } } } #[derive(Clone, Debug, Deserialize, Serialize)] pub struct NotificationCreate { - session: String, - snapshot: SnapshotRef + session: String, + snapshot: SnapshotRef, } impl NotificationUpdate { pub fn unwrap(self) -> (Time, Option, SnapshotRef, DeltaRef, u64) { - (self.time, self.session, self.snapshot, self.delta, self.last_delta) + ( + self.time, + self.session, + self.snapshot, + self.delta, + self.last_delta, + ) } } @@ -180,7 +204,7 @@ impl Notification { /// Cleans up all old references from before the given time. pub fn clean_up(&mut self, t: Time) { - self.old_refs.retain(|old_ref| {! old_ref.0.on_or_before(&t)}) + self.old_refs.retain(|old_ref| !old_ref.0.on_or_before(&t)) } pub fn create(session: String, snapshot: SnapshotRef) -> Self { @@ -190,7 +214,7 @@ impl Notification { time: Time::now(), snapshot, deltas: vec![], - old_refs: vec![] + old_refs: vec![], } } @@ -198,8 +222,7 @@ impl Notification { debug!("Writing notification file: {}", path.to_string_lossy()); let mut file = file::create_file_with_path(&path)?; - XmlWriter::encode_to_file(& mut file, |w| { - + XmlWriter::encode_to_file(&mut file, |w| { let a = [ ("xmlns", NS), ("version", VERSION), @@ -207,75 +230,64 @@ impl Notification { ("serial", &format!("{}", self.serial)), ]; - w.put_element( - "notification", - Some(&a), - |w| { - { - // snapshot ref - let uri = self.snapshot.uri.to_string(); - let a = [ - ("uri", uri.as_str()), - ("hash", self.snapshot.hash.as_ref()) - ]; - w.put_element( - "snapshot", - Some(&a), - |w| { w.empty() } - )?; - } - - { - // delta refs - for delta in &self.deltas { - let serial = format!("{}", delta.serial); - let uri = delta.file_ref.uri.to_string(); - let a = [ - ("serial", serial.as_ref()), - ("uri", uri.as_str()), - ("hash", delta.file_ref.hash.as_ref()) - ]; - w.put_element( - "delta", - Some(&a), - |w| { w.empty() } - )?; - } - } - - Ok(()) + w.put_element("notification", Some(&a), |w| { + { + // snapshot ref + let uri = self.snapshot.uri.to_string(); + let a = [("uri", uri.as_str()), ("hash", self.snapshot.hash.as_ref())]; + w.put_element("snapshot", Some(&a), |w| w.empty())?; } - ) + + { + // delta refs + for delta in &self.deltas { + let serial = format!("{}", delta.serial); + let uri = delta.file_ref.uri.to_string(); + let a = [ + ("serial", serial.as_ref()), + ("uri", uri.as_str()), + ("hash", delta.file_ref.hash.as_ref()), + ]; + w.put_element("delta", Some(&a), |w| w.empty())?; + } + } + + Ok(()) + }) })?; Ok(()) - } - } #[derive(Clone, Debug, Deserialize, Serialize)] pub struct FileRef { - uri: uri::Https, - path: PathBuf, - hash: EncodedHash, + uri: uri::Https, + path: PathBuf, + hash: EncodedHash, } impl FileRef { pub fn new(uri: uri::Https, path: PathBuf, hash: EncodedHash) -> Self { FileRef { uri, path, hash } } - pub fn uri(&self) -> &uri::Https { &self.uri } - pub fn path(&self) -> &PathBuf { &self.path } - pub fn hash(&self) -> &EncodedHash { &self.hash } + pub fn uri(&self) -> &uri::Https { + &self.uri + } + pub fn path(&self) -> &PathBuf { + &self.path + } + pub fn hash(&self) -> &EncodedHash { + &self.hash + } } pub type SnapshotRef = FileRef; #[derive(Clone, Debug, Deserialize, Serialize)] pub struct DeltaRef { - serial: u64, - file_ref: FileRef + serial: u64, + file_ref: FileRef, } impl DeltaRef { @@ -283,7 +295,9 @@ impl DeltaRef { DeltaRef { serial, file_ref } } - pub fn serial(&self) -> u64 { self.serial } + pub fn serial(&self) -> u64 { + self.serial + } } impl AsRef for DeltaRef { @@ -292,7 +306,6 @@ impl AsRef for DeltaRef { } } - //------------ CurrentObjects ------------------------------------------------ /// Defines a current set of published elements. @@ -322,19 +335,22 @@ impl CurrentObjects { } } - //------------ VerificationError --------------------------------------------- /// Issues with relation to verifying deltas. #[derive(Clone, Debug, Display)] pub enum VerificationError { - #[display(fmt="Publishing ({}) outside of jail URI ({}) is not allowed.", _0, _1)] + #[display( + fmt = "Publishing ({}) outside of jail URI ({}) is not allowed.", + _0, + _1 + )] UriOutsideJail(uri::Rsync, uri::Rsync), - #[display(fmt="File already exists for uri (use update!): {}", _0)] + #[display(fmt = "File already exists for uri (use update!): {}", _0)] ObjectAlreadyPresent(uri::Rsync), - #[display(fmt="File does not match hash at uri: {}", _0)] + #[display(fmt = "File does not match hash at uri: {}", _0)] NoObjectForHashAndOrUri(uri::Rsync), } @@ -353,42 +369,36 @@ impl VerificationError { } impl CurrentObjects { - - fn has_match( - &self, - hash: &EncodedHash, - uri: &uri::Rsync - ) -> bool { + fn has_match(&self, hash: &EncodedHash, uri: &uri::Rsync) -> bool { match self.0.get(hash) { Some(el) => el.uri() == uri, - None => false + None => false, } } pub fn verify_delta( &self, delta: &DeltaElements, - jail: &uri::Rsync + jail: &uri::Rsync, ) -> Result<(), VerificationError> { - for p in delta.publishes() { - if ! jail.is_parent_of(p.uri()) { - return Err(VerificationError::outside(jail, p.uri())) + if !jail.is_parent_of(p.uri()) { + return Err(VerificationError::outside(jail, p.uri())); } let hash = p.base64().to_encoded_hash(); if self.0.contains_key(&hash) { - return Err(VerificationError::present(p.uri())) + return Err(VerificationError::present(p.uri())); } } for u in delta.updates() { - if ! self.has_match(u.hash(), u.uri()) { + if !self.has_match(u.hash(), u.uri()) { return Err(VerificationError::no_match(u.uri())); } } for w in delta.withdraws() { - if ! self.has_match(w.hash(), w.uri()) { + if !self.has_match(w.hash(), w.uri()) { return Err(VerificationError::no_match(w.uri())); } } @@ -418,22 +428,29 @@ impl CurrentObjects { } } - pub fn len(&self) -> usize { self.0.len() } + pub fn len(&self) -> usize { + self.0.len() + } - pub fn is_empty(&self) -> bool { self.0.is_empty() } + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } pub fn to_list_reply(&self) -> publication::ListReply { - let elements = self.0.iter().map(|el| { - let hash = el.0.clone(); - let uri = el.1.uri().clone(); - publication::ListElement::new(uri, hash) - }).collect(); + let elements = self + .0 + .iter() + .map(|el| { + let hash = el.0.clone(); + let uri = el.1.uri().clone(); + publication::ListElement::new(uri, hash) + }) + .collect(); publication::ListReply::new(elements) } } - //------------ Snapshot ------------------------------------------------------ /// A structure to contain the RRDP snapshot data. @@ -441,13 +458,17 @@ impl CurrentObjects { pub struct Snapshot { session: String, serial: u64, - current_objects: CurrentObjects + current_objects: CurrentObjects, } impl Snapshot { pub fn new(session: String) -> Self { let current_objects = CurrentObjects::default(); - Snapshot { session, serial: 0, current_objects } + Snapshot { + session, + serial: 0, + current_objects, + } } pub fn apply_delta(&mut self, delta: Delta) { @@ -457,9 +478,13 @@ impl Snapshot { self.current_objects.apply_delta(elements) } - pub fn len(&self) -> usize { self.current_objects.len() } + pub fn len(&self) -> usize { + self.current_objects.len() + } - pub fn is_empty(&self) -> bool { self.current_objects.is_empty() } + pub fn is_empty(&self) -> bool { + self.current_objects.is_empty() + } pub fn write_xml(&self, path: &PathBuf) -> Result { let vec = XmlWriter::encode_vec(|w| { @@ -470,24 +495,14 @@ impl Snapshot { ("serial", &format!("{}", self.serial)), ]; - w.put_element( - "snapshot", - Some(&a), - |w| { - for el in self.current_objects.elements() { - let uri = el.uri.to_string(); - let atr = [ ("uri", uri.as_ref())]; - w.put_element( - "publish", - Some(&atr), - |w| { - w.put_text(el.base64.as_ref()) - } - )?; - } - Ok(()) + w.put_element("snapshot", Some(&a), |w| { + for el in self.current_objects.elements() { + let uri = el.uri.to_string(); + let atr = [("uri", uri.as_ref())]; + w.put_element("publish", Some(&atr), |w| w.put_text(el.base64.as_ref()))?; } - ) + Ok(()) + }) }); let bytes = Bytes::from(vec); @@ -498,7 +513,6 @@ impl Snapshot { } } - //------------ DeltaElements ------------------------------------------------- /// Defines the elements for an RRDP delta. @@ -506,7 +520,7 @@ impl Snapshot { pub struct DeltaElements { publishes: Vec, updates: Vec, - withdraws: Vec + withdraws: Vec, } impl From for DeltaElements { @@ -517,14 +531,22 @@ impl From for DeltaElements { let updates = upds.into_iter().map(UpdateElement::from).collect(); let withdraws = wdrs.into_iter().map(WithdrawElement::from).collect(); - DeltaElements { publishes, updates, withdraws } + DeltaElements { + publishes, + updates, + withdraws, + } } } impl DeltaElements { pub fn unwrap( - self - ) -> (Vec, Vec, Vec) { + self, + ) -> ( + Vec, + Vec, + Vec, + ) { (self.publishes, self.updates, self.withdraws) } @@ -549,47 +571,58 @@ impl DeltaElements { } } - //------------ Delta --------------------------------------------------------- /// Defines an RRDP delta. #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Delta { - session: String, - serial: u64, - time: Time, - elements: DeltaElements + session: String, + serial: u64, + time: Time, + elements: DeltaElements, } impl Delta { - pub fn new( - session: String, - serial: u64, - elements: DeltaElements - ) -> Self { - Delta { session, time: Time::now(), serial, elements } + pub fn new(session: String, serial: u64, elements: DeltaElements) -> Self { + Delta { + session, + time: Time::now(), + serial, + elements, + } } - pub fn session(&self) -> &str { &self.session } - pub fn serial(&self) -> u64 { self.serial } - pub fn time(&self) -> &Time { &self.time } - pub fn elements(&self) -> &DeltaElements { &self.elements } + pub fn session(&self) -> &str { + &self.session + } + pub fn serial(&self) -> u64 { + self.serial + } + pub fn time(&self) -> &Time { + &self.time + } + pub fn elements(&self) -> &DeltaElements { + &self.elements + } /// Total number of elements /// /// This is a cheap approximation of the size of the delta that can help /// in determining the choice of how many deltas to include in a /// notification file. - pub fn len(&self) -> usize { self.elements.len() } + pub fn len(&self) -> usize { + self.elements.len() + } - pub fn is_empty(&self) -> bool { self.elements.is_empty() } + pub fn is_empty(&self) -> bool { + self.elements.is_empty() + } pub fn unwrap(self) -> (String, u64, DeltaElements) { (self.session, self.serial, self.elements) } pub fn write_xml(&self, path: &PathBuf) -> Result { - let vec = XmlWriter::encode_vec(|w| { let a = [ ("xmlns", NS), @@ -598,53 +631,27 @@ impl Delta { ("serial", &format!("{}", self.serial)), ]; - w.put_element( - "delta", - Some(&a), - |w| { - for el in &self.elements.publishes { - let uri = el.uri.to_string(); - let atr = [ ("uri", uri.as_ref())]; - w.put_element( - "publish", - Some(&atr), - |w| { - w.put_text(el.base64.as_ref()) - } - )?; - } - - for el in &self.elements.updates { - let uri = el.uri.to_string(); - let atr = [ - ("uri", uri.as_ref()), - ("hash", el.hash.as_ref()) - ]; - w.put_element( - "publish", - Some(&atr), - |w| { - w.put_text(el.base64.as_ref()) - } - )?; - } - - for el in &self.elements.withdraws { - let uri = el.uri.to_string(); - let atr = [ - ("uri", uri.as_ref()), - ("hash", el.hash.as_ref()) - ]; - w.put_element( - "withdraw", - Some(&atr), - |w| { w.empty() } - )?; - } - - Ok(()) + w.put_element("delta", Some(&a), |w| { + for el in &self.elements.publishes { + let uri = el.uri.to_string(); + let atr = [("uri", uri.as_ref())]; + w.put_element("publish", Some(&atr), |w| w.put_text(el.base64.as_ref()))?; } - ) + + for el in &self.elements.updates { + let uri = el.uri.to_string(); + let atr = [("uri", uri.as_ref()), ("hash", el.hash.as_ref())]; + w.put_element("publish", Some(&atr), |w| w.put_text(el.base64.as_ref()))?; + } + + for el in &self.elements.withdraws { + let uri = el.uri.to_string(); + let atr = [("uri", uri.as_ref()), ("hash", el.hash.as_ref())]; + w.put_element("withdraw", Some(&atr), |w| w.empty())?; + } + + Ok(()) + }) }); let bytes = Bytes::from(vec); @@ -653,5 +660,4 @@ impl Delta { Ok(hash) } - } diff --git a/commons/src/eventsourcing/agg.rs b/commons/src/eventsourcing/agg.rs index 1a98fd9d..b7fa5c2e 100644 --- a/commons/src/eventsourcing/agg.rs +++ b/commons/src/eventsourcing/agg.rs @@ -1,14 +1,8 @@ -use super::{ - Command, - Event, - Storable -}; - +use super::{Command, Event, Storable}; //------------ Aggregate ----------------------------------------------------- pub trait Aggregate: Storable + Send + Sync + 'static { - type Command: Command; type Event: Event; type InitEvent: Event; @@ -48,4 +42,4 @@ pub trait Aggregate: Storable + Send + Sync + 'static { /// The command is moved, because we want to enable moving its data /// without reallocating. fn process_command(&self, command: Self::Command) -> Result, Self::Error>; -} \ No newline at end of file +} diff --git a/commons/src/eventsourcing/agg_store.rs b/commons/src/eventsourcing/agg_store.rs index 00a8706f..76cc4d50 100644 --- a/commons/src/eventsourcing/agg_store.rs +++ b/commons/src/eventsourcing/agg_store.rs @@ -6,14 +6,7 @@ use std::sync::RwLock; use crate::api::admin::Handle; -use super::{ - Aggregate, - DiskKeyStore, - Event, - EventListener, - KeyStore, - KeyStoreError, -}; +use super::{Aggregate, DiskKeyStore, Event, EventListener, KeyStore, KeyStoreError}; const SNAPSHOT_FREQ: u64 = 5; @@ -47,7 +40,6 @@ pub trait AggregateStore: Send + Sync { fn add_listener>(&mut self, listener: Arc); } - /// This type defines possible Errors for the AggregateStore #[derive(Debug, Display)] pub enum AggregateStoreError { @@ -68,16 +60,17 @@ pub enum AggregateStoreError { } impl From for AggregateStoreError { - fn from(e: KeyStoreError) -> Self { AggregateStoreError::KeyStoreError(e) } + fn from(e: KeyStoreError) -> Self { + AggregateStoreError::KeyStoreError(e) + } } - pub struct DiskAggregateStore { store: DiskKeyStore, cache: RwLock>>, use_cache: bool, listeners: Vec>>, - outer_lock: RwLock<()> + outer_lock: RwLock<()>, } impl DiskAggregateStore { @@ -87,17 +80,22 @@ impl DiskAggregateStore { let use_cache = true; let listeners = vec![]; let lock = RwLock::new(()); - Ok(DiskAggregateStore { store, cache, use_cache, listeners, outer_lock: lock }) + Ok(DiskAggregateStore { + store, + cache, + use_cache, + listeners, + outer_lock: lock, + }) } } impl DiskAggregateStore { - fn has_updates( - &self, - id: &Handle, - aggregate: &A - ) -> StoreResult { - Ok(self.store.get_event::(id, aggregate.version())?.is_some()) + fn has_updates(&self, id: &Handle, aggregate: &A) -> StoreResult { + Ok(self + .store + .get_event::(id, aggregate.version())? + .is_some()) } fn cache_get(&self, id: &Handle) -> Option> { @@ -117,18 +115,16 @@ impl DiskAggregateStore { fn get_latest_no_lock(&self, handle: &Handle) -> StoreResult> { debug!("Trying to load aggregate id: {}", handle); match self.cache_get(handle) { - None => { - match self.store.get_aggregate(handle)? { - None => { - error!("Could not load aggregate with id: {} from disk", handle); - Err(AggregateStoreError::UnknownAggregate(handle.clone())) - }, - Some(agg) => { - let arc: Arc = Arc::new(agg); - self.cache_update(handle, arc.clone()); - debug!("Loaded aggregate id: {} from disk", handle); - Ok(arc) - } + None => match self.store.get_aggregate(handle)? { + None => { + error!("Could not load aggregate with id: {} from disk", handle); + Err(AggregateStoreError::UnknownAggregate(handle.clone())) + } + Some(agg) => { + let arc: Arc = Arc::new(agg); + self.cache_update(handle, arc.clone()); + debug!("Loaded aggregate id: {} from disk", handle); + Ok(arc) } }, Some(mut arc) => { @@ -149,10 +145,7 @@ impl AggregateStore for DiskAggregateStore { self.get_latest_no_lock(handle) } - fn add( - &self, - init: A::InitEvent - ) -> StoreResult> { + fn add(&self, init: A::InitEvent) -> StoreResult> { let _lock = self.outer_lock.write().unwrap(); self.store.store_event(&init)?; @@ -168,13 +161,7 @@ impl AggregateStore for DiskAggregateStore { Ok(arc) } - - fn update( - &self, - handle: &Handle, - prev: Arc, - events: Vec - ) -> StoreResult> { + fn update(&self, handle: &Handle, prev: Arc, events: Vec) -> StoreResult> { let _lock = self.outer_lock.write().unwrap(); // Get the latest arc. @@ -182,7 +169,7 @@ impl AggregateStore for DiskAggregateStore { { // Verify whether there is a concurrency issue if prev.version() != latest.version() { - return Err(AggregateStoreError::ConcurrentModification(handle.clone())) + return Err(AggregateStoreError::ConcurrentModification(handle.clone())); } // forget the previous version @@ -191,7 +178,6 @@ impl AggregateStore for DiskAggregateStore { // make the arc mutable, hopefully forgetting prev will avoid the clone let agg = Arc::make_mut(&mut latest); - // Using a lock on the hashmap here to ensure that all updates happen sequentially. // It would be better to get a lock only for this specific aggregate. So it may be // worth rethinking the structure. @@ -213,8 +199,7 @@ impl AggregateStore for DiskAggregateStore { for i in 0..nr_events { let event = &events[i as usize]; - if event.version() != version_before + i || - event.handle() != handle { + if event.version() != version_before + i || event.handle() != handle { return Err(AggregateStoreError::WrongEventForAggregate); } } @@ -253,4 +238,4 @@ impl AggregateStore for DiskAggregateStore { self.listeners.push(listener) } -} \ No newline at end of file +} diff --git a/commons/src/eventsourcing/cmd.rs b/commons/src/eventsourcing/cmd.rs index c2625f61..31400be7 100644 --- a/commons/src/eventsourcing/cmd.rs +++ b/commons/src/eventsourcing/cmd.rs @@ -2,7 +2,6 @@ use crate::api::admin::Handle; use super::Event; - //------------ Command ------------------------------------------------------- /// Commands are used to send an intent to change an aggregate. @@ -33,10 +32,11 @@ pub trait Command { /// Note that this defaults to true, which is the safe choice when in /// doubt. If you choose to implement this, then you will also need to /// implement the ['set_affected_version'] function. - fn conflicts(&self, _events: &[Self::Event]) -> bool { true } + fn conflicts(&self, _events: &[Self::Event]) -> bool { + true + } } - //------------ SentCommand --------------------------------------------------- /// Convenience wrapper so that implementations can just implement @@ -45,7 +45,7 @@ pub trait Command { pub struct SentCommand { handle: Handle, version: Option, - details: C + details: C, } impl Command for SentCommand { @@ -61,15 +61,19 @@ impl Command for SentCommand { } impl SentCommand { - pub fn new(id: &Handle, version: Option, details: C) -> Self { - SentCommand { handle: id.clone(), version, details } + SentCommand { + handle: id.clone(), + version, + details, + } } - pub fn into_details(self) -> C { self.details } + pub fn into_details(self) -> C { + self.details + } } - //------------ CommandDetails ------------------------------------------------ /// Implement this for an enum with CommandDetails, so you you can reuse the diff --git a/commons/src/eventsourcing/evt.rs b/commons/src/eventsourcing/evt.rs index c157bf61..938e86a8 100644 --- a/commons/src/eventsourcing/evt.rs +++ b/commons/src/eventsourcing/evt.rs @@ -2,7 +2,6 @@ use crate::api::admin::Handle; use super::Storable; - //------------ Event -------------------------------------------------------- pub trait Event: Storable + 'static { @@ -20,18 +19,25 @@ pub struct StoredEvent { id: Handle, version: u64, #[serde(deserialize_with = "E::deserialize")] - details: E + details: E, } impl StoredEvent { - pub fn new(id: &Handle, version: u64, event: E) -> Self { - StoredEvent { id: id.clone(), version, details: event } + StoredEvent { + id: id.clone(), + version, + details: event, + } } - pub fn details(&self) -> &E { & self.details } + pub fn details(&self) -> &E { + &self.details + } - pub fn into_details(self) -> E { self.details } + pub fn into_details(self) -> E { + self.details + } /// Return the parts of this event. pub fn unwrap(self) -> (Handle, u64, E) { @@ -47,4 +53,4 @@ impl Event for StoredEvent { fn version(&self) -> u64 { self.version } -} \ No newline at end of file +} diff --git a/commons/src/eventsourcing/listener.rs b/commons/src/eventsourcing/listener.rs index de52710e..b614f5c8 100644 --- a/commons/src/eventsourcing/listener.rs +++ b/commons/src/eventsourcing/listener.rs @@ -16,21 +16,22 @@ pub trait EventListener: Send + Sync + 'static { fn listen(&self, agg: &A, event: &A::Event); } - //------------ EventCounter -------------------------------------------------- /// Example listener that simply counts all events pub struct EventCounter { - counter: RwLock + counter: RwLock, } struct Counter { - total: usize + total: usize, } impl Default for EventCounter { fn default() -> Self { - EventCounter { counter: RwLock::new(Counter { total: 0 }) } + EventCounter { + counter: RwLock::new(Counter { total: 0 }), + } } } diff --git a/commons/src/eventsourcing/mod.rs b/commons/src/eventsourcing/mod.rs index 2b6b9343..5e7f3a04 100644 --- a/commons/src/eventsourcing/mod.rs +++ b/commons/src/eventsourcing/mod.rs @@ -1,44 +1,22 @@ //! Event sourcing support for Krill mod agg; -pub use self::agg::{ - Aggregate, -}; +pub use self::agg::Aggregate; mod evt; -pub use self::evt::{ - Event, - StoredEvent -}; +pub use self::evt::{Event, StoredEvent}; mod cmd; -pub use self::cmd::{ - Command, - CommandDetails, - SentCommand -}; +pub use self::cmd::{Command, CommandDetails, SentCommand}; mod store; -pub use self::store::{ - DiskKeyStore, - KeyStore, - KeyStoreError, - Storable -}; +pub use self::store::{DiskKeyStore, KeyStore, KeyStoreError, Storable}; mod agg_store; -pub use self::agg_store::{ - AggregateStore, - AggregateStoreError, - DiskAggregateStore -}; +pub use self::agg_store::{AggregateStore, AggregateStoreError, DiskAggregateStore}; mod listener; -pub use self::listener::{ - EventCounter, - EventListener -}; - +pub use self::listener::{EventCounter, EventListener}; //------------ Tests --------------------------------------------------------- @@ -69,19 +47,23 @@ mod tests { type InitPersonEvent = StoredEvent; impl InitPersonEvent { - pub fn init(id: &Handle, name: &str) -> Self { - StoredEvent::new(id, 0, InitPersonDetails { name: name.to_string()}) + StoredEvent::new( + id, + 0, + InitPersonDetails { + name: name.to_string(), + }, + ) } } #[derive(Clone, Deserialize, Serialize)] struct InitPersonDetails { - pub name: String + pub name: String, } - -//------------ InitPersonEvent ----------------------------------------------- + //------------ InitPersonEvent ----------------------------------------------- /// Every aggregate defines their own set of events - i.e. state changes. The /// state of an aggregate can only change when events are applied. And events @@ -97,7 +79,7 @@ mod tests { #[derive(Clone, Deserialize, Serialize)] enum PersonEventDetails { NameChanged(String), - HadBirthday + HadBirthday, } impl PersonEvent { @@ -106,14 +88,10 @@ mod tests { } pub fn name_changed(p: &Person, name: String) -> Self { - StoredEvent::new( - p.id(), - p.version, - PersonEventDetails::NameChanged(name)) + StoredEvent::new(p.id(), p.version, PersonEventDetails::NameChanged(name)) } } - //------------ PersonCommand ------------------------------------------------- /// In order to change an aggregate a command is sent to it. The aggregate @@ -134,7 +112,7 @@ mod tests { #[derive(Clone, Deserialize, Serialize)] enum PersonCommandDetails { ChangeName(String), - GoAroundTheSun + GoAroundTheSun, } impl CommandDetails for PersonCommandDetails { @@ -142,12 +120,10 @@ mod tests { } impl PersonCommand { - pub fn go_around_sun(id: &Handle, version: Option) -> Self { Self::new(id, version, PersonCommandDetails::GoAroundTheSun) } - pub fn change_name(id: &Handle, version: Option, s: &str) -> Self { let details = PersonCommandDetails::ChangeName(s.to_string()); Self::new(id, version, details) @@ -161,19 +137,17 @@ mod tests { #[derive(Clone, Debug, Display)] enum PersonError { #[display(fmt = "No person can live longer than 255 years")] - TooOld + TooOld, } impl std::error::Error for PersonError {} - //------------ PersonResult -------------------------------------------------- /// A shorthand for the result type returned by the process_command function /// of the Person aggregate. type PersonResult = Result, PersonError>; - //------------ Person ------------------------------------------------------ /// Defines a person object. Persons have a name and an age. @@ -191,14 +165,22 @@ mod tests { version: u64, name: String, - age: u8 + age: u8, } impl Person { - pub fn id(&self) -> &Handle { &self.id } - pub fn version(&self) -> u64 { self.version } - pub fn name(&self) -> &String { &self.name } - pub fn age(&self) -> u8 { self.age } + pub fn id(&self) -> &Handle { + &self.id + } + pub fn version(&self) -> u64 { + self.version + } + pub fn name(&self) -> &String { + &self.name + } + pub fn age(&self) -> u8 { + self.age + } } impl Aggregate for Person { @@ -210,7 +192,10 @@ mod tests { fn init(event: InitPersonEvent) -> Result { let (id, _version, init) = event.unwrap(); Ok(Person { - id, version: 1, name: init.name, age: 0 + id, + version: 1, + name: init.name, + age: 0, }) } @@ -220,8 +205,8 @@ mod tests { fn apply(&mut self, event: PersonEvent) { match event.into_details() { - PersonEventDetails::NameChanged(name) => { self.name = name }, - PersonEventDetails::HadBirthday => { self.age += 1 } + PersonEventDetails::NameChanged(name) => self.name = name, + PersonEventDetails::HadBirthday => self.age += 1, } self.version += 1; } @@ -231,7 +216,7 @@ mod tests { PersonCommandDetails::ChangeName(name) => { let event = PersonEvent::name_changed(&self, name); Ok(vec![event]) - }, + } PersonCommandDetails::GoAroundTheSun => { if self.age == 255 { Err(PersonError::TooOld) @@ -247,7 +232,6 @@ mod tests { #[test] fn test() { test::test_under_tmp(|d| { - let counter = Arc::new(EventCounter::default()); let mut manager = DiskAggregateStore::::new(&d, "person").unwrap(); manager.add_listener(counter.clone()); @@ -269,7 +253,7 @@ mod tests { age += 1; if age == 21 { - break + break; } } @@ -290,7 +274,6 @@ mod tests { assert_eq!(21, alice.age()); assert_eq!(22, counter.total()) - }) } -} \ No newline at end of file +} diff --git a/commons/src/eventsourcing/store.rs b/commons/src/eventsourcing/store.rs index 543e3f97..f42c8732 100644 --- a/commons/src/eventsourcing/store.rs +++ b/commons/src/eventsourcing/store.rs @@ -5,30 +5,24 @@ use std::io; use std::io::Write; use std::path::PathBuf; -use serde::Serialize; use serde::de::DeserializeOwned; +use serde::Serialize; use serde_json; use crate::api::admin::Handle; use crate::util::file; -use super::{ - Aggregate, - Event, -}; - +use super::{Aggregate, Event}; //------------ Storable ------------------------------------------------------ pub trait Storable: Clone + Serialize + DeserializeOwned + Sized + 'static {} -impl Storable for T { } - +impl Storable for T {} //------------ KeyStore ------------------------------------------------------ /// Generic KeyStore for AggregateManager pub trait KeyStore { - type Key; fn key_for_snapshot() -> Self::Key; @@ -38,7 +32,6 @@ pub trait KeyStore { fn has_key(&self, id: &Handle, key: &Self::Key) -> bool; - fn has_aggregate(&self, id: &Handle) -> bool; fn aggregates(&self) -> Vec; // Use Iterator? @@ -49,7 +42,7 @@ pub trait KeyStore { &self, id: &Handle, key: &Self::Key, - value: &V + value: &V, ) -> Result<(), KeyStoreError>; /// Get the value for this key, if any exists. @@ -57,39 +50,28 @@ pub trait KeyStore { fn get( &self, id: &Handle, - key: &Self::Key + key: &Self::Key, ) -> Result, KeyStoreError>; /// Get the value for this key, if any exists. - fn get_event( - &self, - id: &Handle, - version: u64 - ) -> Result, KeyStoreError>; + fn get_event(&self, id: &Handle, version: u64) -> Result, KeyStoreError>; - fn store_event( - &self, - event: &V - ) -> Result<(), KeyStoreError>; + fn store_event(&self, event: &V) -> Result<(), KeyStoreError>; /// Get the latest aggregate - fn get_aggregate( - &self, - id: &Handle - ) -> Result, KeyStoreError>; + fn get_aggregate(&self, id: &Handle) -> Result, KeyStoreError>; /// Saves the latest snapshot - overwrites any previous snapshot. fn store_aggregate( &self, id: &Handle, - aggregate: &V + aggregate: &V, ) -> Result<(), KeyStoreError>; } - //------------ KeyStoreError ------------------------------------------------- /// This type defines possible Errors for KeyStore @@ -105,19 +87,22 @@ pub enum KeyStoreError { KeyExists(String), #[display(fmt = "Aggregate init event exists, but cannot be applied")] - InitError + InitError, } impl From for KeyStoreError { - fn from(e: io::Error) -> Self { KeyStoreError::IoError(e) } + fn from(e: io::Error) -> Self { + KeyStoreError::IoError(e) + } } impl From for KeyStoreError { - fn from(e: serde_json::Error) -> Self { KeyStoreError::JsonError(e) } + fn from(e: serde_json::Error) -> Self { + KeyStoreError::JsonError(e) + } } -impl std::error::Error for KeyStoreError { } - +impl std::error::Error for KeyStoreError {} //------------ DiskKeyStore -------------------------------------------------- @@ -166,7 +151,7 @@ impl KeyStore for DiskKeyStore { &self, id: &Handle, key: &Self::Key, - value: &V + value: &V, ) -> Result<(), KeyStoreError> { let mut f = file::create_file_with_path(&self.file_path(id, key))?; let json = serde_json::to_string_pretty(value)?; @@ -177,7 +162,7 @@ impl KeyStore for DiskKeyStore { fn get( &self, id: &Handle, - key: &Self::Key + key: &Self::Key, ) -> Result, KeyStoreError> { let path = self.file_path(id, key); let path_str = path.to_string_lossy().into_owned(); @@ -188,7 +173,7 @@ impl KeyStore for DiskKeyStore { Err(e) => { error!("Could not deserialize json at: {}, error: {}", path_str, e); Err(KeyStoreError::JsonError(e)) - }, + } Ok(v) => { debug!("Deserialized json at: {}", path_str); Ok(Some(v)) @@ -201,11 +186,7 @@ impl KeyStore for DiskKeyStore { } /// Get the value for this key, if any exists. - fn get_event( - &self, - id: &Handle, - version: u64 - ) -> Result, KeyStoreError> { + fn get_event(&self, id: &Handle, version: u64) -> Result, KeyStoreError> { let path = self.path_for_event(id, version); let path_str = path.to_string_lossy().into_owned(); @@ -215,7 +196,7 @@ impl KeyStore for DiskKeyStore { Err(e) => { error!("Could not deserialize json at: {}, error: {}", path_str, e); Err(KeyStoreError::JsonError(e)) - }, + } Ok(v) => { debug!("Deserialized event at: {}", path_str); Ok(Some(v)) @@ -227,10 +208,7 @@ impl KeyStore for DiskKeyStore { } } - fn store_event( - &self, - event: &V - ) -> Result<(), KeyStoreError> { + fn store_event(&self, event: &V) -> Result<(), KeyStoreError> { let id = event.handle(); let key = Self::key_for_event(event.version()); if self.has_key(id, &key) { @@ -240,22 +218,17 @@ impl KeyStore for DiskKeyStore { } } - fn get_aggregate( - &self, - id: &Handle - ) -> Result, KeyStoreError> { + fn get_aggregate(&self, id: &Handle) -> Result, KeyStoreError> { // try to get a snapshot. // If that fails, try to get the init event. // Then replay all newer events that can be found. let key = Self::key_for_snapshot(); let aggregate_opt = match self.get::(id, &key)? { Some(aggregate) => Some(aggregate), - None => { - match self.get_event::(id, 0)? { - Some(e) => Some(V::init(e).map_err(|_|KeyStoreError::InitError)?), - None => None - } - } + None => match self.get_event::(id, 0)? { + Some(e) => Some(V::init(e).map_err(|_| KeyStoreError::InitError)?), + None => None, + }, }; match aggregate_opt { @@ -270,7 +243,7 @@ impl KeyStore for DiskKeyStore { fn store_aggregate( &self, id: &Handle, - aggregate: &V + aggregate: &V, ) -> Result<(), KeyStoreError> { let key = Self::key_for_snapshot(); self.store(id, &key, aggregate) @@ -285,13 +258,10 @@ impl DiskKeyStore { } /// Creates a directory for the name_space under the work_dir. - pub fn under_work_dir( - work_dir: &PathBuf, - name_space: &str - ) -> Result { + pub fn under_work_dir(work_dir: &PathBuf, name_space: &str) -> Result { let mut path = work_dir.clone(); path.push(name_space); - if ! path.is_dir() { + if !path.is_dir() { fs::create_dir_all(&path)?; } Ok(Self::new(work_dir, name_space)) @@ -309,11 +279,7 @@ impl DiskKeyStore { dir_path } - fn path_for_event( - &self, - id: &Handle, - version: u64 - ) -> PathBuf { + fn path_for_event(&self, id: &Handle, version: u64) -> PathBuf { let mut file_path = self.dir_for_aggregate(id); file_path.push(format!("delta-{}.json", version)); file_path @@ -322,11 +288,11 @@ impl DiskKeyStore { pub fn update_aggregate( &self, id: &Handle, - aggregate: &mut A + aggregate: &mut A, ) -> Result<(), KeyStoreError> { while let Some(e) = self.get_event(id, aggregate.version())? { aggregate.apply(e); } Ok(()) } -} \ No newline at end of file +} diff --git a/commons/src/lib.rs b/commons/src/lib.rs index d8bd0046..96d47e2c 100644 --- a/commons/src/lib.rs +++ b/commons/src/lib.rs @@ -1,22 +1,26 @@ //! Common types used by the various Krill components. extern crate base64; -#[macro_use] extern crate bcder; +#[macro_use] +extern crate bcder; extern crate bytes; extern crate chrono; -#[macro_use] extern crate derive_more; +#[macro_use] +extern crate derive_more; extern crate futures; extern crate hex; -#[macro_use] extern crate log; +#[macro_use] +extern crate log; extern crate openssl; extern crate rand; extern crate reqwest; extern crate rpki; -#[macro_use] extern crate serde; +#[macro_use] +extern crate serde; +extern crate core; extern crate serde_json; extern crate syslog; extern crate xml as xmlrs; -extern crate core; pub mod api; pub mod eventsourcing; diff --git a/commons/src/remote/api.rs b/commons/src/remote/api.rs index 4394c7c9..88740447 100644 --- a/commons/src/remote/api.rs +++ b/commons/src/remote/api.rs @@ -15,33 +15,38 @@ pub struct ClientAuth { } impl ClientAuth { - pub fn new( - cert: IdCert, - ) -> Self { + pub fn new(cert: IdCert) -> Self { ClientAuth { cert } } - pub fn cert(&self) -> &IdCert { &self.cert } - pub fn set_cert(&mut self, cert: IdCert) { self.cert = cert; } + pub fn cert(&self) -> &IdCert { + &self.cert + } + pub fn set_cert(&mut self, cert: IdCert) { + self.cert = cert; + } } - //------------ ClientInfo --------------------------------------------------- #[derive(Debug, Clone, Deserialize, Eq, PartialEq, Serialize)] pub struct ClientInfo { handle: Handle, - auth: ClientAuth + auth: ClientAuth, } impl ClientInfo { pub fn new(handle: Handle, auth: ClientAuth) -> Self { ClientInfo { handle, auth } } - pub fn unwrap(self) -> (Handle, ClientAuth ) { + pub fn unwrap(self) -> (Handle, ClientAuth) { (self.handle, self.auth) } - pub fn handle(&self) -> &Handle { &self.handle } - pub fn auth(&self) -> &ClientAuth { &self.auth } + pub fn handle(&self) -> &Handle { + &self.handle + } + pub fn auth(&self) -> &ClientAuth { + &self.auth + } } //------------ CmsClientInfo ----------------------------------------------- @@ -59,17 +64,38 @@ impl CmsClientInfo { handle: Handle, cert: IdCert, key_id: SignerKeyId, - publication_uri: uri::Https + publication_uri: uri::Https, ) -> Self { - CmsClientInfo { handle, server_cert: cert, key_id, publication_uri } + CmsClientInfo { + handle, + server_cert: cert, + key_id, + publication_uri, + } } - pub fn handle(&self) -> &Handle { &self.handle } - pub fn set_handle(&mut self, handle: Handle) { self.handle = handle; } - pub fn server_cert(&self) -> &IdCert { &self.server_cert } - pub fn set_server_cert(&mut self, cert: IdCert) { self.server_cert = cert; } - pub fn key_id(&self) -> &SignerKeyId { &self.key_id } - pub fn set_key_id(&mut self, key_id: SignerKeyId) { self.key_id = key_id; } - pub fn publication_uri(&self) -> &uri::Https { &self.publication_uri } - pub fn set_publication_uri(&mut self, uri: uri::Https) { self.publication_uri = uri; } -} \ No newline at end of file + pub fn handle(&self) -> &Handle { + &self.handle + } + pub fn set_handle(&mut self, handle: Handle) { + self.handle = handle; + } + pub fn server_cert(&self) -> &IdCert { + &self.server_cert + } + pub fn set_server_cert(&mut self, cert: IdCert) { + self.server_cert = cert; + } + pub fn key_id(&self) -> &SignerKeyId { + &self.key_id + } + pub fn set_key_id(&mut self, key_id: SignerKeyId) { + self.key_id = key_id; + } + pub fn publication_uri(&self) -> &uri::Https { + &self.publication_uri + } + pub fn set_publication_uri(&mut self, uri: uri::Https) { + self.publication_uri = uri; + } +} diff --git a/commons/src/remote/builder.rs b/commons/src/remote/builder.rs index a0eb146f..78ae4bfd 100644 --- a/commons/src/remote/builder.rs +++ b/commons/src/remote/builder.rs @@ -1,44 +1,32 @@ //! Support for building RPKI Certificates and Objects -use std::fmt; -use bcder::{BitString, Mode, OctetString, Oid, Tag}; -use bcder::{decode, encode}; use bcder::encode::{Constructed, PrimitiveContent, Values}; +use bcder::{decode, encode}; +use bcder::{BitString, Mode, OctetString, Oid, Tag}; use bytes::Bytes; use chrono::Utc; -use rpki::cert::ext::{ - AuthorityKeyIdentifier, - CrlNumber, - Extensions, - KeyIdentifier -}; +use rpki::cert::ext::{AuthorityKeyIdentifier, CrlNumber, Extensions, KeyIdentifier}; use rpki::crl::Crl; -use rpki::crypto::{ - DigestAlgorithm, - Signature, - SignatureAlgorithm, - Signer, - SigningError, - PublicKey -}; use rpki::crypto::signer::KeyError; +use rpki::crypto::{ + DigestAlgorithm, PublicKey, Signature, SignatureAlgorithm, Signer, SigningError, +}; use rpki::oid; -use rpki::x509::{Name, Validity, Time}; +use rpki::x509::{Name, Time, Validity}; +use std::fmt; use crate::remote::id::{IdCert, IdExtensions}; - //------------ TbsCertificate ------------------------------------------------ /// The supported extension types for our RPKI TbsCertificate #[allow(clippy::large_enum_variant)] pub enum RpkiTbsExtension { ResourceExtensions(Extensions), - IdExtensions(IdExtensions) + IdExtensions(IdExtensions), } /// This type represents the signed content part of an RPKI Certificate. pub struct RpkiTbsCertificate { - // The General structure is documented in section 4.1 or RFC5280 // // TBSCertificate ::= SEQUENCE { @@ -77,7 +65,6 @@ pub struct RpkiTbsCertificate { /// # Encoding /// impl RpkiTbsCertificate { - /// Encodes this certificate. pub fn encode<'a>(&'a self) -> impl encode::Values + 'a { match self.extensions { @@ -86,23 +73,21 @@ impl RpkiTbsCertificate { ( Constructed::new( Tag::CTX_0, - 2.encode() // Version 3 is encoded as 2 + 2.encode(), // Version 3 is encoded as 2 ), self.serial_number.encode(), SignatureAlgorithm::default().x509_encode(), - self.issuer.encode_ref() + self.issuer.encode_ref(), ), ( self.validity.encode(), self.subject.encode_ref(), self.subject_public_key_info.clone().encode(), - id_ext.encode() - ) + id_ext.encode(), + ), )) - }, - RpkiTbsExtension::ResourceExtensions(ref _ext) => { - unimplemented!() } + RpkiTbsExtension::ResourceExtensions(ref _ext) => unimplemented!(), } } } @@ -116,7 +101,7 @@ impl RpkiTbsCertificate { validity: Validity, subject: Name, subject_public_key_info: PublicKey, - extensions: RpkiTbsExtension + extensions: RpkiTbsExtension, ) -> Self { Self { serial_number, @@ -124,7 +109,7 @@ impl RpkiTbsCertificate { validity, subject, subject_public_key_info, - extensions + extensions, } } } @@ -154,9 +139,8 @@ impl IdCertBuilder { duration: ::chrono::Duration, issuing_key: &PublicKey, subject_key: &PublicKey, - ext: IdExtensions - ) -> RpkiTbsCertificate - { + ext: IdExtensions, + ) -> RpkiTbsCertificate { let issuer = Name::from_pub_key(issuing_key); let validity = Validity::from_duration(duration); let subject = Name::from_pub_key(subject_key); @@ -167,7 +151,7 @@ impl IdCertBuilder { validity, subject, subject_public_key_info: subject_key.clone(), - extensions: RpkiTbsExtension::IdExtensions(ext) + extensions: RpkiTbsExtension::IdExtensions(ext), } } @@ -175,18 +159,12 @@ impl IdCertBuilder { issuing_key: &S::KeyId, subject_key: &PublicKey, ext: IdExtensions, - signer: &S + signer: &S, ) -> Result> { let issuing_key_info = signer.get_key_info(issuing_key)?; let dur = ::chrono::Duration::weeks(52000); - let tbs = Self::make_tbs_certificate_request( - 1, - dur, - &issuing_key_info, - &subject_key, - ext - ); + let tbs = Self::make_tbs_certificate_request(1, dur, &issuing_key_info, &subject_key, ext); let enc_cert = tbs.encode(); let enc_cert_c = enc_cert.to_captured(Mode::Der); @@ -194,20 +172,18 @@ impl IdCertBuilder { let signature = BitString::new( 0, - signer.sign( - issuing_key, - SignatureAlgorithm::default(), - enc_cert_b - )?.value().clone() + signer + .sign(issuing_key, SignatureAlgorithm::default(), enc_cert_b)? + .value() + .clone(), ); - let captured_cert = encode::sequence ( - ( - enc_cert, - SignatureAlgorithm::default().x509_encode(), - signature.encode() - ) - ).to_captured(Mode::Der); + let captured_cert = encode::sequence(( + enc_cert, + SignatureAlgorithm::default().x509_encode(), + signature.encode(), + )) + .to_captured(Mode::Der); // Todo -> Return the bytes, or a captured, not a parsed cert let id_cert = IdCert::decode(captured_cert.as_ref()).unwrap(); @@ -221,80 +197,57 @@ impl IdCertBuilder { /// component. pub fn new_ta_id_cert( issuing_key: &S::KeyId, - signer: &S + signer: &S, ) -> Result> { let issuing_key_info = signer.get_key_info(issuing_key)?; let ext = IdExtensions::for_id_ta_cert(&issuing_key_info); - let cert = IdCertBuilder::create_signed_cert( - issuing_key, - &issuing_key_info, - ext, - signer - )?; + let cert = IdCertBuilder::create_signed_cert(issuing_key, &issuing_key_info, ext, signer)?; Ok(cert) } pub fn new_ee_cert( issuing_key: &S::KeyId, subject_key: &PublicKey, - signer: &S + signer: &S, ) -> Result> { let issuing_key_info = signer.get_key_info(issuing_key)?; - let ext = IdExtensions::for_id_ee_cert( - subject_key, - &issuing_key_info - ); + let ext = IdExtensions::for_id_ee_cert(subject_key, &issuing_key_info); - let cert = IdCertBuilder::create_signed_cert( - issuing_key, - subject_key, - ext, - signer - )?; + let cert = IdCertBuilder::create_signed_cert(issuing_key, subject_key, ext, signer)?; Ok(cert) } } - //------------ SignedMessageBuilder ------------------------------------------ pub struct SignedMessageBuilder { content: OctetString, signer_info: SignedSignerInfo, ee_cert: IdCert, - crl: Crl + crl: Crl, } impl SignedMessageBuilder { pub fn create( issuing_key: &S::KeyId, signer: &S, - message: Bytes + message: Bytes, ) -> Result> { let content = OctetString::new(message); - let signer_info = SignerInfoBuilder::create( - signer, - &content.to_bytes() - )?; + let signer_info = SignerInfoBuilder::create(signer, &content.to_bytes())?; - let ee_cert = IdCertBuilder::new_ee_cert( - issuing_key, - signer_info.one_off_key(), - signer - )?; + let ee_cert = IdCertBuilder::new_ee_cert(issuing_key, signer_info.one_off_key(), signer)?; let crl = CrlBuilder::create(issuing_key, signer)?; - Ok( - SignedMessageBuilder { - content, - signer_info, - ee_cert, - crl - } - ) + Ok(SignedMessageBuilder { + content, + signer_info, + ee_cert, + crl, + }) } pub fn as_bytes(&self) -> Bytes { @@ -302,7 +255,6 @@ impl SignedMessageBuilder { } pub fn encode<'a>(&'a self) -> impl encode::Values + 'a { - // ContentInfo ::= SEQUENCE { // contentType ContentType, // content [0] EXPLICIT ANY DEFINED BY contentType } @@ -324,57 +276,32 @@ impl SignedMessageBuilder { // The eContentType for the RPKI Protocol Message object is defined as // id-ct-xml, and has the numerical value of 1.2.840.113549.1.9.16.1.28. - let digest_algorithms = encode::set( - encode::sequence( - rpki::oid::SHA256.encode() - ) - ); + let digest_algorithms = encode::set(encode::sequence(rpki::oid::SHA256.encode())); - let encap_content_info = encode::sequence( - ( - oid::PROTOCOL_CONTENT_TYPE.encode(), - Constructed::new(Tag::CTX_0, self.content.clone().encode()) - ) - ); + let encap_content_info = encode::sequence(( + oid::PROTOCOL_CONTENT_TYPE.encode(), + Constructed::new(Tag::CTX_0, self.content.clone().encode()), + )); - let certificates = Constructed::new( - Tag::CTX_0, - self.ee_cert.encode() - ); + let certificates = Constructed::new(Tag::CTX_0, self.ee_cert.encode()); - let crls = Constructed::new( - Tag::CTX_1, - self.crl.encode_ref() - ); + let crls = Constructed::new(Tag::CTX_1, self.crl.encode_ref()); let signer_infos = encode::set(self.signer_info.encode()); - encode::sequence( - ( - oid::SIGNED_DATA.encode(), - Constructed::new( - Tag::CTX_0, - encode::sequence( - ( - ( - 3.encode(), - digest_algorithms, - encap_content_info - ), - ( - certificates, - crls, - signer_infos - ) - ) - ) - ) - ) - ) + encode::sequence(( + oid::SIGNED_DATA.encode(), + Constructed::new( + Tag::CTX_0, + encode::sequence(( + (3.encode(), digest_algorithms, encap_content_info), + (certificates, crls, signer_infos), + )), + ), + )) } } - /// This type represent Signed Attributes in Signer Info. /// /// ```text @@ -393,13 +320,12 @@ impl SignedMessageBuilder { /// See section 2.1.6.4 of RFC 6488 for specifications. /// ``` pub struct SignedAttributes { - content_type: &'static Oid<& 'static [u8]>, + content_type: &'static Oid<&'static [u8]>, digest: OctetString, - signing_time: Time + signing_time: Time, } impl SignedAttributes { - /// Creates a new SignedAttributes. /// /// Needs the content type for this specific kind of CMS (protocol, ROA, @@ -408,11 +334,7 @@ impl SignedAttributes { /// /// This implementation will include a signing-time attribute using the /// time that the SignedAttributes was created. - pub fn new( - content_type: &'static Oid<&'static [u8]>, - content: &Bytes - ) -> Self { - + pub fn new(content_type: &'static Oid<&'static [u8]>, content: &Bytes) -> Self { let content_digest = DigestAlgorithm::default().digest(content); let digest = Bytes::from(content_digest.as_ref()); @@ -421,70 +343,54 @@ impl SignedAttributes { Self { content_type, digest, - signing_time: Time::now() + signing_time: Time::now(), } } /// Encodes the SignedAttributes for inclusion in a CMS. pub fn encode<'a>(&'a self) -> impl encode::Values + 'a { ( - encode::sequence( - ( - oid::CONTENT_TYPE.encode(), - encode::set( - self.content_type.encode() - ) - ) - ), - encode::sequence ( - ( - // This implementation will include a signing-time - // attribute using the time that the SignedAttributes - // was created. - oid::SIGNING_TIME.encode(), - encode::set( - self.signing_time.encode() - ) - ) - ), - encode::sequence( - ( - oid::MESSAGE_DIGEST.encode(), - encode::set( - self.digest.clone().encode() - ) - ) - ) + encode::sequence(( + oid::CONTENT_TYPE.encode(), + encode::set(self.content_type.encode()), + )), + encode::sequence(( + // This implementation will include a signing-time + // attribute using the time that the SignedAttributes + // was created. + oid::SIGNING_TIME.encode(), + encode::set(self.signing_time.encode()), + )), + encode::sequence(( + oid::MESSAGE_DIGEST.encode(), + encode::set(self.digest.clone().encode()), + )), ) } /// Generates a signature using a one time key - pub fn sign( - &self, - signer: &S - ) -> Result<(Signature, PublicKey), Error> { + pub fn sign(&self, signer: &S) -> Result<(Signature, PublicKey), Error> { // See section 5.4 of RFC 5652 // ...The IMPLICIT [0] tag in the signedAttrs is not used for the DER // encoding, rather an EXPLICIT SET OF tag is used... let encode_in_set = encode::set(self.encode()).to_captured(Mode::Der); - signer.sign_one_off(SignatureAlgorithm::default(), encode_in_set.as_slice()) + signer + .sign_one_off(SignatureAlgorithm::default(), encode_in_set.as_slice()) .map_err(Error::SignerError) } - } - //------------ SignedSignerInfo ---------------------------------------------- pub struct SignedSignerInfo { signed_attributes: SignedAttributes, key: PublicKey, key_id: KeyIdentifier, - signature: OctetString + signature: OctetString, } impl SignedSignerInfo { - pub fn encode<'a>(&'a self) -> impl encode::Values + 'a { + pub fn encode<'a>(&'a self) -> impl encode::Values + 'a { // SignerInfo ::= SEQUENCE { // version CMSVersion, // sid SignerIdentifier, @@ -510,25 +416,15 @@ impl SignedSignerInfo { // it seems this MUST NOT include the explicit NULL here let digest_algo = encode::sequence(oid::SHA256.encode()); - let signed_attrs = Constructed::new( - Tag::CTX_0, - self.signed_attributes.encode() - ); + let signed_attrs = Constructed::new(Tag::CTX_0, self.signed_attributes.encode()); - encode::sequence( + encode::sequence(( + (version, sid, digest_algo, signed_attrs), ( - ( - version, - sid, - digest_algo, - signed_attrs - ), - ( - SignatureAlgorithm::default().cms_encode(), - self.signature.clone().encode() - ) - ) - ) + SignatureAlgorithm::default().cms_encode(), + self.signature.clone().encode(), + ), + )) } pub fn one_off_key(&self) -> &PublicKey { @@ -536,8 +432,6 @@ impl SignedSignerInfo { } } - - //------------ SignerInfoBuilder --------------------------------------------- pub struct SignerInfoBuilder; @@ -553,12 +447,11 @@ impl SignerInfoBuilder { /// really only require some bits. pub fn create( signer: &S, - message: &Bytes + message: &Bytes, ) -> Result> { - let signed_attributes = SignedAttributes::new( &oid::PROTOCOL_CONTENT_TYPE, // XXX TODO: derive from message - message + message, ); let (signature, key) = signed_attributes.sign(signer)?; @@ -566,27 +459,20 @@ impl SignerInfoBuilder { let key_id = KeyIdentifier::new(&key); let signature = OctetString::new(signature.value().clone()); - Ok( - SignedSignerInfo { - signed_attributes, - key, - key_id, - signature - } - ) + Ok(SignedSignerInfo { + signed_attributes, + key, + key_id, + signature, + }) } - } - - - //------------ CrlBuilder ---------------------------------------------------- pub struct CrlBuilder; impl CrlBuilder { - /// Creates a CRL for use with protocol messages. I.e. it revokes nothing, /// because smart people use single use keys for EE certs, and it's valid /// for, like, forever -- cause really this thing is useless. Still it is @@ -594,61 +480,51 @@ impl CrlBuilder { /// /// This will all be changed in future when we implement generating CRLs /// for the RPKI CA. - pub fn create( - issuing_key: &S::KeyId, - signer: &S - ) -> Result> - { + pub fn create(issuing_key: &S::KeyId, signer: &S) -> Result> { let pub_key = signer.get_key_info(issuing_key)?; let name = Name::from_pub_key(&pub_key); let now = Time::new(Utc::now()); - let eternity = Time::new(Utc::now()+::chrono::Duration::weeks(52000)); + let eternity = Time::new(Utc::now() + ::chrono::Duration::weeks(52000)); let crl_number = CrlNumber::new(1); let aki = AuthorityKeyIdentifier::new(&pub_key); let extensions = Constructed::new( Tag::CTX_0, - encode::sequence( - ( - aki.encode(), - crl_number.encode() - ) - ) + encode::sequence((aki.encode(), crl_number.encode())), ); - let crl_data = encode::sequence( + let crl_data = encode::sequence(( ( - ( - 1.encode(), - SignatureAlgorithm::default().x509_encode(), - name.encode_ref() - ), - ( - now.encode(), - eternity.encode(), - // Real revocations go here - extensions - ) - ) - ); + 1.encode(), + SignatureAlgorithm::default().x509_encode(), + name.encode_ref(), + ), + ( + now.encode(), + eternity.encode(), + // Real revocations go here + extensions, + ), + )); let signature = BitString::new( 0, - signer.sign( - issuing_key, - SignatureAlgorithm::default(), - crl_data.to_captured(Mode::Der).as_slice() - )?.value().clone() + signer + .sign( + issuing_key, + SignatureAlgorithm::default(), + crl_data.to_captured(Mode::Der).as_slice(), + )? + .value() + .clone(), ); - let crl_obj = encode::sequence( - ( - crl_data, - SignatureAlgorithm::default().x509_encode(), - signature.encode() - ) - ); + let crl_obj = encode::sequence(( + crl_data, + SignatureAlgorithm::default().x509_encode(), + signature.encode(), + )); let crl = Crl::decode(crl_obj.to_captured(Mode::Der).as_ref())?; @@ -656,7 +532,6 @@ impl CrlBuilder { } } - #[derive(Debug, Display)] pub enum Error { #[display(fmt = "{}", _0)] @@ -676,15 +551,21 @@ pub enum Error { } impl From> for Error { - fn from(e: KeyError) -> Self { Error::KeyError(e) } + fn from(e: KeyError) -> Self { + Error::KeyError(e) + } } impl From> for Error { - fn from(e: SigningError) -> Self { Error::SigningError(e) } + fn from(e: SigningError) -> Self { + Error::SigningError(e) + } } impl From for Error { - fn from(e: decode::Error) -> Self { Error::DecodeError(e) } + fn from(e: decode::Error) -> Self { + Error::DecodeError(e) + } } //------------ Tests --------------------------------------------------------- @@ -695,13 +576,13 @@ pub mod tests { use super::*; use crate::util::test; - use signing::softsigner::OpenSslSigner; - use signing::PublicKeyAlgorithm; - use remote::sigmsg::SignedMessage; use publication::query::ListQuery; - use util::softsigner::OpenSslSigner; use remote::publication::query::ListQuery; use remote::rfc8181::ListQuery; + use remote::sigmsg::SignedMessage; + use signing::softsigner::OpenSslSigner; + use signing::PublicKeyAlgorithm; + use util::softsigner::OpenSslSigner; #[test] fn should_create_self_signed_ta_id_cert() { @@ -709,7 +590,7 @@ pub mod tests { let mut s = OpenSslSigner::build(&d); let key_id = s.create_key(&PublicKeyAlgorithm::RsaEncryption).unwrap(); - let id_cert = IdCertBuilder::new_ta_id_cert(&key_id, & mut s).unwrap(); + let id_cert = IdCertBuilder::new_ta_id_cert(&key_id, &mut s).unwrap(); id_cert.validate_ta().unwrap(); }); } @@ -721,7 +602,7 @@ pub mod tests { let key_id = s.create_key(&PublicKeyAlgorithm::RsaEncryption).unwrap(); let key_info = s.get_key_info(&key_id).unwrap(); - let crl = CrlBuilder::create(&key_id, & mut s).unwrap(); + let crl = CrlBuilder::create(&key_id, &mut s).unwrap(); crl.validate(&key_info).unwrap(); }) } @@ -731,15 +612,11 @@ pub mod tests { test::test_with_tmp_dir(|d| { let mut s = OpenSslSigner::build(&d); let key_id = s.create_key(&PublicKeyAlgorithm::RsaEncryption).unwrap(); - let id_cert = IdCertBuilder::new_ta_id_cert(&key_id, & mut s).unwrap(); + let id_cert = IdCertBuilder::new_ta_id_cert(&key_id, &mut s).unwrap(); let message = ListQuery::build_message(); - let builder = SignedMessageBuilder::create( - &key_id, - &mut s, - message.clone() - ).unwrap(); + let builder = SignedMessageBuilder::create(&key_id, &mut s, message.clone()).unwrap(); let encoded_cms = builder.encode().to_captured(Mode::Der); @@ -752,7 +629,4 @@ pub mod tests { }); } - } - - diff --git a/commons/src/remote/clients.rs b/commons/src/remote/clients.rs index f940cd0c..ef6235ce 100644 --- a/commons/src/remote/clients.rs +++ b/commons/src/remote/clients.rs @@ -1,24 +1,14 @@ -use std::collections::HashMap; use crate::api::admin::Handle; -use crate::eventsourcing::{ - Aggregate, - Command, - CommandDetails, - Event, - SentCommand, - StoredEvent -}; -use crate::remote::api::{ - ClientAuth, - ClientInfo -}; +use crate::eventsourcing::{Aggregate, Command, CommandDetails, Event, SentCommand, StoredEvent}; +use crate::remote::api::{ClientAuth, ClientInfo}; use crate::remote::id::IdCert; +use std::collections::HashMap; // const fn is not stable yet const ID: &str = "cms-clients"; -pub fn id() -> Handle { Handle::from(ID) } - - +pub fn id() -> Handle { + Handle::from(ID) +} //------------ ClientsEvents -------------------------------------------- @@ -30,11 +20,19 @@ impl ClientsEvents { } pub fn added_client(version: u64, handle: Handle, client: ClientAuth) -> ClientsEvent { - StoredEvent::new(&id(), version, ClientsEventDetails::AddedClient(handle, client)) + StoredEvent::new( + &id(), + version, + ClientsEventDetails::AddedClient(handle, client), + ) } pub fn updated_cert(version: u64, handle: Handle, cert: IdCert) -> ClientsEvent { - StoredEvent::new(&id(), version, ClientsEventDetails::UpdatedClientCert(handle, cert)) + StoredEvent::new( + &id(), + version, + ClientsEventDetails::UpdatedClientCert(handle, cert), + ) } pub fn removed_client(version: u64, handle: Handle) -> ClientsEvent { @@ -52,22 +50,29 @@ pub type ClientsInit = StoredEvent; pub enum ClientsEventDetails { AddedClient(Handle, ClientAuth), UpdatedClientCert(Handle, IdCert), - RemovedClient(Handle) + RemovedClient(Handle), } pub type ClientsEvent = StoredEvent; - //------------ ClientsCommands ------------------------------------------- pub struct ClientsCommands; impl ClientsCommands { pub fn add(handle: Handle, client: ClientAuth) -> ClientsCommand { - SentCommand::new(&id(), None, ClientsCommandDetails::AddClient(handle, client)) + SentCommand::new( + &id(), + None, + ClientsCommandDetails::AddClient(handle, client), + ) } pub fn update_cert(handle: Handle, cert: IdCert) -> ClientsCommand { - SentCommand::new(&id(), None, ClientsCommandDetails::UpdateClientCert(handle, cert)) + SentCommand::new( + &id(), + None, + ClientsCommandDetails::UpdateClientCert(handle, cert), + ) } pub fn remove(handle: Handle) -> ClientsCommand { SentCommand::new(&id(), None, ClientsCommandDetails::RemoveClient(handle)) @@ -79,7 +84,7 @@ impl ClientsCommands { pub enum ClientsCommandDetails { AddClient(Handle, ClientAuth), UpdateClientCert(Handle, IdCert), - RemoveClient(Handle) + RemoveClient(Handle), } impl CommandDetails for ClientsCommandDetails { @@ -88,7 +93,6 @@ impl CommandDetails for ClientsCommandDetails { pub type ClientsCommand = SentCommand; - //------------ ClientManager ------------------------------------------------- /// This type manages the known clients for the CMS proxy server. I.e. it @@ -101,10 +105,9 @@ pub struct ClientManager { version: u64, // Clients known by this proxy - clients: HashMap + clients: HashMap, } - impl Aggregate for ClientManager { type Command = ClientsCommand; type Event = ClientsEvent; @@ -131,12 +134,12 @@ impl Aggregate for ClientManager { ) } match event.into_details() { - ClientsEventDetails::AddedClient(handle, client) => { + ClientsEventDetails::AddedClient(handle, client) => { self.clients.insert(handle, client); - }, + } ClientsEventDetails::UpdatedClientCert(handle, id_cert) => { self.clients.get_mut(&handle).unwrap().set_cert(id_cert); - }, + } ClientsEventDetails::RemovedClient(handle) => { self.clients.remove(&handle); } @@ -148,7 +151,7 @@ impl Aggregate for ClientManager { fn process_command(&self, command: Self::Command) -> Result, Self::Error> { if let Some(version) = command.version() { if version != self.version { - return Err(Error::ConcurrentModification(version, self.version)) + return Err(Error::ConcurrentModification(version, self.version)); } } @@ -158,11 +161,11 @@ impl Aggregate for ClientManager { ClientsCommandDetails::AddClient(handle, client) => { self.assert_new(&handle)?; res.push(ClientsEvents::added_client(self.version, handle, client)) - }, + } ClientsCommandDetails::UpdateClientCert(handle, cert) => { self.assert_exists(&handle)?; res.push(ClientsEvents::updated_cert(self.version, handle, cert)) - }, + } ClientsCommandDetails::RemoveClient(handle) => { self.assert_exists(&handle)?; res.push(ClientsEvents::removed_client(self.version, handle)) @@ -181,8 +184,8 @@ impl ClientManager { pub fn list(&self) -> Vec { let mut res = vec![]; for (handle, auth) in self.clients.iter() { - res.push(ClientInfo::new(handle.clone(), auth.clone())); - }; + res.push(ClientInfo::new(handle.clone(), auth.clone())); + } res } @@ -193,20 +196,22 @@ impl ClientManager { fn assert_new(&self, handle: &Handle) -> ProxyResult<()> { if self.has_client(handle) { Err(Error::ClientExists(handle.clone())) - } else { Ok(()) } + } else { + Ok(()) + } } - fn assert_exists(&self, handle: &Handle) -> ProxyResult<()> { - if ! self.has_client(handle) { + if !self.has_client(handle) { Err(Error::NoClient(handle.clone())) - } else { Ok(()) } + } else { + Ok(()) + } } } type ProxyResult = Result; - //------------ Error --------------------------------------------------------- #[derive(Debug, Display)] @@ -229,14 +234,14 @@ impl std::error::Error for Error {} pub mod tests { use super::*; - use std::path::PathBuf; - use rpki::crypto::PublicKeyFormat; - use rpki::crypto::Signer; - use crate::util::test; use crate::eventsourcing::AggregateStore; use crate::eventsourcing::DiskAggregateStore; - use crate::util::softsigner::OpenSslSigner; use crate::remote::builder::IdCertBuilder; + use crate::util::softsigner::OpenSslSigner; + use crate::util::test; + use rpki::crypto::PublicKeyFormat; + use rpki::crypto::Signer; + use std::path::PathBuf; pub fn new_id_cert(work_dir: &PathBuf) -> IdCert { let mut s = OpenSslSigner::build(work_dir).unwrap(); @@ -248,17 +253,12 @@ pub mod tests { let cert = new_id_cert(work_dir); let handle = Handle::from(name); - ClientsCommands::add( - handle, - ClientAuth::new(cert) - ) + ClientsCommands::add(handle, ClientAuth::new(cert)) } - #[test] fn should_manage_clients() { test::test_under_tmp(|d| { - // Set up a store for the proxy let store = DiskAggregateStore::::new(&d, "proxy").unwrap(); @@ -274,10 +274,8 @@ pub mod tests { let alice_cert1 = new_id_cert(&d); let alice_handle = Handle::from("alice"); - let add_alice = ClientsCommands::add( - alice_handle.clone(), - ClientAuth::new(alice_cert1.clone()) - ); + let add_alice = + ClientsCommands::add(alice_handle.clone(), ClientAuth::new(alice_cert1.clone())); let events = proxy.process_command(add_alice).unwrap(); assert_eq!(1, events.len()); @@ -299,10 +297,8 @@ pub mod tests { // Update cert let alice_cert2 = new_id_cert(&d); - let update_alice_cert = ClientsCommands::update_cert( - alice_handle.clone(), - alice_cert2.clone() - ); + let update_alice_cert = + ClientsCommands::update_cert(alice_handle.clone(), alice_cert2.clone()); let events = proxy.process_command(update_alice_cert).unwrap(); assert_eq!(1, events.len()); @@ -320,7 +316,6 @@ pub mod tests { let proxy = store.update(&id(), proxy, events).unwrap(); assert!(proxy.client_auth(&alice_handle).is_none()); - }) } } diff --git a/commons/src/remote/id.rs b/commons/src/remote/id.rs index 40bdfbb0..8cd3f992 100644 --- a/commons/src/remote/id.rs +++ b/commons/src/remote/id.rs @@ -1,23 +1,18 @@ -use bcder::{Mode, OctetString, Oid, Tag, Unsigned}; -use bcder::{decode, encode}; -use bcder::encode::Values; use bcder::encode::Constructed; +use bcder::encode::Values; +use bcder::{decode, encode}; +use bcder::{Mode, OctetString, Oid, Tag, Unsigned}; use bytes::Bytes; use serde::{Deserialize, Deserializer, Serialize, Serializer}; -use rpki::uri; -use rpki::cert::ext::{ - AuthorityKeyIdentifier, - BasicCa, - SubjectKeyIdentifier -}; +use rpki::cert::ext::{AuthorityKeyIdentifier, BasicCa, SubjectKeyIdentifier}; use rpki::crypto::{PublicKey, SignatureAlgorithm}; +use rpki::uri; use rpki::x509::{Name, SignedData, Time, ValidationError, Validity}; use crate::remote::rfc8183::ServiceUri; use crate::util::softsigner::SignerKeyId; - //------------ MyIdentity ---------------------------------------------------- /// This type stores identity details for a client or server involved in RPKI @@ -28,7 +23,7 @@ pub struct MyIdentity { id_cert: IdCert, - key_id: SignerKeyId + key_id: SignerKeyId, } impl MyIdentity { @@ -36,7 +31,7 @@ impl MyIdentity { MyIdentity { name: name.to_string(), id_cert, - key_id + key_id, } } @@ -59,15 +54,14 @@ impl MyIdentity { impl PartialEq for MyIdentity { fn eq(&self, other: &MyIdentity) -> bool { - self.name == other.name && - self.id_cert.to_bytes() == other.id_cert.to_bytes() && - self.key_id == other.key_id + self.name == other.name + && self.id_cert.to_bytes() == other.id_cert.to_bytes() + && self.key_id == other.key_id } } impl Eq for MyIdentity {} - //------------ ParentInfo ---------------------------------------------------- /// This type stores details about a parent publication server: in @@ -80,11 +74,7 @@ pub struct ParentInfo { } impl ParentInfo { - pub fn new( - publisher_handle: String, - id_cert: IdCert, - service_uri: ServiceUri, - ) -> Self { + pub fn new(publisher_handle: String, id_cert: IdCert, service_uri: ServiceUri) -> Self { ParentInfo { publisher_handle, id_cert, @@ -110,15 +100,14 @@ impl ParentInfo { impl PartialEq for ParentInfo { fn eq(&self, other: &ParentInfo) -> bool { - self.id_cert.to_bytes() == other.id_cert.to_bytes() && - self.service_uri == other.service_uri && - self.publisher_handle == other.publisher_handle + self.id_cert.to_bytes() == other.id_cert.to_bytes() + && self.service_uri == other.service_uri + && self.publisher_handle == other.publisher_handle } } impl Eq for ParentInfo {} - //------------ MyRepoInfo ---------------------------------------------------- /// This type stores details about the repository URIs available to a @@ -126,15 +115,15 @@ impl Eq for ParentInfo {} #[derive(Clone, Debug, Deserialize, Serialize)] pub struct MyRepoInfo { sia_base: uri::Rsync, - notify_sia: uri::Https + notify_sia: uri::Https, } impl MyRepoInfo { - pub fn new( - sia_base: uri::Rsync, - notify_sia: uri::Https - ) -> Self { - MyRepoInfo { sia_base, notify_sia } + pub fn new(sia_base: uri::Rsync, notify_sia: uri::Https) -> Self { + MyRepoInfo { + sia_base, + notify_sia, + } } /// The base rsync directory under which the publisher may publish. @@ -150,14 +139,12 @@ impl MyRepoInfo { impl PartialEq for MyRepoInfo { fn eq(&self, other: &MyRepoInfo) -> bool { - self.sia_base == other.sia_base && - self.notify_sia == other.notify_sia + self.sia_base == other.sia_base && self.notify_sia == other.notify_sia } } impl Eq for MyRepoInfo {} - //------------ IdCert -------------------------------------------------------- /// An Identity Certificate. @@ -246,40 +233,40 @@ impl IdCert { } /// Takes an encoded certificate from the beginning of a value. - pub fn take_from( - cons: &mut decode::Constructed - ) -> Result { + pub fn take_from(cons: &mut decode::Constructed) -> Result { cons.take_sequence(Self::from_constructed) } /// Parses the content of a Certificate sequence. pub fn from_constructed( - cons: &mut decode::Constructed + cons: &mut decode::Constructed, ) -> Result { let signed_data = SignedData::from_constructed(cons)?; - signed_data.data().clone().decode(|cons| { - cons.take_sequence(|cons| { - // version [0] EXPLICIT Version DEFAULT v1. - // -- we need extensions so apparently, we want v3 which, - // confusingly, is 2. - cons.take_constructed_if(Tag::CTX_0, |c| c.skip_u8_if(2))?; + signed_data + .data() + .clone() + .decode(|cons| { + cons.take_sequence(|cons| { + // version [0] EXPLICIT Version DEFAULT v1. + // -- we need extensions so apparently, we want v3 which, + // confusingly, is 2. + cons.take_constructed_if(Tag::CTX_0, |c| c.skip_u8_if(2))?; - Ok(IdCert { - signed_data, - serial_number: Unsigned::take_from(cons)?, - signature: SignatureAlgorithm::x509_take_from(cons)?, - issuer: Name::take_from(cons)?, - validity: Validity::take_from(cons)?, - subject: Name::take_from(cons)?, - subject_public_key_info: PublicKey::take_from(cons)?, - extensions: cons.take_constructed_if( - Tag::CTX_3, - IdExtensions::take_from - )?, + Ok(IdCert { + signed_data, + serial_number: Unsigned::take_from(cons)?, + signature: SignatureAlgorithm::x509_take_from(cons)?, + issuer: Name::take_from(cons)?, + validity: Validity::take_from(cons)?, + subject: Name::take_from(cons)?, + subject_public_key_info: PublicKey::take_from(cons)?, + extensions: cons + .take_constructed_if(Tag::CTX_3, IdExtensions::take_from)?, + }) }) }) - }).map_err(Into::into) + .map_err(Into::into) } pub fn encode<'a>(&'a self) -> impl encode::Values + 'a { @@ -316,7 +303,8 @@ impl IdCert { } // Verify that this is self signed - self.signed_data.verify_signature(&self.subject_public_key_info)?; + self.signed_data + .verify_signature(&self.subject_public_key_info)?; Ok(()) } @@ -327,25 +315,18 @@ impl IdCert { /// by the provided `issuer` certificate. /// /// Note that this does _not_ check the CRL. - pub fn validate_ee( - &self, - issuer: &IdCert, - ) -> Result<(), ValidationError> { + pub fn validate_ee(&self, issuer: &IdCert) -> Result<(), ValidationError> { self.validate_ee_at(issuer, Time::now()) } - pub fn validate_ee_at( - &self, - issuer: &IdCert, - now: Time, - ) -> Result<(), ValidationError> { + pub fn validate_ee_at(&self, issuer: &IdCert, now: Time) -> Result<(), ValidationError> { self.validate_basics(now)?; self.validate_issued(issuer)?; // Basic Constraints: Must not be a CA cert. if let Some(basic_ca) = &self.extensions.basic_ca { if basic_ca.ca() { - return Err(ValidationError) + return Err(ValidationError); } } @@ -354,7 +335,6 @@ impl IdCert { Ok(()) } - //--- Validation Components /// Validates basic compliance with RFC8183 and RFC6492 @@ -369,7 +349,7 @@ impl IdCert { if self.extensions.subject_key_id().as_slice().unwrap() != self.subject_public_key_info().key_identifier().as_ref() { - return Err(ValidationError) + return Err(ValidationError); } Ok(()) @@ -383,18 +363,14 @@ impl IdCert { /// /// This check assumes for now that we are always dealing with V3 /// certificates and AKI and SKI have to match. - fn validate_issued( - &self, - issuer: &IdCert, - ) -> Result<(), ValidationError> { + fn validate_issued(&self, issuer: &IdCert) -> Result<(), ValidationError> { // Authority Key Identifier. Must be present and match the // subject key ID of `issuer`. if let Some(aki) = self.extensions.authority_key_id() { if aki != issuer.extensions.subject_key_id() { - return Err(ValidationError) + return Err(ValidationError); } - } - else { + } else { return Err(ValidationError); } @@ -410,7 +386,7 @@ impl IdCert { // und the “cA” flag must be set (RFC5280). if let Some(ref ca) = self.extensions.basic_ca { if ca.ca() { - return Ok(()) + return Ok(()); } } @@ -418,15 +394,12 @@ impl IdCert { } /// Validates the certificate’s signature. - fn validate_signature( - &self, - issuer: &IdCert - ) -> Result<(), ValidationError> { - self.signed_data.verify_signature(issuer.subject_public_key_info()) + fn validate_signature(&self, issuer: &IdCert) -> Result<(), ValidationError> { + self.signed_data + .verify_signature(issuer.subject_public_key_info()) } } - //--- AsRef impl AsRef for IdCert { @@ -436,10 +409,10 @@ impl AsRef for IdCert { } impl Serialize for IdCert { - fn serialize( - &self, - serializer: S - ) -> Result where S: Serializer { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { let bytes = self.to_bytes(); let str = base64::encode(&bytes); str.serialize(serializer) @@ -455,9 +428,10 @@ impl PartialEq for IdCert { impl Eq for IdCert {} impl<'de> Deserialize<'de> for IdCert { - fn deserialize( - deserializer: D - ) -> Result where D: Deserializer<'de> { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { use serde::de; let some = String::deserialize(deserializer)?; @@ -467,8 +441,6 @@ impl<'de> Deserialize<'de> for IdCert { } } - - //------------ IdExtensions -------------------------------------------------- #[derive(Clone, Debug, Eq, PartialEq)] @@ -489,9 +461,7 @@ pub struct IdExtensions { /// # Decoding /// impl IdExtensions { - pub fn take_from( - cons: &mut decode::Constructed - ) -> Result { + pub fn take_from(cons: &mut decode::Constructed) -> Result { cons.take_sequence(|cons| { let mut basic_ca = None; let mut subject_key_id = None; @@ -504,13 +474,9 @@ impl IdExtensions { if id == oid::CE_BASIC_CONSTRAINTS { BasicCa::take(content, critical, &mut basic_ca) } else if id == oid::CE_SUBJECT_KEY_IDENTIFIER { - SubjectKeyIdentifier::take( - content, critical, &mut subject_key_id - ) + SubjectKeyIdentifier::take(content, critical, &mut subject_key_id) } else if id == oid::CE_AUTHORITY_KEY_IDENTIFIER { - AuthorityKeyIdentifier::take( - content, critical, &mut authority_key_id - ) + AuthorityKeyIdentifier::take(content, critical, &mut authority_key_id) } else { // Id Certificates are poorly defined and may // contain critical extensions we do not actually @@ -534,45 +500,38 @@ impl IdExtensions { // We have to do this the hard way because some extensions are optional. // Therefore we need logic to determine which ones to encode. impl IdExtensions { - pub fn encode<'a>(&'a self) -> impl encode::Values + 'a { Constructed::new( Tag::CTX_3, - encode::sequence( - ( - self.basic_ca.as_ref().map(BasicCa::encode), - self.subject_key_id.clone().encode(), - self.authority_key_id.clone().map(AuthorityKeyIdentifier::encode) - ) - ) + encode::sequence(( + self.basic_ca.as_ref().map(BasicCa::encode), + self.subject_key_id.clone().encode(), + self.authority_key_id + .clone() + .map(AuthorityKeyIdentifier::encode), + )), ) } - } - /// # Creating /// impl IdExtensions { - /// Creates extensions to be used on a self-signed TA IdCert pub fn for_id_ta_cert(key: &PublicKey) -> Self { - IdExtensions{ + IdExtensions { basic_ca: Some(BasicCa::new(true, true)), subject_key_id: SubjectKeyIdentifier::new(key), - authority_key_id: Some(AuthorityKeyIdentifier::new(key)) + authority_key_id: Some(AuthorityKeyIdentifier::new(key)), } } /// Creates extensions to be used on an EE IdCert in a protocol CMS - pub fn for_id_ee_cert( - subject_key: &PublicKey, - issuing_key: &PublicKey - ) -> Self { - IdExtensions{ + pub fn for_id_ee_cert(subject_key: &PublicKey, issuing_key: &PublicKey) -> Self { + IdExtensions { basic_ca: None, subject_key_id: SubjectKeyIdentifier::new(subject_key), - authority_key_id: Some(AuthorityKeyIdentifier::new(issuing_key)) + authority_key_id: Some(AuthorityKeyIdentifier::new(issuing_key)), } } } @@ -587,12 +546,11 @@ impl IdExtensions { pub fn authority_key_id(&self) -> Option<&OctetString> { match &self.authority_key_id { Some(a) => Some(a.authority_key_id()), - None => None + None => None, } } } - //------------ OIDs ---------------------------------------------------------- mod oid { @@ -603,7 +561,6 @@ mod oid { pub const CE_AUTHORITY_KEY_IDENTIFIER: Oid<&[u8]> = Oid(&[85, 29, 35]); } - //------------ Tests --------------------------------------------------------- // is pub so that we can use a parsed test IdCert for now for testing @@ -620,8 +577,8 @@ pub mod tests { #[test] fn should_parse_id_publisher_ta_cert() { - test_id_certificate().validate_ta_at( - Time::utc(2012, 1, 1, 0, 0, 0) - ).unwrap(); + test_id_certificate() + .validate_ta_at(Time::utc(2012, 1, 1, 0, 0, 0)) + .unwrap(); } } diff --git a/commons/src/remote/mod.rs b/commons/src/remote/mod.rs index 82ec9715..f3740a3f 100644 --- a/commons/src/remote/mod.rs +++ b/commons/src/remote/mod.rs @@ -6,7 +6,7 @@ pub mod clients; pub mod id; pub mod proxy; pub mod responder; +pub mod rfc6492; pub mod rfc8181; pub mod rfc8183; -pub mod rfc6492; -pub mod sigmsg; \ No newline at end of file +pub mod sigmsg; diff --git a/commons/src/remote/proxy.rs b/commons/src/remote/proxy.rs index a0900b9b..1d3be8d0 100644 --- a/commons/src/remote/proxy.rs +++ b/commons/src/remote/proxy.rs @@ -2,84 +2,42 @@ use std::io; use std::path::PathBuf; use std::sync::Arc; -use bcder::{Captured, Mode}; use bcder::encode::Values; +use bcder::{Captured, Mode}; use rpki::uri; use rpki::x509::ValidationError; -use crate::api::{ - ErrorCode, - ErrorResponse, -}; use crate::api::admin::Handle; -use crate::api::publication::{ - ListReply, - PublishRequest, - PublishDelta, -}; -use crate::eventsourcing::{ - Aggregate, - AggregateStore, - AggregateStoreError, - DiskAggregateStore, -}; -use crate::util::httpclient; -use crate::util::softsigner::{OpenSslSigner, SignerError}; -use rpki::crypto::{ - PublicKeyFormat, - Signer -}; -use crate::remote::api::{ - ClientInfo, -}; -use crate::remote::clients::{ - self, - ClientManager, - ClientsEvents, - ClientsCommand, - ClientsCommands -}; -use crate::remote::builder::{ - self, - IdCertBuilder, - SignedMessageBuilder, -}; -use crate::remote::id::{ - IdCert, - MyIdentity, - ParentInfo -}; -use crate::remote::responder::{ - self, - Responder, - ResponderEvents -}; +use crate::api::publication::{ListReply, PublishDelta, PublishRequest}; +use crate::api::{ErrorCode, ErrorResponse}; +use crate::eventsourcing::{Aggregate, AggregateStore, AggregateStoreError, DiskAggregateStore}; +use crate::remote::api::ClientInfo; +use crate::remote::builder::{self, IdCertBuilder, SignedMessageBuilder}; +use crate::remote::clients::{self, ClientManager, ClientsCommand, ClientsCommands, ClientsEvents}; +use crate::remote::id::{IdCert, MyIdentity, ParentInfo}; +use crate::remote::responder::{self, Responder, ResponderEvents}; use crate::remote::rfc8181::{ - self, - ErrorReply, - Message, - ReplyMessage, - ReportError, - ReportErrorCode, + self, ErrorReply, Message, ReplyMessage, ReportError, ReportErrorCode, }; use crate::remote::rfc8183::RepositoryResponse; use crate::remote::rfc8183::ServiceUri; use crate::remote::sigmsg::SignedMessage; - +use crate::util::httpclient; +use crate::util::softsigner::{OpenSslSigner, SignerError}; +use rpki::crypto::{PublicKeyFormat, Signer}; #[derive(Clone)] pub struct ProxyServer { signer: OpenSslSigner, clients_store: Arc>, responder_store: Arc>, - krill_uri: uri::Https + krill_uri: uri::Https, } /// # Server Life Cycle /// impl ProxyServer { - /// Initialises the Proxy Server. This will re-use the existing clients and /// responder (i.e. server certificate and all), if they exist for this work_dir. /// If they do not exist, they will be initialised as well. @@ -89,18 +47,23 @@ impl ProxyServer { let responder_store = Arc::new(DiskAggregateStore::::new(work_dir, "proxy")?); let clients_id = clients::id(); - if ! clients_store.has(&clients_id) { + if !clients_store.has(&clients_id) { clients_store.add(ClientsEvents::init())?; } let responder_id = responder::id(); - if ! responder_store.has(&responder_id) { + if !responder_store.has(&responder_id) { let my_id = Self::new_id(&mut signer)?; let init = ResponderEvents::init(my_id); responder_store.add(init)?; } - Ok(ProxyServer { signer, clients_store, responder_store, krill_uri: krill_uri.clone() }) + Ok(ProxyServer { + signer, + clients_store, + responder_store, + krill_uri: krill_uri.clone(), + }) } fn new_id(signer: &mut OpenSslSigner) -> Result { @@ -139,7 +102,7 @@ impl ProxyServer { handle: &Handle, service_uri: uri::Https, sia_base: uri::Rsync, - rrdp_notification_uri: uri::Https + rrdp_notification_uri: uri::Https, ) -> Result { let tag = None; @@ -157,7 +120,7 @@ impl ProxyServer { id_cert, service_uri, sia_base, - rrdp_notification_uri + rrdp_notification_uri, )) } @@ -170,20 +133,21 @@ impl ProxyServer { } fn clients(&self) -> Result, Error> { - self.clients_store.get_latest(&clients::id()).map_err(Error::StoreError) + self.clients_store + .get_latest(&clients::id()) + .map_err(Error::StoreError) } } /// # Proxy RFC8181 requests to a Krill server /// impl ProxyServer { - /// Takes an RFC8181 request, validates it, and then returns the /// request type pub fn convert_rfc8181_req( &self, msg: SignedMessage, - handle: &Handle + handle: &Handle, ) -> Result { self.validate_msg(&msg, handle)?; self.convert_to_json_request(&msg) @@ -208,16 +172,12 @@ impl ProxyServer { self.sign_msg(msg) } - fn validate_msg( - &self, - msg: &SignedMessage, - handle: &Handle - ) -> Result<(), Error> { + fn validate_msg(&self, msg: &SignedMessage, handle: &Handle) -> Result<(), Error> { match self.clients()?.client_auth(handle) { None => { warn!("Received RFC8181 message for unknown client: {}", &handle); Err(Error::UnknownClient(handle.clone())) - }, + } Some(client) => { let id_cert = client.cert(); match msg.validate(id_cert) { @@ -233,10 +193,7 @@ impl ProxyServer { /// Retrieves the QueryMessage contained in the SignedMessage and /// converts into the (json) equivalent request for the API. - fn convert_to_json_request( - &self, - msg: &SignedMessage - ) -> Result { + fn convert_to_json_request(&self, msg: &SignedMessage) -> Result { debug!("Convert contained message to Json equivalent"); let msg = rfc8181::Message::from_signed_message(&msg)?; let msg = msg.into_query()?; @@ -246,11 +203,8 @@ impl ProxyServer { fn sign_msg(&self, msg: Message) -> Result { let responder = self.responder_store.get_latest(&responder::id())?; - let builder = SignedMessageBuilder::create( - responder.id().key_id(), - &self.signer, - msg.into_bytes() - )?; + let builder = + SignedMessageBuilder::create(responder.id().key_id(), &self.signer, msg.into_bytes())?; let enc = builder.encode(); @@ -258,8 +212,6 @@ impl ProxyServer { } } - - //------------ Error --------------------------------------------------------- #[derive(Debug, Display)] @@ -296,35 +248,51 @@ pub enum Error { } impl From for Error { - fn from(e: io::Error) -> Self { Error::IoError(e) } + fn from(e: io::Error) -> Self { + Error::IoError(e) + } } impl From for Error { - fn from(e: AggregateStoreError) -> Self { Error::StoreError(e) } + fn from(e: AggregateStoreError) -> Self { + Error::StoreError(e) + } } impl From for Error { - fn from(e: clients::Error) -> Self { Error::ClientsError(e) } + fn from(e: clients::Error) -> Self { + Error::ClientsError(e) + } } impl From for Error { - fn from(e: SignerError) -> Self { Error::SignerError(e) } + fn from(e: SignerError) -> Self { + Error::SignerError(e) + } } impl From> for Error { - fn from(e: builder::Error) -> Self { Error::BuilderError(e) } + fn from(e: builder::Error) -> Self { + Error::BuilderError(e) + } } impl From for Error { - fn from(e: ValidationError) -> Self { Error::ValidationError(e) } + fn from(e: ValidationError) -> Self { + Error::ValidationError(e) + } } impl From for Error { - fn from(e: rfc8181::MessageError) -> Self { Error::Rfc8181MessageError(e) } + fn from(e: rfc8181::MessageError) -> Self { + Error::Rfc8181MessageError(e) + } } impl From for Error { - fn from(e: httpclient::Error) -> Self { Error::HttpClientError(e) } + fn from(e: httpclient::Error) -> Self { + Error::HttpClientError(e) + } } impl Error { @@ -333,55 +301,54 @@ impl Error { Error::ValidationError(_) => ReportErrorCode::PermissionFailure, Error::Rfc8181MessageError(_) => ReportErrorCode::XmlError, Error::UnknownClient(_) => ReportErrorCode::PermissionFailure, - Error::HttpClientError(http_error) => { - match http_error { - httpclient::Error::ErrorWithBody(_code, body) => { - match serde_json::from_str::(body) { - Ok(response) => { - let error_nr = response.code(); - let error_code: ErrorCode = response.into(); - match error_code { - ErrorCode::InvalidPublicationXml => ReportErrorCode::XmlError, - ErrorCode::ObjectAlreadyPresent => ReportErrorCode::ObjectAlreadyPresent, - ErrorCode::NoObjectForHashAndOrUri => ReportErrorCode::NoObjectMatchingHash, - _ => { - if error_nr > 2000 && error_nr < 3000 { - ReportErrorCode::PermissionFailure - } else { - ReportErrorCode::OtherError - } + Error::HttpClientError(http_error) => match http_error { + httpclient::Error::ErrorWithBody(_code, body) => { + match serde_json::from_str::(body) { + Ok(response) => { + let error_nr = response.code(); + let error_code: ErrorCode = response.into(); + match error_code { + ErrorCode::InvalidPublicationXml => ReportErrorCode::XmlError, + ErrorCode::ObjectAlreadyPresent => { + ReportErrorCode::ObjectAlreadyPresent + } + ErrorCode::NoObjectForHashAndOrUri => { + ReportErrorCode::NoObjectMatchingHash + } + _ => { + if error_nr > 2000 && error_nr < 3000 { + ReportErrorCode::PermissionFailure + } else { + ReportErrorCode::OtherError } } } - Err(_) => ReportErrorCode::OtherError } + Err(_) => ReportErrorCode::OtherError, } - _ => ReportErrorCode::OtherError } - - } - _ => ReportErrorCode::OtherError + _ => ReportErrorCode::OtherError, + }, + _ => ReportErrorCode::OtherError, } } } - - /// This type proxies native Krill requests to a remote RFC compliant server #[derive(Clone, Debug, Deserialize, Serialize)] pub struct ClientProxy { id: MyIdentity, parent: ParentInfo, - work_dir: PathBuf + work_dir: PathBuf, } impl ClientProxy { - pub fn new( - id: MyIdentity, - parent: ParentInfo, - work_dir: PathBuf - ) -> Self { - ClientProxy { id, parent, work_dir } + pub fn new(id: MyIdentity, parent: ParentInfo, work_dir: PathBuf) -> Self { + ClientProxy { + id, + parent, + work_dir, + } } pub fn list(&self) -> Result { @@ -391,7 +358,7 @@ impl ClientProxy { match reply { rfc8181::ReplyMessage::ErrorReply(e) => Err(ClientError::ErrorReply(e)), rfc8181::ReplyMessage::SuccessReply => Err(ClientError::UnexpectedReply), - rfc8181::ReplyMessage::ListReply(list) => Ok(list) + rfc8181::ReplyMessage::ListReply(list) => Ok(list), } } @@ -402,20 +369,16 @@ impl ClientProxy { match reply { rfc8181::ReplyMessage::ErrorReply(e) => Err(ClientError::ErrorReply(e)), rfc8181::ReplyMessage::ListReply(_) => Err(ClientError::UnexpectedReply), - rfc8181::ReplyMessage::SuccessReply => Ok(()) + rfc8181::ReplyMessage::SuccessReply => Ok(()), } } - fn proxy_msg( - &self, - msg: rfc8181::Message, - ) -> Result { - + fn proxy_msg(&self, msg: rfc8181::Message) -> Result { let signed = self.sign(msg)?.into_bytes(); let res = httpclient::post_binary( &self.parent.service_uri().to_string(), &signed, - "application/rpki-publication" + "application/rpki-publication", )?; let res_msg = SignedMessage::decode(res, true)?; @@ -425,22 +388,16 @@ impl ClientProxy { } fn sign(&self, msg: Message) -> Result { - let key_id = self.id.key_id(); let signer = OpenSslSigner::build(&self.work_dir)?; - let builder = SignedMessageBuilder::create( - key_id, - &signer, - msg.into_bytes() - )?; + let builder = SignedMessageBuilder::create(key_id, &signer, msg.into_bytes())?; let enc = builder.encode(); Ok(enc.to_captured(Mode::Der)) } } - //------------ ClientError ---------------------------------------------------- #[derive(Debug, Display)] @@ -460,41 +417,52 @@ pub enum ClientError { #[display(fmt = "{}", _0)] BuilderError(builder::Error), - #[display(fmt="Received error from server: {:?}", _0)] + #[display(fmt = "Received error from server: {:?}", _0)] ErrorReply(rfc8181::ErrorReply), - #[display(fmt="Received unexpected reply (list vs success)")] + #[display(fmt = "Received unexpected reply (list vs success)")] UnexpectedReply, - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] SignerError(SignerError), } impl From for ClientError { - fn from(e: httpclient::Error) -> Self { ClientError::HttpError(e) } + fn from(e: httpclient::Error) -> Self { + ClientError::HttpError(e) + } } impl From for ClientError { - fn from(e: bcder::decode::Error) -> Self { ClientError::DecodeError(e) } + fn from(e: bcder::decode::Error) -> Self { + ClientError::DecodeError(e) + } } impl From for ClientError { - fn from(e: ValidationError) -> Self { ClientError::ValidationError(e) } + fn from(e: ValidationError) -> Self { + ClientError::ValidationError(e) + } } impl From for ClientError { - fn from(e: rfc8181::MessageError) -> Self { ClientError::MessageError(e) } + fn from(e: rfc8181::MessageError) -> Self { + ClientError::MessageError(e) + } } impl From> for ClientError { - fn from(e: builder::Error) -> Self { ClientError::BuilderError(e) } + fn from(e: builder::Error) -> Self { + ClientError::BuilderError(e) + } } impl From for ClientError { - fn from(e: SignerError) -> Self { ClientError::SignerError(e) } + fn from(e: SignerError) -> Self { + ClientError::SignerError(e) + } } - //------------ Tests --------------------------------------------------------- #[cfg(test)] @@ -515,4 +483,4 @@ mod tests { }); } -} \ No newline at end of file +} diff --git a/commons/src/remote/responder.rs b/commons/src/remote/responder.rs index 16782c6a..3866afa2 100644 --- a/commons/src/remote/responder.rs +++ b/commons/src/remote/responder.rs @@ -1,16 +1,12 @@ use crate::api::admin::Handle; -use crate::eventsourcing::{ - Aggregate, - CommandDetails, - SentCommand, - StoredEvent -}; +use crate::eventsourcing::{Aggregate, CommandDetails, SentCommand, StoredEvent}; use crate::remote::id::MyIdentity; - // const fn is not stable yet const ID: &str = "cms-responder"; -pub fn id() -> Handle { Handle::from(ID) } +pub fn id() -> Handle { + Handle::from(ID) +} //------------ ResponderEvent --------------------------------------------- @@ -33,7 +29,6 @@ impl ResponderEvents { } } - //------------ ResponderCommand -------------------------------------------- #[derive(Clone, Deserialize, Serialize)] @@ -57,7 +52,6 @@ pub struct Responder { id: MyIdentity, } - impl Aggregate for Responder { type Command = ResponderCommand; type Event = ResponderEvent; @@ -67,12 +61,7 @@ impl Aggregate for Responder { fn init(event: Self::InitEvent) -> Result { let id = event.into_details().id; let version = 1; - Ok ( - Responder { - version, - id - } - ) + Ok(Responder { version, id }) } fn version(&self) -> u64 { @@ -96,7 +85,6 @@ impl Responder { } } - //------------ Error --------------------------------------------------------- #[derive(Debug, Display)] @@ -107,22 +95,20 @@ pub enum Error { impl std::error::Error for Error {} - - //------------ Tests --------------------------------------------------------- #[cfg(test)] mod tests { - use std::path::PathBuf; - use rpki::crypto::PublicKeyFormat; - use rpki::crypto::Signer; - use crate::util::test; + use super::*; use crate::eventsourcing::AggregateStore; use crate::eventsourcing::DiskAggregateStore; - use crate::util::softsigner::OpenSslSigner; use crate::remote::builder::IdCertBuilder; - use super::*; + use crate::util::softsigner::OpenSslSigner; + use crate::util::test; + use rpki::crypto::PublicKeyFormat; + use rpki::crypto::Signer; + use std::path::PathBuf; pub fn new_id(work_dir: &PathBuf) -> MyIdentity { let mut s = OpenSslSigner::build(work_dir).unwrap(); @@ -135,7 +121,6 @@ mod tests { #[test] fn should_init() { test::test_under_tmp(|d| { - // Set up a store for the proxy let store = DiskAggregateStore::::new(&d, "proxy").unwrap(); @@ -147,4 +132,4 @@ mod tests { }); } -} \ No newline at end of file +} diff --git a/commons/src/remote/rfc6492.rs b/commons/src/remote/rfc6492.rs index d3ce8282..d4e6b39f 100644 --- a/commons/src/remote/rfc6492.rs +++ b/commons/src/remote/rfc6492.rs @@ -1,9 +1,9 @@ +use std::convert::TryFrom; use std::io; use std::str::FromStr; -use std::convert::TryFrom; use bytes::Bytes; -use chrono::{Utc, DateTime, SecondsFormat}; +use chrono::{DateTime, SecondsFormat, Utc}; use serde::export::fmt::Display; use rpki::cert::Cert; @@ -13,20 +13,14 @@ use rpki::resources::{AsResources, Ipv4Resources, Ipv6Resources}; use rpki::uri; use rpki::x509::Time; +use crate::api::ca::{IssuedCert, ResSetErr, ResourceSet}; use crate::api::{ - EntitlementClass, - Entitlements, - IssuanceRequest, - IssuanceResponse, - RevocationRequest, - RequestResourceLimit, - SigningCert, + EntitlementClass, Entitlements, IssuanceRequest, IssuanceResponse, RequestResourceLimit, + RevocationRequest, SigningCert, }; -use crate::api::ca::{ResourceSet, ResSetErr, IssuedCert}; -use crate::util::xml::{XmlReader, XmlReaderErr, AttributesError, XmlWriter}; -use remote::sigmsg::SignedMessage; +use crate::util::xml::{AttributesError, XmlReader, XmlReaderErr, XmlWriter}; use api::admin::Handle; - +use remote::sigmsg::SignedMessage; //------------ Consts -------------------------------------------------------- @@ -57,10 +51,9 @@ pub type Recipient = String; pub struct Message { sender: Sender, recipient: Recipient, - content: Content + content: Content, } - /// # Data Access /// impl Message { @@ -68,10 +61,18 @@ impl Message { (self.sender, self.recipient, self.content) } - pub fn sender_handle(&self) -> Handle { Handle::from(self.sender.as_str())} - pub fn sender(&self) -> &str { &self.sender } - pub fn recipient(&self) -> &str { &self.recipient } - pub fn content(&self) -> &Content { &self.content } + pub fn sender_handle(&self) -> Handle { + Handle::from(self.sender.as_str()) + } + pub fn sender(&self) -> &str { + &self.sender + } + pub fn recipient(&self) -> &str { + &self.recipient + } + pub fn content(&self) -> &Content { + &self.content + } } /// # Convenience accessors @@ -80,7 +81,7 @@ impl Message { pub fn into_reply(self) -> Result { match self.content { Content::Res(res) => Ok(res), - Content::Qry(_) => Err(Error::WrongMessageType) + Content::Qry(_) => Err(Error::WrongMessageType), } } } @@ -88,82 +89,94 @@ impl Message { /// # Constructing /// impl Message { - pub fn list( - sender: String, - recipient: String, - ) -> Self { + pub fn list(sender: String, recipient: String) -> Self { let content = Content::Qry(Qry::List); - Message { sender, recipient, content } + Message { + sender, + recipient, + content, + } } - pub fn list_response( - sender: String, - recipient: String, - entitlements: Entitlements - ) -> Self { + pub fn list_response(sender: String, recipient: String, entitlements: Entitlements) -> Self { let content = Content::Res(Res::List(entitlements)); - Message { sender, recipient, content} + Message { + sender, + recipient, + content, + } } - pub fn issue( - sender: String, - recipient: String, - issuance_request: IssuanceRequest - ) -> Self { + pub fn issue(sender: String, recipient: String, issuance_request: IssuanceRequest) -> Self { let content = Content::Qry(Qry::Issue(issuance_request)); - Message { sender, recipient, content } + Message { + sender, + recipient, + content, + } } pub fn issue_response( sender: String, recipient: String, - issuance_response: IssuanceResponse + issuance_response: IssuanceResponse, ) -> Self { let content = Content::Res(Res::Issue(issuance_response)); - Message { sender, recipient, content } + Message { + sender, + recipient, + content, + } } - pub fn revoke( - sender: String, - recipient: String, - revocation: RevocationRequest - ) -> Self { + pub fn revoke(sender: String, recipient: String, revocation: RevocationRequest) -> Self { let content = Content::Qry(Qry::Revoke(revocation)); - Message { sender, recipient, content } + Message { + sender, + recipient, + content, + } } pub fn revoke_response( sender: String, recipient: String, - revocation: RevocationRequest + revocation: RevocationRequest, ) -> Self { let content = Content::Res(Res::Revoke(revocation)); - Message { sender, recipient, content } + Message { + sender, + recipient, + content, + } } pub fn error_response( sender: String, recipient: String, - err: NotPerformedResponse + err: NotPerformedResponse, ) -> Result { let content = Content::Res(Res::Error(err)); - Ok(Message { sender, recipient, content }) + Ok(Message { + sender, + recipient, + content, + }) } } - #[derive(Clone, Debug, Eq, PartialEq)] #[allow(clippy::large_enum_variant)] pub enum Content { Qry(Qry), - Res(Res) + Res(Res), } impl Content { fn msg_type(&self) -> &str { match self { Content::Qry(q) => q.msg_type(), - Content::Res(r) => r.msg_type() + Content::Res(r) => r.msg_type(), } } } @@ -172,13 +185,15 @@ impl Content { /// impl Message { /// Decodes an XML structure - pub fn decode(reader: R) -> Result where R: io::Read { + pub fn decode(reader: R) -> Result + where + R: io::Read, + { XmlReader::decode(reader, |r| { - r.take_named_element("message",|mut a, r| { - + r.take_named_element("message", |mut a, r| { match a.take_req("version")?.as_ref() { - VERSION => { }, - _ => return Err(Error::InvalidVersion) + VERSION => {} + _ => return Err(Error::InvalidVersion), } let sender = a.take_req("sender")?; let recipient = a.take_req("recipient")?; @@ -188,32 +203,29 @@ impl Message { let content = match msg_type.as_ref() { TYPE_LIST_QRY | TYPE_ISSUE_QRY | TYPE_REVOKE_QRY => { Ok(Content::Qry(Qry::decode(&msg_type, r)?)) - }, - TYPE_LIST_RES | TYPE_ISSUE_RES | - TYPE_REVOKE_RES | TYPE_ERROR_RES => { + } + TYPE_LIST_RES | TYPE_ISSUE_RES | TYPE_REVOKE_RES | TYPE_ERROR_RES => { Ok(Content::Res(Res::decode(&msg_type, r)?)) } - _ => Err(Error::UnknownMessageType) + _ => Err(Error::UnknownMessageType), }?; - Ok(Message { sender, recipient, content }) + Ok(Message { + sender, + recipient, + content, + }) }) }) } /// Parses the content of a SignedMessage as a Message. - pub fn from_signed_message( - msg: &SignedMessage - ) -> Result { + pub fn from_signed_message(msg: &SignedMessage) -> Result { Message::decode(msg.content().to_bytes().as_ref()) } /// Encode into XML - pub fn encode( - &self, - target: &mut XmlWriter - ) -> Result<(), io::Error> { - + pub fn encode(&self, target: &mut XmlWriter) -> Result<(), io::Error> { let msg_type = self.content.msg_type(); let attrs = [ @@ -221,26 +233,18 @@ impl Message { ("version", VERSION), ("sender", &self.sender), ("recipient", &self.recipient), - ("type", msg_type) + ("type", msg_type), ]; - target.put_element( - "message", - Some(&attrs), - |w| { - match &self.content { - Content::Qry(q) => q.encode(w), - Content::Res(r) => r.encode(w) - } - } - ) + target.put_element("message", Some(&attrs), |w| match &self.content { + Content::Qry(q) => q.encode(w), + Content::Res(r) => r.encode(w), + }) } /// Encodes to a Vec pub fn encode_vec(&self) -> Vec { - XmlWriter::encode_vec(|w| { - self.encode(w) - }) + XmlWriter::encode_vec(|w| self.encode(w)) } /// Consumes the message and turns it into bytes @@ -249,7 +253,6 @@ impl Message { } } - //------------ Query --------------------------------------------------------- /// This type defines the various RFC6492 queries. @@ -258,7 +261,7 @@ impl Message { pub enum Qry { List, Issue(IssuanceRequest), - Revoke(RevocationRequest) + Revoke(RevocationRequest), } /// # Data Access @@ -268,7 +271,7 @@ impl Qry { match self { Qry::List => TYPE_LIST_QRY, Qry::Issue(_) => TYPE_ISSUE_QRY, - Qry::Revoke(_) => TYPE_REVOKE_QRY + Qry::Revoke(_) => TYPE_REVOKE_QRY, } } } @@ -276,67 +279,61 @@ impl Qry { /// # Decoding /// impl Qry { - fn decode( - msg_type: &str, - r: &mut XmlReader - ) -> Result where R: io::Read { + fn decode(msg_type: &str, r: &mut XmlReader) -> Result + where + R: io::Read, + { match msg_type { TYPE_LIST_QRY => Ok(Qry::List), TYPE_ISSUE_QRY => Ok(Qry::Issue(Self::decode_issue(r)?)), TYPE_REVOKE_QRY => Ok(Qry::Revoke(Self::decode_revoke(r)?)), - _ => Err(Error::UnknownMessageType) + _ => Err(Error::UnknownMessageType), } } - fn decode_revoke( - r: &mut XmlReader - ) -> Result where R: io::Read { + fn decode_revoke(r: &mut XmlReader) -> Result + where + R: io::Read, + { r.take_named_element("key", |mut a, r| { let class_name = a.take_req("class_name")?; a.exhausted()?; let ski_bytes = r.take_bytes_url_safe_pad()?; - let ski = KeyIdentifier::try_from(ski_bytes.as_ref()) - .map_err(|_| Error::InvalidSki)?; + let ski = KeyIdentifier::try_from(ski_bytes.as_ref()).map_err(|_| Error::InvalidSki)?; Ok(RevocationRequest::new(class_name.to_string(), ski)) }) } - fn decode_issue( - r: &mut XmlReader - ) -> Result where R: io::Read { + fn decode_issue(r: &mut XmlReader) -> Result + where + R: io::Read, + { r.take_named_element("request", |mut a, r| { let class_name = a.take_req("class_name")?; let mut limit = RequestResourceLimit::default(); if let Some(asn) = a.take_opt("req_resource_set_as") { - let asn = AsResources::from_str(&asn) - .map_err(Error::inr_syntax)?; + let asn = AsResources::from_str(&asn).map_err(Error::inr_syntax)?; limit.with_asn(asn); } if let Some(ipv4) = a.take_opt("req_resource_set_ipv4") { - let ipv4 = Ipv4Resources::from_str(&ipv4) - .map_err(Error::inr_syntax)?; + let ipv4 = Ipv4Resources::from_str(&ipv4).map_err(Error::inr_syntax)?; limit.with_ipv4(ipv4); } if let Some(ipv6) = a.take_opt("req_resource_set_ipv6") { - let ipv6 = Ipv6Resources::from_str(&ipv6) - .map_err(Error::inr_syntax)?; + let ipv6 = Ipv6Resources::from_str(&ipv6).map_err(Error::inr_syntax)?; limit.with_ipv6(ipv6); } let csr_bytes = r.take_bytes_std()?; let csr = Csr::decode(csr_bytes).map_err(|_| Error::InvalidCsr)?; - Ok(IssuanceRequest::new( - class_name.to_string(), - limit, - csr - )) + Ok(IssuanceRequest::new(class_name.to_string(), limit, csr)) }) } } @@ -344,20 +341,17 @@ impl Qry { /// # Encoding /// impl Qry { - fn encode( - &self, - w: &mut XmlWriter - ) -> Result<(), io::Error> { + fn encode(&self, w: &mut XmlWriter) -> Result<(), io::Error> { match self { Qry::List => w.empty(), Qry::Issue(issue_req) => Self::encode_issue(issue_req, w), - Qry::Revoke(rev) => Self::encode_revoke(rev, w) + Qry::Revoke(rev) => Self::encode_revoke(rev, w), } } fn encode_issue( issue: &IssuanceRequest, - w: &mut XmlWriter + w: &mut XmlWriter, ) -> Result<(), io::Error> { let class_name = issue.class_name(); let limit = issue.limit(); @@ -390,17 +384,14 @@ impl Qry { fn encode_revoke( rev: &RevocationRequest, - w: &mut XmlWriter + w: &mut XmlWriter, ) -> Result<(), io::Error> { - let att = [ ("class_name", rev.class_name() )]; + let att = [("class_name", rev.class_name())]; let bytes = rev.key().as_slice(); - w.put_element("key", Some(&att), |w| { - w.put_base64_url_safe(bytes) - }) + w.put_element("key", Some(&att), |w| w.put_base64_url_safe(bytes)) } } - //------------ Res ----------------------------------------------------------- /// This type defines the various RFC6492 queries. @@ -410,10 +401,9 @@ pub enum Res { List(Entitlements), Issue(IssuanceResponse), Revoke(RevocationRequest), - Error(NotPerformedResponse) + Error(NotPerformedResponse), } - /// # Data Access /// impl Res { @@ -422,48 +412,46 @@ impl Res { Res::List(_) => TYPE_LIST_RES, Res::Issue(_) => TYPE_ISSUE_RES, Res::Revoke(_) => TYPE_REVOKE_RES, - Res::Error(_) => TYPE_ERROR_RES + Res::Error(_) => TYPE_ERROR_RES, } } } - /// Decoding /// impl Res { - fn decode( - msg_type: &str, - r: &mut XmlReader - ) -> Result where R: io::Read { + fn decode(msg_type: &str, r: &mut XmlReader) -> Result + where + R: io::Read, + { match msg_type { TYPE_LIST_RES => { let entitlements = Self::decode_entitlements(r)?; Ok(Res::List(entitlements)) - }, + } TYPE_ISSUE_RES => { let issuance_response = Self::decode_issue_response(r)?; Ok(Res::Issue(issuance_response)) - }, + } TYPE_REVOKE_RES => { let request = Qry::decode_revoke(r)?; Ok(Res::Revoke(request)) - }, + } TYPE_ERROR_RES => { let err = Self::decode_error_response(r)?; Ok(Res::Error(err)) - }, - _ => Err(Error::UnknownMessageType) + } + _ => Err(Error::UnknownMessageType), } } - fn decode_issue_response( - r: &mut XmlReader - ) -> Result where R: io::Read { + fn decode_issue_response(r: &mut XmlReader) -> Result + where + R: io::Read, + { r.take_named_element("class", |mut a, r| { let name = a.take_req("class_name")?; - let cert_url = uri::Rsync::from_str( - &a.take_req("cert_url")? - )?; + let cert_url = uri::Rsync::from_str(&a.take_req("cert_url")?)?; let asn = a.take_req("resource_set_as")?; let v4 = a.take_req("resource_set_ipv4")?; @@ -490,14 +478,15 @@ impl Res { issuer, resource_set, not_after, - issued + issued, )) }) } - fn decode_entitlements( - r: &mut XmlReader - ) -> Result where R: io::Read { + fn decode_entitlements(r: &mut XmlReader) -> Result + where + R: io::Read, + { let mut classes = vec![]; while let Some(class) = Self::decode_entitlement_class(r)? { classes.push(class); @@ -505,88 +494,84 @@ impl Res { Ok(Entitlements::new(classes)) } - fn decode_entitlement_class( - r: &mut XmlReader - ) -> Result, Error> where R: io::Read { - r.take_opt_element(|t, mut a, r| { - match t.name.as_ref() { - "class" => { - let name = a.take_req("class_name")?; - let cert_url = uri::Rsync::from_str( - &a.take_req("cert_url")? - )?; + fn decode_entitlement_class(r: &mut XmlReader) -> Result, Error> + where + R: io::Read, + { + r.take_opt_element(|t, mut a, r| match t.name.as_ref() { + "class" => { + let name = a.take_req("class_name")?; + let cert_url = uri::Rsync::from_str(&a.take_req("cert_url")?)?; - let asn = a.take_req("resource_set_as")?; - let v4 = a.take_req("resource_set_ipv4")?; - let v6 = a.take_req("resource_set_ipv6")?; + let asn = a.take_req("resource_set_as")?; + let v4 = a.take_req("resource_set_ipv4")?; + let v6 = a.take_req("resource_set_ipv6")?; - let resource_set = ResourceSet::from_strs(&asn, &v4, &v6)?; + let resource_set = ResourceSet::from_strs(&asn, &v4, &v6)?; - let not_after = a.take_req("resource_set_notafter")?; - let not_after = DateTime::::from_str(¬_after)?; - let not_after = Time::new(not_after); + let not_after = a.take_req("resource_set_notafter")?; + let not_after = DateTime::::from_str(¬_after)?; + let not_after = Time::new(not_after); + a.exhausted()?; + + let mut issued = vec![]; + while let Some(issued_cert) = Self::decode_opt_issued_cert(r)? { + issued.push(issued_cert); + } + + let cert = r.take_named_element("issuer", |a, r| { a.exhausted()?; + Self::decode_cert(r) + })?; - let mut issued = vec![]; - while let Some(issued_cert) = Self::decode_opt_issued_cert(r)? { - issued.push(issued_cert); - } + let issuer = SigningCert::new(cert_url, cert); - let cert = r.take_named_element("issuer", |a, r| { - a.exhausted()?; - Self::decode_cert(r) - })?; - - let issuer = SigningCert::new(cert_url, cert); - - Ok(Some(EntitlementClass::new( - name, issuer, resource_set, not_after, issued - ))) - }, - _ => Err(Error::UnexpectedStart(t.name.clone())) + Ok(Some(EntitlementClass::new( + name, + issuer, + resource_set, + not_after, + issued, + ))) } + _ => Err(Error::UnexpectedStart(t.name.clone())), }) } - fn decode_opt_issued_cert( - r: &mut XmlReader - ) -> Result, Error> where R: io::Read { + fn decode_opt_issued_cert(r: &mut XmlReader) -> Result, Error> + where + R: io::Read, + { match r.next_start_name() { Some("certificate") => { let cert = Self::decode_issued_cert(r)?; Ok(Some(cert)) - }, - _ => Ok(None) + } + _ => Ok(None), } } - fn decode_issued_cert( - r: &mut XmlReader - ) -> Result where R: io::Read { + fn decode_issued_cert(r: &mut XmlReader) -> Result + where + R: io::Read, + { r.take_named_element("certificate", |mut a, r| { - let cert_url = uri::Rsync::from_str( - &a.take_req("cert_url").map_err(Error::XmlAttributesError)? - )?; + let cert_url = + uri::Rsync::from_str(&a.take_req("cert_url").map_err(Error::XmlAttributesError)?)?; let mut limit = RequestResourceLimit::default(); if let Some(asn) = a.take_opt("req_resource_set_as") { - limit.with_asn( - AsResources::from_str(&asn).map_err(Error::inr_syntax)? - ); + limit.with_asn(AsResources::from_str(&asn).map_err(Error::inr_syntax)?); } if let Some(v4) = a.take_opt("req_resource_set_ipv4") { - limit.with_ipv4( - Ipv4Resources::from_str(&v4).map_err(Error::inr_syntax)? - ); + limit.with_ipv4(Ipv4Resources::from_str(&v4).map_err(Error::inr_syntax)?); } if let Some(v6) = a.take_opt("req_resource_set_ipv6") { - limit.with_ipv6( - Ipv6Resources::from_str(&v6).map_err(Error::inr_syntax)? - ); + limit.with_ipv6(Ipv6Resources::from_str(&v6).map_err(Error::inr_syntax)?); } let cert = Self::decode_cert(r)?; @@ -596,23 +581,21 @@ impl Res { }) } - fn decode_cert( - r: &mut XmlReader - ) -> Result where R: io::Read { + fn decode_cert(r: &mut XmlReader) -> Result + where + R: io::Read, + { let bytes = r.take_bytes_std()?; Cert::decode(bytes).map_err(|_| Error::InvalidCert) } - fn decode_error_response( - r: &mut XmlReader - ) -> Result where R: io::Read { - let code = r.take_named_element("status", |_a, r| { - r.take_chars() - })?; + fn decode_error_response(r: &mut XmlReader) -> Result + where + R: io::Read, + { + let code = r.take_named_element("status", |_a, r| r.take_chars())?; - let _desc = r.take_named_element("description", |_a, r| { - r.take_chars() - })?; + let _desc = r.take_named_element("description", |_a, r| r.take_chars())?; NotPerformedResponse::from_code(&code) } @@ -621,21 +604,18 @@ impl Res { /// # Encoding /// impl Res { - fn encode( - &self, - w: &mut XmlWriter - ) -> Result<(), io::Error> { + fn encode(&self, w: &mut XmlWriter) -> Result<(), io::Error> { match self { Res::List(ents) => Self::encode_entitlements(ents, w), Res::Issue(response) => Self::encode_issuance_response(response, w), Res::Revoke(request) => Qry::encode_revoke(request, w), - Res::Error(err) => Self::encode_error_response(err, w) + Res::Error(err) => Self::encode_error_response(err, w), } } fn encode_entitlements( e: &Entitlements, - w: &mut XmlWriter + w: &mut XmlWriter, ) -> Result<(), io::Error> { for class in e.classes() { Self::encode_entitlement_class(class, w)?; @@ -645,7 +625,7 @@ impl Res { fn encode_issuance_response( res: &IssuanceResponse, - w: &mut XmlWriter + w: &mut XmlWriter, ) -> Result<(), io::Error> { Self::encode_class( res.class_name(), @@ -654,13 +634,13 @@ impl Res { res.resource_set(), [res.issued().clone()].iter(), res.issuer(), - w + w, ) } fn encode_entitlement_class( c: &EntitlementClass, - w: &mut XmlWriter + w: &mut XmlWriter, ) -> Result<(), io::Error> { Self::encode_class( c.class_name(), @@ -669,7 +649,7 @@ impl Res { c.resource_set(), c.issued().iter(), c.issuer(), - w + w, ) } @@ -678,9 +658,9 @@ impl Res { cert_url: &uri::Rsync, not_after: Time, inrs: &ResourceSet, - issued: impl Iterator, + issued: impl Iterator, issuer: &SigningCert, - w: &mut XmlWriter + w: &mut XmlWriter, ) -> Result<(), io::Error> { let cert_url = cert_url.to_string(); let not_after = not_after.to_rfc3339_opts(SecondsFormat::Secs, true); @@ -703,15 +683,13 @@ impl Res { Self::encode_issued(issued, w)?; } let issuer_cert = issuer.cert().to_captured().into_bytes(); - w.put_element("issuer", None, |w| { w.put_base64_std(&issuer_cert) }) + w.put_element("issuer", None, |w| w.put_base64_std(&issuer_cert)) }) } - - fn encode_issued( issued: &IssuedCert, - w: &mut XmlWriter + w: &mut XmlWriter, ) -> Result<(), io::Error> { let cert_url = issued.uri().to_string(); let limit = issued.limit(); @@ -745,20 +723,17 @@ impl Res { fn encode_error_response( error: &NotPerformedResponse, - w: &mut XmlWriter + w: &mut XmlWriter, ) -> Result<(), io::Error> { - w.put_element("status", None, |w| { - w.put_text(&format!("{}", error.status)) - })?; + w.put_element("status", None, |w| w.put_text(&format!("{}", error.status)))?; - let att = [ ( "xml:lang", "en-US" )]; + let att = [("xml:lang", "en-US")]; w.put_element("description", Some(&att), |w| { w.put_text(&error.description) }) } } - //------------ NotPerformedResponse ------------------------------------------ /// This type describes the Not-performed responses defined in section 3.6 @@ -766,56 +741,103 @@ impl Res { #[derive(Clone, Debug, Eq, PartialEq)] pub struct NotPerformedResponse { status: u64, - description: String + description: String, } impl NotPerformedResponse { /// Local helper. Please use [`from_code`] to create a response for an /// status value defined in RFC6492. fn new(status: u64, description: &str) -> Self { - NotPerformedResponse { status, description: description.to_string() } + NotPerformedResponse { + status, + description: description.to_string(), + } } /// Creates a response for a status value defined in RFC6492. Also adds /// the description defined in the RFC. pub fn from_code(code: &str) -> Result { match code { - "1101" => Ok(NotPerformedResponse::new(1101, "already processing request")), + "1101" => Ok(NotPerformedResponse::new( + 1101, + "already processing request", + )), "1102" => Ok(NotPerformedResponse::new(1102, "version number error")), "1103" => Ok(NotPerformedResponse::new(1103, "unrecognized request type")), - "1104" => Ok(NotPerformedResponse::new(1104, "request scheduled for processing")), + "1104" => Ok(NotPerformedResponse::new( + 1104, + "request scheduled for processing", + )), - "1201" => Ok(NotPerformedResponse::new(1201, "request - no such resource class")), - "1202" => Ok(NotPerformedResponse::new(1202, "request - no resources allocated in resource class")), - "1203" => Ok(NotPerformedResponse::new(1203, "request - badly formed certificate request")), - "1204" => Ok(NotPerformedResponse::new(1204, "request - already used key in request")), + "1201" => Ok(NotPerformedResponse::new( + 1201, + "request - no such resource class", + )), + "1202" => Ok(NotPerformedResponse::new( + 1202, + "request - no resources allocated in resource class", + )), + "1203" => Ok(NotPerformedResponse::new( + 1203, + "request - badly formed certificate request", + )), + "1204" => Ok(NotPerformedResponse::new( + 1204, + "request - already used key in request", + )), - "1301" => Ok(NotPerformedResponse::new(1301, "revoke - no such resource class")), + "1301" => Ok(NotPerformedResponse::new( + 1301, + "revoke - no such resource class", + )), "1302" => Ok(NotPerformedResponse::new(1302, "revoke - no such key")), - "2001" => Ok(NotPerformedResponse::new(2001, "Internal Server Error - Request not performed")), - _ => Err(Error::InvalidErrorCode(code.to_string())) + "2001" => Ok(NotPerformedResponse::new( + 2001, + "Internal Server Error - Request not performed", + )), + _ => Err(Error::InvalidErrorCode(code.to_string())), } } - pub fn _1101() -> Self { Self::from_code("1101").unwrap() } - pub fn _1102() -> Self { Self::from_code("1102").unwrap() } - pub fn _1103() -> Self { Self::from_code("1103").unwrap() } - pub fn _1104() -> Self { Self::from_code("1104").unwrap() } + pub fn _1101() -> Self { + Self::from_code("1101").unwrap() + } + pub fn _1102() -> Self { + Self::from_code("1102").unwrap() + } + pub fn _1103() -> Self { + Self::from_code("1103").unwrap() + } + pub fn _1104() -> Self { + Self::from_code("1104").unwrap() + } - pub fn _1201() -> Self { Self::from_code("1201").unwrap() } - pub fn _1202() -> Self { Self::from_code("1202").unwrap() } - pub fn _1203() -> Self { Self::from_code("1203").unwrap() } - pub fn _1204() -> Self { Self::from_code("1204").unwrap() } + pub fn _1201() -> Self { + Self::from_code("1201").unwrap() + } + pub fn _1202() -> Self { + Self::from_code("1202").unwrap() + } + pub fn _1203() -> Self { + Self::from_code("1203").unwrap() + } + pub fn _1204() -> Self { + Self::from_code("1204").unwrap() + } - pub fn _1301() -> Self { Self::from_code("1301").unwrap() } - pub fn _1302() -> Self { Self::from_code("1302").unwrap() } + pub fn _1301() -> Self { + Self::from_code("1301").unwrap() + } + pub fn _1302() -> Self { + Self::from_code("1302").unwrap() + } - pub fn _2001() -> Self { Self::from_code("2001").unwrap() } + pub fn _2001() -> Self { + Self::from_code("2001").unwrap() + } } - - //------------ Error --------------------------------------------------------- #[derive(Debug, Display)] @@ -864,7 +886,9 @@ pub enum Error { } impl Error { - fn inr_syntax(e: impl Display) -> Self { Error::InrSyntax(e.to_string())} + fn inr_syntax(e: impl Display) -> Self { + Error::InrSyntax(e.to_string()) + } } impl From for Error { @@ -905,8 +929,8 @@ mod tests { use std::str; use std::str::from_utf8_unchecked; - use crate::remote::sigmsg::SignedMessage; use crate::remote::id::tests::test_id_certificate; + use crate::remote::sigmsg::SignedMessage; use super::*; use remote::id::IdCert; @@ -923,26 +947,24 @@ mod tests { fn extract_xml(pdu: &[u8]) -> String { let msg = SignedMessage::decode(pdu.as_ref(), false).unwrap(); let content = msg.content().to_bytes(); - let xml = unsafe { - from_utf8_unchecked(content.as_ref()) - }; + let xml = unsafe { from_utf8_unchecked(content.as_ref()) }; xml.to_string() } #[test] fn parse_and_encode_list() { - let xml = extract_xml( - include_bytes!("../../test-resources/remote/rpkid-rfc6492-list.der") - ); + let xml = extract_xml(include_bytes!( + "../../test-resources/remote/rpkid-rfc6492-list.der" + )); let list = Message::decode(xml.as_bytes()).unwrap(); assert_re_encode_equals(list); } #[test] fn parse_and_encode_list_response() { - let xml = extract_xml( - include_bytes!("../../test-resources/remote/rpkid-rfc6492-list_response.der") - ); + let xml = extract_xml(include_bytes!( + "../../test-resources/remote/rpkid-rfc6492-list_response.der" + )); let list_response = Message::decode(xml.as_bytes()).unwrap(); assert_re_encode_equals(list_response); } @@ -953,10 +975,7 @@ mod tests { let msg = SignedMessage::decode(pdu.as_ref(), false).unwrap(); let content = msg.content().to_bytes(); - let xml = unsafe { - from_utf8_unchecked(content.as_ref()) - }; - + let xml = unsafe { from_utf8_unchecked(content.as_ref()) }; let _list_response = Message::decode(xml.as_bytes()).unwrap(); @@ -968,18 +987,18 @@ mod tests { #[test] fn parse_and_encode_issue() { - let xml = extract_xml( - include_bytes!("../../test-resources/remote/rpkid-rfc6492-issue.der") - ); + let xml = extract_xml(include_bytes!( + "../../test-resources/remote/rpkid-rfc6492-issue.der" + )); let issue = Message::decode(xml.as_bytes()).unwrap(); assert_re_encode_equals(issue); } #[test] fn parse_and_encode_issue_response() { - let xml = extract_xml( - include_bytes!("../../test-resources/remote/rpkid-rfc6492-issue_response.der") - ); + let xml = extract_xml(include_bytes!( + "../../test-resources/remote/rpkid-rfc6492-issue_response.der" + )); let issue = Message::decode(xml.as_bytes()).unwrap(); assert_re_encode_equals(issue); } @@ -1023,7 +1042,6 @@ mod tests { assert_eq!(rev, decoded_rev); } - #[test] fn encode_and_parse_error_response() { // No example CMS found for this one, so just composing and @@ -1037,4 +1055,4 @@ mod tests { assert_eq!(err, decoded); } -} \ No newline at end of file +} diff --git a/commons/src/remote/rfc8181.rs b/commons/src/remote/rfc8181.rs index 390c2d48..f3af56c4 100644 --- a/commons/src/remote/rfc8181.rs +++ b/commons/src/remote/rfc8181.rs @@ -1,30 +1,23 @@ //! RFC8181 Messages -use std::io; -use bytes::Bytes; -use rpki::uri; use crate::api::publication; use crate::api::{Base64, EncodedHash}; -use crate::util::xml::{ - Attributes, - AttributesError, - XmlReader, - XmlReaderErr, - XmlWriter -}; use crate::remote::sigmsg::SignedMessage; +use crate::util::xml::{Attributes, AttributesError, XmlReader, XmlReaderErr, XmlWriter}; +use bytes::Bytes; +use rpki::uri; +use std::io; pub const VERSION: &str = "4"; pub const NS: &str = "http://www.hactrn.net/uris/rpki/publication-spec/"; - //------------ Message ------------------------------------------------------- /// This type represents all Publication Messages defined in RFC8181 #[derive(Clone, Debug, Eq, PartialEq)] pub enum Message { QueryMessage(QueryMessage), - ReplyMessage(ReplyMessage) + ReplyMessage(ReplyMessage), } /// # Decoding and Encoding @@ -32,63 +25,43 @@ pub enum Message { impl Message { /// Decodes an XML structure pub fn decode(reader: R) -> Result - where R: io::Read { - + where + R: io::Read, + { XmlReader::decode(reader, |r| { r.take_named_element("msg", |mut a, r| { - match a.take_req("version")?.as_ref() { - VERSION => { }, - _ => return Err(MessageError::InvalidVersion) + VERSION => {} + _ => return Err(MessageError::InvalidVersion), } let msg_type = a.take_req("type")?; a.exhausted()?; match msg_type.as_ref() { - "query" => { - Ok(Message::QueryMessage(QueryMessage::decode(r)?)) - }, - "reply" => { - Ok(Message::ReplyMessage(ReplyMessage::decode(r)?)) - } - _ => { - Err(MessageError::UnknownMessageType) - } + "query" => Ok(Message::QueryMessage(QueryMessage::decode(r)?)), + "reply" => Ok(Message::ReplyMessage(ReplyMessage::decode(r)?)), + _ => Err(MessageError::UnknownMessageType), } }) }) } - pub fn encode(&self, target: &mut XmlWriter) - -> Result<(), io::Error> { - + pub fn encode(&self, target: &mut XmlWriter) -> Result<(), io::Error> { let msg_type = match self { Message::QueryMessage(_) => "query", - Message::ReplyMessage(_) => "reply" + Message::ReplyMessage(_) => "reply", }; - let a = [ - ("xmlns", NS), - ("version", VERSION), - ("type", msg_type), - ]; + let a = [("xmlns", NS), ("version", VERSION), ("type", msg_type)]; - target.put_element( - "msg", - Some(&a), - |w| { - match self { - Message::ReplyMessage(r) => { r.encode(w) } - Message::QueryMessage(q) => { q.encode(w) } - } - } - ) + target.put_element("msg", Some(&a), |w| match self { + Message::ReplyMessage(r) => r.encode(w), + Message::QueryMessage(q) => q.encode(w), + }) } /// Encodes to a Vec pub fn encode_vec(&self) -> Vec { - XmlWriter::encode_vec(|w| { - self.encode(w) - }) + XmlWriter::encode_vec(|w| self.encode(w)) } /// Consumes the message and turns it into bytes @@ -97,9 +70,7 @@ impl Message { } /// Parses the content of a SignedMessage as a Message. - pub fn from_signed_message( - msg: &SignedMessage - ) -> Result { + pub fn from_signed_message(msg: &SignedMessage) -> Result { Message::decode(msg.content().to_bytes().as_ref()) } @@ -108,7 +79,7 @@ impl Message { pub fn into_query(self) -> Result { match self { Message::QueryMessage(q) => Ok(q), - _ => Err(MessageError::WrongMessageType) + _ => Err(MessageError::WrongMessageType), } } @@ -117,7 +88,7 @@ impl Message { pub fn into_reply(self) -> Result { match self { Message::ReplyMessage(r) => Ok(r), - _ => Err(MessageError::WrongMessageType) + _ => Err(MessageError::WrongMessageType), } } } @@ -125,7 +96,6 @@ impl Message { /// Constructing /// impl Message { - pub fn list_reply(reply: publication::ListReply) -> Self { Message::ReplyMessage(ReplyMessage::ListReply(reply)) } @@ -143,66 +113,59 @@ impl Message { } } - //------------ QueryMessage -------------------------------------------------- /// This type represents query type Publication Messages defined in RFC8181 #[derive(Clone, Debug, Eq, PartialEq)] pub enum QueryMessage { PublishDelta(publication::PublishDelta), - ListQuery + ListQuery, } /// # Decoding and Encoding /// impl QueryMessage { fn decode(r: &mut XmlReader) -> Result - where R: io::Read { + where + R: io::Read, + { match r.next_start_name() { - Some("list") =>{ + Some("list") => { Self::decode_list_query(r)?; Ok(QueryMessage::ListQuery) - }, + } Some("publish") | Some("withdraw") => { Ok(QueryMessage::PublishDelta(PublishDeltaXml::decode(r)?)) - }, + } None => { // empty publish query Ok(QueryMessage::PublishDelta(PublishDeltaXml::decode(r)?)) - }, - _ => { - Err(MessageError::ExpectedStart( - "list, publish, or withdraw".to_string())) + } + _ => Err(MessageError::ExpectedStart( + "list, publish, or withdraw".to_string(), + )), + } + } + + fn decode_list_query(r: &mut XmlReader) -> Result<(), MessageError> { + r.take_named_element("list", |_, r| r.take_empty())?; + Ok(()) + } + + pub fn encode(&self, w: &mut XmlWriter) -> Result<(), io::Error> { + match self { + QueryMessage::PublishDelta(d) => { + PublishDeltaXml::encode(d, w)?; + } + QueryMessage::ListQuery => { + Self::encode_list_query(w)?; } } - } - - fn decode_list_query( - r: &mut XmlReader - ) -> Result<(), MessageError> { - r.take_named_element("list", |_, r| { r.take_empty() })?; Ok(()) } - pub fn encode( - &self, - w: &mut XmlWriter - ) -> Result<(), io::Error> { - match self { - QueryMessage::PublishDelta(d) => { PublishDeltaXml::encode(d, w)?; } - QueryMessage::ListQuery => { Self::encode_list_query(w)?; } - } - Ok(()) - } - - fn encode_list_query( - w: &mut XmlWriter - ) -> Result<(), io::Error> { - w.put_element( - "list", - None, - |w| { w.empty() } - )?; + fn encode_list_query(w: &mut XmlWriter) -> Result<(), io::Error> { + w.put_element("list", None, |w| w.empty())?; Ok(()) } @@ -210,13 +173,12 @@ impl QueryMessage { /// Consumes this and returns this a PublishRequest for our (json) API pub fn into_publish_request(self) -> publication::PublishRequest { match self { - QueryMessage::ListQuery => publication::PublishRequest::List, - QueryMessage::PublishDelta(d) => publication::PublishRequest::Delta(d) + QueryMessage::ListQuery => publication::PublishRequest::List, + QueryMessage::PublishDelta(d) => publication::PublishRequest::Delta(d), } } } - //------------ PublishDeltaXml ----------------------------------------------- /// Marker struct to give a name space to all code related to decoding, and @@ -227,21 +189,15 @@ pub struct PublishDeltaXml; pub enum PublishDeltaElement { Publish(publication::Publish), Update(publication::Update), - Withdraw(publication::Withdraw) + Withdraw(publication::Withdraw), } impl PublishDeltaElement { - fn encode( - &self, - w: &mut XmlWriter - ) -> Result<(), io::Error> { + fn encode(&self, w: &mut XmlWriter) -> Result<(), io::Error> { match self { - PublishDeltaElement::Publish(p) => - PublishDeltaXml::encode_publish(p, w), - PublishDeltaElement::Update(u) => - PublishDeltaXml::encode_update(u, w), - PublishDeltaElement::Withdraw(wd) => - PublishDeltaXml::encode_withdraw(wd, w) + PublishDeltaElement::Publish(p) => PublishDeltaXml::encode_publish(p, w), + PublishDeltaElement::Update(u) => PublishDeltaXml::encode_update(u, w), + PublishDeltaElement::Withdraw(wd) => PublishDeltaXml::encode_withdraw(wd, w), } } } @@ -253,9 +209,8 @@ impl PublishDeltaXml { /// Publish element, or an Update - wrapped in a PublishElement. fn decode_publish_or_update( a: &mut Attributes, - r: &mut XmlReader + r: &mut XmlReader, ) -> Result { - let uri = uri::Rsync::from_string(a.take_req("uri")?)?; let tag = a.take_req("tag")?; let base64_string = r.take_chars()?; @@ -264,11 +219,9 @@ impl PublishDeltaXml { let res = match a.take_opt("hash") { Some(hash_str) => { let hash = EncodedHash::from(hash_str); - let update = publication::Update::new( - Some(tag), uri, base64, hash - ); + let update = publication::Update::new(Some(tag), uri, base64, hash); Ok(PublishDeltaElement::Update(update)) - }, + } None => { let publish = publication::Publish::new(Some(tag), uri, base64); Ok(PublishDeltaElement::Publish(publish)) @@ -280,10 +233,7 @@ impl PublishDeltaXml { } /// Decodes a XML element. - fn decode_withdraw( - a: &mut Attributes - ) -> Result { - + fn decode_withdraw(a: &mut Attributes) -> Result { let hash_str = a.take_req("hash")?; let hash = EncodedHash::from(hash_str); let uri = uri::Rsync::from_string(a.take_req("uri")?)?; @@ -298,38 +248,27 @@ impl PublishDeltaXml { /// Decodes from an XML input. Used for processing a list of elements. /// Will return None when there is no (more) applicable element. fn decode_opt( - r: &mut XmlReader + r: &mut XmlReader, ) -> Result, MessageError> { - - r.take_opt_element(|t, mut a, r| { - match t.name.as_ref() { - "publish" => { - Ok(Some(Self::decode_publish_or_update(&mut a, r)?)) - }, - "withdraw" => { - Ok(Some(Self::decode_withdraw(&mut a)?)) - }, - _ => { - Err(MessageError::UnexpectedStart(t.name.clone())) - } - } + r.take_opt_element(|t, mut a, r| match t.name.as_ref() { + "publish" => Ok(Some(Self::decode_publish_or_update(&mut a, r)?)), + "withdraw" => Ok(Some(Self::decode_withdraw(&mut a)?)), + _ => Err(MessageError::UnexpectedStart(t.name.clone())), }) } - - /// Decodes a query XML structure. Expects that the outer element /// is processed by PublicationMessage::decode pub fn decode( - r: &mut XmlReader + r: &mut XmlReader, ) -> Result { let mut bld = publication::PublishDeltaBuilder::new(); while let Some(pde) = Self::decode_opt(r)? { match pde { - PublishDeltaElement::Publish(p) => bld.add_publish(p), - PublishDeltaElement::Update(u) => bld.add_update(u), - PublishDeltaElement::Withdraw(w) => bld.add_withdraw(w) + PublishDeltaElement::Publish(p) => bld.add_publish(p), + PublishDeltaElement::Update(u) => bld.add_update(u), + PublishDeltaElement::Withdraw(w) => bld.add_withdraw(w), } } @@ -344,85 +283,68 @@ impl PublishDeltaXml { /// RFC8181 CMS. pub fn encode( delta: &publication::PublishDelta, - w: &mut XmlWriter + w: &mut XmlWriter, ) -> Result<(), io::Error> { - for p in delta.publishes() { Self::encode_publish(p, w)?; } - for u in delta.updates() { Self::encode_update(u, w)?; } - for wd in delta.withdraws() { Self::encode_withdraw(wd, w)?; } + for p in delta.publishes() { + Self::encode_publish(p, w)?; + } + for u in delta.updates() { + Self::encode_update(u, w)?; + } + for wd in delta.withdraws() { + Self::encode_withdraw(wd, w)?; + } Ok(()) } fn encode_publish( publish: &publication::Publish, - w: &mut XmlWriter + w: &mut XmlWriter, ) -> Result<(), io::Error> { - let uri = publish.uri().to_string(); let tag = publish.tag_for_xml(); let content = publish.content().to_string(); - let a = [ - ("tag", tag.as_ref()), - ("uri", uri.as_ref()), - ]; + let a = [("tag", tag.as_ref()), ("uri", uri.as_ref())]; - w.put_element( - "publish", - Some(&a), - |w| { - w.put_text(content.as_ref()) - } - ) + w.put_element("publish", Some(&a), |w| w.put_text(content.as_ref())) } fn encode_update( update: &publication::Update, - w: &mut XmlWriter + w: &mut XmlWriter, ) -> Result<(), io::Error> { - let uri = update.uri().to_string(); let tag = update.tag_for_xml(); let a = [ ("tag", tag.as_ref()), ("hash", update.hash().as_ref()), - ("uri", uri.as_ref()) + ("uri", uri.as_ref()), ]; - w.put_element( - "publish", - Some(&a), - |w| { - w.put_text(update.content().as_ref()) - } - ) + w.put_element("publish", Some(&a), |w| { + w.put_text(update.content().as_ref()) + }) } fn encode_withdraw( withdraw: &publication::Withdraw, - w: &mut XmlWriter + w: &mut XmlWriter, ) -> Result<(), io::Error> { - let uri = withdraw.uri().to_string(); let tag = withdraw.tag_for_xml(); let a = [ ("hash", withdraw.hash().as_ref()), ("tag", tag.as_ref()), - ("uri", uri.as_ref()) + ("uri", uri.as_ref()), ]; - w.put_element( - "withdraw", - Some(&a), - |w| { - w.empty() - } - ) + w.put_element("withdraw", Some(&a), |w| w.empty()) } } - //------------ ReplyMessage -------------------------------------------------- /// This type represents reply type Publication Messages defined in RFC8181 @@ -430,7 +352,7 @@ impl PublishDeltaXml { pub enum ReplyMessage { SuccessReply, ListReply(publication::ListReply), - ErrorReply(ErrorReply) + ErrorReply(ErrorReply), } /// # Decoding and Encoding @@ -439,76 +361,70 @@ impl ReplyMessage { /// Decodes XML into a ReplyMessage containing either a Success, List or /// Error. fn decode(r: &mut XmlReader) -> Result - where R: io::Read { + where + R: io::Read, + { match r.next_start_name() { Some("success") => { Self::decode_success_reply(r)?; Ok(ReplyMessage::SuccessReply) - }, - Some("report_error") => { - Ok(ReplyMessage::ErrorReply(ErrorReply::decode(r)?)) - }, - Some("list") => { - Ok(ReplyMessage::ListReply(Self::decode_list_reply(r)?)) - }, + } + Some("report_error") => Ok(ReplyMessage::ErrorReply(ErrorReply::decode(r)?)), + Some("list") => Ok(ReplyMessage::ListReply(Self::decode_list_reply(r)?)), None => { // An empty list response Ok(ReplyMessage::ListReply(Self::decode_list_reply(r)?)) - }, + } _ => Err(MessageError::ExpectedStart( - "success, list or report_error".to_string())) + "success, list or report_error".to_string(), + )), } } /// Decodes a reply from XML. - pub fn decode_success_reply( - r: &mut XmlReader - ) -> Result<(), MessageError> { - r.take_named_element("success", |_, r| { r.take_empty() })?; + pub fn decode_success_reply(r: &mut XmlReader) -> Result<(), MessageError> { + r.take_named_element("success", |_, r| r.take_empty())?; Ok(()) } /// Decodes XML to a ListReply. fn decode_list_reply( - r: &mut XmlReader + r: &mut XmlReader, ) -> Result { - let mut elements = vec![]; loop { - let e = r.take_opt_element(|t, mut a, _r| { - match t.name.as_ref() { - "list" => { - let hash = EncodedHash::from(a.take_req("hash")?); - let uri = uri::Rsync::from_string(a.take_req("uri")?)?; - a.exhausted()?; + let e = r.take_opt_element(|t, mut a, _r| match t.name.as_ref() { + "list" => { + let hash = EncodedHash::from(a.take_req("hash")?); + let uri = uri::Rsync::from_string(a.take_req("uri")?)?; + a.exhausted()?; - Ok(Some(publication::ListElement::new(uri, hash))) - }, - _ => { - Err(MessageError::UnexpectedStart(t.name.clone())) - } + Ok(Some(publication::ListElement::new(uri, hash))) } + _ => Err(MessageError::UnexpectedStart(t.name.clone())), })?; match e { Some(e) => elements.push(e), - None => break + None => break, } } Ok(publication::ListReply::new(elements)) } /// Encodes a ReplyMessage for inclusion in an RFC8181 Protocol CMS. - pub fn encode( - &self, - w: &mut XmlWriter - ) -> Result<(), io::Error> { - + pub fn encode(&self, w: &mut XmlWriter) -> Result<(), io::Error> { match self { - ReplyMessage::SuccessReply => { Self::encode_success_reply(w)?; } - ReplyMessage::ListReply(l) => { Self::encode_list_reply(l, w)?; } - ReplyMessage::ErrorReply(e) => { e.encode(w)?; } + ReplyMessage::SuccessReply => { + Self::encode_success_reply(w)?; + } + ReplyMessage::ListReply(l) => { + Self::encode_list_reply(l, w)?; + } + ReplyMessage::ErrorReply(e) => { + e.encode(w)?; + } } Ok(()) } @@ -516,16 +432,15 @@ impl ReplyMessage { /// Encodes a ListReply to XML. fn encode_list_reply( reply: &publication::ListReply, - w: &mut XmlWriter + w: &mut XmlWriter, ) -> Result<(), io::Error> { - for el in reply.elements() { let uri = el.uri().to_string(); w.put_element( "list", Some(&[("hash", el.hash().as_ref()), ("uri", uri.as_ref())]), - |w| { w.empty() } + |w| w.empty(), )?; } @@ -533,19 +448,11 @@ impl ReplyMessage { } /// Encodes a success reply to xml - pub fn encode_success_reply( - w: &mut XmlWriter - ) -> Result<(), io::Error> { - - w.put_element( - "success", - None, - |w| { w.empty() } - )?; + pub fn encode_success_reply(w: &mut XmlWriter) -> Result<(), io::Error> { + w.put_element("success", None, |w| w.empty())?; Ok(()) } - } //------------ ErrorReply ---------------------------------------------------- @@ -554,51 +461,46 @@ impl ReplyMessage { /// https://tools.ietf.org/html/rfc8181#section-3.5 and 3.6 #[derive(Clone, Debug, Eq, PartialEq)] pub struct ErrorReply { - errors: Vec + errors: Vec, } impl ErrorReply { - fn decode_error_text(r: &mut XmlReader) - -> Result, MessageError> { - + fn decode_error_text( + r: &mut XmlReader, + ) -> Result, MessageError> { Ok(Some(r.take_named_element( "error_text", |a, r| -> Result { a.exhausted()?; Ok(r.take_chars()?) - } + }, )?)) } fn decode_failed_pdu( - r: &mut XmlReader + r: &mut XmlReader, ) -> Result, MessageError> { Ok(Some(r.take_named_element( "failed_pdu", - |a, r| -> Result{ + |a, r| -> Result { a.exhausted()?; match PublishDeltaXml::decode_opt(r)? { Some(p) => Ok(p), - None => { - Err(MessageError::MissingContent( - "Expected PDU".to_string())) - } + None => Err(MessageError::MissingContent("Expected PDU".to_string())), } - } + }, )?)) } /// Decodes XML into an ErrorReport. - pub fn decode(r: &mut XmlReader) - -> Result { - + pub fn decode(r: &mut XmlReader) -> Result { let mut errors = vec![]; loop { let e = r.take_opt_element(|t, mut a, r| { match t.name.as_ref() { "report_error" => { - let error_code = ReportErrorCode::from_str( - a.take_req("error_code")?.as_ref())?; + let error_code = + ReportErrorCode::from_str(a.take_req("error_code")?.as_ref())?; let tag = a.take_req("tag")?; let mut error_text: Option = None; let mut failed_pdu: Option = None; @@ -609,77 +511,55 @@ impl ErrorReply { match r.next_start_name() { Some("error_text") => { error_text = Self::decode_error_text(r)?; - }, + } Some("failed_pdu") => { failed_pdu = Self::decode_failed_pdu(r)?; - }, - _ => { } + } + _ => {} } } - Ok(Some( - ReportError{ - error_code, - tag, - error_text, - failed_pdu - })) - }, - _ => { - Err(MessageError::UnexpectedStart(t.name.clone())) + Ok(Some(ReportError { + error_code, + tag, + error_text, + failed_pdu, + })) } + _ => Err(MessageError::UnexpectedStart(t.name.clone())), } })?; match e { Some(e) => errors.push(e), - None => break + None => break, } } - Ok(ErrorReply{errors}) + Ok(ErrorReply { errors }) } /// Encodes an ErrorReport into XML. - pub fn encode(&self, w: &mut XmlWriter) - -> Result<(), io::Error> { - + pub fn encode(&self, w: &mut XmlWriter) -> Result<(), io::Error> { for e in &self.errors { - let error_code = format!("{}", e.error_code); - let a = [ - ("error_code", error_code.as_ref()), - ("tag", e.tag.as_ref()) - ]; + let a = [("error_code", error_code.as_ref()), ("tag", e.tag.as_ref())]; - w.put_element( - "report_error", - Some(&a), - |w| { - - match &e.error_text { - None => {}, - Some(t) => { - w.put_element( - "error_text", - None, - |w| { w.put_text(t.as_ref())} - )?; - } + w.put_element("report_error", Some(&a), |w| { + match &e.error_text { + None => {} + Some(t) => { + w.put_element("error_text", None, |w| w.put_text(t.as_ref()))?; } - - match &e.failed_pdu { - None => {}, - Some(p) => { - w.put_element( - "failed_pdu", - None, - |w| { p.encode(w) } - )?; - } - } - - w.empty() } - )?; + + match &e.failed_pdu { + None => {} + Some(p) => { + w.put_element("failed_pdu", None, |w| p.encode(w))?; + } + } + + w.empty() + })?; } Ok(()) @@ -701,17 +581,18 @@ impl ErrorReply { } } - //------------ ErrorReplyBuilder --------------------------------------------- #[derive(Default)] pub struct ErrorReplyBuilder { - errors: Vec + errors: Vec, } impl ErrorReplyBuilder { fn with_capacity(n: usize) -> Self { - ErrorReplyBuilder { errors: Vec::with_capacity(n) } + ErrorReplyBuilder { + errors: Vec::with_capacity(n), + } } /// Adds a ReportError to the ErrorReply. Multiple allowed. @@ -722,15 +603,12 @@ impl ErrorReplyBuilder { /// Creates an ErrorReply wrapped in a Message for inclusion in a publication /// protocol CMS message. pub fn build_message(self) -> Message { - Message::ReplyMessage( - ReplyMessage::ErrorReply( - ErrorReply { errors: self.errors } - ) - ) + Message::ReplyMessage(ReplyMessage::ErrorReply(ErrorReply { + errors: self.errors, + })) } } - //------------ ReportError --------------------------------------------------- #[derive(Clone, Debug, Eq, PartialEq)] @@ -738,65 +616,63 @@ pub struct ReportError { error_code: ReportErrorCode, tag: String, error_text: Option, - failed_pdu: Option + failed_pdu: Option, } impl ReportError { /// Creates an entry to include in an ErrorReply. Multiple entries may be /// included. - pub fn reply( - error_code: ReportErrorCode, - failed_pdu: Option - ) -> Self { + pub fn reply(error_code: ReportErrorCode, failed_pdu: Option) -> Self { let tag = match failed_pdu { None => "".to_string(), Some(ref pdu) => match pdu { - PublishDeltaElement::Publish(p) => p.tag_for_xml(), - PublishDeltaElement::Update(u) => u.tag_for_xml(), - PublishDeltaElement::Withdraw(w) => w.tag_for_xml() - } + PublishDeltaElement::Publish(p) => p.tag_for_xml(), + PublishDeltaElement::Update(u) => u.tag_for_xml(), + PublishDeltaElement::Withdraw(w) => w.tag_for_xml(), + }, }; let error_text = Some(error_code.to_text()); ReportError { - error_code, tag, error_text, failed_pdu + error_code, + tag, + error_text, + failed_pdu, } } } - //------------ ReportErrorCodes ---------------------------------------------- /// The allowed error codes defined in RFC8181 section 2.5 #[derive(Clone, Debug, Display, Eq, PartialEq)] pub enum ReportErrorCode { - #[display(fmt="xml_error")] + #[display(fmt = "xml_error")] XmlError, - #[display(fmt="permission_failure")] + #[display(fmt = "permission_failure")] PermissionFailure, - #[display(fmt="bad_cms_signature")] + #[display(fmt = "bad_cms_signature")] BadCmsSignature, - #[display(fmt="object_already_present")] + #[display(fmt = "object_already_present")] ObjectAlreadyPresent, - #[display(fmt="no_object_present")] + #[display(fmt = "no_object_present")] NoObjectPresent, - #[display(fmt="no_object_matching_hash")] + #[display(fmt = "no_object_matching_hash")] NoObjectMatchingHash, - #[display(fmt="consistency_problem")] + #[display(fmt = "consistency_problem")] ConsistencyProblem, - #[display(fmt="other_error")] + #[display(fmt = "other_error")] OtherError, } impl ReportErrorCode { - /// Resolves the error type strings used in XML to the correct types. fn from_str(v: &str) -> Result { match v { @@ -808,7 +684,7 @@ impl ReportErrorCode { "no_object_matching_hash" => Ok(ReportErrorCode::NoObjectMatchingHash), "consistency_problem" => Ok(ReportErrorCode::ConsistencyProblem), "other_error" => Ok(ReportErrorCode::OtherError), - _ => Err(MessageError::InvalidErrorCode(v.to_string())) + _ => Err(MessageError::InvalidErrorCode(v.to_string())), } } @@ -828,7 +704,6 @@ impl ReportErrorCode { } } - //------------ PublicationMessageError --------------------------------------- #[derive(Debug, Display)] @@ -882,7 +757,6 @@ impl From for MessageError { } } - //------------ Tests --------------------------------------------------------- #[cfg(test)] @@ -896,13 +770,14 @@ mod tests { use crate::util::test::rsync; struct ListReplyBuilder { - elements: Vec + elements: Vec, } impl ListReplyBuilder { - fn with_capacity(n: usize) -> ListReplyBuilder { - ListReplyBuilder { elements: Vec::with_capacity(n) } + ListReplyBuilder { + elements: Vec::with_capacity(n), + } } pub fn add(&mut self, object: &Bytes, uri: uri::Rsync) { @@ -914,9 +789,7 @@ mod tests { /// Creates a ListReply wrapped in a Message for inclusion in a publication /// protocol CMS message. pub fn build_message(self) -> Message { - Message::list_reply( - publication::ListReply::new(self.elements) - ) + Message::list_reply(publication::ListReply::new(self.elements)) } } @@ -981,7 +854,8 @@ mod tests { let m = Message::success_reply(); let v = m.encode_vec(); let produced_xml = str::from_utf8(&v).unwrap(); - let expected_xml = include_str!("../../test-resources/publication/generated/success_reply_result.xml"); + let expected_xml = + include_str!("../../test-resources/publication/generated/success_reply_result.xml"); assert_eq!(produced_xml, expected_xml); } @@ -998,7 +872,8 @@ mod tests { let v = m.encode_vec(); let produced_xml = str::from_utf8(&v).unwrap(); - let expected_xml = include_str!("../../test-resources/publication/generated/list_reply_result.xml"); + let expected_xml = + include_str!("../../test-resources/publication/generated/list_reply_result.xml"); assert_eq!(produced_xml, expected_xml); } @@ -1007,24 +882,22 @@ mod tests { fn should_create_error_reply() { let object = Bytes::from_static(include_bytes!("../../test-resources/remote/cms_ta.cer")); let object = Base64::from_content(&object); - let publish = publication::Publish::with_hash_tag( - rsync("rsync://host/path/cms-ta.cer"), - object - ); + let publish = + publication::Publish::with_hash_tag(rsync("rsync://host/path/cms-ta.cer"), object); let error_pdu = PublishDeltaElement::Publish(publish); let mut b = ErrorReply::build_with_capacity(2); b.add(ReportError::reply( - ReportErrorCode::ObjectAlreadyPresent, Some(error_pdu)) - ); - b.add(ReportError::reply( - ReportErrorCode::OtherError, None) - ); + ReportErrorCode::ObjectAlreadyPresent, + Some(error_pdu), + )); + b.add(ReportError::reply(ReportErrorCode::OtherError, None)); let m = b.build_message(); let v = m.encode_vec(); let produced_xml = str::from_utf8(&v).unwrap(); - let expected_xml = include_str!("../../test-resources/publication/generated/error_reply_result.xml"); + let expected_xml = + include_str!("../../test-resources/publication/generated/error_reply_result.xml"); assert_eq!(produced_xml, expected_xml); } @@ -1034,7 +907,8 @@ mod tests { let lq = Message::list_query(); let vec = lq.encode_vec(); let produced_xml = str::from_utf8(&vec).unwrap(); - let expected_xml = include_str!("../../test-resources/publication/generated/list_query_result.xml"); + let expected_xml = + include_str!("../../test-resources/publication/generated/list_query_result.xml"); assert_eq!(produced_xml, expected_xml); } @@ -1049,34 +923,29 @@ mod tests { let mut builder = publication::PublishDeltaBuilder::new(); - builder.add_withdraw( - publication::Withdraw::with_hash_tag( - rsync("rsync://host/path/cms-ta.cer"), - object_hash.clone() - ) - ); + builder.add_withdraw(publication::Withdraw::with_hash_tag( + rsync("rsync://host/path/cms-ta.cer"), + object_hash.clone(), + )); - builder.add_publish( - publication::Publish::with_hash_tag( - rsync("rsync://host/path/cms-ta.cer"), - object - ) - ); + builder.add_publish(publication::Publish::with_hash_tag( + rsync("rsync://host/path/cms-ta.cer"), + object, + )); - builder.add_update( - publication::Update::with_hash_tag( - rsync("rsync://host/path/cms-ta.cer"), - object2, - object_hash - ) - ); + builder.add_update(publication::Update::with_hash_tag( + rsync("rsync://host/path/cms-ta.cer"), + object2, + object_hash, + )); let m = Message::publish_delta_query(builder.finish()); let vec = m.encode_vec(); let produced_xml = str::from_utf8(&vec).unwrap(); - let expected_xml = include_str!("../../test-resources/publication/generated/publish_query_result.xml"); + let expected_xml = + include_str!("../../test-resources/publication/generated/publish_query_result.xml"); assert_eq!(produced_xml, expected_xml); } -} \ No newline at end of file +} diff --git a/commons/src/remote/rfc8183.rs b/commons/src/remote/rfc8183.rs index ac00208e..c31b69b2 100644 --- a/commons/src/remote/rfc8183.rs +++ b/commons/src/remote/rfc8183.rs @@ -3,10 +3,10 @@ //! Support for the RFC8183 out-of-band setup requests and responses //! used to exchange identity and configuration between CAs and their //! parent CA and/or RPKI Publication Servers. -use std::{io, fmt}; -use std::path::PathBuf; -use std::str::{FromStr, from_utf8_unchecked}; use std::convert::TryFrom; +use std::path::PathBuf; +use std::str::{from_utf8_unchecked, FromStr}; +use std::{fmt, io}; use base64::DecodeError; use bcder::decode; @@ -19,20 +19,13 @@ use rpki::x509::Time; use crate::api::admin::Handle; use crate::util::file; -use crate::util::xml::{ - AttributesError, - XmlReader, - XmlReaderErr, - XmlWriter -}; - +use crate::util::xml::{AttributesError, XmlReader, XmlReaderErr, XmlWriter}; use crate::remote::id::IdCert; pub const VERSION: &str = "1"; pub const NS: &str = "http://www.hactrn.net/uris/rpki/rpki-setup/"; - //------------ ChildRequest -------------------------------------------------- /// Type representing a defined in section 5.2.1 of @@ -54,16 +47,26 @@ pub struct ChildRequest { /// impl ChildRequest { pub fn new(child_handle: Handle, id_cert: IdCert) -> Self { - ChildRequest { tag: None, child_handle, id_cert } + ChildRequest { + tag: None, + child_handle, + id_cert, + } } pub fn unwrap(self) -> (Option, Handle, IdCert) { (self.tag, self.child_handle, self.id_cert) } - pub fn tag(&self) -> Option<&String> { self.tag.as_ref() } - pub fn child_handle(&self) -> &Handle { &self.child_handle } - pub fn id_cert(&self) -> &IdCert { &self.id_cert } + pub fn tag(&self) -> Option<&String> { + self.tag.as_ref() + } + pub fn child_handle(&self) -> &Handle { + &self.child_handle + } + pub fn id_cert(&self) -> &IdCert { + &self.id_cert + } } /// # Validation @@ -71,42 +74,49 @@ impl ChildRequest { impl ChildRequest { /// Parses a message, and validates the /// embedded certificate. MUST be a validly signed TA cert. - pub fn validate( - reader: R - ) -> Result where R: io::Read { + pub fn validate(reader: R) -> Result + where + R: io::Read, + { Self::validate_at(reader, Time::now()) } /// Parses a message. - fn validate_at( - reader: R, - now: Time - ) -> Result where R: io::Read { + fn validate_at(reader: R, now: Time) -> Result + where + R: io::Read, + { XmlReader::decode(reader, |r| { r.take_named_element("child_request", |mut a, r| { if a.take_req("version")? != VERSION { - return Err(Error::InvalidVersion) + return Err(Error::InvalidVersion); } let tag = a.take_opt("tag"); let child_handle = Handle::from(a.take_req("child_handle")?); if a.take_opt("valid_until").is_some() { - warn!("Found deprecated attribute 'valid_until' used by \ - old rpkid implementations. Ignoring this, but other \ - things may break.") + warn!( + "Found deprecated attribute 'valid_until' used by \ + old rpkid implementations. Ignoring this, but other \ + things may break." + ) } a.exhausted()?; - let bytes = r.take_named_element("child_bpki_ta", |a,r| { + let bytes = r.take_named_element("child_bpki_ta", |a, r| { a.exhausted()?; r.take_bytes_std() })?; let id_cert = IdCert::decode(bytes)?; id_cert.validate_ta_at(now)?; - Ok(ChildRequest { child_handle, tag, id_cert }) + Ok(ChildRequest { + child_handle, + tag, + id_cert, + }) }) }) } @@ -118,41 +128,29 @@ impl ChildRequest { /// Encodes the to a Vec pub fn encode_vec(&self) -> Vec { XmlWriter::encode_vec(|w| { - let mut a = vec![ ("xmlns", NS), ("version", VERSION), - ("child_handle", self.child_handle.as_ref()) + ("child_handle", self.child_handle.as_ref()), ]; if let Some(ref t) = self.tag { a.push(("tag", t.as_ref())); } - w.put_element( - "child_request", - Some(a.as_ref()), - |w| { - w.put_element( - "child_bpki_ta", - None, - |w| { - w.put_base64_std(&self.id_cert.to_bytes()) - } - ) - } - ) + w.put_element("child_request", Some(a.as_ref()), |w| { + w.put_element("child_bpki_ta", None, |w| { + w.put_base64_std(&self.id_cert.to_bytes()) + }) + }) }) } } - impl fmt::Display for ChildRequest { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s = self.encode_vec(); - let s = unsafe { - from_utf8_unchecked(s.as_slice()) - }; + let s = unsafe { from_utf8_unchecked(s.as_slice()) }; s.fmt(f) } } @@ -191,35 +189,49 @@ impl ParentResponse { service_uri: ServiceUri, ) -> Self { ParentResponse { - tag, id_cert, parent_handle, child_handle, service_uri + tag, + id_cert, + parent_handle, + child_handle, + service_uri, } } - pub fn tag(&self) -> Option<&String> { self.tag.as_ref() } - pub fn id_cert(&self) -> &IdCert { &self.id_cert } - pub fn parent_handle(&self) -> &Handle { &self.parent_handle } - pub fn child_handle(&self) -> &Handle { &self.child_handle } - pub fn service_uri(&self) -> &ServiceUri { &self.service_uri } + pub fn tag(&self) -> Option<&String> { + self.tag.as_ref() + } + pub fn id_cert(&self) -> &IdCert { + &self.id_cert + } + pub fn parent_handle(&self) -> &Handle { + &self.parent_handle + } + pub fn child_handle(&self) -> &Handle { + &self.child_handle + } + pub fn service_uri(&self) -> &ServiceUri { + &self.service_uri + } } /// # Validation /// impl ParentResponse { - pub fn validate( - reader: R - ) -> Result where R: io::Read { + pub fn validate(reader: R) -> Result + where + R: io::Read, + { Self::validate_at(reader, Time::now()) } - fn validate_at( - reader: R, - now: Time - ) -> Result where R: io::Read { + fn validate_at(reader: R, now: Time) -> Result + where + R: io::Read, + { XmlReader::decode(reader, |r| { r.take_named_element("parent_response", |mut a, r| { - if a.take_req("version")? != VERSION { - return Err(Error::InvalidVersion) + return Err(Error::InvalidVersion); } let tag = a.take_opt("tag"); @@ -228,9 +240,11 @@ impl ParentResponse { let service_uri = ServiceUri::try_from(a.take_req("service_uri")?)?; if a.take_opt("valid_until").is_some() { - warn!("Found deprecated attribute 'valid_until' used by \ - old rpkid implementations. Ignoring this, but other \ - things may break.") + warn!( + "Found deprecated attribute 'valid_until' used by \ + old rpkid implementations. Ignoring this, but other \ + things may break." + ) } a.exhausted()?; @@ -248,20 +262,21 @@ impl ParentResponse { /// /// I.e. the child needs to set up their publication server /// exchange separately, and explicitly. - fn ignore_offer_or_referral( - r: &mut XmlReader - ) -> Result<(), Error> where R: io::Read { + fn ignore_offer_or_referral(r: &mut XmlReader) -> Result<(), Error> + where + R: io::Read, + { r.take_opt_element(|tag, _a, r| { match tag.name.as_str() { "offer" => { r.take_empty()?; Ok(None) - }, + } "referral" => { let chars = r.take_chars()?; Ok(Some(chars)) // help return type inference. - }, - _ => Err(Error::InvalidXml) + } + _ => Err(Error::InvalidXml), } })?; Ok(()) @@ -272,7 +287,11 @@ impl ParentResponse { } Ok(ParentResponse { - tag, id_cert, parent_handle, child_handle, service_uri + tag, + id_cert, + parent_handle, + child_handle, + service_uri, }) }) }) @@ -285,7 +304,6 @@ impl ParentResponse { /// Encodes the to a Vec pub fn encode_vec(&self) -> Vec { XmlWriter::encode_vec(|w| { - let service_uri = self.service_uri.to_string(); let mut a = vec![ @@ -300,19 +318,11 @@ impl ParentResponse { a.push(("tag", t.as_ref())); } - w.put_element( - "parent_response", - Some(a.as_ref()), - |w| { - w.put_element( - "parent_bpki_ta", - None, - |w| { - w.put_base64_std(&self.id_cert.to_bytes()) - } - ) - } - ) + w.put_element("parent_response", Some(a.as_ref()), |w| { + w.put_element("parent_bpki_ta", None, |w| { + w.put_base64_std(&self.id_cert.to_bytes()) + }) + }) }) } } @@ -342,9 +352,9 @@ pub struct PublisherRequest { impl PublisherRequest { pub fn new(tag: Option<&str>, publisher_handle: &str, id_cert: IdCert) -> Self { PublisherRequest { - tag: tag.map(|s| { s.to_string() }), + tag: tag.map(|s| s.to_string()), publisher_handle: publisher_handle.to_string(), - id_cert + id_cert, } } @@ -357,25 +367,25 @@ impl PublisherRequest { } } - /// # Validation /// impl PublisherRequest { - pub fn validate( - reader: R - ) -> Result where R: io::Read { + pub fn validate(reader: R) -> Result + where + R: io::Read, + { Self::validate_at(reader, Time::now()) } /// Parses a message. - fn validate_at( - reader: R, - now: Time - ) -> Result where R: io::Read { + fn validate_at(reader: R, now: Time) -> Result + where + R: io::Read, + { XmlReader::decode(reader, |r| { r.take_named_element("publisher_request", |mut a, r| { if a.take_req("version")? != "1" { - return Err(Error::InvalidVersion) + return Err(Error::InvalidVersion); } let tag = a.take_opt("tag"); @@ -390,7 +400,11 @@ impl PublisherRequest { let id_cert = IdCert::decode(bytes)?; id_cert.validate_ta_at(now)?; - Ok(PublisherRequest { tag, publisher_handle, id_cert }) + Ok(PublisherRequest { + tag, + publisher_handle, + id_cert, + }) }) }) } @@ -402,31 +416,21 @@ impl PublisherRequest { /// Encodes a to a Vec pub fn encode_vec(&self) -> Vec { XmlWriter::encode_vec(|w| { - let mut a = vec![ ("xmlns", NS), ("version", VERSION), - ("publisher_handle", self.publisher_handle.as_ref()) + ("publisher_handle", self.publisher_handle.as_ref()), ]; if let Some(ref t) = self.tag { a.push(("tag", t.as_ref())); } - w.put_element( - "publisher_request", - Some(a.as_ref()), - |w| { - w.put_element( - "publisher_bpki_ta", - None, - |w| { - w.put_base64_std(&self.id_cert.to_bytes()) - } - ) - } - - ) + w.put_element("publisher_request", Some(a.as_ref()), |w| { + w.put_element("publisher_bpki_ta", None, |w| { + w.put_base64_std(&self.id_cert.to_bytes()) + }) + }) }) } @@ -437,7 +441,6 @@ impl PublisherRequest { } } - //------------ RepositoryResponse -------------------------------------------- /// Type representing a @@ -465,7 +468,7 @@ pub struct RepositoryResponse { sia_base: uri::Rsync, /// The HTTPS notification URI that the CA can use - rrdp_notification_uri: uri::Https + rrdp_notification_uri: uri::Https, } /// # Construct and Data Access @@ -478,7 +481,7 @@ impl RepositoryResponse { id_cert: IdCert, service_uri: ServiceUri, sia_base: uri::Rsync, - rrdp_notification_uri: uri::Https + rrdp_notification_uri: uri::Https, ) -> Self { RepositoryResponse { tag, @@ -486,7 +489,7 @@ impl RepositoryResponse { id_cert, service_uri, sia_base, - rrdp_notification_uri + rrdp_notification_uri, } } @@ -519,39 +522,36 @@ impl RepositoryResponse { /// impl RepositoryResponse { /// Parses a message. - pub fn validate( - reader: R - ) -> Result where R: io::Read { + pub fn validate(reader: R) -> Result + where + R: io::Read, + { Self::validate_at(reader, Time::now()) } - fn validate_at( - reader: R, - now: Time - ) -> Result - where R: io::Read { + fn validate_at(reader: R, now: Time) -> Result + where + R: io::Read, + { XmlReader::decode(reader, |r| { r.take_named_element("repository_response", |mut a, r| { if a.take_req("version")? != VERSION { - return Err(Error::InvalidVersion) + return Err(Error::InvalidVersion); } let tag = a.take_opt("tag"); let publisher_handle = a.take_req("publisher_handle")?; - let service_uri = ServiceUri::try_from( - a.take_req("service_uri")?)?; - let sia_base = uri::Rsync::from_string( - a.take_req("sia_base")?)?; - let rrdp_notification_uri = uri::Https::from_string( - a.take_req("rrdp_notification_uri")?)?; + let service_uri = ServiceUri::try_from(a.take_req("service_uri")?)?; + let sia_base = uri::Rsync::from_string(a.take_req("sia_base")?)?; + let rrdp_notification_uri = + uri::Https::from_string(a.take_req("rrdp_notification_uri")?)?; a.exhausted()?; - let id_cert = r.take_named_element( - "repository_bpki_ta", |a, r| { - a.exhausted()?; - r.take_bytes_std() - })?; + let id_cert = r.take_named_element("repository_bpki_ta", |a, r| { + a.exhausted()?; + r.take_bytes_std() + })?; let id_cert = IdCert::decode(id_cert)?; id_cert.validate_ta_at(now)?; @@ -562,7 +562,7 @@ impl RepositoryResponse { id_cert, service_uri, sia_base, - rrdp_notification_uri + rrdp_notification_uri, }) }) }) @@ -575,7 +575,6 @@ impl RepositoryResponse { /// Encodes the to a Vec pub fn encode_vec(&self) -> Vec { XmlWriter::encode_vec(|w| { - let service_uri = self.service_uri.to_string(); let sia_base = self.sia_base.to_string(); let rrdp_notification_uri = self.rrdp_notification_uri.to_string(); @@ -586,27 +585,18 @@ impl RepositoryResponse { ("publisher_handle", self.publisher_handle.as_ref()), ("service_uri", service_uri.as_ref()), ("sia_base", sia_base.as_ref()), - ("rrdp_notification_uri", rrdp_notification_uri.as_ref()) + ("rrdp_notification_uri", rrdp_notification_uri.as_ref()), ]; if let Some(ref t) = self.tag { a.push(("tag", t.as_ref())); } - w.put_element( - "repository_response", - Some(&a), - |w| { - w.put_element( - "repository_bpki_ta", - None, - |w| { - w.put_base64_std(&self.id_cert.to_bytes()) - } - ) - } - - ) + w.put_element("repository_response", Some(&a), |w| { + w.put_element("repository_bpki_ta", None, |w| { + w.put_base64_std(&self.id_cert.to_bytes()) + }) + }) }) } @@ -617,14 +607,13 @@ impl RepositoryResponse { } } - //------------ ServiceUri ---------------------------------------------------- /// The service URI where a child or publisher needs to send its #[derive(Clone, Debug, Deserialize, Eq, Serialize, PartialEq)] pub enum ServiceUri { Https(uri::Https), - Http(String) + Http(String), } impl TryFrom for ServiceUri { @@ -644,15 +633,13 @@ impl fmt::Display for ServiceUri { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { ServiceUri::Http(string) => string.fmt(f), - ServiceUri::Https(https) => https.fmt(f) + ServiceUri::Https(https) => https.fmt(f), } } } - //------------ Error --------------------------------------------------------- - #[derive(Debug, Display)] pub enum Error { #[display(fmt = "Invalid XML")] @@ -720,10 +707,10 @@ impl From for Error { #[cfg(test)] mod tests { - use rpki::x509::Time; + use super::*; use crate::remote::id::tests::test_id_certificate; use crate::util::test; - use super::*; + use rpki::x509::Time; fn rpkid_time() -> Time { Time::utc(2012, 1, 1, 0, 0, 0) @@ -738,18 +725,13 @@ mod tests { } fn example_service_uri() -> ServiceUri { - ServiceUri::Https( - test::https("https://a.example/publication/Alice/Bob-42") - ) + ServiceUri::Https(test::https("https://a.example/publication/Alice/Bob-42")) } #[test] fn validate_rpkid_publisher_request() { let xml = include_str!("../../test-resources/oob/publisher_request.xml"); - let pr = PublisherRequest::validate_at( - xml.as_bytes(), - rpkid_time() - ).unwrap(); + let pr = PublisherRequest::validate_at(xml.as_bytes(), rpkid_time()).unwrap(); assert_eq!("Bob".to_string(), pr.publisher_handle); assert_eq!(Some("A0001".to_string()), pr.tag); } @@ -757,10 +739,7 @@ mod tests { #[test] fn validate_rpkid_repository_response() { let xml = include_str!("../../test-resources/oob/repository_response.xml"); - let rr = RepositoryResponse::validate_at( - xml.as_bytes(), - rpkid_time() - ).unwrap(); + let rr = RepositoryResponse::validate_at(xml.as_bytes(), rpkid_time()).unwrap(); assert_eq!(Some("A0001".to_string()), rr.tag); assert_eq!("Alice/Bob-42".to_string(), rr.publisher_handle); assert_eq!(example_service_uri(), rr.service_uri); @@ -775,15 +754,12 @@ mod tests { let pr = PublisherRequest { tag: Some("tag".to_string()), publisher_handle: "tim".to_string(), - id_cert: cert + id_cert: cert, }; let enc = pr.encode_vec(); - PublisherRequest::validate_at( - enc.as_slice(), - rpkid_time() - ).unwrap(); + PublisherRequest::validate_at(enc.as_slice(), rpkid_time()).unwrap(); } #[test] @@ -796,33 +772,24 @@ mod tests { rrdp_notification_uri: example_rrdp_uri(), sia_base: example_sia_base(), service_uri: example_service_uri(), - id_cert: cert + id_cert: cert, }; let enc = pr.encode_vec(); - RepositoryResponse::validate_at( - enc.as_slice(), - rpkid_time() - ).unwrap(); + RepositoryResponse::validate_at(enc.as_slice(), rpkid_time()).unwrap(); } #[test] fn child_request() { let xml = include_str!("../../test-resources/remote/rpkid-child-id.xml"); - let req = ChildRequest::validate_at( - xml.as_bytes(), - rpkid_time() - ).unwrap(); + let req = ChildRequest::validate_at(xml.as_bytes(), rpkid_time()).unwrap(); assert_eq!(&Handle::from("Carol"), req.child_handle()); assert_eq!(None, req.tag()); let encoded = req.encode_vec(); - let decoded = ChildRequest::validate_at( - encoded.as_slice(), - rpkid_time() - ).unwrap(); + let decoded = ChildRequest::validate_at(encoded.as_slice(), rpkid_time()).unwrap(); assert_eq!(req, decoded); } @@ -830,27 +797,17 @@ mod tests { #[test] fn validate_rpkid_parent_response_referral() { let xml = include_str!("../../test-resources/remote/rpkid-parent-response-referral.xml"); - let _res = ParentResponse::validate_at( - xml.as_bytes(), - rpkid_time() - ).unwrap(); + let _res = ParentResponse::validate_at(xml.as_bytes(), rpkid_time()).unwrap(); } #[test] fn parent_response() { let xml = include_str!("../../test-resources/remote/rpkid-parent-response-offer.xml"); - let res = ParentResponse::validate_at( - xml.as_bytes(), - rpkid_time() - ).unwrap(); + let res = ParentResponse::validate_at(xml.as_bytes(), rpkid_time()).unwrap(); let encoded = res.encode_vec(); - let decoded = ParentResponse::validate_at( - encoded.as_slice(), - rpkid_time() - ).unwrap(); + let decoded = ParentResponse::validate_at(encoded.as_slice(), rpkid_time()).unwrap(); assert_eq!(res, decoded); } } - diff --git a/commons/src/remote/sigmsg.rs b/commons/src/remote/sigmsg.rs index 58f31c21..8ebd3bea 100644 --- a/commons/src/remote/sigmsg.rs +++ b/commons/src/remote/sigmsg.rs @@ -4,20 +4,12 @@ use bytes::Bytes; use bcder::decode; -use bcder::{Mode, Oid, Tag}; use bcder::string::OctetString; +use bcder::{Mode, Oid, Tag}; -use rpki::crypto::{ - DigestAlgorithm, - KeyIdentifier, - Signature, - SignatureAlgorithm -}; +use rpki::crypto::{DigestAlgorithm, KeyIdentifier, Signature, SignatureAlgorithm}; use rpki::oid; -use rpki::sigobj::{ - SignedAttrs, - MessageDigest -}; +use rpki::sigobj::{MessageDigest, SignedAttrs}; use rpki::x509::{Time, ValidationError}; use crate::remote::id::IdCert; @@ -46,22 +38,15 @@ pub struct SignedMessage { //--- SignedAttributes // - message_digest: MessageDigest + message_digest: MessageDigest, } /// # Decoding /// impl SignedMessage { - - pub fn decode( - source: S, - strict: bool - ) -> Result { - if strict { Mode::Der } - else { Mode::Ber } - .decode(source, Self::take_from) + pub fn decode(source: S, strict: bool) -> Result { + if strict { Mode::Der } else { Mode::Ber }.decode(source, Self::take_from) } - } /// # Accessors @@ -75,56 +60,50 @@ impl SignedMessage { /// # Parsing /// impl SignedMessage { - fn take_signed_data( - cons: &mut decode::Constructed + cons: &mut decode::Constructed, ) -> Result { cons.take_sequence(|cons| { cons.skip_u8_if(3)?; // version -- must be 3 - let digest_algorithm = - DigestAlgorithm::take_set_from(cons)?; + let digest_algorithm = DigestAlgorithm::take_set_from(cons)?; let (content_type, content) = { - cons.take_sequence(|cons| { // encapContentInfo + cons.take_sequence(|cons| { + // encapContentInfo Ok(( Oid::take_from(cons)?, - cons.take_constructed_if( - Tag::CTX_0, - OctetString::take_from - )? + cons.take_constructed_if(Tag::CTX_0, OctetString::take_from)?, )) })? }; if content_type != oid::PROTOCOL_CONTENT_TYPE { - return xerr!(Err(decode::Malformed.into())) + return xerr!(Err(decode::Malformed.into())); } let id_cert = Self::take_certificates(cons)?; let _whatever = Self::drop_crls(cons); - - let (sid, attrs, signature) = { // signerInfos + let (sid, attrs, signature) = { + // signerInfos cons.take_set(|cons| { cons.take_sequence(|cons| { cons.skip_u8_if(3)?; - let sid = cons.take_value_if( - Tag::CTX_0, |content| { - KeyIdentifier::from_content(content) - } - )?; + let sid = cons.take_value_if(Tag::CTX_0, |content| { + KeyIdentifier::from_content(content) + })?; let alg = DigestAlgorithm::take_from(cons)?; if alg != digest_algorithm { - return Err(decode::Malformed.into()) + return Err(decode::Malformed.into()); } let attrs = SignedAttrs::take_from_signed_message(cons)?; if attrs.2 != content_type { - return Err(decode::Malformed.into()) + return Err(decode::Malformed.into()); } let signature = Signature::new( SignatureAlgorithm::cms_take_from(cons)?, - OctetString::take_from(cons)?.into_bytes() + OctetString::take_from(cons)?.into_bytes(), ); // no unsignedAttributes Ok((sid, attrs, signature)) @@ -142,15 +121,12 @@ impl SignedMessage { signed_attrs: attrs.0, signature, - message_digest: attrs.1 + message_digest: attrs.1, }) - }) } - pub fn take_from( - cons: &mut decode::Constructed - ) -> Result { + pub fn take_from(cons: &mut decode::Constructed) -> Result { cons.take_sequence(|cons| { oid::SIGNED_DATA.skip_if(cons)?; // contentType cons.take_constructed_if(Tag::CTX_0, Self::take_signed_data) @@ -158,16 +134,12 @@ impl SignedMessage { } fn take_certificates( - cons: &mut decode::Constructed + cons: &mut decode::Constructed, ) -> Result { cons.take_constructed_if(Tag::CTX_0, |cons| { - cons.take_constructed(|tag, cons| { - match tag { - Tag::SEQUENCE => IdCert::from_constructed(cons), - _ => { - xerr!(Err(decode::Unimplemented.into())) - } - } + cons.take_constructed(|tag, cons| match tag { + Tag::SEQUENCE => IdCert::from_constructed(cons), + _ => xerr!(Err(decode::Unimplemented.into())), }) }) } @@ -182,16 +154,11 @@ impl SignedMessage { // re-signed CRL by the CA cert for inclusion.. then if the EE // key is stolen you get a bit of protection. // - fn drop_crls( - cons: &mut decode::Constructed - ) -> Result<(), S::Err> { - cons.take_constructed_if(Tag::CTX_1, |cons| { - cons.skip_all() - }) + fn drop_crls(cons: &mut decode::Constructed) -> Result<(), S::Err> { + cons.take_constructed_if(Tag::CTX_1, |cons| cons.skip_all()) } } - /// # Validation /// impl SignedMessage { @@ -204,11 +171,7 @@ impl SignedMessage { } /// Validates a signed message for a given point in time. - pub fn validate_at( - &self, - issuer: &IdCert, - now: Time - ) -> Result<(), ValidationError> { + pub fn validate_at(&self, issuer: &IdCert, now: Time) -> Result<(), ValidationError> { self.id_cert.validate_ee_at(issuer, now)?; self.verify_signature()?; Ok(()) @@ -224,17 +187,16 @@ impl SignedMessage { context.finish() }; if digest.as_ref() != self.message_digest.as_ref() { - return Err(ValidationError) + return Err(ValidationError); } let msg = self.signed_attrs.encode_verify(); - self.id_cert.subject_public_key_info().verify( - &msg, - &self.signature - ).map_err(Into::into) + self.id_cert + .subject_public_key_info() + .verify(&msg, &self.signature) + .map_err(Into::into) } } - //------------ Tests --------------------------------------------------------- #[cfg(test)] @@ -244,30 +206,26 @@ mod tests { #[test] fn should_parse_and_validate_signed_message() { let der = include_bytes!("../../test-resources/remote/pdu_200.der"); - let msg = SignedMessage::decode( - Bytes::from_static(der), false - ).unwrap(); + let msg = SignedMessage::decode(Bytes::from_static(der), false).unwrap(); let b = include_bytes!("../../test-resources/remote/cms_ta.cer"); let id_cert = IdCert::decode(Bytes::from_static(b)).unwrap(); - msg.validate_at(&id_cert, Time::utc(2012, 1, 1, 0, 0, 0)).unwrap(); + msg.validate_at(&id_cert, Time::utc(2012, 1, 1, 0, 0, 0)) + .unwrap(); } #[test] fn should_reject_invalid_signed_message() { let der = include_bytes!("../../test-resources/remote/pdu_200.der"); - let msg = SignedMessage::decode( - Bytes::from_static(der), false - ).unwrap(); + let msg = SignedMessage::decode(Bytes::from_static(der), false).unwrap(); let b = include_bytes!("../../test-resources/oob/id_publisher_ta.cer"); let id_cert = IdCert::decode(Bytes::from_static(b)).unwrap(); assert_eq!( - msg.validate_at( - &id_cert, Time::utc(2012, 1, 1, 0, 0, 0) - ).unwrap_err(), + msg.validate_at(&id_cert, Time::utc(2012, 1, 1, 0, 0, 0)) + .unwrap_err(), ValidationError, ); } @@ -275,9 +233,6 @@ mod tests { #[test] fn parse_lacnic_issue_response() { let der = include_bytes!("../../test-resources/remote/lacnic-res-2.der"); - let _msg = SignedMessage::decode( - Bytes::from_static(der), - false - ).unwrap(); + let _msg = SignedMessage::decode(Bytes::from_static(der), false).unwrap(); } } diff --git a/commons/src/util/ext_serde.rs b/commons/src/util/ext_serde.rs index 03d2a922..ea3f14a7 100644 --- a/commons/src/util/ext_serde.rs +++ b/commons/src/util/ext_serde.rs @@ -2,15 +2,15 @@ use base64; use bytes::Bytes; use log::LevelFilter; -use serde::{Deserialize, Deserializer, Serialize, Serializer}; use serde::de; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; use syslog::Facility; - //------------ Bytes --------------------------------------------------------- pub fn de_bytes<'de, D>(d: D) -> Result -where D: Deserializer<'de> +where + D: Deserializer<'de>, { let some = String::deserialize(d)?; let dec = base64::decode(&some).map_err(de::Error::custom)?; @@ -18,31 +18,31 @@ where D: Deserializer<'de> } pub fn ser_bytes(b: &Bytes, s: S) -> Result -where S: Serializer +where + S: Serializer, { base64::encode(b).serialize(s) } - //------------ LevelFilter --------------------------------------------------- pub fn de_level_filter<'de, D>(d: D) -> Result -where D: Deserializer<'de> +where + D: Deserializer<'de>, { use std::str::FromStr; let string = String::deserialize(d)?; LevelFilter::from_str(&string).map_err(de::Error::custom) } - //------------ Facility ------------------------------------------------------ pub fn de_facility<'de, D>(d: D) -> Result - where D: Deserializer<'de> +where + D: Deserializer<'de>, { use std::str::FromStr; let string = String::deserialize(d)?; - Facility::from_str(&string).map_err( - |_| { de::Error::custom( - format!("Unsupported syslog_facility: \"{}\"", string))}) -} \ No newline at end of file + Facility::from_str(&string) + .map_err(|_| de::Error::custom(format!("Unsupported syslog_facility: \"{}\"", string))) +} diff --git a/commons/src/util/file.rs b/commons/src/util/file.rs index e37255c6..998fb1a5 100644 --- a/commons/src/util/file.rs +++ b/commons/src/util/file.rs @@ -1,15 +1,14 @@ +use crate::api::publication; +use crate::api::{Base64, EncodedHash}; +use bytes::Bytes; +use rpki::uri; +use serde::de::DeserializeOwned; +use serde::Serialize; use std::fs; use std::fs::File; use std::io::{self, Read, Write}; use std::path::PathBuf; use std::str::FromStr; -use bytes::Bytes; -use rpki::uri; -use crate::api::{ Base64, EncodedHash }; -use crate::api::publication; -use serde::Serialize; -use serde::de::DeserializeOwned; - /// Creates a sub dir if needed, return full path to it pub fn sub_dir(base: &PathBuf, name: &str) -> Result { @@ -20,14 +19,14 @@ pub fn sub_dir(base: &PathBuf, name: &str) -> Result { } pub fn create_dir(dir: &PathBuf) -> Result<(), io::Error> { - if ! dir.is_dir() { + if !dir.is_dir() { fs::create_dir(dir)?; } Ok(()) } pub fn create_file_with_path(path: &PathBuf) -> Result { - if ! path.exists() { + if !path.exists() { if let Some(parent) = path.parent() { trace!("Creating path: {}", parent.to_string_lossy()); fs::create_dir_all(parent)?; @@ -43,7 +42,6 @@ pub fn file_path(base_path: &PathBuf, file_name: &str) -> PathBuf { path } - /// Saves a file, creating parent dirs as needed pub fn save(content: &Bytes, full_path: &PathBuf) -> Result<(), io::Error> { let mut f = create_file_with_path(full_path)?; @@ -64,15 +62,11 @@ pub fn save_json(object: &O, full_path: &PathBuf) -> Result<(), io pub fn load_json(full_path: &PathBuf) -> Result { let bytes = read(full_path)?; serde_json::from_slice(&bytes) - .map_err(|_| - io::Error::new(io::ErrorKind::Other, "could not deserialize json")) + .map_err(|_| io::Error::new(io::ErrorKind::Other, "could not deserialize json")) } /// Saves a file, creating parent dirs as needed -pub fn save_in_dir( - content: &Bytes, - base_path: &PathBuf, - name: &str) -> Result<(), io::Error> { +pub fn save_in_dir(content: &Bytes, base_path: &PathBuf, name: &str) -> Result<(), io::Error> { let mut full_path = base_path.clone(); full_path.push(name); save(content, &full_path) @@ -83,7 +77,7 @@ pub fn save_in_dir( pub fn save_with_rsync_uri( content: &Bytes, base_path: &PathBuf, - uri: &uri::Rsync + uri: &uri::Rsync, ) -> Result<(), io::Error> { let path = path_with_rsync(base_path, uri); save(content, &path) @@ -97,25 +91,16 @@ pub fn read(path: &PathBuf) -> Result { Ok(Bytes::from(bytes)) } -pub fn read_with_rsync_uri( - base_path: &PathBuf, - uri: &uri::Rsync -) -> Result { +pub fn read_with_rsync_uri(base_path: &PathBuf, uri: &uri::Rsync) -> Result { let path = path_with_rsync(base_path, uri); read(&path) } -pub fn delete_with_rsync_uri( - base_path: &PathBuf, - uri: &uri::Rsync -) -> Result<(), io::Error> { +pub fn delete_with_rsync_uri(base_path: &PathBuf, uri: &uri::Rsync) -> Result<(), io::Error> { delete(&path_with_rsync(base_path, uri)) } -pub fn delete_in_dir( - base_path: &PathBuf, - name: &str -) -> Result<(), io::Error> { +pub fn delete_in_dir(base_path: &PathBuf, name: &str) -> Result<(), io::Error> { let mut full_path = base_path.clone(); full_path.push(name); delete(&full_path) @@ -154,14 +139,13 @@ fn path_with_rsync(base_path: &PathBuf, uri: &uri::Rsync) -> PathBuf { path } - /// Recurses a path on disk and returns all files found as ['CurrentFile'], /// using the provided rsync_base URI as the rsync prefix. /// Allows a publication client to publish the contents below some base /// dir, in their own designated rsync URI name space. pub fn crawl_incl_rsync_base( base_path: &PathBuf, - rsync_base: &uri::Rsync + rsync_base: &uri::Rsync, ) -> Result, Error> { crawl_disk(base_path, base_path, Some(rsync_base)) } @@ -170,16 +154,14 @@ pub fn crawl_incl_rsync_base( /// deriving the rsync_base URI from the directory structure. This is /// useful when reading ['CurrentFile'] instances that were saved in some /// base directory as is done by the ['FileStore']. -pub fn crawl_derive_rsync_uri( - base_path: &PathBuf -) -> Result, Error> { +pub fn crawl_derive_rsync_uri(base_path: &PathBuf) -> Result, Error> { crawl_disk(base_path, base_path, None) } fn crawl_disk( base_path: &PathBuf, path: &PathBuf, - rsync_base: Option<&uri::Rsync> + rsync_base: Option<&uri::Rsync>, ) -> Result, Error> { let mut res = Vec::new(); @@ -204,7 +186,7 @@ fn crawl_disk( fn derive_uri( base_path: &PathBuf, path: &PathBuf, - rsync_base: Option<&uri::Rsync> + rsync_base: Option<&uri::Rsync>, ) -> Result { let rel = path .strip_prefix(base_path) @@ -213,25 +195,21 @@ fn derive_uri( let rel_string = rel.to_string_lossy().to_string(); let uri_string = match rsync_base { - Some(rsync_base) => - format!("{}{}", rsync_base.to_string(), rel_string), - None => - format!("rsync://{}", rel_string) + Some(rsync_base) => format!("{}{}", rsync_base.to_string(), rel_string), + None => format!("rsync://{}", rel_string), }; - let uri = uri::Rsync::from_str(&uri_string) - .map_err(|_| Error::UnsupportedFileName(uri_string))?; + let uri = + uri::Rsync::from_str(&uri_string).map_err(|_| Error::UnsupportedFileName(uri_string))?; Ok(uri) } - - //------------ CurrentFile --------------------------------------------------- #[derive(Clone, Debug, Deserialize, Serialize)] pub struct CurrentFile { /// The full uri for this file. - uri: uri::Rsync, + uri: uri::Rsync, /// The actual file content. Note that we may want to store this /// only on disk in future (look up by sha256 hash), to save memory. @@ -241,15 +219,14 @@ pub struct CurrentFile { /// in the publication protocol for list, update and withdraw). Saving /// this rather than calculating on demand seems a small price for some /// performance gain. - hash: EncodedHash + hash: EncodedHash, } - impl CurrentFile { pub fn new(uri: uri::Rsync, content: &Bytes) -> Self { let content = Base64::from_content(&content); let hash = content.to_encoded_hash(); - CurrentFile {uri, content, hash} + CurrentFile { uri, content, hash } } /// Saves this file under a base directory, based on the (rsync) uri of @@ -299,28 +276,23 @@ impl CurrentFile { pub fn into_list_element(self) -> publication::ListElement { publication::ListElement::new(self.uri, self.hash) } - } impl PartialEq for CurrentFile { fn eq(&self, other: &CurrentFile) -> bool { - self.uri == other.uri && - self.hash == other.hash && - self.content == other.content + self.uri == other.uri && self.hash == other.hash && self.content == other.content } } impl Eq for CurrentFile {} - //------------ Error --------------------------------------------------------- #[derive(Debug, Display)] pub enum Error { - - #[display(fmt="Cannot read: {}", _0)] + #[display(fmt = "Cannot read: {}", _0)] CannotRead(String), - #[display(fmt="Unsupported characters: {}", _0)] + #[display(fmt = "Unsupported characters: {}", _0)] UnsupportedFileName(String), #[display(fmt = "Cannot use path outside of rsync jail")] @@ -352,22 +324,21 @@ mod tests { #[test] fn should_scan_disk() { test::test_under_tmp(|base_dir| { - let file_1 = CurrentFile::new( test::rsync("rsync://host:10873/module/alice/file1.txt"), - &Bytes::from("content 1") + &Bytes::from("content 1"), ); let file_2 = CurrentFile::new( test::rsync("rsync://host:10873/module/alice/file2.txt"), - &Bytes::from("content 2") + &Bytes::from("content 2"), ); let file_3 = CurrentFile::new( test::rsync("rsync://host:10873/module/alice/sub/file1.txt"), - &Bytes::from("content sub file") + &Bytes::from("content sub file"), ); let file_4 = CurrentFile::new( test::rsync("rsync://host:10873/module/bob/file.txt"), - &Bytes::from("content") + &Bytes::from("content"), ); file_1.save(&base_dir).unwrap(); diff --git a/commons/src/util/httpclient.rs b/commons/src/util/httpclient.rs index c4aac063..f90673e0 100644 --- a/commons/src/util/httpclient.rs +++ b/commons/src/util/httpclient.rs @@ -1,29 +1,21 @@ //! Some helper functions for HTTP calls +use bytes::Bytes; +use reqwest::header::{HeaderMap, HeaderValue, InvalidHeaderValue, CONTENT_TYPE, USER_AGENT}; +use reqwest::{Client, Response, StatusCode}; +use serde::de::DeserializeOwned; +use serde::Serialize; use std::io::Read; use std::time::Duration; -use bytes::Bytes; -use reqwest::{Client, Response, StatusCode}; -use reqwest::header::{ - HeaderMap, - HeaderValue, - InvalidHeaderValue, - USER_AGENT, - CONTENT_TYPE}; -use serde::Serialize; -use serde::de::DeserializeOwned; -use crate::api::ErrorResponse; use crate::api::admin::Token; +use crate::api::ErrorResponse; const JSON_CONTENT: &str = "application/json"; /// Performs a GET request that expects a json response that can be /// deserialized into the an owned value of the expected type. Returns an error /// if nothing is returned. -pub fn get_json( - uri: &str, - token: Option<&Token> -) -> Result { +pub fn get_json(uri: &str, token: Option<&Token>) -> Result { let headers = headers(Some(JSON_CONTENT), token)?; let res = client(uri)?.get(uri).headers(headers).send()?; process_json_response(res) @@ -31,16 +23,12 @@ pub fn get_json( /// Performs a get request and expects a response that can be turned /// into a string (in particular, not a binary response). -pub fn get_text( - uri: &str, - content_type: &str, - token: Option<&Token> -) -> Result { +pub fn get_text(uri: &str, content_type: &str, token: Option<&Token>) -> Result { let headers = headers(Some(content_type), token)?; let res = client(uri)?.get(uri).headers(headers).send()?; match opt_text_response(res)? { Some(res) => Ok(res), - None => Err(Error::EmptyResponse) + None => Err(Error::EmptyResponse), } } @@ -53,14 +41,9 @@ pub fn get_ok(uri: &str, token: Option<&Token>) -> Result<(), Error> { Ok(()) } - /// Performs a POST of data that can be serialized into json, and expects /// a 200 OK response, without a body. -pub fn post_json( - uri: &str, - data: impl Serialize, - token: Option<&Token> -) -> Result<(), Error> { +pub fn post_json(uri: &str, data: impl Serialize, token: Option<&Token>) -> Result<(), Error> { let headers = headers(Some(JSON_CONTENT), token)?; let body = serde_json::to_string(&data)?; let res = client(uri)?.post(uri).headers(headers).body(body).send()?; @@ -71,14 +54,13 @@ pub fn post_json( } } - /// Performs a POST of data that can be serialized into json, and expects /// a json response that can be deserialized into the an owned value of the /// expected type. pub fn post_json_with_response( uri: &str, data: impl Serialize, - token: Option<&Token> + token: Option<&Token>, ) -> Result { let headers = headers(Some(JSON_CONTENT), token)?; let body = serde_json::to_string(&data)?; @@ -97,16 +79,11 @@ pub fn post_empty(uri: &str, token: Option<&Token>) -> Result<(), Error> { } } - /// Posts binary data, and expects a binary response. /// /// Note: Bytes may be empty if the post was successful, but the response was /// empty. -pub fn post_binary( - uri: &str, - data: &Bytes, - content_type: &str -) -> Result { +pub fn post_binary(uri: &str, data: &Bytes, content_type: &str) -> Result { let headers = headers(Some(content_type), None)?; let body = data.to_vec(); @@ -118,71 +95,58 @@ pub fn post_binary( res.read_to_end(&mut bytes).unwrap(); let bytes = bytes::Bytes::from(bytes); Ok(bytes) - }, - status => { - match res.text() { - Ok(body) => { - if body.is_empty() { - Err(Error::BadStatus(status)) - } else { - Err(Error::ErrorWithBody(status, body)) - } - }, - _ => Err(Error::BadStatus(status)) - } } + status => match res.text() { + Ok(body) => { + if body.is_empty() { + Err(Error::BadStatus(status)) + } else { + Err(Error::ErrorWithBody(status, body)) + } + } + _ => Err(Error::BadStatus(status)), + }, } } /// Sends a delete request to the specified url. -pub fn delete( - uri: &str, - token: Option<&Token> -) -> Result<(), Error> { +pub fn delete(uri: &str, token: Option<&Token>) -> Result<(), Error> { let headers = headers(None, token)?; client(uri)?.delete(uri).headers(headers).send()?; Ok(()) } - fn client(uri: &str) -> Result { - let builder = Client::builder().gzip(true).timeout(Duration::from_secs(300)); + let builder = Client::builder() + .gzip(true) + .timeout(Duration::from_secs(300)); if uri.starts_with("https://localhost") || uri.starts_with("https://127.0.0.1") { - builder.danger_accept_invalid_certs(true) - .build().map_err(Error::RequestError) + builder + .danger_accept_invalid_certs(true) + .build() + .map_err(Error::RequestError) } else { builder.build().map_err(Error::RequestError) } } -fn headers( - content_type: Option<&str>, - token: Option<&Token> -) -> Result { +fn headers(content_type: Option<&str>, token: Option<&Token>) -> Result { let mut headers = HeaderMap::new(); - headers.insert( - USER_AGENT, - HeaderValue::from_str("krill")? - ); + headers.insert(USER_AGENT, HeaderValue::from_str("krill")?); if let Some(content_type) = content_type { - headers.insert( - CONTENT_TYPE, - HeaderValue::from_str(content_type)? - ); + headers.insert(CONTENT_TYPE, HeaderValue::from_str(content_type)?); } if let Some(token) = token { headers.insert( "Authorization", - HeaderValue::from_str(&format!("Bearer {}", token))? + HeaderValue::from_str(&format!("Bearer {}", token))?, ); } Ok(headers) } -fn process_json_response( - res: Response -) -> Result { +fn process_json_response(res: Response) -> Result { match opt_text_response(res) { Err(e) => Err(e), Ok(None) => Err(Error::EmptyResponse), @@ -195,31 +159,27 @@ fn process_json_response( fn opt_text_response(mut res: Response) -> Result, Error> { match res.status() { - StatusCode::OK => { - match res.text().ok() { - None => Ok(None), - Some(s) => { - if s.is_empty() { - Ok(None) - } else { - Ok(Some(s)) - } + StatusCode::OK => match res.text().ok() { + None => Ok(None), + Some(s) => { + if s.is_empty() { + Ok(None) + } else { + Ok(Some(s)) } } }, StatusCode::FORBIDDEN => Err(Error::Forbidden), - status => { - match res.text() { - Ok(body) => { - if body.is_empty() { - Err(Error::BadStatus(status)) - } else { - Err(Error::wrap_err_res(status, body)) - } - }, - _ => Err(Error::BadStatus(status)) + status => match res.text() { + Ok(body) => { + if body.is_empty() { + Err(Error::BadStatus(status)) + } else { + Err(Error::wrap_err_res(status, body)) + } } - } + _ => Err(Error::BadStatus(status)), + }, } } @@ -227,51 +187,57 @@ fn opt_text_response(mut res: Response) -> Result, Error> { #[derive(Debug, Display)] pub enum Error { - #[display(fmt="Request Error: {}", _0)] + #[display(fmt = "Request Error: {}", _0)] RequestError(reqwest::Error), - #[display(fmt="Access Forbidden")] + #[display(fmt = "Access Forbidden")] Forbidden, - #[display(fmt="Received bad status: {}", _0)] + #[display(fmt = "Received bad status: {}", _0)] BadStatus(StatusCode), - #[display(fmt="Status: {}, Error: {}", _0, _1)] + #[display(fmt = "Status: {}, Error: {}", _0, _1)] ErrorWithBody(StatusCode, String), - #[display(fmt="Status: {}, Error: {}", _0, _1)] + #[display(fmt = "Status: {}, Error: {}", _0, _1)] ErrorWithJson(StatusCode, ErrorResponse), - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] JsonError(serde_json::Error), - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] InvalidHeader(InvalidHeaderValue), - #[display(fmt="Empty response received from server")] + #[display(fmt = "Empty response received from server")] EmptyResponse, - #[display(fmt="Unexpected response: {}", _0)] - UnexpectedResponse(String) + #[display(fmt = "Unexpected response: {}", _0)] + UnexpectedResponse(String), } impl Error { fn wrap_err_res(code: StatusCode, content: String) -> Error { match serde_json::from_str::(&content) { Ok(res) => Error::ErrorWithJson(code, res), - Err(_) => Error::ErrorWithBody(code, content) + Err(_) => Error::ErrorWithBody(code, content), } } } impl From for Error { - fn from(e: reqwest::Error) -> Self { Error::RequestError(e) } + fn from(e: reqwest::Error) -> Self { + Error::RequestError(e) + } } impl From for Error { - fn from(e: serde_json::Error) -> Self { Error::JsonError(e) } + fn from(e: serde_json::Error) -> Self { + Error::JsonError(e) + } } impl From for Error { - fn from(v: InvalidHeaderValue) -> Self { Error::InvalidHeader(v) } + fn from(v: InvalidHeaderValue) -> Self { + Error::InvalidHeader(v) + } } diff --git a/commons/src/util/mod.rs b/commons/src/util/mod.rs index 3022c51d..227eee92 100644 --- a/commons/src/util/mod.rs +++ b/commons/src/util/mod.rs @@ -1,14 +1,14 @@ //! General utility modules for use all over the code base -use std::time::Duration; use bytes::Bytes; +use chrono::offset::TimeZone; use chrono::DateTime; use chrono::Utc; -use chrono::offset::TimeZone; use rpki::crypto::DigestAlgorithm; +use serde::Deserialize; +use serde::Deserializer; use serde::Serialize; use serde::Serializer; -use serde::Deserializer; -use serde::Deserialize; +use std::time::Duration; pub mod ext_serde; pub mod file; @@ -42,20 +42,20 @@ impl Time { } impl Serialize for Time { - fn serialize( - &self, serializer: S - ) -> Result where S: Serializer { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { serializer.serialize_i64(self.0.timestamp_millis()) } } impl<'de> Deserialize<'de> for Time { - fn deserialize( - deserializer: D - ) -> Result where D: Deserializer<'de> { - + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { let timestamp: i64 = i64::deserialize(deserializer)?; Ok(Time(Utc.timestamp_millis(timestamp))) } } - diff --git a/commons/src/util/softsigner.rs b/commons/src/util/softsigner.rs index bf34f1f5..8de1126d 100644 --- a/commons/src/util/softsigner.rs +++ b/commons/src/util/softsigner.rs @@ -1,26 +1,20 @@ //! Support for signing things using software keys (through openssl) and //! storing them unencrypted on disk. -use std::{fs, io}; -use std::path::PathBuf; use bytes::Bytes; -use openssl::rsa::Rsa; -use openssl::hash::MessageDigest; use openssl::error::ErrorStack; +use openssl::hash::MessageDigest; use openssl::pkey::{PKey, PKeyRef, Private}; -use rpki::crypto::{ - Signature, - SignatureAlgorithm, - Signer, - SigningError, - PublicKey, - PublicKeyFormat -}; +use openssl::rsa::Rsa; use rpki::crypto::signer::KeyError; +use rpki::crypto::{ + PublicKey, PublicKeyFormat, Signature, SignatureAlgorithm, Signer, SigningError, +}; use serde::{de, ser}; use serde::{Deserialize, Deserializer, Serialize, Serializer}; use std::fs::File; use std::io::Write; - +use std::path::PathBuf; +use std::{fs, io}; //------------ SignerKeyId --------------------------------------------------- @@ -40,24 +34,24 @@ impl AsRef for SignerKeyId { } impl Serialize for SignerKeyId { - fn serialize( - &self, - serializer: S - ) -> Result where S: Serializer { + fn serialize(&self, serializer: S) -> Result + where + S: Serializer, + { self.as_ref().serialize(serializer) } } impl<'de> Deserialize<'de> for SignerKeyId { - fn deserialize( - deserializer: D - ) -> Result where D: Deserializer<'de> { + fn deserialize(deserializer: D) -> Result + where + D: Deserializer<'de>, + { let s = String::deserialize(deserializer)?; Ok(SignerKeyId::new(&s)) } } - //------------ OpenSslSigner ------------------------------------------------- /// An openssl based signer. @@ -65,21 +59,20 @@ impl<'de> Deserialize<'de> for SignerKeyId { /// Keeps the keys in memory (for now). #[derive(Clone, Debug, Deserialize, Serialize)] pub struct OpenSslSigner { - keys_dir: PathBuf + keys_dir: PathBuf, } impl OpenSslSigner { pub fn build(work_dir: &PathBuf) -> Result { let meta_data = fs::metadata(&work_dir)?; if meta_data.is_dir() { - let mut keys_dir = PathBuf::from(work_dir); keys_dir.push("keys"); - if ! keys_dir.is_dir() { + if !keys_dir.is_dir() { fs::create_dir_all(&keys_dir)?; } - Ok(OpenSslSigner { keys_dir } ) + Ok(OpenSslSigner { keys_dir }) } else { Err(SignerError::InvalidWorkDir(work_dir.clone())) } @@ -89,17 +82,15 @@ impl OpenSslSigner { impl OpenSslSigner { fn sign_with_key + ?Sized>( pkey: &PKeyRef, - data: &D + data: &D, ) -> Result { - let mut signer = ::openssl::sign::Signer::new( - MessageDigest::sha256(), - pkey - )?; + let mut signer = ::openssl::sign::Signer::new(MessageDigest::sha256(), pkey)?; signer.update(data.as_ref())?; let signature = Signature::new( SignatureAlgorithm::default(), - Bytes::from(signer.sign_to_vec()?)); + Bytes::from(signer.sign_to_vec()?), + ); Ok(signature) } @@ -113,7 +104,6 @@ impl OpenSslSigner { } else { Err(SignerError::KeyNotFound) } - } fn key_path(&self, key_id: &SignerKeyId) -> PathBuf { @@ -124,14 +114,10 @@ impl OpenSslSigner { } impl Signer for OpenSslSigner { - type KeyId = SignerKeyId; type Error = SignerError; - fn create_key( - &mut self, - _algorithm: PublicKeyFormat - ) -> Result { + fn create_key(&mut self, _algorithm: PublicKeyFormat) -> Result { let kp = OpenSslKeyPair::build()?; let pk = &kp.subject_public_key_info()?; @@ -147,18 +133,12 @@ impl Signer for OpenSslSigner { Ok(key_id) } - fn get_key_info( - &self, - key_id: &Self::KeyId - ) -> Result> { + fn get_key_info(&self, key_id: &Self::KeyId) -> Result> { let key_pair = self.load_key(key_id)?; Ok(key_pair.subject_public_key_info()?) } - fn destroy_key( - &mut self, - key_id: &Self::KeyId - ) -> Result<(), KeyError> { + fn destroy_key(&mut self, key_id: &Self::KeyId) -> Result<(), KeyError> { let path = self.key_path(key_id); if path.exists() { fs::remove_file(path).map_err(SignerError::IoError)?; @@ -170,24 +150,20 @@ impl Signer for OpenSslSigner { &self, key_id: &Self::KeyId, _algorithm: SignatureAlgorithm, - data: &D + data: &D, ) -> Result> { let key_pair = self.load_key(key_id)?; - Self::sign_with_key(key_pair.pkey.as_ref(), data) - .map_err(|e| { SigningError::Signer(e)}) + Self::sign_with_key(key_pair.pkey.as_ref(), data).map_err(|e| SigningError::Signer(e)) } fn sign_one_off + ?Sized>( &self, _algorithm: SignatureAlgorithm, - data: &D + data: &D, ) -> Result<(Signature, PublicKey), SignerError> { let kp = OpenSslKeyPair::build()?; - let signature = Self::sign_with_key( - kp.pkey.as_ref(), - data - )?; + let signature = Self::sign_with_key(kp.pkey.as_ref(), data)?; let key = kp.subject_public_key_info()?; @@ -199,21 +175,22 @@ impl Signer for OpenSslSigner { } } - //------------ OpenSslKeyPair ------------------------------------------------ /// An openssl based RSA key pair pub struct OpenSslKeyPair { - pkey: PKey + pkey: PKey, } impl Serialize for OpenSslKeyPair { - fn serialize( - &self, - s: S - ) -> Result where - S: Serializer { - let bytes: Vec = self.pkey.as_ref().private_key_to_der() + fn serialize(&self, s: S) -> Result + where + S: Serializer, + { + let bytes: Vec = self + .pkey + .as_ref() + .private_key_to_der() .map_err(ser::Error::custom)?; base64::encode(&bytes).serialize(s) @@ -221,25 +198,19 @@ impl Serialize for OpenSslKeyPair { } impl<'de> Deserialize<'de> for OpenSslKeyPair { - fn deserialize( - d: D - ) -> Result where - D: Deserializer<'de> { + fn deserialize(d: D) -> Result + where + D: Deserializer<'de>, + { match String::deserialize(d) { Ok(base64) => { - let bytes = base64::decode(&base64) - .map_err(de::Error::custom)?; + let bytes = base64::decode(&base64).map_err(de::Error::custom)?; - let pkey = PKey::private_key_from_der(&bytes) - .map_err(de::Error::custom)?; + let pkey = PKey::private_key_from_der(&bytes).map_err(de::Error::custom)?; - Ok( - OpenSslKeyPair { - pkey - } - ) - }, - Err(err) => Err(err) + Ok(OpenSslKeyPair { pkey }) + } + Err(err) => Err(err), } } } @@ -250,7 +221,7 @@ impl OpenSslKeyPair { // So, there is no way to recover. let rsa = Rsa::generate(2048)?; let pkey = PKey::from_rsa(rsa)?; - Ok(OpenSslKeyPair{ pkey }) + Ok(OpenSslKeyPair { pkey }) } fn subject_public_key_info(&self) -> Result { @@ -261,7 +232,6 @@ impl OpenSslKeyPair { } } - //------------ OpenSslKeyError ----------------------------------------------- #[derive(Debug, Display)] @@ -323,7 +293,6 @@ pub mod tests { #[test] fn should_serialize_and_deserialize_key() { - let key = OpenSslKeyPair::build().unwrap(); let json = serde_json::to_string(&key).unwrap(); let key_des: OpenSslKeyPair = serde_json::from_str(json.as_str()).unwrap(); diff --git a/commons/src/util/test.rs b/commons/src/util/test.rs index d4e5d4bc..170832ba 100644 --- a/commons/src/util/test.rs +++ b/commons/src/util/test.rs @@ -1,11 +1,11 @@ +use bytes::Bytes; +use rand::{thread_rng, Rng}; +use rpki::uri; use std::fs; use std::fs::File; use std::io::Write; use std::path::PathBuf; use std::str::FromStr; -use bytes::Bytes; -use rand::{thread_rng, Rng}; -use rpki::uri; /// This method sets up a test directory with a random name (a number) /// under 'work', relative to where cargo is running. It then runs the @@ -13,7 +13,10 @@ use rpki::uri; /// directory. /// /// Note that if your test fails the directory is not cleaned up. -pub fn test_under_tmp(op: F) where F: FnOnce(PathBuf) -> () { +pub fn test_under_tmp(op: F) +where + F: FnOnce(PathBuf) -> (), +{ let dir = sub_dir(&PathBuf::from("work")); let path = PathBuf::from(&dir); @@ -41,13 +44,17 @@ pub fn rsync(s: &str) -> uri::Rsync { uri::Rsync::from_str(s).unwrap() } -pub fn https(s: &str) -> uri::Https { uri::Https::from_str(s).unwrap() } +pub fn https(s: &str) -> uri::Https { + uri::Https::from_str(s).unwrap() +} -pub fn as_bytes(s: &str) -> Bytes { Bytes::from(s) } +pub fn as_bytes(s: &str) -> Bytes { + Bytes::from(s) +} pub fn save_file(base_dir: &PathBuf, file_name: &str, content: &[u8]) { let mut full_name = base_dir.clone(); full_name.push(PathBuf::from(file_name)); let mut f = File::create(full_name).unwrap(); f.write_all(content).unwrap(); -} \ No newline at end of file +} diff --git a/commons/src/util/xml.rs b/commons/src/util/xml.rs index a44bcf5b..bcd9c178 100644 --- a/commons/src/util/xml.rs +++ b/commons/src/util/xml.rs @@ -1,17 +1,16 @@ //! Support for RPKI XML structures. -use std::{fs, io}; -use std::fs::File; -use std::path::Path; use base64; use base64::DecodeError; use bytes::Bytes; use hex; use hex::FromHexError; -use xmlrs::{reader, writer}; -use xmlrs::{EmitterConfig, EventReader, EventWriter, ParserConfig}; +use std::fs::File; +use std::path::Path; +use std::{fs, io}; use xmlrs::attribute::OwnedAttribute; use xmlrs::reader::XmlEvent; - +use xmlrs::{reader, writer}; +use xmlrs::{EmitterConfig, EventReader, EventWriter, ParserConfig}; //------------ XmlReader ----------------------------------------------------- @@ -28,20 +27,18 @@ pub struct XmlReader { cached_event: Option, /// Name of the next start element, if any - next_start_name: Option + next_start_name: Option, } - /// Reader methods -impl XmlReader { - +impl XmlReader { /// Gets the next XmlEvent /// /// Will take cached event if there is one fn next(&mut self) -> Result { match self.cached_event.take() { Some(e) => Ok(e), - None => Ok(self.reader.next()?) + None => Ok(self.reader.next()?), } } @@ -51,42 +48,46 @@ impl XmlReader { } } - /// Basic operations to parse the XML. /// /// These methods are private because they are used by the higher level /// closure based methods, defined below, that one should use to parse /// XML safely. -impl XmlReader { +impl XmlReader { /// Takes the next element and expects a start of document. fn start_document(&mut self) -> Result<(), XmlReaderErr> { match self.next() { - Ok(reader::XmlEvent::StartDocument {..}) => Ok(()), - _ => Err(XmlReaderErr::ExpectedStartDocument) + Ok(reader::XmlEvent::StartDocument { .. }) => Ok(()), + _ => Err(XmlReaderErr::ExpectedStartDocument), } } /// Takes the next element and expects a start element with the given name. fn expect_element(&mut self) -> Result<(Tag, Attributes), XmlReaderErr> { match self.next() { - Ok(reader::XmlEvent::StartElement { name, attributes, ..}) => { - Ok((Tag{name: name.local_name}, Attributes{attributes})) - }, - _ => Err(XmlReaderErr::ExpectedStart) + Ok(reader::XmlEvent::StartElement { + name, attributes, .. + }) => Ok(( + Tag { + name: name.local_name, + }, + Attributes { attributes }, + )), + _ => Err(XmlReaderErr::ExpectedStart), } } /// Takes the next element and expects a close element with the given name. fn expect_close(&mut self, tag: Tag) -> Result<(), XmlReaderErr> { match self.next() { - Ok(reader::XmlEvent::EndElement { name, ..}) => { + Ok(reader::XmlEvent::EndElement { name, .. }) => { if name.local_name == tag.name { Ok(()) } else { Err(XmlReaderErr::ExpectedClose(tag.name)) } } - _ => Err(XmlReaderErr::ExpectedClose(tag.name)) + _ => Err(XmlReaderErr::ExpectedClose(tag.name)), } } @@ -97,7 +98,7 @@ impl XmlReader { fn end_document(&mut self) -> Result<(), XmlReaderErr> { match self.next() { Ok(reader::XmlEvent::EndDocument) => Ok(()), - _ => Err(XmlReaderErr::ExpectedEnd) + _ => Err(XmlReaderErr::ExpectedEnd), } } } @@ -108,23 +109,25 @@ impl XmlReader { /// content (such as Characters), and process the enclosed content. In /// particular it ensures that the consumer cannot accidentally get close /// tags - so it forces that execution returns. -impl XmlReader { +impl XmlReader { /// Decodes an XML structure /// /// This method checks that the document starts, then passes a reader /// instance to the provided closure, and will return the result from /// that after checking that the XML document is fully processed. pub fn decode(source: R, op: F) -> Result - where F: FnOnce(&mut Self) -> Result, - E: From { + where + F: FnOnce(&mut Self) -> Result, + E: From, + { let mut config = ParserConfig::new(); config.trim_whitespace = true; config.ignore_comments = true; - let mut xml = XmlReader{ + let mut xml = XmlReader { reader: config.create_reader(source), cached_event: None, - next_start_name: None + next_start_name: None, }; xml.start_document()?; @@ -141,8 +144,10 @@ impl XmlReader { /// the closure completes it will verify that the next element is the /// Close Element for this Tag, and returns the result from the closure. pub fn take_element(&mut self, op: F) -> Result - where F: FnOnce(&Tag, Attributes, &mut Self) -> Result, - E: From { + where + F: FnOnce(&Tag, Attributes, &mut Self) -> Result, + E: From, + { let (tag, attr) = self.expect_element()?; let res = op(&tag, attr, self)?; self.expect_close(tag)?; @@ -153,20 +158,15 @@ impl XmlReader { /// /// Checks that the element has the expected name and passed the closure /// to the generic take_element method. - pub fn take_named_element( - &mut self, - name: &str, - op: F - ) -> Result + pub fn take_named_element(&mut self, name: &str, op: F) -> Result where F: FnOnce(Attributes, &mut Self) -> Result, - E: From + E: From, { self.take_element(|t, a, r| { if t.name != name { Err(XmlReaderErr::ExpectedNamedStart(name.to_string()).into()) - } - else { + } else { op(a, r) } }) @@ -184,21 +184,22 @@ impl XmlReader { /// that a 'take_*' method with a closure was used for the parent element, /// then we will get a clear error there (expect end element). pub fn take_opt_element(&mut self, op: F) -> Result, E> - where F: FnOnce(&Tag, Attributes, &mut Self) -> Result, E>, - E: From { - + where + F: FnOnce(&Tag, Attributes, &mut Self) -> Result, E>, + E: From, + { let n = self.next()?; match n { - XmlEvent::StartElement { name, attributes, ..} => { - let tag = Tag{name: name.local_name}; - let res = op( - &tag, - Attributes{attributes}, - self - )?; + XmlEvent::StartElement { + name, attributes, .. + } => { + let tag = Tag { + name: name.local_name, + }; + let res = op(&tag, Attributes { attributes }, self)?; self.expect_close(tag)?; Ok(res) - }, + } _ => { self.cache(n); Ok(None) @@ -209,10 +210,8 @@ impl XmlReader { /// Takes characters pub fn take_chars(&mut self) -> Result { match self.next() { - Ok(reader::XmlEvent::Characters(chars)) => { - Ok(chars) - } - _ => Err(XmlReaderErr::ExpectedCharacters) + Ok(reader::XmlEvent::Characters(chars)) => Ok(chars), + _ => Err(XmlReaderErr::ExpectedCharacters), } } @@ -226,15 +225,13 @@ impl XmlReader { self.take_bytes(base64::URL_SAFE_NO_PAD) } - fn take_bytes( - &mut self, - config: base64::Config - ) -> Result { + fn take_bytes(&mut self, config: base64::Config) -> Result { let chars = self.take_chars()?; // strip whitespace and padding (we are liberal in what we accept here) // TODO: Avoid allocation, pass in an AsRef<[u8]> that // removes any whitespace on the fly. - let chars: Vec = chars.into_bytes() + let chars: Vec = chars + .into_bytes() .into_iter() .filter(|c| !b" \n\t\r\x0b\x0c=".contains(c)) .collect(); @@ -243,7 +240,6 @@ impl XmlReader { Ok(Bytes::from(b64)) } - pub fn take_empty(&mut self) -> Result<(), XmlReaderErr> { Ok(()) } @@ -254,8 +250,8 @@ impl XmlReader { pub fn next_start_name(&mut self) -> Option<&str> { match self.next() { Err(_) => None, - Ok(e) => { - if let XmlEvent::StartElement { ref name, ..} = e { + Ok(e) => { + if let XmlEvent::StartElement { ref name, .. } = e { // XXX not the most efficient.. but need a different // underlying XML parser to get around ownership // issues. @@ -271,12 +267,13 @@ impl XmlReader { } impl XmlReader { - /// Opens a file and decodes it as an XML file. pub fn open(path: P, op: F) -> Result - where F: FnOnce(&mut Self) -> Result, - P: AsRef, - E: From + From { + where + F: FnOnce(&mut Self) -> Result, + P: AsRef, + E: From + From, + { Self::decode(fs::File::open(path)?, op) } } @@ -313,11 +310,11 @@ pub enum XmlReaderErr { ReaderError(reader::Error), #[display(fmt = "Base64 decoding issue: {}", _0)] - Base64Error(DecodeError) + Base64Error(DecodeError), } impl From for XmlReaderErr { - fn from(e: io::Error) -> XmlReaderErr{ + fn from(e: io::Error) -> XmlReaderErr { XmlReaderErr::IoError(e) } } @@ -340,26 +337,27 @@ impl From for XmlReaderErr { } } - //------------ Attributes ---------------------------------------------------- /// A convenient wrapper for XML tag attributes pub struct Attributes { /// The underlying xml-rs structure - attributes: Vec + attributes: Vec, } impl Attributes { - /// Takes an optional attribute by name pub fn take_opt(&mut self, name: &str) -> Option { - let i = self.attributes.iter().position(|a| a.name.local_name == name); + let i = self + .attributes + .iter() + .position(|a| a.name.local_name == name); match i { Some(i) => { let a = self.attributes.swap_remove(i); Some(a.value) } - None => None + None => None, } } @@ -375,12 +373,10 @@ impl Attributes { } /// Takes a required hexencoded attribute and converts it to Bytes - pub fn take_req_hex(&mut self, name: &str) - -> Result { - + pub fn take_req_hex(&mut self, name: &str) -> Result { match hex::decode(self.take_req(name)?) { Err(e) => Err(AttributesError::HexError(e)), - Ok(b) => Ok(Bytes::from(b)) + Ok(b) => Ok(Bytes::from(b)), } } @@ -394,7 +390,6 @@ impl Attributes { } } - //------------ AttributesError ----------------------------------------------- #[derive(Debug, Display)] @@ -406,7 +401,7 @@ pub enum AttributesError { ExtraAttributes(String), #[display(fmt = "Wrong hex encoding: {}", _0)] - HexError(FromHexError) + HexError(FromHexError), } impl AttributesError { @@ -417,14 +412,12 @@ impl AttributesError { } } - //------------ Tag ----------------------------------------------------------- pub struct Tag { - pub name: String + pub name: String, } - //------------ XmlWriter ----------------------------------------------------- /// A convenience wrapper for RPKI XML generation @@ -432,14 +425,11 @@ pub struct Tag { /// This type only exposes things we need for the RPKI XML structures. pub struct XmlWriter { /// The underlying xml-rs writer - writer: EventWriter + writer: EventWriter, } - /// Generate the XML. -impl XmlWriter { - - +impl XmlWriter { fn unwrap_emitter_error(r: Result) -> Result { match r { Ok(t) => Ok(t), @@ -463,8 +453,11 @@ impl XmlWriter { &mut self, name: &str, attr: Option<&[(&str, &str)]>, - op: F) -> Result<(), io::Error> - where F: FnOnce(&mut Self) -> Result<(), io::Error> { + op: F, + ) -> Result<(), io::Error> + where + F: FnOnce(&mut Self) -> Result<(), io::Error>, + { let mut start = writer::XmlEvent::start_element(name); if let Some(v) = attr { @@ -475,18 +468,14 @@ impl XmlWriter { Self::unwrap_emitter_error(self.writer.write(start))?; op(self)?; - Self::unwrap_emitter_error( - self.writer.write(writer::XmlEvent::end_element()) - )?; + Self::unwrap_emitter_error(self.writer.write(writer::XmlEvent::end_element()))?; Ok(()) } /// Puts some String in a characters element pub fn put_text(&mut self, text: &str) -> Result<(), io::Error> { - Self::unwrap_emitter_error( - self.writer.write(writer::XmlEvent::Characters(text)) - )?; + Self::unwrap_emitter_error(self.writer.write(writer::XmlEvent::Characters(text)))?; Ok(()) } @@ -516,8 +505,9 @@ impl XmlWriter { /// method, and in future others like it, to set up the writer for a /// specific type (Vec, File, etc.). fn encode(w: W, op: F) -> Result<(), io::Error> - where F: FnOnce(&mut Self) -> Result<(), io::Error> { - + where + F: FnOnce(&mut Self) -> Result<(), io::Error>, + { let writer = EmitterConfig::new() .write_document_declaration(false) .normalize_empty_elements(true) @@ -531,11 +521,10 @@ impl XmlWriter { } impl XmlWriter<()> { - /// Call this to encode XML into a Vec pub fn encode_vec(op: F) -> Vec - where F: FnOnce(&mut XmlWriter<&mut Vec>) - -> Result<(), io::Error> + where + F: FnOnce(&mut XmlWriter<&mut Vec>) -> Result<(), io::Error>, { let mut b = Vec::new(); XmlWriter::encode(&mut b, op).unwrap(); // IO error impossible for vec @@ -543,12 +532,13 @@ impl XmlWriter<()> { } pub fn encode_to_file(file: &mut File, op: F) -> Result<(), io::Error> - where F: FnOnce(&mut XmlWriter<&mut File>) -> Result<(), io::Error> { + where + F: FnOnce(&mut XmlWriter<&mut File>) -> Result<(), io::Error>, + { XmlWriter::encode(file, op) } } - //------------ Tests --------------------------------------------------------- #[cfg(test)] @@ -559,20 +549,10 @@ mod tests { #[test] fn should_write_xml() { - let xml = XmlWriter::encode_vec(|w| { - w.put_element( - "a", - Some(&[ - ("xmlns", "http://ns/"), - ("c", "d") - ]), - |w| { - w.put_element("b", None, |w| { - w.put_base64_std(&Bytes::from("X")) - }) - } - ) + w.put_element("a", Some(&[("xmlns", "http://ns/"), ("c", "d")]), |w| { + w.put_element("b", None, |w| w.put_base64_std(&Bytes::from("X"))) + }) }); assert_eq!( diff --git a/daemon/build-ui.rs b/daemon/build-ui.rs index 67f12ffa..229bcf3b 100644 --- a/daemon/build-ui.rs +++ b/daemon/build-ui.rs @@ -1,7 +1,7 @@ extern crate ignore; -use std::process::Command; use ignore::Walk; +use std::process::Command; //#[allow(dead_code)] fn main() { @@ -11,4 +11,4 @@ fn main() { } } Command::new("./build-dist.sh").status().unwrap(); -} \ No newline at end of file +} diff --git a/daemon/src/auth.rs b/daemon/src/auth.rs index 332f2c19..7f444741 100644 --- a/daemon/src/auth.rs +++ b/daemon/src/auth.rs @@ -1,19 +1,8 @@ //! Authorization for the API -use actix_web::{ - Error, - FromRequest, - HttpResponse, - HttpRequest, - ResponseError, -}; -use actix_web::dev::{ - Payload, -}; use actix_identity::Identity; -use actix_web::web::{ - self, - Json -}; +use actix_web::dev::Payload; +use actix_web::web::{self, Json}; +use actix_web::{Error, FromRequest, HttpRequest, HttpResponse, ResponseError}; use krill_commons::api::admin::Token; @@ -22,20 +11,19 @@ use std::fmt; pub const AUTH_COOKIE_NAME: &str = "krill_auth"; - //------------ Authorizer ---------------------------------------------------- /// This type is responsible for checking authorisations when the API is /// accessed. #[derive(Clone, Debug)] pub struct Authorizer { - krill_auth_token: Token + krill_auth_token: Token, } impl Authorizer { pub fn new(krill_auth_token: &Token) -> Self { Authorizer { - krill_auth_token: krill_auth_token.clone() + krill_auth_token: krill_auth_token.clone(), } } @@ -44,19 +32,14 @@ impl Authorizer { } } - //------------ Credentials --------------------------------------------------- #[derive(Deserialize)] pub struct Credentials { - token: Token + token: Token, } -pub fn login( - server: web::Data, - cred: Json, - id: Identity -) -> HttpResponse { +pub fn login(server: web::Data, cred: Json, id: Identity) -> HttpResponse { if server.read().login(cred.token.clone()) { id.remember("admin".to_string()); HttpResponse::Ok().finish() @@ -66,20 +49,15 @@ pub fn login( } } -pub fn logout( - id: Identity -) -> HttpResponse { +pub fn logout(id: Identity) -> HttpResponse { id.forget(); HttpResponse::Ok().finish() } -pub fn is_logged_in( - _auth: Auth -) -> HttpResponse { +pub fn is_logged_in(_auth: Auth) -> HttpResponse { HttpResponse::Ok().finish() } - pub type UserName = String; //------------ Auth ---------------------------------------------------------- @@ -87,7 +65,7 @@ pub type UserName = String; #[derive(Clone, Debug)] pub enum Auth { User(UserName), - Bearer(Token) + Bearer(Token), } impl Auth { @@ -101,7 +79,7 @@ impl Auth { let token = Token::from(token.trim()); if "bearer" == bearer { - return Ok(token) + return Ok(token); } } @@ -112,7 +90,7 @@ impl Auth { impl fmt::Display for Auth { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self { - Auth::User(user) => write!(f, "User: {}", user), + Auth::User(user) => write!(f, "User: {}", user), Auth::Bearer(token) => write!(f, "Bearer: {}", token), } } @@ -122,7 +100,7 @@ impl Into for Auth { fn into(self) -> Token { match self { Auth::Bearer(token) => token, - _ => Token::from("") + _ => Token::from(""), } } } @@ -137,9 +115,8 @@ impl FromRequest for Auth { debug!("Found user: {}", &identity); Ok(Auth::User(identity)) } else if let Some(header) = req.headers().get("Authorization") { - let token = Auth::extract_bearer_token( - header.to_str().map_err(|_| AuthError::InvalidToken)? - )?; + let token = + Auth::extract_bearer_token(header.to_str().map_err(|_| AuthError::InvalidToken)?)?; Ok(Auth::Bearer(token)) } else { @@ -148,7 +125,6 @@ impl FromRequest for Auth { } } - //------------ AuthError ----------------------------------------------------- #[derive(Debug, Display)] @@ -157,7 +133,7 @@ pub enum AuthError { Unauthorised, #[display(fmt = "Invalid token")] - InvalidToken + InvalidToken, } impl ResponseError for AuthError { diff --git a/daemon/src/ca/certauth.rs b/daemon/src/ca/certauth.rs index eb5ed48e..2fe969d9 100644 --- a/daemon/src/ca/certauth.rs +++ b/daemon/src/ca/certauth.rs @@ -1,80 +1,52 @@ use std::collections::HashMap; use std::marker::PhantomData; -use std::ops::{Deref}; +use std::ops::Deref; use std::sync::{Arc, RwLock}; use bytes::Bytes; use chrono::Duration; -use rpki::cert::{TbsCert, KeyUsage, Overclaim}; +use rpki::cert::{KeyUsage, Overclaim, TbsCert}; use rpki::crypto::{PublicKey, PublicKeyFormat}; use rpki::csr::Csr; -use rpki::x509::{Serial, Validity, Time, Name}; +use rpki::x509::{Name, Serial, Time, Validity}; -use krill_commons::api::{ - self, - DFLT_CLASS, - EncodedHash, - EntitlementClass, - Entitlements, - IssuanceRequest, - SigningCert, - RequestResourceLimit, - IssuanceResponse -}; -use krill_commons::api::admin::{ - Handle, - ParentCaContact, - Token, - PubServerContact -}; +use krill_commons::api::admin::{Handle, ParentCaContact, PubServerContact, Token}; use krill_commons::api::ca::{ - AddedObject, - AllCurrentObjects, - CaParentsInfo, - CertAuthInfo, - CertifiedKey, - ChildCa, - ChildCaDetails, - CurrentObject, - CurrentObjects, - IssuedCert, - KeyRef, - ObjectName, - ObjectsDelta, - ParentCaInfo, - PendingKey, - PublicationDelta, - RcvdCert, - RepoInfo, - ResourceClassInfo, - ResourceSet, - TrustAnchorInfo, - TrustAnchorLocator, - UpdatedObject, + AddedObject, AllCurrentObjects, CaParentsInfo, CertAuthInfo, CertifiedKey, ChildCa, + ChildCaDetails, CurrentObject, CurrentObjects, IssuedCert, KeyRef, ObjectName, ObjectsDelta, + ParentCaInfo, PendingKey, PublicationDelta, RcvdCert, RepoInfo, ResourceClassInfo, ResourceSet, + TrustAnchorInfo, TrustAnchorLocator, UpdatedObject, +}; +use krill_commons::api::{ + self, EncodedHash, EntitlementClass, Entitlements, IssuanceRequest, IssuanceResponse, + RequestResourceLimit, SigningCert, DFLT_CLASS, }; use krill_commons::eventsourcing::Aggregate; use krill_commons::remote::builder::{IdCertBuilder, SignedMessageBuilder}; use krill_commons::remote::id::IdCert; -use krill_commons::remote::sigmsg::SignedMessage; -use krill_commons::remote::rfc8183::ChildRequest; use krill_commons::remote::rfc6492; +use krill_commons::remote::rfc8183::ChildRequest; +use krill_commons::remote::sigmsg::SignedMessage; use krill_commons::util::softsigner::SignerKeyId; -use ca::{self, CmdDet, Cmd, CertIssued, CertRequested, CertReceived, Error, Evt, EvtDet, Ini, ParentHandle, Result, Signer, SignSupport}; - +use ca::{ + self, CertIssued, CertReceived, CertRequested, Cmd, CmdDet, Error, Evt, EvtDet, Ini, + ParentHandle, Result, SignSupport, Signer, +}; //------------ Rfc8183Id --------------------------------------------------- #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] pub struct Rfc8183Id { key: SignerKeyId, - cert: IdCert + cert: IdCert, } impl Rfc8183Id { pub fn generate(signer: &mut S) -> Result { - let key = signer.create_key(PublicKeyFormat::default()) + let key = signer + .create_key(PublicKeyFormat::default()) .map_err(|e| Error::SignerError(e.to_string()))?; let cert = IdCertBuilder::new_ta_id_cert(&key, signer.deref()) .map_err(|e| Error::SignerError(e.to_string()))?; @@ -82,14 +54,13 @@ impl Rfc8183Id { } } - //------------ CaType ------------------------------------------------------ #[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)] #[allow(clippy::large_enum_variant)] pub enum CaType { Child, - Ta(CertifiedKey, TrustAnchorLocator) + Ta(CertifiedKey, TrustAnchorLocator), } //------------ CaParents --------------------------------------------------- @@ -98,15 +69,13 @@ pub enum CaType { #[allow(clippy::large_enum_variant)] pub enum CaParents { SelfSigned(CertifiedKey, TrustAnchorLocator), - Parents(HashMap) + Parents(HashMap), } impl CaParents { fn as_info(&self) -> CaParentsInfo { match self { - CaParents::SelfSigned(key, tal) => { - CaParentsInfo::SelfSigned(key.clone(), tal.clone()) - }, + CaParents::SelfSigned(key, tal) => CaParentsInfo::SelfSigned(key.clone(), tal.clone()), CaParents::Parents(map) => { let mut map_info = HashMap::new(); @@ -121,14 +90,14 @@ impl CaParents { fn is_self_signed(&self) -> bool { match self { - CaParents::SelfSigned(_,_) => true, - _ => false + CaParents::SelfSigned(_, _) => true, + _ => false, } } fn assert_parent_new(&self, parent: &Handle) -> Result<()> { match self { - CaParents::SelfSigned(_,_) => Err(Error::NotAllowedForTa), + CaParents::SelfSigned(_, _) => Err(Error::NotAllowedForTa), CaParents::Parents(map) => { if map.contains_key(parent) { Err(Error::DuplicateParent(parent.clone())) @@ -141,7 +110,7 @@ impl CaParents { fn insert(&mut self, handle: Handle, parent: ParentCa) -> Result<()> { match self { - CaParents::SelfSigned(_,_) => Err(Error::NotAllowedForTa), + CaParents::SelfSigned(_, _) => Err(Error::NotAllowedForTa), CaParents::Parents(map) => { map.insert(handle, parent); Ok(()) @@ -151,33 +120,30 @@ impl CaParents { fn get(&self, handle: &Handle) -> Result<&ParentCa> { match self { - CaParents::SelfSigned(_,_) => Err(Error::NotAllowedForTa), - CaParents::Parents(map) => Ok( - map.get(handle) - .ok_or_else(|| Error::UnknownParent(handle.clone()))? - ) + CaParents::SelfSigned(_, _) => Err(Error::NotAllowedForTa), + CaParents::Parents(map) => Ok(map + .get(handle) + .ok_or_else(|| Error::UnknownParent(handle.clone()))?), } } fn get_mut(&mut self, handle: &Handle) -> Result<&mut ParentCa> { match self { - CaParents::SelfSigned(_,_) => Err(Error::NotAllowedForTa), - CaParents::Parents(map) => Ok( - map.get_mut(handle) - .ok_or_else(|| Error::UnknownParent(handle.clone()))? - ) + CaParents::SelfSigned(_, _) => Err(Error::NotAllowedForTa), + CaParents::Parents(map) => Ok(map + .get_mut(handle) + .ok_or_else(|| Error::UnknownParent(handle.clone()))?), } } fn ta_key_mut(&mut self) -> Result<&mut CertifiedKey> { match self { - CaParents::SelfSigned(key,_) => Ok(key), - CaParents::Parents(_map) => Err(Error::NotTa) + CaParents::SelfSigned(key, _) => Ok(key), + CaParents::Parents(_map) => Err(Error::NotTa), } } } - //------------ CertAuth ---------------------------------------------------- #[derive(Clone, Debug, Deserialize, Serialize)] @@ -194,7 +160,7 @@ pub struct CertAuth { children: HashMap, - phantom_signer: PhantomData + phantom_signer: PhantomData, } impl Aggregate for CertAuth { @@ -209,12 +175,12 @@ impl Aggregate for CertAuth { let (token, id, base_repo, ca_type) = details.unwrap(); if ca_type == CaType::Child && handle == Handle::from("ta") { - return Err(Error::NameReservedTa) + return Err(Error::NameReservedTa); } let parents = match ca_type { CaType::Child => CaParents::Parents(HashMap::new()), - CaType::Ta(key, tal) => CaParents::SelfSigned(key, tal) + CaType::Ta(key, tal) => CaParents::SelfSigned(key, tal), }; let pubserver = PubServerContact::embedded(); @@ -233,7 +199,7 @@ impl Aggregate for CertAuth { children, - phantom_signer: PhantomData + phantom_signer: PhantomData, }) } @@ -248,7 +214,7 @@ impl Aggregate for CertAuth { EvtDet::ChildAdded(child) => { let (handle, details) = child.unwrap(); self.children.insert(handle, details); - }, + } EvtDet::CertificateIssued(cert_issued) => { let (child_handle, response) = cert_issued.unwrap(); let (class_name, _, _, issued) = response.unwrap(); @@ -256,33 +222,38 @@ impl Aggregate for CertAuth { let child = self.children.get_mut(&child_handle).unwrap(); child.add_cert(&class_name, issued); - }, + } // Being a child EvtDet::ParentAdded(handle, info) => { let parent = ParentCa::without_resource(info); self.parents.insert(handle, parent).unwrap(); - }, + } EvtDet::ResourceClassAdded(parent, name, rc) => { // Evt cannot occur without parent existing - self.parents.get_mut(&parent).unwrap() - .resources.insert(name, rc); + self.parents + .get_mut(&parent) + .unwrap() + .resources + .insert(name, rc); } EvtDet::CertificateRequested(req) => { let (parent, status, req) = req.unwrap(); let class = req.class_name().to_owned(); - self.parents.get_mut(&parent).unwrap() - .resources.get_mut(&class).unwrap() + self.parents + .get_mut(&parent) + .unwrap() + .resources + .get_mut(&class) + .unwrap() .add_request(status, req) - }, + } EvtDet::PendingKeyActivated(parent, class_name, cert) => { let parent = self.parent_mut(&parent).unwrap(); let rc = parent.class_mut(&class_name).unwrap(); rc.pending_key_activated(cert); } - EvtDet::CertificateReceived(_rcvd) => { - unimplemented!() - }, + EvtDet::CertificateReceived(_rcvd) => unimplemented!(), // General functions EvtDet::Published(parent, class_name, status, delta) => { @@ -290,46 +261,40 @@ impl Aggregate for CertAuth { let rc = parent.class_mut(&class_name).unwrap(); let ck = rc.get_key_mut(status).unwrap(); ck.apply_delta(delta); - }, + } EvtDet::TaPublished(delta) => { let ta_key = self.ta_key_mut().unwrap(); ta_key.apply_delta(delta); } - } } fn process_command(&self, command: Cmd) -> ca::Result> { match command.into_details() { // being a parent - CmdDet::AddChild(child, token, id_cert_opt, resources) => { + CmdDet::AddChild(child, token, id_cert_opt, resources) => { self.add_child(child, token, id_cert_opt, resources) - }, - CmdDet::UpdateChild(_,_,_,_) => unimplemented!(), + } + CmdDet::UpdateChild(_, _, _, _) => unimplemented!(), CmdDet::CertifyChild(child, request, token, signer) => { self.certify_child(child, request, token, signer) } // being a child - CmdDet::AddParent(parent, info) => { - self.add_parent(parent,info) - }, + CmdDet::AddParent(parent, info) => self.add_parent(parent, info), CmdDet::UpdateEntitlements(parent, entitlements, signer) => { self.update_entitlements(parent, entitlements, signer) - }, + } CmdDet::UpdateRcvdCert(parent, class_name, rcvd_cert, signer) => { self.update_received_cert(parent, class_name, rcvd_cert, signer) - }, + } // general CA functions - CmdDet::Republish(signer) => { - self.republish(signer) - } + CmdDet::Republish(signer) => self.republish(signer), } } } - /// # Data presentation /// impl CertAuth { @@ -337,17 +302,12 @@ impl CertAuth { if let CaParents::SelfSigned(key, tal) = &self.parents { let resources = key.incoming_cert().resources().clone(); let repo_info = self.base_repo.clone(); - let children = self.children.clone(); + let children = self.children.clone(); let cert = key.incoming_cert().clone(); let tal = tal.clone(); - Ok(TrustAnchorInfo::new( - resources, - repo_info, - children, - cert, - tal + resources, repo_info, children, cert, tal, )) } else { unimplemented!() @@ -358,7 +318,7 @@ impl CertAuth { let handle = self.handle.clone(); let base_repo = self.base_repo.clone(); let parents = self.parents.as_info(); - let children = self.children.clone(); + let children = self.children.clone(); CertAuthInfo::new(handle, base_repo, parents, children) } @@ -367,9 +327,15 @@ impl CertAuth { ChildRequest::new(self.handle.clone(), self.id.cert.clone()) } - pub fn id_cert(&self) -> &IdCert { &self.id.cert } - pub(crate) fn id_key(&self) -> &SignerKeyId { &self.id.key } - pub fn handle(&self) -> &Handle { &self.handle } + pub fn id_cert(&self) -> &IdCert { + &self.id.cert + } + pub(crate) fn id_key(&self) -> &SignerKeyId { + &self.id.key + } + pub fn handle(&self) -> &Handle { + &self.handle + } } /// # Publishing @@ -382,7 +348,7 @@ impl CertAuth { match &self.parents { CaParents::SelfSigned(key, _tal) => { objects.add_name_space(DFLT_CLASS, key.current_set().objects()) - }, + } CaParents::Parents(parents) => { for parent in parents.values() { for rc in parent.resources.values() { @@ -408,17 +374,12 @@ impl CertAuth { key: &CertifiedKey, repo_info: &RepoInfo, name_space: &str, - signer: Arc> + signer: Arc>, ) -> Result { let ca_repo = repo_info.ca_repository(name_space); let objects_delta = ObjectsDelta::new(ca_repo); - SignSupport::publish( - signer, - key, - repo_info, - name_space, - objects_delta - ).map_err(Error::signer) + SignSupport::publish(signer, key, repo_info, name_space, objects_delta) + .map_err(Error::signer) } /// Republish objects for this CA @@ -427,23 +388,13 @@ impl CertAuth { match &self.parents { CaParents::SelfSigned(key, _tal) => { if key.needs_publication() { - let delta = Self::republish_delta_for_key( - key, - &self.base_repo, - "", - signer.clone() - )?; + let delta = + Self::republish_delta_for_key(key, &self.base_repo, "", signer.clone())?; - res.push(EvtDet::published_ta( - &self.handle, - self.version, - delta - )) + res.push(EvtDet::published_ta(&self.handle, self.version, delta)) } - }, - CaParents::Parents(_map) => { - unimplemented!() } + CaParents::Parents(_map) => unimplemented!(), } Ok(res) } @@ -452,53 +403,37 @@ impl CertAuth { /// # Being a parent /// impl CertAuth { - - pub fn verify_rfc6492( - &self, - msg: SignedMessage - ) -> Result<(rfc6492::Message, Token)> { + pub fn verify_rfc6492(&self, msg: SignedMessage) -> Result<(rfc6492::Message, Token)> { let content = rfc6492::Message::from_signed_message(&msg)?; let child_handle = Handle::from(content.sender()); let child = self.get_child(&child_handle)?; - let child_cert = child.id_cert() + let child_cert = child + .id_cert() .ok_or_else(|| Error::Unauthorized(child_handle))?; - msg.validate(child_cert).map_err(|_| Error::InvalidRfc6492)?; + msg.validate(child_cert) + .map_err(|_| Error::InvalidRfc6492)?; let token = child.token().clone(); Ok((content, token)) } - pub fn sign_rfc6492_response( - &self, - msg: rfc6492::Message, - signer: &S - ) -> Result { + pub fn sign_rfc6492_response(&self, msg: rfc6492::Message, signer: &S) -> Result { let key = &self.id.key; - Ok(SignedMessageBuilder::create( - key, - signer, - msg.into_bytes() - ).map_err(Error::signer)?.as_bytes()) + Ok(SignedMessageBuilder::create(key, signer, msg.into_bytes()) + .map_err(Error::signer)? + .as_bytes()) } /// List entitlements (section 3.3.2 of RFC6492). Return an error if /// the child is not authorized -- or unknown etc. /// /// Only supported in TAs until issue #25 is implemented. - pub fn list( - &self, - child_handle: &Handle, - token: &Token - ) -> Result { + pub fn list(&self, child_handle: &Handle, token: &Token) -> Result { // TODO: Support arbitrary resource classes. See issue #25. - let dflt_entitlement_class = self.entitlement_class( - child_handle, - DFLT_CLASS, - token - )?; + let dflt_entitlement_class = self.entitlement_class(child_handle, DFLT_CLASS, token)?; Ok(Entitlements::new(vec![dflt_entitlement_class])) } @@ -510,30 +445,26 @@ impl CertAuth { child_handle: &Handle, class_name: &str, pub_key: &PublicKey, - token: &Token + token: &Token, ) -> Result { - let entitlement_class = self.entitlement_class( - child_handle, - class_name, - token - )?; + let entitlement_class = self.entitlement_class(child_handle, class_name, token)?; entitlement_class .into_issuance_response(pub_key) .ok_or_else(|| Error::NoIssuedCert) } - /// Returns the EntitlementClass for this child for the given class name. fn entitlement_class( &self, child_handle: &Handle, class_name: &str, - token: &Token + token: &Token, ) -> Result { let child = self.get_authorised_child(child_handle, token)?; - let child_resources = child.resources_for_class(class_name) + let child_resources = child + .resources_for_class(class_name) .ok_or_else(|| Error::MissingResources)?; let until = child_resources.not_after(); @@ -541,7 +472,7 @@ impl CertAuth { let cert = match &self.parents { CaParents::SelfSigned(key, _tal) => key.incoming_cert(), - CaParents::Parents(_) => unimplemented!("Issue #25 (delegate from CA)") + CaParents::Parents(_) => unimplemented!("Issue #25 (delegate from CA)"), }; let resources = cert.resources().clone(); let cert = SigningCert::new(cert.uri().clone(), cert.cert().clone()); @@ -551,7 +482,7 @@ impl CertAuth { cert, resources, until, - issued + issued, )) } @@ -560,7 +491,7 @@ impl CertAuth { pub fn get_authorised_child( &self, child_handle: &Handle, - token: &Token + token: &Token, ) -> Result<&ChildCaDetails> { let child = self.get_child(child_handle)?; @@ -575,7 +506,7 @@ impl CertAuth { pub fn get_child(&self, child: &Handle) -> Result<&ChildCaDetails> { match self.children.get(child) { None => Err(Error::UnknownChild(child.clone())), - Some(child) => Ok(child) + Some(child) => Ok(child), } } @@ -587,21 +518,21 @@ impl CertAuth { handle: Handle, token: Token, id_cert: Option, - resources: ResourceSet + resources: ResourceSet, ) -> ca::Result> { // check that // 1) the resource set is not empty if resources.is_empty() { - return Err(Error::MustHaveResources) + return Err(Error::MustHaveResources); } // 2) the resources are held by me match &self.parents { CaParents::SelfSigned(key, _tal) => { - if ! key.incoming_cert().resources().contains(&resources) { - return Err(Error::MissingResources) + if !key.incoming_cert().resources().contains(&resources) { + return Err(Error::MissingResources); } - }, + } CaParents::Parents(_map) => { unimplemented!("#25 Issue #25 (delegate from CA)"); } @@ -609,19 +540,14 @@ impl CertAuth { // 3) there is no existing child by this name if self.has_child(&handle) { - return Err(Error::DuplicateChild(handle)) + return Err(Error::DuplicateChild(handle)); } // TODO: Handle add child to normal CA (issue #25) let mut child = ChildCa::without_resources(handle, token, id_cert); child.add_resources(DFLT_CLASS, resources); - - Ok(vec![EvtDet::child_added( - &self.handle, - self.version, - child - )]) + Ok(vec![EvtDet::child_added(&self.handle, self.version, child)]) } /// Certifies a child, unless: @@ -637,27 +563,29 @@ impl CertAuth { child: Handle, request: IssuanceRequest, token: Token, - signer: Arc> + signer: Arc>, ) -> ca::Result> { let (class_name, limit, csr) = request.unwrap(); let issuing_key = match &self.parents { CaParents::SelfSigned(key, _tal) => key, - CaParents::Parents(_) => unimplemented!("Issue #25 (delegate from CA)") + CaParents::Parents(_) => unimplemented!("Issue #25 (delegate from CA)"), }; let issuing_cert = issuing_key.incoming_cert(); // verify child and resources - let child_resources = self.get_authorised_child(&child, &token)? + let child_resources = self + .get_authorised_child(&child, &token)? .resources_for_class(&class_name) .ok_or_else(|| Error::MissingResourceClass)?; if child_resources.resources().is_empty() { - return Err(Error::MissingResources) + return Err(Error::MissingResources); } - let resources = limit.resolve(child_resources.resources()) + let resources = limit + .resolve(child_resources.resources()) .ok_or_else(|| Error::MissingResources)?; csr.validate() @@ -668,15 +596,12 @@ impl CertAuth { // create new cert let issued_cert = { - let serial = { - Serial::random(signer.read().unwrap().deref()) - .map_err(Error::signer)? - }; + let serial = { Serial::random(signer.read().unwrap().deref()).map_err(Error::signer)? }; let issuer = issuing_cert.cert().subject().clone(); let validity = Validity::new( Time::now() - Duration::minutes(3), - child_resources.not_after() + child_resources.not_after(), ); let subject = Some(Name::from_pub_key(csr.public_key())); @@ -686,7 +611,7 @@ impl CertAuth { let overclaim = Overclaim::Refuse; let mut cert = TbsCert::new( - serial, issuer, validity, subject, pub_key, key_usage, overclaim + serial, issuer, validity, subject, pub_key, key_usage, overclaim, ); cert.set_basic_ca(Some(true)); @@ -696,9 +621,11 @@ impl CertAuth { // because the publication server for those URIs should verify the // identity of the publisher, and that RPs will not invalidate the // content of another CA's repo, if they it is wrongfully claimed. - let ca_repository = csr.ca_repository() + let ca_repository = csr + .ca_repository() .ok_or_else(|| Error::invalid_csr(&child, "missing ca repo"))?; - let rpki_manifest = csr.rpki_manifest() + let rpki_manifest = csr + .rpki_manifest() .ok_or_else(|| Error::invalid_csr(&child, "missing mft uri"))?; let rpki_notify = csr.rpki_notify(); @@ -713,15 +640,11 @@ impl CertAuth { cert.set_v4_resources(Some(resources.v4().deref().clone())); cert.set_v6_resources(Some(resources.v6().deref().clone())); - cert.set_authority_key_identifier( - Some(issuing_cert.cert().subject_key_identifier()) - ); + cert.set_authority_key_identifier(Some(issuing_cert.cert().subject_key_identifier())); let cert = { - cert.into_cert( - signer.read().unwrap().deref(), - issuing_key.key_id() - ).map_err(Error::signer)? + cert.into_cert(signer.read().unwrap().deref(), issuing_key.key_id()) + .map_err(Error::signer)? }; let cert_uri = issuing_cert.uri_for_object(&cert); @@ -741,15 +664,11 @@ impl CertAuth { signing_cert, resources, issued_cert.cert().validity().not_after(), - issued_cert.clone() - ) + issued_cert.clone(), + ), ); - let issued_event = EvtDet::certificate_issued( - &self.handle, - version, - cert_issued - ); + let issued_event = EvtDet::certificate_issued(&self.handle, version, cert_issued); let delta = { let ca_repo = self.base_repo.ca_repository(""); @@ -757,16 +676,10 @@ impl CertAuth { let cert_name = ObjectName::from(issued_cert.cert()); match current_cert { - None => { - delta.add(AddedObject::new(cert_name,cert_object)) - }, + None => delta.add(AddedObject::new(cert_name, cert_object)), Some(old) => { - let old_hash = EncodedHash::from_content( - old.cert().to_captured().as_slice() - ); - delta.update(UpdatedObject::new( - cert_name, cert_object, old_hash - )) + let old_hash = EncodedHash::from_content(old.cert().to_captured().as_slice()); + delta.update(UpdatedObject::new(cert_name, cert_object, old_hash)) } } delta @@ -775,13 +688,8 @@ impl CertAuth { let publish_event = EvtDet::published_ta( &self.handle, version + 1, - SignSupport::publish( - signer, - issuing_key, - &self.base_repo, - "", - delta - ).map_err(Error::signer)? + SignSupport::publish(signer, issuing_key, &self.base_repo, "", delta) + .map_err(Error::signer)?, ); Ok(vec![issued_event, publish_event]) @@ -803,10 +711,8 @@ impl CertAuth { /// List all parents pub fn parents(&self) -> Result> { match &self.parents { - CaParents::SelfSigned(_,_) => Err(Error::NotAllowedForTa), - CaParents::Parents(map) => { - Ok(map.iter().map(|e| (e.0.clone(), e.1.clone())).collect()) - } + CaParents::SelfSigned(_, _) => Err(Error::NotAllowedForTa), + CaParents::Parents(map) => Ok(map.iter().map(|e| (e.0.clone(), e.1.clone())).collect()), } } @@ -824,19 +730,14 @@ impl CertAuth { /// Adds a parent. This method will return an error in case a parent /// by this name (handle) is already known. - fn add_parent( - &self, - parent: Handle, - info: ParentCaContact - ) -> ca::Result> { - + fn add_parent(&self, parent: Handle, info: ParentCaContact) -> ca::Result> { self.parents.assert_parent_new(&parent)?; Ok(vec![EvtDet::parent_added( &self.handle, self.version, parent, - info + info, )]) } @@ -845,17 +746,15 @@ impl CertAuth { pub fn cert_requests(&self, parent_handle: &ParentHandle) -> Vec { let mut res = vec![]; - if let Ok(parent)= self.parent(parent_handle) { + if let Ok(parent) = self.parent(parent_handle) { for (_class_name, rc) in parent.resources.iter() { if let Some(p) = &rc.pending_key { if let Some(r) = p.request() { - res.push( - CertRequested::new( - parent_handle.clone(), - KeyStatus::Pending, - r.clone() - ) - ) + res.push(CertRequested::new( + parent_handle.clone(), + KeyStatus::Pending, + r.clone(), + )) } } } @@ -872,7 +771,7 @@ impl CertAuth { &self, parent_handle: Handle, entitlements: Entitlements, - signer: Arc> + signer: Arc>, ) -> ca::Result> { let mut res = vec![]; @@ -881,7 +780,6 @@ impl CertAuth { // Check if there is a resource class for each entitlement let mut version = self.version; for ent in entitlements.classes() { - let name = ent.class_name(); if let Some(_rc) = parent.resources.get(name) { @@ -895,7 +793,9 @@ impl CertAuth { } else { // Create a resource class with a pending key let key_id = { - signer.write().unwrap() + signer + .write() + .unwrap() .create_key(PublicKeyFormat::default()) .map_err(Error::signer)? }; @@ -907,11 +807,10 @@ impl CertAuth { let csr = { // there must be simpler way to take the one CSR // that must be in the resulting Vec - rc.request_certs( - ent, - &self.base_repo, - &signer - )?.into_iter().next().unwrap() + rc.request_certs(ent, &self.base_repo, &signer)? + .into_iter() + .next() + .unwrap() }; let cert_issue_req = CertRequested::new( @@ -920,8 +819,8 @@ impl CertAuth { IssuanceRequest::new( ent.class_name().to_string(), RequestResourceLimit::default(), - csr - ) + csr, + ), ); let added = EvtDet::resource_class_added( @@ -929,16 +828,12 @@ impl CertAuth { version, parent_handle.clone(), name.to_string(), - rc + rc, ); version += 1; - let req = EvtDet::certificate_requested( - &self.handle, - version, - cert_issue_req - ); + let req = EvtDet::certificate_requested(&self.handle, version, cert_issue_req); version += 1; @@ -949,7 +844,6 @@ impl CertAuth { Ok(res) } - /// This method updates the received certificate for the given parent /// and resource class, and will return an error if either is unknown. /// @@ -967,18 +861,18 @@ impl CertAuth { parent_handle: Handle, class_name: String, rcvd_cert: RcvdCert, - signer: Arc> + signer: Arc>, ) -> ca::Result> { - debug!("CA {}: Updating received cert for {}", self.handle, class_name); + debug!( + "CA {}: Updating received cert for {}", + self.handle, class_name + ); let parent = self.parent(&parent_handle)?; let rc = parent.class(&class_name)?; let mut res = vec![]; - let mut status = rc.match_cert( - &rcvd_cert, - signer.read().unwrap().deref() - )?; + let mut status = rc.match_cert(&rcvd_cert, signer.read().unwrap().deref())?; let handle = &self.handle; let mut version = self.version; @@ -990,7 +884,7 @@ impl CertAuth { &class_name, rcvd_cert.clone(), rc.new_status_for_pending(), - version + version, )? } else { self.update_cert_for_certified_key( @@ -999,29 +893,22 @@ impl CertAuth { &class_name, rcvd_cert.clone(), status, - version + version, ) }; res.push(event); version += 1; - // Get the key that needs publishing and apply the cert to it. let key_to_publish = match status { KeyStatus::Pending => { let (key_id, _req) = rc.pending_key.clone().unwrap().unwrap(); CertifiedKey::new(key_id, rcvd_cert) - }, - KeyStatus::New => { - rc.new_key.clone().unwrap().with_new_cert(rcvd_cert) - }, - KeyStatus::Current => { - rc.current_key.clone().unwrap().with_new_cert(rcvd_cert) - }, - KeyStatus::Revoke => { - rc.revoke_key.clone().unwrap().with_new_cert(rcvd_cert) - }, + } + KeyStatus::New => rc.new_key.clone().unwrap().with_new_cert(rcvd_cert), + KeyStatus::Current => rc.current_key.clone().unwrap().with_new_cert(rcvd_cert), + KeyStatus::Revoke => rc.revoke_key.clone().unwrap().with_new_cert(rcvd_cert), }; // TODO: Check current objects in relation to resources @@ -1045,8 +932,9 @@ impl CertAuth { &key_to_publish, &self.base_repo, &rc.name_space, - delta - ).map_err(Error::signer)? + delta, + ) + .map_err(Error::signer)?, )); Ok(res) @@ -1065,25 +953,25 @@ impl CertAuth { version: u64, ) -> Result { match new_status { - KeyStatus::Pending => - Err(Error::KeyStatusChange(KeyStatus::Pending, - KeyStatus::Pending)), + KeyStatus::Pending => Err(Error::KeyStatusChange( + KeyStatus::Pending, + KeyStatus::Pending, + )), KeyStatus::New => unimplemented!("Issue #23 (key rolls)"), - KeyStatus::Current => { - Ok(EvtDet::pending_activated( - handle, - version, - parent_handle.clone(), - class_name.to_string(), - cert - )) - }, + KeyStatus::Current => Ok(EvtDet::pending_activated( + handle, + version, + parent_handle.clone(), + class_name.to_string(), + cert, + )), - KeyStatus::Revoke => - Err(Error::KeyStatusChange(KeyStatus::Pending, - KeyStatus::Revoke)) + KeyStatus::Revoke => Err(Error::KeyStatusChange( + KeyStatus::Pending, + KeyStatus::Revoke, + )), } } @@ -1101,17 +989,11 @@ impl CertAuth { EvtDet::certificate_received( handle, version, - CertReceived::new( - parent_handle.clone(), - class_name.to_string(), - status, - cert - ) + CertReceived::new(parent_handle.clone(), class_name.to_string(), status, cert), ) } } - //------------ ParentCa ------------------------------------------------------ /// This type defines a parent for a CA and includes the information @@ -1120,7 +1002,7 @@ impl CertAuth { #[derive(Clone, Debug, Deserialize, Serialize)] pub struct ParentCa { contact: ParentCaContact, - resources: HashMap + resources: HashMap, } impl ParentCa { @@ -1135,18 +1017,25 @@ impl ParentCa { } pub fn without_resource(contact: ParentCaContact) -> Self { - ParentCa { contact, resources: HashMap::new() } + ParentCa { + contact, + resources: HashMap::new(), + } } - pub fn contact(&self) -> &ParentCaContact { &self.contact } + pub fn contact(&self) -> &ParentCaContact { + &self.contact + } fn class(&self, class_name: &str) -> Result<&ResourceClass> { - self.resources.get(class_name) + self.resources + .get(class_name) .ok_or_else(|| Error::UnknownResourceClass(class_name.to_string())) } fn class_mut(&mut self, class_name: &str) -> Result<&mut ResourceClass> { - self.resources.get_mut(class_name) + self.resources + .get_mut(class_name) .ok_or_else(|| Error::UnknownResourceClass(class_name.to_string())) } } @@ -1211,7 +1100,7 @@ pub struct ResourceClass { pending_key: Option, new_key: Option, current_key: Option, - revoke_key: Option + revoke_key: Option, } impl ResourceClass { @@ -1223,32 +1112,30 @@ impl ResourceClass { pending_key: Some(pending_key), new_key: None, current_key: None, - revoke_key: None + revoke_key: None, } } - pub fn add_request( - &mut self, - status: KeyStatus, - req: IssuanceRequest - ) { + pub fn add_request(&mut self, status: KeyStatus, req: IssuanceRequest) { match status { KeyStatus::Pending => { self.pending_key.as_mut().unwrap().add_request(req); - }, + } KeyStatus::New => { self.new_key.as_mut().unwrap().add_request(req); - }, + } KeyStatus::Current => { self.current_key.as_mut().unwrap().add_request(req); - }, + } KeyStatus::Revoke => { self.revoke_key.as_mut().unwrap().add_request(req); - }, + } } } - pub fn name_space(&self) -> &str { &self.name_space } + pub fn name_space(&self) -> &str { + &self.name_space + } pub fn new_objects(&self) -> Option<&CurrentObjects> { self.new_key.as_ref().map(|k| k.current_set().objects()) @@ -1270,10 +1157,9 @@ impl ResourceClass { self.pending_key.clone(), self.new_key.clone(), self.current_key.clone(), - self.revoke_key.clone() + self.revoke_key.clone(), ) } - } /// # Request certificates @@ -1285,7 +1171,7 @@ impl ResourceClass { &self, _entitlement: &EntitlementClass, base_repo: &RepoInfo, - signer: &Arc> + signer: &Arc>, ) -> Result> { let mut res = vec![]; let signer = signer.read().map_err(Error::signer)?; @@ -1295,9 +1181,7 @@ impl ResourceClass { res.push(csr) } - if self.new_key.is_some() || - self.current_key.is_some() || - self.revoke_key.is_some() { + if self.new_key.is_some() || self.current_key.is_some() || self.revoke_key.is_some() { // TODO Request updated cert for keys with cert if needed unimplemented!() } @@ -1313,7 +1197,7 @@ impl ResourceClass { &self, base_repo: &RepoInfo, key: &SignerKeyId, - signer: &S + signer: &S, ) -> Result { let pub_key = signer.get_key_info(key).map_err(Error::signer)?; @@ -1322,7 +1206,9 @@ impl ResourceClass { key, &base_repo.ca_repository(&self.name_space), &base_repo.rpki_manifest(&self.name_space, &pub_key.key_identifier()), - Some(&base_repo.rpki_notify())).map_err(Error::signer)?; + Some(&base_repo.rpki_notify()), + ) + .map_err(Error::signer)?; let csr = Csr::decode(enc.as_slice()).map_err(Error::signer)?; @@ -1330,18 +1216,16 @@ impl ResourceClass { } } - /// # Key Life Cycle and Receiving Certificates /// impl ResourceClass { - /// Gets a mutable reference to a certified key of the given status. fn get_key_mut(&mut self, status: KeyStatus) -> Option<&mut CertifiedKey> { match status { KeyStatus::Pending => None, KeyStatus::New => self.new_key.as_mut(), KeyStatus::Current => self.current_key.as_mut(), - KeyStatus::Revoke => self.revoke_key.as_mut() + KeyStatus::Revoke => self.revoke_key.as_mut(), } } @@ -1356,7 +1240,6 @@ impl ResourceClass { self.current_key = Some(certified_key); } - /// Returns the new status for a pending key which receives a RcvdCert. fn new_status_for_pending(&self) -> KeyStatus { if self.current_key.is_some() { @@ -1366,59 +1249,46 @@ impl ResourceClass { } } - /// This function will find the status of the matching key for a received /// certificate. An error is returned if no matching key could be found. - fn match_cert( - &self, - rcvd_cert: &RcvdCert, - signer: &S - ) -> Result { - self.match_key( - rcvd_cert.cert().subject_public_key_info(), - signer - ) + fn match_cert(&self, rcvd_cert: &RcvdCert, signer: &S) -> Result { + self.match_key(rcvd_cert.cert().subject_public_key_info(), signer) } /// Helper to find which of the key_id-s of held keys in different stages /// match the public key, and return that status. Returns an error if /// there is no match. - fn match_key( - &self, - pub_key: &PublicKey, - signer: &S - ) -> ca::Result { - + fn match_key(&self, pub_key: &PublicKey, signer: &S) -> ca::Result { if self.matches_key_id( self.pending_key.as_ref().map(PendingKey::key_id), pub_key, - signer + signer, ) { - return Ok(KeyStatus::Pending) + return Ok(KeyStatus::Pending); } if self.matches_key_id( self.new_key.as_ref().map(CertifiedKey::key_id), pub_key, - signer + signer, ) { - return Ok(KeyStatus::New) + return Ok(KeyStatus::New); } if self.matches_key_id( self.current_key.as_ref().map(CertifiedKey::key_id), pub_key, - signer + signer, ) { - return Ok(KeyStatus::Current) + return Ok(KeyStatus::Current); } if self.matches_key_id( self.revoke_key.as_ref().map(CertifiedKey::key_id), pub_key, - signer + signer, ) { - return Ok(KeyStatus::Revoke) + return Ok(KeyStatus::Revoke); } Err(Error::NoKeyMatch(KeyRef::from(&pub_key.key_identifier()))) @@ -1429,7 +1299,7 @@ impl ResourceClass { &self, key_id: Option<&SignerKeyId>, pub_key: &PublicKey, - signer: &S + signer: &S, ) -> bool { if let Some(id) = key_id { if let Ok(info) = signer.get_key_info(id) { @@ -1443,7 +1313,6 @@ impl ResourceClass { } } - //------------ KeyStatus ----------------------------------------------------- #[derive(Copy, Clone, Debug, Deserialize, Display, Eq, Serialize, PartialEq)] @@ -1451,7 +1320,5 @@ pub enum KeyStatus { Pending, New, Current, - Revoke + Revoke, } - - diff --git a/daemon/src/ca/commands.rs b/daemon/src/ca/commands.rs index 4c926a25..ea0bceaf 100644 --- a/daemon/src/ca/commands.rs +++ b/daemon/src/ca/commands.rs @@ -1,25 +1,17 @@ use std::sync::{Arc, RwLock}; -use krill_commons::api::{Entitlements, IssuanceRequest}; use krill_commons::api::admin::{Handle, ParentCaContact, Token}; use krill_commons::api::ca::{RcvdCert, ResourceSet}; +use krill_commons::api::{Entitlements, IssuanceRequest}; use krill_commons::eventsourcing; use krill_commons::remote::id::IdCert; -use crate::ca::{ - Evt, - Signer, - ChildHandle, - ParentHandle, - ResourceClassName -}; - +use crate::ca::{ChildHandle, Evt, ParentHandle, ResourceClassName, Signer}; //------------ Command ----------------------------------------------------- pub type Cmd = eventsourcing::SentCommand>; - //------------ CommandDetails ---------------------------------------------- #[derive(Clone, Debug)] @@ -27,7 +19,12 @@ pub type Cmd = eventsourcing::SentCommand>; pub enum CmdDet { // Being a parent AddChild(ChildHandle, Token, Option, ResourceSet), - UpdateChild(ChildHandle, Option, Option, Option), + UpdateChild( + ChildHandle, + Option, + Option, + Option, + ), CertifyChild(ChildHandle, IssuanceRequest, Token, Arc>), // Being a child @@ -36,7 +33,7 @@ pub enum CmdDet { UpdateRcvdCert(ParentHandle, ResourceClassName, RcvdCert, Arc>), // General - Republish(Arc>) + Republish(Arc>), } impl eventsourcing::CommandDetails for CmdDet { @@ -44,7 +41,6 @@ impl eventsourcing::CommandDetails for CmdDet { } impl CmdDet { - /// Adds a child to this CA. Will return an error in case you try /// to give the child resources not held by the CA. And until issue /// #25 is implemented, returns an error when the CA is not a TA. @@ -58,33 +54,22 @@ impl CmdDet { eventsourcing::SentCommand::new( handle, None, - CmdDet::AddChild( - child_handle, - child_token, - child_id_cert, - child_resources - ) + CmdDet::AddChild(child_handle, child_token, child_id_cert, child_resources), ) } pub fn update_child_resources( handle: &Handle, child_handle: ChildHandle, - child_resources: ResourceSet + child_resources: ResourceSet, ) -> Cmd { eventsourcing::SentCommand::new( handle, None, - CmdDet::UpdateChild( - child_handle, - None, - None, - Some(child_resources) - ) + CmdDet::UpdateChild(child_handle, None, None, Some(child_resources)), ) } - /// Certify a child. Will return an error in case the child is /// unknown, or in case resources are not held by the child. pub fn certify_child( @@ -92,42 +77,29 @@ impl CmdDet { child_handle: Handle, request: IssuanceRequest, token: Token, - signer: Arc> + signer: Arc>, ) -> Cmd { eventsourcing::SentCommand::new( handle, None, - CmdDet::CertifyChild(child_handle, request, token, signer) + CmdDet::CertifyChild(child_handle, request, token, signer), ) } - - pub fn add_parent( - handle: &Handle, - name: &str, - info: ParentCaContact - ) -> Cmd { - eventsourcing::SentCommand::new( - handle, - None, - CmdDet::AddParent(Handle::from(name), info) - ) + pub fn add_parent(handle: &Handle, name: &str, info: ParentCaContact) -> Cmd { + eventsourcing::SentCommand::new(handle, None, CmdDet::AddParent(Handle::from(name), info)) } pub fn upd_entitlements( handle: &Handle, parent: &ParentHandle, entitlements: Entitlements, - signer: Arc> + signer: Arc>, ) -> Cmd { eventsourcing::SentCommand::new( handle, None, - CmdDet::UpdateEntitlements( - parent.clone(), - entitlements, - signer - ) + CmdDet::UpdateEntitlements(parent.clone(), entitlements, signer), ) } @@ -136,29 +108,16 @@ impl CmdDet { parent: &ParentHandle, class_name: &str, cert: RcvdCert, - signer: Arc> + signer: Arc>, ) -> Cmd { eventsourcing::SentCommand::new( handle, None, - CmdDet::UpdateRcvdCert( - parent.clone(), - class_name.to_string(), - cert, - signer - ) + CmdDet::UpdateRcvdCert(parent.clone(), class_name.to_string(), cert, signer), ) } - - pub fn publish( - handle: &Handle, - signer: Arc> - ) -> Cmd { - eventsourcing::SentCommand::new( - handle, - None, - CmdDet::Republish(signer) - ) + pub fn publish(handle: &Handle, signer: Arc>) -> Cmd { + eventsourcing::SentCommand::new(handle, None, CmdDet::Republish(signer)) } -} \ No newline at end of file +} diff --git a/daemon/src/ca/error.rs b/daemon/src/ca/error.rs index 2c9f29a8..a0a3554d 100644 --- a/daemon/src/ca/error.rs +++ b/daemon/src/ca/error.rs @@ -1,14 +1,14 @@ use std::fmt::Display; -use krill_commons::api::admin::{Handle}; -use krill_commons::api::ca::{KeyRef}; -use krill_commons::eventsourcing::{AggregateStoreError}; +use krill_commons::api::admin::Handle; +use krill_commons::api::ca::KeyRef; +use krill_commons::eventsourcing::AggregateStoreError; use krill_commons::remote::rfc6492; -use crate::ca::signing::{Signer}; -use ca::{KeyStatus}; -use std::{io, fmt}; +use crate::ca::signing::Signer; +use ca::KeyStatus; use krill_commons::util::httpclient; +use std::{fmt, io}; //------------ Error --------------------------------------------------------- @@ -87,13 +87,10 @@ impl Error { pub fn invalid_csr(handle: &Handle, msg: &str) -> Self { Error::InvalidCsr(handle.clone(), msg.to_string()) } - } impl std::error::Error for Error {} - - //------------ Error --------------------------------------------------------- #[derive(Debug, Display)] @@ -136,13 +133,19 @@ impl ServerError { } impl From for ServerError { - fn from(e: io::Error) -> Self { ServerError::IoError(e) } + fn from(e: io::Error) -> Self { + ServerError::IoError(e) + } } impl From for ServerError { - fn from(e: Error) -> Self { ServerError::CertAuth(e) } + fn from(e: Error) -> Self { + ServerError::CertAuth(e) + } } impl From for ServerError { - fn from(e: AggregateStoreError) -> Self { ServerError::AggregateStoreError(e) } -} \ No newline at end of file + fn from(e: AggregateStoreError) -> Self { + ServerError::AggregateStoreError(e) + } +} diff --git a/daemon/src/ca/events.rs b/daemon/src/ca/events.rs index 1110dbba..ee4df4c3 100644 --- a/daemon/src/ca/events.rs +++ b/daemon/src/ca/events.rs @@ -1,34 +1,36 @@ use std::ops::{Deref, DerefMut}; use std::sync::{Arc, RwLock}; -use rpki::cert::{Cert, TbsCert, KeyUsage, Overclaim}; -use rpki::crypto::{PublicKeyFormat}; +use rpki::cert::{Cert, KeyUsage, Overclaim, TbsCert}; +use rpki::crypto::PublicKeyFormat; use rpki::csr::Csr; use rpki::uri; -use rpki::x509::{Serial, Validity, Time}; +use rpki::x509::{Serial, Time, Validity}; -use krill_commons::api::{IssuanceRequest, RequestResourceLimit, IssuanceResponse}; use krill_commons::api::admin::{Handle, ParentCaContact, Token}; -use krill_commons::api::ca::{CertifiedKey, ChildCa, PublicationDelta, RcvdCert, RepoInfo, ResourceSet, TrustAnchorLocator}; +use krill_commons::api::ca::{ + CertifiedKey, ChildCa, PublicationDelta, RcvdCert, RepoInfo, ResourceSet, TrustAnchorLocator, +}; +use krill_commons::api::{IssuanceRequest, IssuanceResponse, RequestResourceLimit}; use krill_commons::eventsourcing::StoredEvent; use crate::ca::signing::Signer; -use ca::{Result, CaType, Error, ParentHandle, ResourceClassName, KeyStatus}; -use ca::{Rfc8183Id, ResourceClass}; - +use ca::{CaType, Error, KeyStatus, ParentHandle, ResourceClassName, Result}; +use ca::{ResourceClass, Rfc8183Id}; //------------ Ini ----------------------------------------------------------- pub type Ini = StoredEvent; - //------------ IniDet -------------------------------------------------------- #[derive(Clone, Debug, Deserialize, Serialize)] pub struct IniDet(Token, Rfc8183Id, RepoInfo, CaType); impl IniDet { - pub fn token(&self) -> &Token { &self.0 } + pub fn token(&self) -> &Token { + &self.0 + } pub fn unwrap(self) -> (Token, Rfc8183Id, RepoInfo, CaType) { (self.0, self.1, self.2, self.3) @@ -40,15 +42,11 @@ impl IniDet { handle: &Handle, token: Token, info: RepoInfo, - signer: Arc> + signer: Arc>, ) -> Result { let mut signer = signer.write().unwrap(); let id = Rfc8183Id::generate(signer.deref_mut())?; - Ok(Ini::new( - handle, - 0, - IniDet(token, id, info, CaType::Child) - )) + Ok(Ini::new(handle, 0, IniDet(token, id, info, CaType::Child))) } pub fn init_ta( @@ -62,7 +60,8 @@ impl IniDet { let id = Rfc8183Id::generate(signer.deref_mut())?; - let key = signer.create_key(PublicKeyFormat::default()) + let key = signer + .create_key(PublicKeyFormat::default()) .map_err(|e| Error::SignerError(e.to_string()))?; let token = Token::random(signer.deref()); @@ -75,7 +74,7 @@ impl IniDet { Ok(Ini::new( handle, 0, - IniDet(token, id, info, CaType::Ta(key, tal)) + IniDet(token, id, info, CaType::Ta(key, tal)), )) } @@ -83,7 +82,7 @@ impl IniDet { repo_info: &RepoInfo, resources: &ResourceSet, key: &S::KeyId, - signer: &S + signer: &S, ) -> Result { let serial: Serial = Serial::random(signer).map_err(Error::signer)?; @@ -97,7 +96,7 @@ impl IniDet { Some(name), pub_key.clone(), KeyUsage::Ca, - Overclaim::Refuse + Overclaim::Refuse, ); cert.set_basic_ca(Some(true)); @@ -110,34 +109,24 @@ impl IniDet { cert.set_v4_resources(Some(resources.v4().deref().clone())); cert.set_v6_resources(Some(resources.v6().deref().clone())); - cert.into_cert( - signer.deref(), - key - ).map_err(Error::signer) + cert.into_cert(signer.deref(), key).map_err(Error::signer) } - - } - //------------ Evt --------------------------------------------------------- pub type Evt = StoredEvent; - //------------ CertIssued --------------------------------------------------- #[derive(Clone, Debug, Deserialize, Serialize)] pub struct CertIssued { child: Handle, - response: IssuanceResponse + response: IssuanceResponse, } impl CertIssued { - pub fn new( - child: Handle, - response: IssuanceResponse - ) -> Self { + pub fn new(child: Handle, response: IssuanceResponse) -> Self { CertIssued { child, response } } pub fn unwrap(self) -> (Handle, IssuanceResponse) { @@ -145,23 +134,22 @@ impl CertIssued { } } - //------------ CertRequested ----------------------------------------------- #[derive(Clone, Debug, Deserialize, Serialize)] pub struct CertRequested { parent: ParentHandle, key_status: KeyStatus, - request: IssuanceRequest + request: IssuanceRequest, } impl CertRequested { - pub fn new( - parent: ParentHandle, - key_status: KeyStatus, - request: IssuanceRequest - ) -> Self { - CertRequested { parent, key_status, request } + pub fn new(parent: ParentHandle, key_status: KeyStatus, request: IssuanceRequest) -> Self { + CertRequested { + parent, + key_status, + request, + } } pub fn unwrap(self) -> (ParentHandle, KeyStatus, IssuanceRequest) { @@ -173,7 +161,9 @@ impl CertRequested { pub fn class_name(&self) -> &str { self.request.class_name() } - pub fn status(&self) -> KeyStatus { self.key_status } + pub fn status(&self) -> KeyStatus { + self.key_status + } pub fn limit(&self) -> &RequestResourceLimit { self.request.limit() } @@ -188,7 +178,6 @@ impl Into for CertRequested { } } - //------------ CertReceived ------------------------------------------------ #[derive(Clone, Debug, Deserialize, Serialize)] @@ -196,7 +185,7 @@ pub struct CertReceived { parent: ParentHandle, class_name: ResourceClassName, key_status: KeyStatus, - cert: RcvdCert + cert: RcvdCert, } impl CertReceived { @@ -204,13 +193,17 @@ impl CertReceived { parent: ParentHandle, class_name: ResourceClassName, key_status: KeyStatus, - cert: RcvdCert + cert: RcvdCert, ) -> Self { - CertReceived { parent, class_name, key_status, cert } + CertReceived { + parent, + class_name, + key_status, + cert, + } } } - //------------ EvtDet ------------------------------------------------------- #[derive(Clone, Debug, Deserialize, Serialize)] @@ -233,38 +226,32 @@ pub enum EvtDet { // Publishing Published(ParentHandle, ResourceClassName, KeyStatus, PublicationDelta), - TaPublished(PublicationDelta) + TaPublished(PublicationDelta), } impl EvtDet { /// This marks a parent as added to the CA. - pub (super) fn parent_added( + pub(super) fn parent_added( handle: &Handle, version: u64, parent_handle: ParentHandle, - info: ParentCaContact + info: ParentCaContact, ) -> Evt { - StoredEvent::new( - handle, - version, - EvtDet::ParentAdded(parent_handle, info) - ) + StoredEvent::new(handle, version, EvtDet::ParentAdded(parent_handle, info)) } /// This marks a resource class as added under a parent for the CA. - pub (super) fn resource_class_added( + pub(super) fn resource_class_added( handle: &Handle, version: u64, parent_handle: ParentHandle, class_name: String, - resource_class: ResourceClass + resource_class: ResourceClass, ) -> Evt { StoredEvent::new( handle, version, - EvtDet::ResourceClassAdded( - parent_handle, class_name, resource_class - ) + EvtDet::ResourceClassAdded(parent_handle, class_name, resource_class), ) } @@ -274,30 +261,26 @@ impl EvtDet { /// then gets a new certificate, it will send a command to the CA with /// the new certificate to mark it as received, and take other /// appropriate actions (key life cycle, publication). - pub (super) fn certificate_requested( + pub(super) fn certificate_requested( handle: &Handle, version: u64, - cert_issue_req: CertRequested + cert_issue_req: CertRequested, ) -> Evt { StoredEvent::new( handle, version, - EvtDet::CertificateRequested(cert_issue_req) + EvtDet::CertificateRequested(cert_issue_req), ) } /// This marks a certificate as received for the key of the given status /// in a given resource class under a parent. - pub (super) fn certificate_received( + pub(super) fn certificate_received( handle: &Handle, version: u64, - received: CertReceived + received: CertReceived, ) -> Evt { - StoredEvent::new( - handle, - version, - EvtDet::CertificateReceived(received) - ) + StoredEvent::new(handle, version, EvtDet::CertificateReceived(received)) } /// This marks the pending key as activated. This occurs when a resource @@ -307,70 +290,50 @@ impl EvtDet { /// Note that key roll management is going to be implemented in the near /// future and then there will also be appropriate events for all the /// stages in a key roll. - pub (super) fn pending_activated( + pub(super) fn pending_activated( handle: &Handle, version: u64, parent: ParentHandle, class_name: ResourceClassName, - received: RcvdCert + received: RcvdCert, ) -> Evt { StoredEvent::new( handle, version, - EvtDet::PendingKeyActivated(parent, class_name, received) + EvtDet::PendingKeyActivated(parent, class_name, received), ) } /// This marks a delta as published for a key under a resource class /// under a parent CA. - pub (super) fn published( + pub(super) fn published( handle: &Handle, version: u64, parent: ParentHandle, class_name: ResourceClassName, key_status: KeyStatus, - delta: PublicationDelta + delta: PublicationDelta, ) -> Evt { StoredEvent::new( handle, version, - EvtDet::Published(parent, class_name, key_status, delta) + EvtDet::Published(parent, class_name, key_status, delta), ) } - pub (super) fn child_added( - handle: &Handle, - version: u64, - child: ChildCa - ) -> Evt { - StoredEvent::new( - handle, - version, - EvtDet::ChildAdded(child) - ) + pub(super) fn child_added(handle: &Handle, version: u64, child: ChildCa) -> Evt { + StoredEvent::new(handle, version, EvtDet::ChildAdded(child)) } - pub (super) fn certificate_issued( + pub(super) fn certificate_issued( handle: &Handle, version: u64, - cert_issued: CertIssued + cert_issued: CertIssued, ) -> Evt { - StoredEvent::new( - handle, - version, - EvtDet::CertificateIssued(cert_issued) - ) + StoredEvent::new(handle, version, EvtDet::CertificateIssued(cert_issued)) } - pub (super) fn published_ta( - handle: &Handle, - version: u64, - delta: PublicationDelta - ) -> Evt { - StoredEvent::new( - handle, - version, - EvtDet::TaPublished(delta) - ) + pub(super) fn published_ta(handle: &Handle, version: u64, delta: PublicationDelta) -> Evt { + StoredEvent::new(handle, version, EvtDet::TaPublished(delta)) } -} \ No newline at end of file +} diff --git a/daemon/src/ca/mod.rs b/daemon/src/ca/mod.rs index 615c4999..64bb1bed 100644 --- a/daemon/src/ca/mod.rs +++ b/daemon/src/ca/mod.rs @@ -3,37 +3,36 @@ use krill_commons::api::admin::Handle; mod certauth; -pub use self::certauth::CertAuth; pub use self::certauth::CaType; -pub use self::certauth::Rfc8183Id; -pub use self::certauth::ResourceClass; +pub use self::certauth::CertAuth; pub use self::certauth::KeyStatus; +pub use self::certauth::ResourceClass; +pub use self::certauth::Rfc8183Id; mod commands; pub use self::commands::Cmd; pub use self::commands::CmdDet; mod events; -pub use self::events::Ini; -pub use self::events::IniDet; +pub use self::events::CertIssued; +pub use self::events::CertReceived; +pub use self::events::CertRequested; pub use self::events::Evt; pub use self::events::EvtDet; -pub use self::events::CertIssued; -pub use self::events::CertRequested; -pub use self::events::CertReceived; +pub use self::events::Ini; +pub use self::events::IniDet; mod server; pub use self::server::CaServer; mod signing; -pub use self::signing::Signer; pub use self::signing::SignSupport; +pub use self::signing::Signer; mod error; pub use self::error::Error; pub use self::error::ServerError; - pub type Result = std::result::Result; pub type ServerResult = std::result::Result>; pub type ParentHandle = Handle; @@ -44,4 +43,4 @@ pub const TA_NAME: &str = "ta"; // reserved for TA pub fn ta_handle() -> Handle { Handle::from(TA_NAME) -} \ No newline at end of file +} diff --git a/daemon/src/ca/server.rs b/daemon/src/ca/server.rs index b0bc1d2e..c61663bd 100644 --- a/daemon/src/ca/server.rs +++ b/daemon/src/ca/server.rs @@ -7,78 +7,45 @@ use bytes::Bytes; use rpki::uri; use krill_commons::api; -use krill_commons::api::{ - DFLT_CLASS, - Entitlements, - IssuanceRequest, - IssuanceResponse -}; use krill_commons::api::admin::{ - AddChildRequest, - AddParentRequest, - ChildAuthRequest, - Handle, - ParentCaContact, - Token, -}; -use krill_commons::api::ca::{ - CertAuthList, - CertAuthSummary, - IssuedCert, - RcvdCert, - RepoInfo, -}; -use krill_commons::eventsourcing::{ - Aggregate, - AggregateStore, - DiskAggregateStore + AddChildRequest, AddParentRequest, ChildAuthRequest, Handle, ParentCaContact, Token, }; +use krill_commons::api::ca::{CertAuthList, CertAuthSummary, IssuedCert, RcvdCert, RepoInfo}; +use krill_commons::api::{Entitlements, IssuanceRequest, IssuanceResponse, DFLT_CLASS}; +use krill_commons::eventsourcing::{Aggregate, AggregateStore, DiskAggregateStore}; use krill_commons::remote::builder::SignedMessageBuilder; -use krill_commons::remote::{rfc8183, rfc6492}; use krill_commons::remote::sigmsg::SignedMessage; +use krill_commons::remote::{rfc6492, rfc8183}; use krill_commons::util::httpclient; use krill_commons::util::softsigner::SignerKeyId; -use crate::ca::{ - self, - CmdDet, - IniDet, - Signer, - CertAuth, - ParentHandle, - ServerResult, - ServerError, -}; +use crate::ca::{self, CertAuth, CmdDet, IniDet, ParentHandle, ServerError, ServerResult, Signer}; use crate::mq::EventQueueListener; - const CA_NS: &str = "cas"; - //------------ CaServer ------------------------------------------------------ #[derive(Clone)] pub struct CaServer { signer: Arc>, - ca_store: Arc>> + ca_store: Arc>>, } - impl CaServer { - /// Builds a new CaServer. Will return an error if the TA store cannot be /// initialised. pub fn build( work_dir: &PathBuf, events_queue: Arc, - signer: S + signer: S, ) -> ServerResult { let mut ca_store = DiskAggregateStore::>::new(work_dir, CA_NS)?; ca_store.add_listener(events_queue); Ok(CaServer { signer: Arc::new(RwLock::new(signer)), - ca_store: Arc::new(ca_store) + ca_store: Arc::new(ca_store), }) } @@ -94,19 +61,13 @@ impl CaServer { &self, info: RepoInfo, ta_aia: uri::Rsync, - ta_uris: Vec + ta_uris: Vec, ) -> ServerResult<(), S> { let handle = ca::ta_handle(); if self.ca_store.has(&handle) { Err(ServerError::TrustAnchorInitialisedError) } else { - let init = IniDet::init_ta( - &handle, - info, - ta_aia, - ta_uris, - self.signer.clone() - )?; + let init = IniDet::init_ta(&handle, info, ta_aia, ta_uris, self.signer.clone())?; self.ca_store.add(init)?; @@ -125,19 +86,15 @@ impl CaServer { Ok(()) } - /// Republish a CA, this is a no-op when there is nothing to publish. pub fn republish(&self, handle: &Handle) -> ServerResult<(), S> { debug!("Republish CA: {}", handle); let ca = self.ca_store.get_latest(handle)?; - let cmd = CmdDet::publish( - handle, - self.signer.clone() - ); + let cmd = CmdDet::publish(handle, self.signer.clone()); let events = ca.process_command(cmd)?; - if ! events.is_empty() { + if !events.is_empty() { self.ca_store.update(handle, ca, events)?; } @@ -148,7 +105,7 @@ impl CaServer { pub fn ta_add_child( &self, req: AddChildRequest, - service_uri: &uri::Https + service_uri: &uri::Https, ) -> ServerResult { let (handle, resources, auth) = req.unwrap(); @@ -160,21 +117,16 @@ impl CaServer { let token = match &auth { ChildAuthRequest::Embedded(token) => token.clone(), ChildAuthRequest::Remote(token) => token.clone(), - ChildAuthRequest::Rfc8183(_) => self.random_token() + ChildAuthRequest::Rfc8183(_) => self.random_token(), }; let id_cert = match &auth { ChildAuthRequest::Embedded(_) | ChildAuthRequest::Remote(_) => None, - ChildAuthRequest::Rfc8183(req) => Some(req.id_cert().clone()) + ChildAuthRequest::Rfc8183(req) => Some(req.id_cert().clone()), }; - let add_child = CmdDet::::add_child( - &ta_handle, - handle.clone(), - token, - id_cert, - resources - ); + let add_child = + CmdDet::::add_child(&ta_handle, handle.clone(), token, id_cert, resources); let events = ta.process_command(add_child)?; let ta = self.ca_store.update(&ta_handle, ta, events)?; @@ -182,17 +134,10 @@ impl CaServer { match auth { ChildAuthRequest::Embedded(token) => { Ok(ParentCaContact::for_embedded(ta_handle, token)) - }, - ChildAuthRequest::Remote(_token) => { - unimplemented!() - }, + } + ChildAuthRequest::Remote(_token) => unimplemented!(), ChildAuthRequest::Rfc8183(req) => { - - let service_uri = format!( - "{}rfc6492/{}", - service_uri.to_string(), - ta.handle() - ); + let service_uri = format!("{}rfc6492/{}", service_uri.to_string(), ta.handle()); let service_uri = uri::Https::from_string(service_uri).unwrap(); let service_uri = rfc8183::ServiceUri::Https(service_uri); @@ -201,7 +146,7 @@ impl CaServer { ta.id_cert().clone(), ta.handle().clone(), handle, - service_uri + service_uri, ); Ok(ParentCaContact::for_rfc6492(response)) } @@ -217,20 +162,16 @@ impl CaServer { /// # CA support /// impl CaServer { - pub fn get_ca(&self, handle: &Handle) -> ServerResult>, S> { - self.ca_store.get_latest(handle) + self.ca_store + .get_latest(handle) .map_err(|_| ServerError::UnknownCa(handle.to_string())) } /// Verifies an RFC6492 message and returns the child handle, token, /// and content of the request, so that the simple 'list' and 'issue' /// functions can be called. - pub fn rfc6492( - &self, - parent_handle: &Handle, - msg: SignedMessage - ) -> ServerResult { + pub fn rfc6492(&self, parent_handle: &Handle, msg: SignedMessage) -> ServerResult { info!("RFC6492 Request: will check"); let (content, token) = { let parent = self.ca_store.get_latest(parent_handle)?; @@ -244,53 +185,35 @@ impl CaServer { match content { rfc6492::Content::Qry(rfc6492::Qry::Revoke(_)) => { unimplemented!("Revocation not yet supported") - }, + } rfc6492::Content::Qry(rfc6492::Qry::List) => { - let entitlements = self.list( - parent_handle, - &sender_handle, - &token - )?; + let entitlements = self.list(parent_handle, &sender_handle, &token)?; - let msg = rfc6492::Message::list_response( - sender, - recipient, - entitlements - ); + let msg = rfc6492::Message::list_response(sender, recipient, entitlements); self.wrap_rfc6492_response(parent_handle, msg) - }, + } rfc6492::Content::Qry(rfc6492::Qry::Issue(req)) => { - let res = self.issue( - parent_handle, - &sender_handle, - req, - token - )?; + let res = self.issue(parent_handle, &sender_handle, req, token)?; - let msg = rfc6492::Message::issue_response( - sender, - recipient, - res - ); + let msg = rfc6492::Message::issue_response(sender, recipient, res); self.wrap_rfc6492_response(parent_handle, msg) - }, - _ => Err(ServerError::custom("Unsupported RFC6492 message")) + } + _ => Err(ServerError::custom("Unsupported RFC6492 message")), } } fn wrap_rfc6492_response( &self, handle: &Handle, - msg: rfc6492::Message + msg: rfc6492::Message, ) -> ServerResult { debug!("RFC6492 Response wrapping for {}", handle); let ca = self.ca_store.get_latest(handle)?; - let res = ca.sign_rfc6492_response( - msg, - self.signer.read().unwrap().deref() - ).map_err(ServerError::::CertAuth); + let res = ca + .sign_rfc6492_response(msg, self.signer.read().unwrap().deref()) + .map_err(ServerError::::CertAuth); debug!("RFC6492 Response wrapped for {}", handle); res } @@ -300,9 +223,9 @@ impl CaServer { &self, parent: &Handle, child: &Handle, - token: &Token + token: &Token, ) -> ServerResult { - if parent != & ca::ta_handle() { + if parent != &ca::ta_handle() { unimplemented!("https://github.com/NLnetLabs/krill/issues/25"); } else { let ta = self.get_trust_anchor()?; @@ -320,7 +243,7 @@ impl CaServer { issue_req: IssuanceRequest, token: Token, ) -> ServerResult { - if parent != & ca::ta_handle() { + if parent != &ca::ta_handle() { unimplemented!("https://github.com/NLnetLabs/krill/issues/25"); } else { let ta = self.get_trust_anchor()?; @@ -337,7 +260,7 @@ impl CaServer { child.clone(), issue_req.clone(), token.clone(), - self.signer.clone() + self.signer.clone(), ); let events = ta.process_command(cmd)?; @@ -345,12 +268,7 @@ impl CaServer { // New entitlements will include this resource class, and // the newly issued certificate. - let response = ta.issuance_response( - child, - &class_name, - &pub_key, - &token - )?; + let response = ta.issuance_response(child, &class_name, &pub_key, &token)?; Ok(response) } @@ -359,9 +277,11 @@ impl CaServer { /// Get the current CAs pub fn cas(&self) -> CertAuthList { CertAuthList::new( - self.ca_store.list().into_iter() + self.ca_store + .list() + .into_iter() .map(CertAuthSummary::new) - .collect() + .collect(), ) } @@ -382,19 +302,11 @@ impl CaServer { } /// Adds a parent to a ca - pub fn ca_add_parent( - &self, - handle: Handle, - parent: AddParentRequest - ) -> ServerResult<(), S> { + pub fn ca_add_parent(&self, handle: Handle, parent: AddParentRequest) -> ServerResult<(), S> { let ca = self.get_ca(&handle)?; let (parent_handle, parent_contact) = parent.unwrap(); - let add = CmdDet::add_parent( - &handle, - parent_handle.as_str(), - parent_contact - ); + let add = CmdDet::add_parent(&handle, parent_handle.as_str(), parent_contact); let events = ca.process_command(add)?; self.ca_store.update(&handle, ca, events)?; @@ -406,12 +318,12 @@ impl CaServer { &self, handle: &Handle, parent: &ParentHandle, - contact: ParentCaContact + contact: ParentCaContact, ) -> ServerResult<(), S> { let entitlements = self.get_entitlements_from_parent(handle, &contact)?; - if ! self.update_if_need(handle, parent, entitlements)? { - return Ok(()) // Nothing to do + if !self.update_if_need(handle, parent, entitlements)? { + return Ok(()); // Nothing to do } self.send_requests(handle, parent, &contact) @@ -421,25 +333,22 @@ impl CaServer { &self, handle: &Handle, parent: &ParentHandle, - contact: &ParentCaContact + contact: &ParentCaContact, ) -> ServerResult<(), S> { match contact { ParentCaContact::Embedded(_p, token) => { self.send_requests_embedded(handle, parent, token) - }, - ParentCaContact::Rfc6492(res) => { - self.send_requests_rfc6492(handle, parent, res) } - _ => unimplemented!() + ParentCaContact::Rfc6492(res) => self.send_requests_rfc6492(handle, parent, res), + _ => unimplemented!(), } - } fn send_requests_embedded( &self, handle: &Handle, parent_h: &ParentHandle, - token: &Token + token: &Token, ) -> ServerResult<(), S> { let mut child = self.ca_store.get_latest(handle)?; let requests = child.cert_requests(parent_h); @@ -449,7 +358,7 @@ impl CaServer { let mut issued_certs: Vec<(String, IssuedCert)> = vec![]; for req in requests.into_iter() { - let (_,_, issuance_req) = req.unwrap(); + let (_, _, issuance_req) = req.unwrap(); let class_name = issuance_req.class_name().to_string(); let pub_key = issuance_req.csr().public_key().clone(); @@ -459,20 +368,15 @@ impl CaServer { handle.clone(), issuance_req, token.clone(), - self.signer.clone() + self.signer.clone(), ); let events = parent.process_command(cmd)?; parent = self.ca_store.update(parent_h, parent, events)?; - let response = parent.issuance_response( - handle, - &class_name, - &pub_key, - &token - )?; + let response = parent.issuance_response(handle, &class_name, &pub_key, &token)?; - let (_,_,_, issued) = response.unwrap(); + let (_, _, _, issued) = response.unwrap(); issued_certs.push((class_name, issued)); } @@ -485,7 +389,7 @@ impl CaServer { parent_h, &class_name, received, - self.signer.clone() + self.signer.clone(), ); let evts = child.process_command(upd_rcvd_cmd)?; @@ -499,7 +403,7 @@ impl CaServer { &self, handle: &Handle, parent_h: &ParentHandle, - parent_res: &rfc8183::ParentResponse + parent_res: &rfc8183::ParentResponse, ) -> ServerResult<(), S> { let mut child = self.ca_store.get_latest(handle)?; let requests = child.cert_requests(parent_h); @@ -507,19 +411,19 @@ impl CaServer { for req in requests.into_iter() { let sender = parent_res.child_handle().to_string(); let recipient = parent_res.parent_handle().to_string(); - let (_,_, issuance_req) = req.unwrap(); + let (_, _, issuance_req) = req.unwrap(); let issue = rfc6492::Message::issue(sender, recipient, issuance_req); let res = self.send_rfc6492_and_validate_response( child.id_key(), parent_res, - issue.into_bytes() + issue.into_bytes(), )?; match res { rfc6492::Res::Error(_) => unimplemented!("Deal with error"), rfc6492::Res::Issue(issue_response) => { - let (class_name,_,_, issued) = issue_response.unwrap(); + let (class_name, _, _, issued) = issue_response.unwrap(); let received = RcvdCert::from(issued); let update_rcvd_cmd = CmdDet::upd_received_cert( @@ -527,15 +431,13 @@ impl CaServer { parent_h, &class_name, received, - self.signer.clone() + self.signer.clone(), ); let events = child.process_command(update_rcvd_cmd)?; child = self.ca_store.update(handle, child, events)?; - }, - _ => { - return Err(ServerError::custom("Got unexpected response to list query")) } + _ => return Err(ServerError::custom("Got unexpected response to list query")), } } @@ -550,19 +452,15 @@ impl CaServer { &self, handle: &Handle, parent: &ParentHandle, - entitlements: Entitlements + entitlements: Entitlements, ) -> ServerResult { let child = self.ca_store.get_latest(handle)?; - let update_entitlements_command = CmdDet::upd_entitlements( - handle, - parent, - entitlements, - self.signer.clone() - ); + let update_entitlements_command = + CmdDet::upd_entitlements(handle, parent, entitlements, self.signer.clone()); let events = child.process_command(update_entitlements_command)?; - if ! events.is_empty() { + if !events.is_empty() { self.ca_store.update(handle, child, events)?; Ok(true) } else { @@ -573,16 +471,14 @@ impl CaServer { fn get_entitlements_from_parent( &self, handle: &Handle, - contact: &ParentCaContact + contact: &ParentCaContact, ) -> ServerResult { match contact { ParentCaContact::Embedded(parent, token) => { self.get_entitlements_embedded(handle, parent, token) - }, - ParentCaContact::Rfc6492(res) => { - self.get_entitlements_rfc6492(handle, res) } - _ => unimplemented!() + ParentCaContact::Rfc6492(res) => self.get_entitlements_rfc6492(handle, res), + _ => unimplemented!(), } } @@ -590,7 +486,7 @@ impl CaServer { &self, handle: &Handle, parent: &ParentHandle, - token: &Token + token: &Token, ) -> ServerResult { let parent = self.ca_store.get_latest(parent)?; @@ -600,7 +496,7 @@ impl CaServer { fn get_entitlements_rfc6492( &self, handle: &Handle, - parent_res: &rfc8183::ParentResponse + parent_res: &rfc8183::ParentResponse, ) -> ServerResult { let child = self.ca_store.get_latest(handle)?; @@ -609,16 +505,13 @@ impl CaServer { let recipient = parent_res.parent_handle().to_string(); let list = rfc6492::Message::list(sender, recipient); - let response = self.send_rfc6492_and_validate_response( - child.id_key(), - parent_res, - list.into_bytes() - )?; + let response = + self.send_rfc6492_and_validate_response(child.id_key(), parent_res, list.into_bytes())?; match response { rfc6492::Res::Error(_) => unimplemented!("Deal with error response"), rfc6492::Res::List(ent) => Ok(ent), - _ => Err(ServerError::custom("Got unexpected response to list query")) + _ => Err(ServerError::custom("Got unexpected response to list query")), } } @@ -626,44 +519,39 @@ impl CaServer { &self, signing_key: &SignerKeyId, parent_res: &rfc8183::ParentResponse, - msg: Bytes - ) -> ServerResult{ + msg: Bytes, + ) -> ServerResult { // wrap it up and sign it - let signed = { - SignedMessageBuilder::create( - signing_key, - self.signer.read().unwrap().deref(), - msg - ) - }.map_err(ServerError::custom)?; - + let signed = + { SignedMessageBuilder::create(signing_key, self.signer.read().unwrap().deref(), msg) } + .map_err(ServerError::custom)?; // send to the server let uri = parent_res.service_uri().to_string(); - debug!("Sending to parent: {}\n{}", - &uri, - base64::encode(&signed.as_bytes()) + debug!( + "Sending to parent: {}\n{}", + &uri, + base64::encode(&signed.as_bytes()) ); - let res = httpclient::post_binary( - &uri, - &signed.as_bytes(), - rfc6492::CONTENT_TYPE - ).map_err(ServerError::HttpClientError)?; + let res = httpclient::post_binary(&uri, &signed.as_bytes(), rfc6492::CONTENT_TYPE) + .map_err(ServerError::HttpClientError)?; // unpack and validate response - let msg = match SignedMessage::decode(res.as_ref(), false) - .map_err(ServerError::custom) { + let msg = match SignedMessage::decode(res.as_ref(), false).map_err(ServerError::custom) { Ok(msg) => msg, Err(e) => { error!("Could not parse response: {}", base64::encode(res.as_ref())); - return Err(e) + return Err(e); } }; if let Err(e) = msg.validate(parent_res.id_cert()) { - error!("Could not validate response: {}", base64::encode(res.as_ref())); - return Err(ServerError::custom(e)) + error!( + "Could not validate response: {}", + base64::encode(res.as_ref()) + ); + return Err(ServerError::custom(e)); } rfc6492::Message::from_signed_message(&msg) @@ -673,15 +561,6 @@ impl CaServer { } } - - - - - - - - - //------------ Tests --------------------------------------------------------- #[cfg(test)] @@ -692,31 +571,14 @@ mod tests { use std::path::PathBuf; use std::sync::{Arc, RwLock}; - use krill_commons::api::{DFLT_CLASS, IssuanceRequest}; - use krill_commons::api::admin::{ - Handle, - Token, - ParentCaContact - }; - use krill_commons::api::ca::{ - RepoInfo, - ResourceSet, - RcvdCert - }; - use krill_commons::eventsourcing::{ - Aggregate, - AggregateStore, - DiskAggregateStore - }; + use ca::EvtDet; + use krill_commons::api::admin::{Handle, ParentCaContact, Token}; + use krill_commons::api::ca::{RcvdCert, RepoInfo, ResourceSet}; + use krill_commons::api::{IssuanceRequest, DFLT_CLASS}; + use krill_commons::eventsourcing::{Aggregate, AggregateStore, DiskAggregateStore}; use krill_commons::util::softsigner::OpenSslSigner; use krill_commons::util::test; - use krill_commons::util::test::{ - sub_dir, - https, - rsync, - test_under_tmp, - }; - use ca::EvtDet; + use krill_commons::util::test::{https, rsync, sub_dir, test_under_tmp}; fn signer(temp_dir: &PathBuf) -> OpenSslSigner { let signer_dir = sub_dir(temp_dir); @@ -730,11 +592,7 @@ mod tests { let event_queue = Arc::new(EventQueueListener::in_mem()); - let server = CaServer::::build( - &d, - event_queue, - signer - ).unwrap(); + let server = CaServer::::build(&d, event_queue, signer).unwrap(); let repo_info = { let base_uri = test::rsync("rsync://localhost/repo/ta/"); @@ -747,20 +605,18 @@ mod tests { assert!(server.get_trust_anchor().is_err()); - server.init_ta(repo_info.clone(), ta_aia, vec![ta_uri]).unwrap(); + server + .init_ta(repo_info.clone(), ta_aia, vec![ta_uri]) + .unwrap(); assert!(server.get_trust_anchor().is_ok()); }) } - - #[test] fn init_ta() { test_under_tmp(|d| { - let ca_store = DiskAggregateStore::>::new( - &d, CA_NS - ).unwrap(); + let ca_store = DiskAggregateStore::>::new(&d, CA_NS).unwrap(); let ta_repo_info = { let base_uri = rsync("rsync://localhost/repo/ta/"); @@ -770,7 +626,6 @@ mod tests { let ta_handle = ca::ta_handle(); - let ta_uri = https("https://localhost/tal/ta.cer"); let ta_aia = rsync("rsync://localhost/repo/ta.cer"); @@ -786,9 +641,9 @@ mod tests { ta_repo_info, ta_aia, vec![ta_uri], - - signer.clone() - ).unwrap(); + signer.clone(), + ) + .unwrap(); ca_store.add(ta_ini).unwrap(); let ta = ca_store.get_latest(&ta_handle).unwrap(); @@ -813,8 +668,9 @@ mod tests { &child_handle, child_token.clone(), ca_repo_info, - signer.clone() - ).unwrap(); + signer.clone(), + ) + .unwrap(); ca_store.add(ca_ini).unwrap(); let child = ca_store.get_latest(&child_handle).unwrap(); @@ -831,7 +687,7 @@ mod tests { child_handle.clone(), child_token.clone(), None, - child_rs + child_rs, ); let events = ta.process_command(cmd).unwrap(); @@ -844,16 +700,9 @@ mod tests { // - Parent added // - let parent = ParentCaContact::for_embedded( - ta_handle.clone(), - child_token.clone() - ); + let parent = ParentCaContact::for_embedded(ta_handle.clone(), child_token.clone()); - let add_parent = CmdDet::add_parent( - &child_handle, - ta_handle.as_str(), - parent - ); + let add_parent = CmdDet::add_parent(&child_handle, ta_handle.as_str(), parent); let events = child.process_command(add_parent).unwrap(); let child = ca_store.update(&child_handle, child, events).unwrap(); @@ -869,12 +718,8 @@ mod tests { let entitlements = ta.list(&child_handle, &child_token).unwrap(); - let upd_ent = CmdDet::upd_entitlements( - &child_handle, - &ta_handle, - entitlements, - signer.clone() - ); + let upd_ent = + CmdDet::upd_entitlements(&child_handle, &ta_handle, entitlements, signer.clone()); let events = child.process_command(upd_ent).unwrap(); assert_eq!(2, events.len()); // rc and csr @@ -883,7 +728,7 @@ mod tests { let req = match req_evt { EvtDet::CertificateRequested(req) => req, - _ => panic!("Expected Csr") + _ => panic!("Expected Csr"), }; let (_handle, _key_status, issuance_req) = req.unwrap(); @@ -899,16 +744,14 @@ mod tests { // - Publication // - let request = IssuanceRequest::new( - DFLT_CLASS.to_string(), limit, csr - ); + let request = IssuanceRequest::new(DFLT_CLASS.to_string(), limit, csr); let ta_cmd = CmdDet::certify_child( &ta_handle, child_handle.clone(), request, child_token.clone(), - signer.clone() + signer.clone(), ); let ta_events = ta.process_command(ta_cmd).unwrap(); @@ -917,7 +760,7 @@ mod tests { let issued = match issued_evt { EvtDet::CertificateIssued(issued) => issued, - _ => panic!("Expected issued certificate.") + _ => panic!("Expected issued certificate."), }; let (handle, issuance_res) = issued.unwrap(); @@ -937,11 +780,15 @@ mod tests { let rcvd_cert = RcvdCert::from(issued); let upd_rcvd = CmdDet::upd_received_cert( - &child_handle, &ta_handle, DFLT_CLASS, rcvd_cert, signer.clone() + &child_handle, + &ta_handle, + DFLT_CLASS, + rcvd_cert, + signer.clone(), ); let events = child.process_command(upd_rcvd).unwrap(); let _child = ca_store.update(&child_handle, child, events).unwrap(); }) } -} \ No newline at end of file +} diff --git a/daemon/src/ca/signing.rs b/daemon/src/ca/signing.rs index 3bf5ecd8..7b60614a 100644 --- a/daemon/src/ca/signing.rs +++ b/daemon/src/ca/signing.rs @@ -8,32 +8,37 @@ use bytes::Bytes; use serde::Serialize; use rpki::crl::{Crl, TbsCertList}; -use rpki::crypto::{self, DigestAlgorithm, KeyIdentifier, SigningError}; use rpki::crypto::signer::KeyError; -use rpki::manifest::{Manifest, ManifestContent, FileAndHash}; +use rpki::crypto::{self, DigestAlgorithm, KeyIdentifier, SigningError}; +use rpki::manifest::{FileAndHash, Manifest, ManifestContent}; use rpki::sigobj::SignedObjectBuilder; use rpki::x509::{Serial, Time, Validity}; use krill_commons::api::ca::{ - AddedObject, - CertifiedKey, - CurrentObject, - ObjectsDelta, - PublicationDelta, - RepoInfo, - Revocation, - RevocationsDelta, - UpdatedObject, + AddedObject, CertifiedKey, CurrentObject, ObjectsDelta, PublicationDelta, RepoInfo, Revocation, + RevocationsDelta, UpdatedObject, }; use krill_commons::util::softsigner::SignerKeyId; - //------------ Signer -------------------------------------------------------- -pub trait Signer: crypto::Signer + Clone + Debug + Serialize + Sized + Sync + Send +'static {} -impl + Clone + Debug + Serialize + Sized + Sync + Send + 'static > Signer for T {} - +pub trait Signer: + crypto::Signer + Clone + Debug + Serialize + Sized + Sync + Send + 'static +{ +} +impl< + T: crypto::Signer + + Clone + + Debug + + Serialize + + Sized + + Sync + + Send + + 'static, + > Signer for T +{ +} //------------ CaSignSupport ------------------------------------------------- @@ -41,7 +46,6 @@ impl + Clone + Debug + Serialize + Sized + pub struct SignSupport; impl SignSupport { - /// Publish for the given Key and repository. /// /// Any updates for existing objects will result in Update, rather @@ -52,13 +56,14 @@ impl SignSupport { ca_key: &CertifiedKey, repo_info: &RepoInfo, name_space: &str, - mut objects_delta: ObjectsDelta + mut objects_delta: ObjectsDelta, ) -> Result> { - let aia = ca_key.incoming_cert().uri(); let key_id = ca_key.key_id(); - let pub_key = signer.read().unwrap() + let pub_key = signer + .read() + .unwrap() .get_key_info(key_id) .map_err(SignError::KeyError)?; @@ -105,20 +110,18 @@ impl SignSupport { tomorrow, revocations.to_crl_entries(), aki, - serial_number + serial_number, ); - crl.into_crl( - signer.read().unwrap().deref(), - key_id - ).map_err(SignError::SigningError)? + crl.into_crl(signer.read().unwrap().deref(), key_id) + .map_err(SignError::SigningError)? }; match current_objects.insert(crl_name.clone(), CurrentObject::from(&crl)) { None => { let added = AddedObject::new(crl_name, CurrentObject::from(&crl)); objects_delta.add(added); - }, + } Some(old_crl) => { let hash = old_crl.content().to_encoded_hash(); let updated = UpdatedObject::new(crl_name, CurrentObject::from(&crl), hash); @@ -132,29 +135,30 @@ impl SignSupport { now, tomorrow, DigestAlgorithm::default(), - current_objects.mft_entries().iter() + current_objects.mft_entries().iter(), ); - mft_content.into_manifest( - SignedObjectBuilder::new( - Serial::random( - signer.read().unwrap().deref() - ).map_err(SignError::SignerError)?, - Validity::new(now, next_week), - crl_uri, - aia.clone(), - mft_uri.clone() - ), - signer.read().unwrap().deref(), - key_id, - ).map_err(SignError::SigningError)? + mft_content + .into_manifest( + SignedObjectBuilder::new( + Serial::random(signer.read().unwrap().deref()) + .map_err(SignError::SignerError)?, + Validity::new(now, next_week), + crl_uri, + aia.clone(), + mft_uri.clone(), + ), + signer.read().unwrap().deref(), + key_id, + ) + .map_err(SignError::SigningError)? }; match old_mft { None => { let added = AddedObject::new(mft_name, CurrentObject::from(&mft)); objects_delta.add(added); - }, + } Some(old_mft) => { let hash = old_mft.content().to_encoded_hash(); let updated = UpdatedObject::new(mft_name, CurrentObject::from(&mft), hash); @@ -167,7 +171,7 @@ impl SignSupport { tomorrow, number, revocations_delta, - objects_delta + objects_delta, )) } } @@ -176,15 +180,13 @@ trait ManifestEntry { fn mft_bytes(&self) -> Bytes; fn mft_hash(&self) -> Bytes { Bytes::from( - DigestAlgorithm::default().digest( - self.mft_bytes().as_ref()).as_ref() + DigestAlgorithm::default() + .digest(self.mft_bytes().as_ref()) + .as_ref(), ) } fn mft_entry(&self, name: &str) -> FileAndHash { - FileAndHash::new( - Bytes::from(name), - self.mft_hash() - ) + FileAndHash::new(Bytes::from(name), self.mft_hash()) } } @@ -194,7 +196,6 @@ impl ManifestEntry for Crl { } } - //------------ SignError ----------------------------------------------------- #[derive(Debug, Display)] diff --git a/daemon/src/config.rs b/daemon/src/config.rs index 8eb7ea90..61d596ac 100644 --- a/daemon/src/config.rs +++ b/daemon/src/config.rs @@ -1,19 +1,19 @@ +use crate::http::ssl; +use clap::{App, Arg}; +use krill_commons::api::admin::Token; +use krill_commons::util::ext_serde; +use log::LevelFilter; +use rpki::uri; +use serde::de; +use serde::{Deserialize, Deserializer}; use std::fs::File; use std::io; use std::io::Read; use std::net::{IpAddr, Ipv4Addr, SocketAddr}; use std::path::PathBuf; use std::str::FromStr; -use clap::{App, Arg}; -use log::LevelFilter; -use rpki::uri; use syslog::Facility; -use serde::de; -use serde::{Deserialize, Deserializer}; use toml; -use krill_commons::util::ext_serde; -use crate::http::ssl; -use krill_commons::api::admin::Token; const SERVER_NAME: &str = "Krill"; @@ -22,20 +22,36 @@ const SERVER_NAME: &str = "Krill"; pub struct ConfigDefaults; impl ConfigDefaults { - fn ip() -> IpAddr { IpAddr::V4(Ipv4Addr::new(127,0,0,1))} - fn port() -> u16 { 3000 } - fn use_ssl() -> SslChoice { SslChoice::Test } - fn data_dir() -> PathBuf { PathBuf::from("./data")} + fn ip() -> IpAddr { + IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)) + } + fn port() -> u16 { + 3000 + } + fn use_ssl() -> SslChoice { + SslChoice::Test + } + fn data_dir() -> PathBuf { + PathBuf::from("./data") + } fn rsync_base() -> uri::Rsync { uri::Rsync::from_str("rsync://localhost/repo/").unwrap() } fn rrdp_base_uri() -> uri::Https { uri::Https::from_str("https://localhost:3000/rrdp/").unwrap() } - fn log_level() -> LevelFilter { LevelFilter::Info } - fn log_type() -> LogType { LogType::Stderr } - fn syslog_facility() -> Facility { Facility::LOG_DAEMON } - fn log_file() -> PathBuf { PathBuf::from("./krill.log")} + fn log_level() -> LevelFilter { + LevelFilter::Info + } + fn log_type() -> LogType { + LogType::Stderr + } + fn syslog_facility() -> Facility { + Facility::LOG_DAEMON + } + fn log_file() -> PathBuf { + PathBuf::from("./krill.log") + } fn auth_token() -> Token { use std::env; @@ -45,12 +61,10 @@ impl ConfigDefaults { eprintln!("You MUST provide a value for the master API key, either by setting \"auth_token\" in the config file, or by setting the KRILL_AUTH_TOKEN environment variable."); ::std::process::exit(1); } - } } } - //------------ Config -------------------------------------------------------- /// Global configuration for the Krill Server. @@ -60,27 +74,22 @@ impl ConfigDefaults { /// to override any of the settings in the config file. #[derive(Debug, Deserialize)] pub struct Config { - - #[serde(default="ConfigDefaults::ip")] + #[serde(default = "ConfigDefaults::ip")] ip: IpAddr, - #[serde(default="ConfigDefaults::port")] + #[serde(default = "ConfigDefaults::port")] port: u16, - #[serde(default="ConfigDefaults::use_ssl")] + #[serde(default = "ConfigDefaults::use_ssl")] use_ssl: SslChoice, - #[serde(default="ConfigDefaults::data_dir")] + #[serde(default = "ConfigDefaults::data_dir")] pub data_dir: PathBuf, - #[serde( - default = "ConfigDefaults::rsync_base", - )] + #[serde(default = "ConfigDefaults::rsync_base")] pub rsync_base: uri::Rsync, - #[serde( - default = "ConfigDefaults::rrdp_base_uri", - )] + #[serde(default = "ConfigDefaults::rrdp_base_uri")] pub rrdp_base_uri: uri::Https, #[serde( @@ -102,7 +111,7 @@ pub struct Config { log_file: PathBuf, #[serde(default = "ConfigDefaults::auth_token")] - pub auth_token: Token + pub auth_token: Token, } /// # Accessors @@ -151,16 +160,14 @@ impl Config { /// # Create impl Config { - pub fn test( - data_dir: &PathBuf, - ) -> Self { + pub fn test(data_dir: &PathBuf) -> Self { let ip = ConfigDefaults::ip(); let port = ConfigDefaults::port(); let use_ssl = SslChoice::Test; let data_dir = data_dir.clone(); let rsync_base = ConfigDefaults::rsync_base(); let rrdp_base_uri = ConfigDefaults::rrdp_base_uri(); - let log_level = LevelFilter::Info; + let log_level = LevelFilter::Info; let log_type = LogType::Stderr; let mut log_file = data_dir.clone(); log_file.push("krill.log"); @@ -178,7 +185,7 @@ impl Config { log_type, log_file, syslog_facility, - auth_token + auth_token, }; c.init_logging().unwrap(); c @@ -188,19 +195,24 @@ impl Config { pub fn create() -> Result { let matches = App::new("NLnet Labs RRDP Server") .version("0.1b") - .arg(Arg::with_name("config") - .short("c") - .long("config") - .value_name("FILE") - .help("Specify non-default config file. If no file is \ - specified './daemon/defaults/krill.conf' will be used to \ - determine default values for all settings. Note that you \ - can use any of the following options to override any of \ - these values..") - .required(false)) + .arg( + Arg::with_name("config") + .short("c") + .long("config") + .value_name("FILE") + .help( + "Specify non-default config file. If no file is \ + specified './daemon/defaults/krill.conf' will be used to \ + determine default values for all settings. Note that you \ + can use any of the following options to override any of \ + these values..", + ) + .required(false), + ) .get_matches(); - let config_file = matches.value_of("config") + let config_file = matches + .value_of("config") .unwrap_or("./daemon/defaults/krill.conf"); let c = Self::read_config(config_file)?; @@ -216,7 +228,7 @@ impl Config { let c: Config = toml::from_slice(v.as_slice())?; if c.port < 1024 { - return Err(ConfigError::other("Port number must be >1024")) + return Err(ConfigError::other("Port number must be >1024")); } Ok(c) @@ -232,53 +244,39 @@ impl Config { dispatch = { if self.log_level == LevelFilter::Debug { dispatch.format(|out, message, record| { - out.finish( - format_args!( - "{} [{}] [{}] {}", - chrono::Local::now() - .format("%Y-%m-%d %H:%M:%S"), - record.target(), - record.level(), - message - ) - ) + out.finish(format_args!( + "{} [{}] [{}] {}", + chrono::Local::now().format("%Y-%m-%d %H:%M:%S"), + record.target(), + record.level(), + message + )) }) } else { dispatch.format(|out, message, record| { - out.finish( - format_args!( - "{} [{}] {}", - chrono::Local::now() - .format("%Y-%m-%d %H:%M:%S"), - record.level(), - message - ) - ) + out.finish(format_args!( + "{} [{}] {}", + chrono::Local::now().format("%Y-%m-%d %H:%M:%S"), + record.level(), + message + )) }) } }; - dispatch.level(self.log_level) + dispatch + .level(self.log_level) .chain(file) .apply() .map_err(|e| { - ConfigError::Other( - format!("Failed to init file logging: {}", e) - ) + ConfigError::Other(format!("Failed to init file logging: {}", e)) })?; - }, + } LogType::Syslog => { - syslog::init( - self.syslog_facility, - self.log_level, - Some(SERVER_NAME) - ).map_err(|e| { - ConfigError::Other( - format!("Failed to init syslog: {}", e) - ) - })?; - }, + syslog::init(self.syslog_facility, self.log_level, Some(SERVER_NAME)) + .map_err(|e| ConfigError::Other(format!("Failed to init syslog: {}", e)))?; + } LogType::Stderr => { let dispatch = fern::Dispatch::new() @@ -286,9 +284,7 @@ impl Config { .chain(io::stderr()); dispatch.apply().map_err(|e| { - ConfigError::Other( - format!("Failed to init stderr logging: {}", e) - ) + ConfigError::Other(format!("Failed to init stderr logging: {}", e)) })?; } } @@ -299,17 +295,17 @@ impl Config { #[derive(Debug, Display)] pub enum ConfigError { - #[display(fmt ="{}", _0)] + #[display(fmt = "{}", _0)] IoError(io::Error), - #[display(fmt ="{}", _0)] + #[display(fmt = "{}", _0)] TomlError(toml::de::Error), - #[display(fmt ="{}", _0)] + #[display(fmt = "{}", _0)] RpkiUriError(uri::Error), - #[display(fmt ="{}", _0)] - Other(String) + #[display(fmt = "{}", _0)] + Other(String), } impl ConfigError { @@ -336,7 +332,6 @@ impl From for ConfigError { } } - //------------ LogType ------------------------------------------------------- /// The target to log to. @@ -344,10 +339,9 @@ impl From for ConfigError { pub enum LogType { Syslog, Stderr, - File + File, } - //--- PartialEq and Eq impl PartialEq for LogType { @@ -356,25 +350,28 @@ impl PartialEq for LogType { (&LogType::Syslog, &LogType::Syslog) => true, (&LogType::Stderr, &LogType::Stderr) => true, (&LogType::File, &LogType::File) => true, - _ => false + _ => false, } } } -impl Eq for LogType { } +impl Eq for LogType {} impl<'de> Deserialize<'de> for LogType { fn deserialize(d: D) -> Result - where D: Deserializer<'de> { + where + D: Deserializer<'de>, + { let string = String::deserialize(d)?; match string.as_str() { "stderr" => Ok(LogType::Stderr), "syslog" => Ok(LogType::Syslog), "file" => Ok(LogType::File), - _ => Err( - de::Error::custom( - format!("expected \"stderr\", \"syslog\", or \ - \"file\", found : \"{}\"", string))) + _ => Err(de::Error::custom(format!( + "expected \"stderr\", \"syslog\", or \ + \"file\", found : \"{}\"", + string + ))), } } } @@ -382,25 +379,27 @@ impl<'de> Deserialize<'de> for LogType { #[derive(Clone, Debug, Eq, PartialEq)] pub enum SslChoice { Yes, - Test + Test, } impl<'de> Deserialize<'de> for SslChoice { fn deserialize(d: D) -> Result - where D: Deserializer<'de> { + where + D: Deserializer<'de>, + { let string = String::deserialize(d)?; match string.as_str() { - "yes" => Ok(SslChoice::Yes), + "yes" => Ok(SslChoice::Yes), "test" => Ok(SslChoice::Test), - _ => Err( - de::Error::custom( - format!("expected \"yes\", or \"test\", \ - found: \"{}\"", string))) + _ => Err(de::Error::custom(format!( + "expected \"yes\", or \"test\", \ + found: \"{}\"", + string + ))), } } } - //------------ Tests --------------------------------------------------------- #[cfg(test)] diff --git a/daemon/src/endpoints.rs b/daemon/src/endpoints.rs index aeb958c4..d4866837 100644 --- a/daemon/src/endpoints.rs +++ b/daemon/src/endpoints.rs @@ -1,24 +1,17 @@ //! Process requests received, delegate, and wrap up the responses. -use actix_web::{ - HttpResponse, - ResponseError -}; use actix_web::http::StatusCode; -use actix_web::web::{ - self, - Json, - Path, -}; +use actix_web::web::{self, Json, Path}; +use actix_web::{HttpResponse, ResponseError}; use bytes::Bytes; use serde::Serialize; -use krill_commons::api::{admin, publication, ErrorCode, ErrorResponse, IssuanceRequest}; -use krill_commons::api::admin::{Handle, CertAuthInit, AddChildRequest, AddParentRequest}; +use krill_commons::api::admin::{AddChildRequest, AddParentRequest, CertAuthInit, Handle}; use krill_commons::api::rrdp::VerificationError; -use krill_commons::util::softsigner::OpenSslSigner; +use krill_commons::api::{admin, publication, ErrorCode, ErrorResponse, IssuanceRequest}; use krill_commons::remote::api::ClientInfo; -use krill_commons::remote::sigmsg::SignedMessage; use krill_commons::remote::rfc6492; +use krill_commons::remote::sigmsg::SignedMessage; +use krill_commons::util::softsigner::OpenSslSigner; use krill_pubd::publishers::PublisherError; use krill_pubd::repo::RrdpServerError; @@ -36,13 +29,11 @@ const NOT_FOUND: &[u8] = include_bytes!("../ui/dist/404.html"); /// /// XXX TODO: Use actix Json<> when returning values fn render_json(object: O) -> HttpResponse { - match serde_json::to_string(&object){ - Ok(enc) => { - HttpResponse::Ok() - .content_type("application/json") - .body(enc) - }, - Err(e) => server_error(&Error::JsonError(e)) + match serde_json::to_string(&object) { + Ok(enc) => HttpResponse::Ok() + .content_type("application/json") + .body(enc), + Err(e) => server_error(&Error::JsonError(e)), } } @@ -53,15 +44,13 @@ fn server_error(error: &Error) -> HttpResponse { error.error_response() } - fn render_empty_res(res: Result<(), krillserver::Error>) -> HttpResponse { match res { Ok(()) => api_ok(), - Err(e) => server_error(&Error::ServerError(e)) + Err(e) => server_error(&Error::ServerError(e)), } } - /// A clean 404 result for the API (no content, not for humans) fn api_not_found() -> HttpResponse { HttpResponse::build(StatusCode::NOT_FOUND).finish() @@ -87,15 +76,20 @@ pub fn api_health(_auth: Auth) -> HttpResponse { } fn if_allowed(allowed: bool, op: F) -> HttpResponse - where F: FnOnce() -> HttpResponse { - if allowed { op() } else { HttpResponse::Forbidden().finish() } +where + F: FnOnce() -> HttpResponse, +{ + if allowed { + op() + } else { + HttpResponse::Forbidden().finish() + } } -fn if_api_allowed( - server: &web::Data, - auth: &Auth, - op: F -) -> HttpResponse where F: FnOnce() -> HttpResponse { +fn if_api_allowed(server: &web::Data, auth: &Auth, op: F) -> HttpResponse +where + F: FnOnce() -> HttpResponse, +{ let allowed = server.read().is_api_allowed(auth); if_allowed(allowed, op) } @@ -104,8 +98,11 @@ fn if_publication_allowed( server: &web::Data, handle: &Handle, auth: &Auth, - op: F -) -> HttpResponse where F: FnOnce() -> HttpResponse { + op: F, +) -> HttpResponse +where + F: FnOnce() -> HttpResponse, +{ let allowed = server.read().is_publication_api_allowed(handle, auth); if_allowed(allowed, op) } @@ -113,14 +110,14 @@ fn if_publication_allowed( //------------ Admin: Publishers --------------------------------------------- /// Returns a json structure with all publishers in it. -pub fn publishers( - server: web::Data, - auth: Auth -) -> HttpResponse { +pub fn publishers(server: web::Data, auth: Auth) -> HttpResponse { let publishers = server.read().publishers(); if_api_allowed(&server, &auth, || { - render_json(admin::PublisherList::build(&publishers, "/api/v1/publishers")) + render_json(admin::PublisherList::build( + &publishers, + "/api/v1/publishers", + )) }) } @@ -129,9 +126,9 @@ pub fn publishers( pub fn add_publisher( server: web::Data, auth: Auth, - pbl: Json + pbl: Json, ) -> HttpResponse { - if_api_allowed(&server, &auth, ||{ + if_api_allowed(&server, &auth, || { render_empty_res(server.write().add_publisher(pbl.into_inner())) }) } @@ -142,7 +139,7 @@ pub fn add_publisher( pub fn deactivate_publisher( server: web::Data, auth: Auth, - handle: Path + handle: Path, ) -> HttpResponse { if_api_allowed(&server, &auth, || { render_empty_res(server.write().deactivate_publisher(&handle)) @@ -154,22 +151,15 @@ pub fn deactivate_publisher( pub fn publisher_details( server: web::Data, auth: Auth, - handle: Path + handle: Path, ) -> HttpResponse { - if_api_allowed(&server, &auth, ||{ - match server.read().publisher(&handle) { - Ok(None) => api_not_found(), - Ok(Some(publisher)) => { - render_json( - &publisher.as_api_details() - ) - }, - Err(e) => server_error(&Error::ServerError(e)) - } + if_api_allowed(&server, &auth, || match server.read().publisher(&handle) { + Ok(None) => api_not_found(), + Ok(Some(publisher)) => render_json(&publisher.as_api_details()), + Err(e) => server_error(&Error::ServerError(e)), }) } - //------------ Publication --------------------------------------------------- /// Processes an RFC8181 query and returns the appropriate response. @@ -180,19 +170,13 @@ pub fn rfc8181( msg_bytes: Bytes, ) -> HttpResponse { match SignedMessage::decode(msg_bytes, true) { - Ok(msg) => { - match server.read().handle_rfc8181_req(msg, handle.into_inner()) { - Ok(captured) => { - HttpResponse::build(StatusCode::OK) - .content_type("application/rpki-publication") - .body(captured.into_bytes()) - } - Err(e) => { - server_error(&Error::ServerError(e)) - } - } - } - Err(_) => server_error(&Error::CmsError) + Ok(msg) => match server.read().handle_rfc8181_req(msg, handle.into_inner()) { + Ok(captured) => HttpResponse::build(StatusCode::OK) + .content_type("application/rpki-publication") + .body(captured.into_bytes()), + Err(e) => server_error(&Error::ServerError(e)), + }, + Err(_) => server_error(&Error::CmsError), } } @@ -202,7 +186,7 @@ pub fn handle_delta( server: web::Data, auth: Auth, delta: Json, - handle: Path + handle: Path, ) -> HttpResponse { let handle = handle.into_inner(); let delta = delta.into_inner(); @@ -214,42 +198,32 @@ pub fn handle_delta( /// Processes a list request sent to the API. #[allow(clippy::needless_pass_by_value)] -pub fn handle_list( - server: web::Data, - auth: Auth, - handle: Path -) -> HttpResponse { +pub fn handle_list(server: web::Data, auth: Auth, handle: Path) -> HttpResponse { let handle = handle.into_inner(); debug!("Received list request for {}", &handle); - if_publication_allowed(&server, &handle, &auth, ||{ + if_publication_allowed(&server, &handle, &auth, || { match server.read().handle_list(&handle) { Ok(list) => render_json(list), - Err(e) => server_error(&Error::ServerError(e)) + Err(e) => server_error(&Error::ServerError(e)), } }) } - //------------ Admin: Rfc8181 ----------------------------------------------- -pub fn rfc8181_clients( - server: web::Data, - auth: Auth -) -> HttpResponse { - if_api_allowed(&server, &auth, ||{ - match server.read().rfc8181_clients() { - Ok(clients) => render_json(clients), - Err(e) => server_error(&Error::ServerError(e )) - } +pub fn rfc8181_clients(server: web::Data, auth: Auth) -> HttpResponse { + if_api_allowed(&server, &auth, || match server.read().rfc8181_clients() { + Ok(clients) => render_json(clients), + Err(e) => server_error(&Error::ServerError(e)), }) } pub fn add_rfc8181_client( server: web::Data, auth: Auth, - client: Json + client: Json, ) -> HttpResponse { - if_api_allowed(&server, &auth, ||{ + if_api_allowed(&server, &auth, || { render_empty_res(server.read().add_rfc8181_client(client.into_inner())) }) } @@ -257,49 +231,36 @@ pub fn add_rfc8181_client( pub fn repository_response( server: web::Data, auth: Auth, - handle: Path + handle: Path, ) -> HttpResponse { let handle = handle.into_inner(); - if_publication_allowed(&server, &handle, &auth, ||{ + if_publication_allowed(&server, &handle, &auth, || { match server.read().repository_response(&handle) { - Ok(res) => { - HttpResponse::Ok() - .content_type("application/xml") - .body(res.encode_vec()) - }, + Ok(res) => HttpResponse::Ok() + .content_type("application/xml") + .body(res.encode_vec()), - Err(e) => server_error(&Error::ServerError(e)) + Err(e) => server_error(&Error::ServerError(e)), } }) } //------------ Admin: TrustAnchor -------------------------------------------- -pub fn ta_info( - server: web::Data, - auth: Auth -) -> HttpResponse { - if_api_allowed(&server, &auth, ||{ - match server.read().ta_info() { - Some(ta) => render_json(ta), - None => api_not_found() - } +pub fn ta_info(server: web::Data, auth: Auth) -> HttpResponse { + if_api_allowed(&server, &auth, || match server.read().ta_info() { + Some(ta) => render_json(ta), + None => api_not_found(), }) } -pub fn ta_init( - server: web::Data, - auth: Auth -) -> HttpResponse { +pub fn ta_init(server: web::Data, auth: Auth) -> HttpResponse { if_api_allowed(&server, &auth, || { render_empty_res(server.write().ta_init()) }) } -pub fn republish_all( - server: web::Data, - auth: Auth -) -> HttpResponse { +pub fn republish_all(server: web::Data, auth: Auth) -> HttpResponse { if_api_allowed(&server, &auth, || { render_empty_res(server.read().republish_all()) }) @@ -307,67 +268,54 @@ pub fn republish_all( pub fn tal(server: web::Data) -> HttpResponse { match server.read().ta_info() { - Some(ta) => { - HttpResponse::Ok() - .content_type("text/plain") - .body(format!("{}", ta.tal())) - }, - None => api_not_found() + Some(ta) => HttpResponse::Ok() + .content_type("text/plain") + .body(format!("{}", ta.tal())), + None => api_not_found(), } } pub fn ta_cer(server: web::Data) -> HttpResponse { match server.read().trust_anchor_cert() { - Some(cert) => { - HttpResponse::Ok().body(cert.der_encoded().to_vec()) - }, - None => api_not_found() + Some(cert) => HttpResponse::Ok().body(cert.der_encoded().to_vec()), + None => api_not_found(), } } pub fn ta_add_child( server: web::Data, req: Json, - auth: Auth + auth: Auth, ) -> HttpResponse { if_api_allowed(&server, &auth, || { match server.read().ta_add_child(req.into_inner()) { Ok(info) => render_json(info), - Err(e) => server_error(&Error::ServerError(e)) + Err(e) => server_error(&Error::ServerError(e)), } }) } //------------ Admin: CertAuth ----------------------------------------------- -pub fn cas( - server: web::Data, - auth: Auth -) -> HttpResponse { - if_api_allowed(&server, &auth, || { - render_json(server.read().cas()) - }) +pub fn cas(server: web::Data, auth: Auth) -> HttpResponse { + if_api_allowed(&server, &auth, || render_json(server.read().cas())) } pub fn ca_init( server: web::Data, auth: Auth, - ca_init: Json + ca_init: Json, ) -> HttpResponse { if_api_allowed(&server, &auth, || { render_empty_res(server.write().ca_init(ca_init.into_inner())) }) } -pub fn ca_info( - server: web::Data, - auth: Auth, - handle: Path -) -> HttpResponse { +pub fn ca_info(server: web::Data, auth: Auth, handle: Path) -> HttpResponse { if_api_allowed(&server, &auth, || { match server.read().ca_info(&handle.into_inner()) { Some(info) => render_json(info), - None => api_not_found() + None => api_not_found(), } }) } @@ -375,17 +323,15 @@ pub fn ca_info( pub fn ca_child_req( server: web::Data, auth: Auth, - handle: Path + handle: Path, ) -> HttpResponse { let handle = handle.into_inner(); if_api_allowed(&server, &auth, || { match server.read().ca_child_req(&handle) { - Some(req) => { - HttpResponse::Ok() - .content_type("application/xml") - .body(req.encode_vec()) - }, - None => api_not_found() + Some(req) => HttpResponse::Ok() + .content_type("application/xml") + .body(req.encode_vec()), + None => api_not_found(), } }) } @@ -394,12 +340,14 @@ pub fn ca_add_parent( server: web::Data, auth: Auth, handle: Path, - parent: Json + parent: Json, ) -> HttpResponse { if_api_allowed(&server, &auth, || { render_empty_res( - server.read() - .ca_add_parent(handle.into_inner(), parent.into_inner())) + server + .read() + .ca_add_parent(handle.into_inner(), parent.into_inner()), + ) }) } @@ -412,15 +360,14 @@ pub fn list( server: web::Data, auth: Auth, parent: Path, - child: Path + child: Path, ) -> HttpResponse { - match server.read().list( - &parent.into_inner(), - &child.into_inner(), - auth - ) { + match server + .read() + .list(&parent.into_inner(), &child.into_inner(), auth) + { Ok(entitlements) => render_json(entitlements), - Err(e) => server_error(&Error::ServerError(e)) + Err(e) => server_error(&Error::ServerError(e)), } } @@ -432,16 +379,16 @@ pub fn issue( auth: Auth, parent: Path, child: Path, - issue_req: Json + issue_req: Json, ) -> HttpResponse { match server.read().issue( &parent.into_inner(), &child.into_inner(), issue_req.into_inner(), - auth + auth, ) { Ok(issued) => render_json(issued), - Err(e) => server_error(&Error::ServerError(e)) + Err(e) => server_error(&Error::ServerError(e)), } } @@ -453,22 +400,15 @@ pub fn rfc6492( msg_bytes: Bytes, ) -> HttpResponse { match SignedMessage::decode(msg_bytes, false) { - Ok(msg) => { - match server.read().rfc6492( - parent.into_inner(), - msg - ) { - Ok(bytes) => { - HttpResponse::build(StatusCode::OK) - .content_type(rfc6492::CONTENT_TYPE) - .body(bytes) - } - Err(e) => { - error!("Error processing RFC6492 req: {}", e); - server_error(&Error::ServerError(e)) - } + Ok(msg) => match server.read().rfc6492(parent.into_inner(), msg) { + Ok(bytes) => HttpResponse::build(StatusCode::OK) + .content_type(rfc6492::CONTENT_TYPE) + .body(bytes), + Err(e) => { + error!("Error processing RFC6492 req: {}", e); + server_error(&Error::ServerError(e)) } - } + }, Err(e) => { error!("Error processing RFC6492 req: {}", e); server_error(&Error::CmsError) @@ -476,17 +416,12 @@ pub fn rfc6492( } } - - //------------ Serving RRDP -------------------------------------------------- pub fn current_snapshot_json(_server: web::Data) -> HttpResponse { unimplemented!() } - - - //------------ Error --------------------------------------------------------- #[derive(Debug, Display)] @@ -502,7 +437,7 @@ pub enum Error { CmsError, #[display(fmt = "Invalid publisher request")] - PublisherRequestError + PublisherRequestError, } /// Translate an error to an HTTP Status Code @@ -527,7 +462,7 @@ impl ErrorToStatus for Error { Error::ServerError(e) => e.status(), Error::JsonError(_) => StatusCode::BAD_REQUEST, Error::CmsError => StatusCode::BAD_REQUEST, - Error::PublisherRequestError => StatusCode::BAD_REQUEST + Error::PublisherRequestError => StatusCode::BAD_REQUEST, } } } @@ -558,7 +493,6 @@ impl ErrorToStatus for krill_pubd::Error { krill_pubd::Error::AggregateStoreError(_) => StatusCode::INTERNAL_SERVER_ERROR, } } - } impl ErrorToStatus for PublisherError { @@ -582,7 +516,7 @@ impl ErrorToStatus for ca::ServerError { fn status(&self) -> StatusCode { match self { ca::ServerError::CertAuth(e) => e.status(), - _ => StatusCode::INTERNAL_SERVER_ERROR + _ => StatusCode::INTERNAL_SERVER_ERROR, } } } @@ -591,22 +525,21 @@ impl ErrorToStatus for ca::Error { fn status(&self) -> StatusCode { match self { ca::Error::Unauthorized(_) => StatusCode::FORBIDDEN, - ca::Error::SignerError(_) | ca::Error::KeyStatusChange(_,_) => - StatusCode::INTERNAL_SERVER_ERROR, - _ => StatusCode::BAD_REQUEST + ca::Error::SignerError(_) | ca::Error::KeyStatusChange(_, _) => { + StatusCode::INTERNAL_SERVER_ERROR + } + _ => StatusCode::BAD_REQUEST, } } } - - impl ToErrorCode for Error { fn code(&self) -> ErrorCode { match self { Error::ServerError(e) => e.code(), Error::JsonError(_) => ErrorCode::InvalidJson, Error::CmsError => ErrorCode::InvalidCms, - Error::PublisherRequestError => ErrorCode::InvalidPublisherRequest + Error::PublisherRequestError => ErrorCode::InvalidPublisherRequest, } } } @@ -653,7 +586,7 @@ impl ToErrorCode for VerificationError { match self { VerificationError::NoObjectForHashAndOrUri(_) => ErrorCode::NoObjectForHashAndOrUri, VerificationError::ObjectAlreadyPresent(_) => ErrorCode::ObjectAlreadyPresent, - VerificationError::UriOutsideJail(_, _) => ErrorCode::UriOutsideJail + VerificationError::UriOutsideJail(_, _) => ErrorCode::UriOutsideJail, } } } @@ -661,7 +594,7 @@ impl ToErrorCode for VerificationError { impl ToErrorCode for RrdpServerError { fn code(&self) -> ErrorCode { match self { - RrdpServerError::IoError(_) => ErrorCode::Persistence + RrdpServerError::IoError(_) => ErrorCode::Persistence, } } } @@ -670,7 +603,7 @@ impl ToErrorCode for ca::ServerError { fn code(&self) -> ErrorCode { match self { ca::ServerError::CertAuth(e) => e.code(), - _ => ErrorCode::CaServerError + _ => ErrorCode::CaServerError, } } } @@ -681,13 +614,11 @@ impl ToErrorCode for ca::Error { ca::Error::DuplicateChild(_) => ErrorCode::DuplicateChild, ca::Error::MustHaveResources => ErrorCode::ChildNeedsResources, ca::Error::MissingResources => ErrorCode::ChildOverclaims, - _ => ErrorCode::CaServerError + _ => ErrorCode::CaServerError, } } } - - impl Error { fn to_error_response(&self) -> ErrorResponse { self.code().clone().into() @@ -699,4 +630,4 @@ impl actix_web::ResponseError for Error { HttpResponse::build(self.status()) .body(serde_json::to_string(&self.to_error_response()).unwrap()) } -} \ No newline at end of file +} diff --git a/daemon/src/http/mod.rs b/daemon/src/http/mod.rs index 75abcd6f..0ffe27f2 100644 --- a/daemon/src/http/mod.rs +++ b/daemon/src/http/mod.rs @@ -1,3 +1,3 @@ pub mod server; pub mod ssl; -pub mod statics; \ No newline at end of file +pub mod statics; diff --git a/daemon/src/http/server.rs b/daemon/src/http/server.rs index d80381b5..4ebf69ff 100644 --- a/daemon/src/http/server.rs +++ b/daemon/src/http/server.rs @@ -3,48 +3,27 @@ //! Here we deal with booting and setup, and once active deal with parsing //! arguments and routing of requests, typically handing off to the //! daemon::api::endpoints functions for processing and responding. -use std::io; use std::fs::File; -use std::sync::{ - Arc, - RwLock, - RwLockReadGuard, - RwLockWriteGuard -}; +use std::io; +use std::sync::{Arc, RwLock, RwLockReadGuard, RwLockWriteGuard}; -use actix_web::{ - App, - FromRequest, - HttpResponse, - HttpServer, -}; -use actix_web::http::StatusCode; -use actix_web::{guard, middleware, web}; -use actix_web::web::{ - delete, - get, - post, - scope, - Path -}; use actix_session::CookieSession; -use openssl::ssl::{SslMethod, SslAcceptor, SslAcceptorBuilder, SslFiletype}; +use actix_web::http::StatusCode; +use actix_web::web::{delete, get, post, scope, Path}; +use actix_web::{guard, middleware, web}; +use actix_web::{App, FromRequest, HttpResponse, HttpServer}; +use openssl::ssl::{SslAcceptor, SslAcceptorBuilder, SslFiletype, SslMethod}; use bcder::decode; use krill_commons::api::publication; -use crate::auth::{ - AUTH_COOKIE_NAME, - is_logged_in, - login, - logout -}; +use crate::auth::{is_logged_in, login, logout, AUTH_COOKIE_NAME}; use crate::config::Config; use crate::endpoints; use crate::endpoints::*; -use crate::http::statics::WithStaticContent; use crate::http::ssl; +use crate::http::statics::WithStaticContent; use crate::krillserver; use crate::krillserver::KrillServer; @@ -63,10 +42,7 @@ impl AppServer { } } - - pub fn start(config: &Config) -> Result<(), Error> { - let server = { let krill = KrillServer::build( &config.data_dir, @@ -85,45 +61,40 @@ pub fn start(config: &Config) -> Result<(), Error> { App::new() .data(server.clone()) .wrap(middleware::Logger::default()) - .wrap(CookieSession::signed(&[0; 32]) - .name(AUTH_COOKIE_NAME) - .secure(true)) + .wrap( + CookieSession::signed(&[0; 32]) + .name(AUTH_COOKIE_NAME) + .secure(true), + ) .route("/health", get().to(endpoints::health)) - // API end-points .service( scope("/api/v1") .route("/health", get().to(api_health)) - .route("/publishers", get().to(publishers)) .route("/publishers", post().to(add_publisher)) .route("/publishers/{handle}", get().to(publisher_details)) .route("/publishers/{handle}", delete().to(deactivate_publisher)) - .route("/rfc8181/clients", get().to(rfc8181_clients)) .route("/rfc8181/clients", post().to(add_rfc8181_client)) - .data(web::Bytes::configure(|cfg| { - cfg.limit(256 * 1024 * 1024) - })) - .route("/rfc8181/{handle}/response.xml", get().to(repository_response)) - + .data(web::Bytes::configure(|cfg| cfg.limit(256 * 1024 * 1024))) + .route( + "/rfc8181/{handle}/response.xml", + get().to(repository_response), + ) .route("/trustanchor", get().to(ta_info)) .route("/trustanchor", post().to(ta_init)) .route("/trustanchor/children", post().to(ta_add_child)) - .route("/cas", post().to(ca_init)) .route("/cas", get().to(cas)) .route("/cas/{handle}", get().to(ca_info)) .route("/cas/{handle}/child_request", get().to(ca_child_req)) .route("/cas/{handle}/parents", post().to(ca_add_parent)) - - .route("/republish", post().to(republish_all)) + .route("/republish", post().to(republish_all)), ) - // Public TA related methods .route("/ta/ta.tal", get().to(tal)) .route("/ta/ta.cer", get().to(ta_cer)) - // Publication by (embedded) clients .route("/publication/{handle}", get().to(handle_list)) .route("/publication/{handle}", post().to(handle_delta)) @@ -131,31 +102,26 @@ pub fn start(config: &Config) -> Result<(), Error> { cfg.limit(256 * 1024 * 1024) })) .route("/rfc8181/{handle}", post().to(rfc8181)) - // Provisioning for remote krill clients .route("/provisioning/{parent}/{child}/list", get().to(list)) .route("/provisioning/{parent}/{child}/issue", post().to(issue)) - // Provisioning for rfc6492 clients .route("/rfc6492/{handle}", post().to(rfc6492)) - - // UI support .route("/ui/is_logged_in", get().to(is_logged_in)) .route("/ui/login", post().to(login)) .route("/ui/logout", post().to(logout)) - // RRDP repository .route("/rrdp/{path:.*}", get().to(serve_rrdp_files)) - - .route("/", get().to(|| { - HttpResponse::Found() - .header("location", "/ui/index.html") - .finish() - })) - + .route( + "/", + get().to(|| { + HttpResponse::Found() + .header("location", "/ui/index.html") + .finish() + }), + ) .add_statics() - // default .default_service( // 404 for GET request @@ -168,13 +134,13 @@ pub fn start(config: &Config) -> Result<(), Error> { .to(HttpResponse::MethodNotAllowed), ), ) - - }).bind_ssl(config.socket_addr(), https_builder)?.run()?; + }) + .bind_ssl(config.socket_addr(), https_builder)? + .run()?; Ok(()) } - /// Used to set up HTTPS. Creates keypair and self signed certificate /// if config has 'use_ssl=test'. fn https_builder(config: &Config) -> Result { @@ -186,14 +152,13 @@ fn https_builder(config: &Config) -> Result { let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()) .map_err(|e| Error::Other(format!("{}", e)))?; - builder.set_private_key_file( - config.https_key_file(), - SslFiletype::PEM - ).map_err(|e| Error::Other(format!("{}", e)))?; + builder + .set_private_key_file(config.https_key_file(), SslFiletype::PEM) + .map_err(|e| Error::Other(format!("{}", e)))?; - builder.set_certificate_chain_file( - config.https_cert_file() - ).map_err(|e| Error::Other(format!("{}", e)))?; + builder + .set_certificate_chain_file(config.https_cert_file()) + .map_err(|e| Error::Other(format!("{}", e)))?; Ok(builder) } @@ -203,11 +168,7 @@ fn https_builder(config: &Config) -> Result { // See also: // https://github.com/actix/actix-website/blob/master/content/docs/static-files.md // https://www.keycdn.com/blog/http-cache-headers -fn serve_rrdp_files( - server: web::Data, - path: Path -) -> HttpResponse -{ +fn serve_rrdp_files(server: web::Data, path: Path) -> HttpResponse { let mut full_path = server.read().rrdp_base_path(); full_path.push(path.into_inner()); match File::open(full_path) { @@ -217,14 +178,11 @@ fn serve_rrdp_files( file.read_to_end(&mut buffer).unwrap(); HttpResponse::build(StatusCode::OK).body(buffer) - }, - _ => { - HttpResponse::build(StatusCode::NOT_FOUND).finish() } + _ => HttpResponse::build(StatusCode::NOT_FOUND).finish(), } } - //------------ Error --------------------------------------------------------- #[derive(Debug, Display)] @@ -250,15 +208,21 @@ pub enum Error { } impl From for Error { - fn from(e: serde_json::Error) -> Self { Error::JsonError(e) } + fn from(e: serde_json::Error) -> Self { + Error::JsonError(e) + } } impl From for Error { - fn from(e: io::Error) -> Self { Error::IoError(e) } + fn from(e: io::Error) -> Self { + Error::IoError(e) + } } impl From for Error { - fn from(e: krillserver::Error) -> Self { Error::ServerError(e) } + fn from(e: krillserver::Error) -> Self { + Error::ServerError(e) + } } impl std::error::Error for Error { @@ -269,8 +233,7 @@ impl std::error::Error for Error { impl actix_web::ResponseError for Error { fn error_response(&self) -> HttpResponse { - HttpResponse::build(StatusCode::INTERNAL_SERVER_ERROR) - .body(format!("{}", self)) + HttpResponse::build(StatusCode::INTERNAL_SERVER_ERROR).body(format!("{}", self)) } } diff --git a/daemon/src/http/ssl.rs b/daemon/src/http/ssl.rs index ee02bf5b..291273d9 100644 --- a/daemon/src/http/ssl.rs +++ b/daemon/src/http/ssl.rs @@ -1,43 +1,23 @@ //! Some helper stuff for creating a private key and certificate for HTTPS //! in case they are not provided -use std::io::Write; -use std::fs::File; -use std::path::PathBuf; -use bcder::{ - BitString, - Mode, - Tag -}; +use bcder::encode::{Constructed, PrimitiveContent, Values}; use bcder::{decode, encode}; -use bcder::encode::{ - Constructed, - Values, - PrimitiveContent -}; +use bcder::{BitString, Mode, Tag}; use bytes::Bytes; +use openssl::hash::MessageDigest; use openssl::pkey::{PKey, Private}; use openssl::rsa::Rsa; -use openssl::hash::MessageDigest; +use std::fs::File; +use std::io::Write; +use std::path::PathBuf; -use rpki::cert::ext::{ - AuthorityKeyIdentifier, - BasicCa, - SubjectKeyIdentifier -}; -use rpki::crypto::{ - PublicKey, - Signature, - SignatureAlgorithm -}; -use rpki::x509::{ - Name, - Validity -}; +use rpki::cert::ext::{AuthorityKeyIdentifier, BasicCa, SubjectKeyIdentifier}; +use rpki::crypto::{PublicKey, Signature, SignatureAlgorithm}; +use rpki::x509::{Name, Validity}; use krill_commons::util::file; - const KEY_SIZE: u32 = 2048; pub const HTTPS_SUB_DIR: &str = "ssl"; pub const KEY_FILE: &str = "key.pem"; @@ -52,7 +32,7 @@ pub fn create_key_cert_if_needed(data_dir: &PathBuf) -> Result<(), Error> { let key_file_path = file::file_path(&https_dir, KEY_FILE); let cert_file_path = file::file_path(&https_dir, CERT_FILE); - if ! key_file_path.exists() || ! cert_file_path.exists() { + if !key_file_path.exists() || !cert_file_path.exists() { create_key_and_cert(&https_dir) } else { Ok(()) @@ -63,7 +43,7 @@ pub fn create_key_cert_if_needed(data_dir: &PathBuf) -> Result<(), Error> { /// Only call this in case there is no current key and certificate file /// present, or have your files ruthlessly overwritten! fn create_key_and_cert(https_dir: &PathBuf) -> Result<(), Error> { - if ! https_dir.exists() { + if !https_dir.exists() { file::create_dir(&https_dir)?; } @@ -74,13 +54,12 @@ fn create_key_and_cert(https_dir: &PathBuf) -> Result<(), Error> { Ok(()) } - //------------ HttpsSigner --------------------------------------------------- /// Signer specifically for generating an HTTPS key pair and certificate, and /// saving them both as PEM files in a directory. struct HttpsSigner { - private: PKey + private: PKey, } impl HttpsSigner { @@ -102,53 +81,43 @@ impl HttpsSigner { fn public_key_info(&self) -> Result { let mut b = Bytes::from( - self.private.rsa().unwrap().public_key_to_der() - .map_err(|e| { Error::OpenSslError(e) })? + self.private + .rsa() + .unwrap() + .public_key_to_der() + .map_err(|e| Error::OpenSslError(e))?, ); - let pk = PublicKey::decode(&mut b) - .map_err(|e| { Error::DecodeError(e)})?; + let pk = PublicKey::decode(&mut b).map_err(|e| Error::DecodeError(e))?; Ok(pk) } fn sign(&self, data: &Bytes) -> Result { - - let mut signer = ::openssl::sign::Signer::new( - MessageDigest::sha256(), - &self.private - )?; + let mut signer = ::openssl::sign::Signer::new(MessageDigest::sha256(), &self.private)?; signer.update(data.as_ref())?; let signature_bytes = signer.sign_to_vec()?; - let signature = Signature::new( - SignatureAlgorithm::default(), - Bytes::from(signature_bytes) - ); + let signature = Signature::new(SignatureAlgorithm::default(), Bytes::from(signature_bytes)); Ok(signature) } /// Saves a self-signed certificate so that actix can use it. fn save_certificate(&mut self, https_dir: &PathBuf) -> Result<(), Error> { - let pub_key = self.public_key_info()?; let tbs_cert = TbsHttpsCertificate::from(&pub_key); let encoded_tbs = tbs_cert.encode().to_captured(Mode::Der); let (_, signature) = self.sign(encoded_tbs.as_ref())?.unwrap(); - let signature = BitString::new( - 0, - signature - ); + let signature = BitString::new(0, signature); - let encoded_cert = encode::sequence( - ( - encoded_tbs, - SignatureAlgorithm::default().x509_encode(), - signature.encode() - ) - ).to_captured(Mode::Der); + let encoded_cert = encode::sequence(( + encoded_tbs, + SignatureAlgorithm::default().x509_encode(), + signature.encode(), + )) + .to_captured(Mode::Der); let cert_pem = base64::encode(&encoded_cert); @@ -191,7 +160,7 @@ struct TbsHttpsCertificate { subject_public_key_info: PublicKey, // issuerUniqueID is not used // subjectUniqueID is not used - extensions: HttpsCertExtensions + extensions: HttpsCertExtensions, } impl From<&PublicKey> for TbsHttpsCertificate { @@ -206,35 +175,37 @@ impl From<&PublicKey> for TbsHttpsCertificate { let extensions = HttpsCertExtensions::from(pk); TbsHttpsCertificate { - issuer, validity, subject, subject_public_key_info, extensions + issuer, + validity, + subject, + subject_public_key_info, + extensions, } } } impl TbsHttpsCertificate { pub fn encode<'a>(&'a self) -> impl encode::Values + 'a { - encode::sequence(( ( Constructed::new( Tag::CTX_0, - 2_i32.encode() // Version 3 is encoded as 2 + 2_i32.encode(), // Version 3 is encoded as 2 ), 1_i32.encode(), SignatureAlgorithm::default().x509_encode(), - self.issuer.encode_ref() + self.issuer.encode_ref(), ), ( self.validity.encode(), self.subject.encode_ref(), self.subject_public_key_info.clone().encode(), - self.extensions.encode() - ) + self.extensions.encode(), + ), )) } } - //------------ IdExtensions -------------------------------------------------- #[derive(Clone, Debug, Eq, PartialEq)] @@ -259,27 +230,25 @@ impl From<&PublicKey> for HttpsCertExtensions { let authority_key_id = AuthorityKeyIdentifier::new(pk); HttpsCertExtensions { - basic_ca, subject_key_id, authority_key_id + basic_ca, + subject_key_id, + authority_key_id, } } } /// # Encoding impl HttpsCertExtensions { - pub fn encode<'a>(&'a self) -> impl encode::Values + 'a { Constructed::new( Tag::CTX_3, - encode::sequence( - ( - self.basic_ca.encode(), - self.subject_key_id.clone().encode(), - self.authority_key_id.clone().encode() - ) - ) + encode::sequence(( + self.basic_ca.encode(), + self.subject_key_id.clone().encode(), + self.authority_key_id.clone().encode(), + )), ) } - } //------------ Error --------------------------------------------------------- @@ -295,8 +264,8 @@ pub enum Error { #[display(fmt = "{}", _0)] DecodeError(decode::Error), - #[display(fmt="Could not make certificate")] - BuildError + #[display(fmt = "Could not make certificate")] + BuildError, } impl From for Error { @@ -318,13 +287,12 @@ mod tests { use super::*; use actix_web::*; - use openssl::ssl::{SslMethod, SslAcceptor, SslFiletype}; use krill_commons::util::test; + use openssl::ssl::{SslAcceptor, SslFiletype, SslMethod}; #[test] fn should_create_key_and_cert_and_start_server() { test::test_under_tmp(|d| { - let mut p_key_file_path = d.clone(); p_key_file_path.push("ssl"); p_key_file_path.push("key.pem"); @@ -335,21 +303,18 @@ mod tests { create_key_cert_if_needed(&d).unwrap(); - let mut builder = SslAcceptor::mozilla_intermediate( - SslMethod::tls() - ).unwrap(); + let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap(); - builder.set_private_key_file( - p_key_file_path, - SslFiletype::PEM - ).unwrap(); + builder + .set_private_key_file(p_key_file_path, SslFiletype::PEM) + .unwrap(); builder.set_certificate_chain_file(cert_file_path).unwrap(); - HttpServer::new(|| {App::new()}) + HttpServer::new(|| App::new()) .bind_ssl("localhost:8443", builder) .unwrap(); }); } -} \ No newline at end of file +} diff --git a/daemon/src/http/statics.rs b/daemon/src/http/statics.rs index 8b12053e..7d415526 100644 --- a/daemon/src/http/statics.rs +++ b/daemon/src/http/statics.rs @@ -1,51 +1,32 @@ -use actix_web::{ - App, - Error, - HttpResponse, - web -}; -use actix_web::dev::{ - MessageBody, - ServiceRequest, - ServiceResponse -}; use actix_service::NewService; - +use actix_web::dev::{MessageBody, ServiceRequest, ServiceResponse}; +use actix_web::{web, App, Error, HttpResponse}; /// This trait allows for adding static content. /// Using a trait here so that it can be used fluidly in the /// building of the 'App'. pub trait WithStaticContent { - /// Add a single static resource. - fn add_static( - self, - static_content: &'static StaticContent - ) -> Self; + fn add_static(self, static_content: &'static StaticContent) -> Self; /// Add all static resources defined in this module. - fn add_statics( - self, - ) -> Self; + fn add_statics(self) -> Self; } /// Implementation for the App type that is returned when App::new() /// is used. impl WithStaticContent for App - where - B: MessageBody, - T: NewService< - Config = (), - Request = ServiceRequest, - Response = ServiceResponse, - Error = Error, - InitError = (), - >, +where + B: MessageBody, + T: NewService< + Config = (), + Request = ServiceRequest, + Response = ServiceResponse, + Error = Error, + InitError = (), + >, { - fn add_static( - self, - static_content: &'static StaticContent - ) -> Self { + fn add_static(self, static_content: &'static StaticContent) -> Self { self.route( static_content.web_path, web::get().to(move || { @@ -53,26 +34,20 @@ impl WithStaticContent for App .content_type(static_content.ctype) .header("Cache-Control", "max-age: 86400") .body(static_content.content) - }) + }), ) } fn add_statics(self) -> Self { - self - .add_static(&NOT_FOUND) + self.add_static(&NOT_FOUND) .add_static(&INDEX) - .add_static(&FAVICON) - .add_static(&APP_JS) .add_static(&APP_JS_MAP) - .add_static(&APP_CSS) - .add_static(&IMG_KRILL_LOG) .add_static(&IMG_ROUTE_LEFT) .add_static(&IMG_ROUTE_RIGHT) - .add_static(&FONTS_EL_ICONS) .add_static(&FONTS_LATIN_100) .add_static(&FONTS_LATIN_100_2) @@ -116,12 +91,12 @@ pub struct StaticContent { //------------ Definition of Statics ----------------------------------------- -static HTML: &'static str = "text/html"; -static FAV: &'static str = "image/x-icon"; -static JS: &'static str = "application/javascript"; -static CSS: &'static str = "text/css"; -static SVG: &'static str = "image/svg+xml"; -static WOFF: &'static str = "font/woff"; +static HTML: &'static str = "text/html"; +static FAV: &'static str = "image/x-icon"; +static JS: &'static str = "application/javascript"; +static CSS: &'static str = "text/css"; +static SVG: &'static str = "image/svg+xml"; +static WOFF: &'static str = "font/woff"; static WOFF2: &'static str = "font/woff2"; static NOT_FOUND: StaticContent = StaticContent { @@ -132,190 +107,190 @@ static NOT_FOUND: StaticContent = StaticContent { static INDEX: StaticContent = StaticContent { web_path: "/ui/index.html", content: include_bytes!("../../ui/dist/index.html"), - ctype: HTML + ctype: HTML, }; static FAVICON: StaticContent = StaticContent { web_path: "/ui/favicon.ico", - content: include_bytes!("../../ui/dist/favicon.ico"), - ctype: FAV + content: include_bytes!("../../ui/dist/favicon.ico"), + ctype: FAV, }; static APP_JS: StaticContent = StaticContent { web_path: "/ui/js/app.js", content: include_bytes!("../../ui/dist/js/app.js"), - ctype: JS + ctype: JS, }; static APP_JS_MAP: StaticContent = StaticContent { web_path: "/ui/js/app.js.map", content: include_bytes!("../../ui/dist/js/app.js.map"), - ctype: JS + ctype: JS, }; static APP_CSS: StaticContent = StaticContent { web_path: "/ui/css/app.css", content: include_bytes!("../../ui/dist/css/app.css"), - ctype: CSS + ctype: CSS, }; static IMG_KRILL_LOG: StaticContent = StaticContent { web_path: "/ui/img/krill_logo_white.svg", content: include_bytes!("../../ui/dist/img/krill_logo_white.svg"), - ctype: SVG + ctype: SVG, }; static IMG_ROUTE_LEFT: StaticContent = StaticContent { web_path: "/ui/img/route_left.svg", content: include_bytes!("../../ui/dist/img/route_left.svg"), - ctype: SVG + ctype: SVG, }; static IMG_ROUTE_RIGHT: StaticContent = StaticContent { web_path: "/ui/img/route_right.svg", content: include_bytes!("../../ui/dist/img/route_right.svg"), - ctype: SVG + ctype: SVG, }; static FONTS_EL_ICONS: StaticContent = StaticContent { web_path: "/ui/fonts/element-icons.woff", content: include_bytes!("../../ui/dist/fonts/element-icons.woff"), - ctype: WOFF + ctype: WOFF, }; static FONTS_LATIN_100: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-100.woff", content: include_bytes!("../../ui/dist/fonts/lato-latin-100.woff"), - ctype: WOFF + ctype: WOFF, }; static FONTS_LATIN_100_2: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-100.woff2", content: include_bytes!("../../ui/dist/fonts/lato-latin-100.woff2"), - ctype: WOFF2 + ctype: WOFF2, }; static FONTS_LATIN_300: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-300.woff", content: include_bytes!("../../ui/dist/fonts/lato-latin-300.woff"), - ctype: WOFF + ctype: WOFF, }; static FONTS_LATIN_300_2: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-300.woff2", content: include_bytes!("../../ui/dist/fonts/lato-latin-300.woff2"), - ctype: WOFF2 + ctype: WOFF2, }; static FONTS_LATIN_400: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-400.woff", content: include_bytes!("../../ui/dist/fonts/lato-latin-400.woff"), - ctype: WOFF + ctype: WOFF, }; static FONTS_LATIN_400_2: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-400.woff2", content: include_bytes!("../../ui/dist/fonts/lato-latin-400.woff2"), - ctype: WOFF2 + ctype: WOFF2, }; static FONTS_LATIN_700: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-700.woff", content: include_bytes!("../../ui/dist/fonts/lato-latin-700.woff"), - ctype: WOFF + ctype: WOFF, }; static FONTS_LATIN_700_2: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-700.woff2", content: include_bytes!("../../ui/dist/fonts/lato-latin-700.woff2"), - ctype: WOFF2 + ctype: WOFF2, }; static FONTS_LATIN_900: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-900.woff", content: include_bytes!("../../ui/dist/fonts/lato-latin-900.woff"), - ctype: WOFF + ctype: WOFF, }; static FONTS_LATIN_900_2: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-900.woff2", content: include_bytes!("../../ui/dist/fonts/lato-latin-900.woff2"), - ctype: WOFF2 + ctype: WOFF2, }; static FONTS_LATIN_100_IT: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-100italic.woff", content: include_bytes!("../../ui/dist/fonts/lato-latin-100italic.woff"), - ctype: WOFF + ctype: WOFF, }; static FONTS_LATIN_100_IT_2: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-100italic.woff2", content: include_bytes!("../../ui/dist/fonts/lato-latin-100italic.woff2"), - ctype: WOFF2 + ctype: WOFF2, }; static FONTS_LATIN_300_IT: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-300italic.woff", content: include_bytes!("../../ui/dist/fonts/lato-latin-300italic.woff"), - ctype: WOFF + ctype: WOFF, }; static FONTS_LATIN_300_IT_2: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-300italic.woff2", content: include_bytes!("../../ui/dist/fonts/lato-latin-300italic.woff2"), - ctype: WOFF2 + ctype: WOFF2, }; static FONTS_LATIN_400_IT: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-400italic.woff", content: include_bytes!("../../ui/dist/fonts/lato-latin-400italic.woff"), - ctype: WOFF + ctype: WOFF, }; static FONTS_LATIN_400_IT_2: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-400italic.woff2", content: include_bytes!("../../ui/dist/fonts/lato-latin-400italic.woff2"), - ctype: WOFF2 + ctype: WOFF2, }; static FONTS_LATIN_700_IT: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-700italic.woff", content: include_bytes!("../../ui/dist/fonts/lato-latin-700italic.woff"), - ctype: WOFF + ctype: WOFF, }; static FONTS_LATIN_700_IT_2: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-700italic.woff2", content: include_bytes!("../../ui/dist/fonts/lato-latin-700italic.woff2"), - ctype: WOFF2 + ctype: WOFF2, }; static FONTS_LATIN_900_IT: StaticContent = StaticContent { web_path: "/ui/fonts/lato-latin-900italic.woff", content: include_bytes!("../../ui/dist/fonts/lato-latin-900italic.woff"), - ctype: WOFF + ctype: WOFF, }; static FONTS_SOURCE_CODE_200: StaticContent = StaticContent { web_path: "/ui/fonts/source-code-pro-latin-200.woff", content: include_bytes!("../../ui/dist/fonts/source-code-pro-latin-200.woff"), - ctype: WOFF + ctype: WOFF, }; static FONTS_SOURCE_CODE_200_2: StaticContent = StaticContent { web_path: "/ui/fonts/source-code-pro-latin-200.woff2", content: include_bytes!("../../ui/dist/fonts/source-code-pro-latin-200.woff2"), - ctype: WOFF2 + ctype: WOFF2, }; static FONTS_SOURCE_CODE_300: StaticContent = StaticContent { web_path: "/ui/fonts/source-code-pro-latin-300.woff", content: include_bytes!("../../ui/dist/fonts/source-code-pro-latin-300.woff"), - ctype: WOFF + ctype: WOFF, }; static FONTS_SOURCE_CODE_300_2: StaticContent = StaticContent { web_path: "/ui/fonts/source-code-pro-latin-300.woff2", content: include_bytes!("../../ui/dist/fonts/source-code-pro-latin-300.woff2"), - ctype: WOFF2 + ctype: WOFF2, }; static FONTS_SOURCE_CODE_400: StaticContent = StaticContent { web_path: "/ui/fonts/source-code-pro-latin-400.woff", content: include_bytes!("../../ui/dist/fonts/source-code-pro-latin-400.woff"), - ctype: WOFF + ctype: WOFF, }; static FONTS_SOURCE_CODE_400_2: StaticContent = StaticContent { web_path: "/ui/fonts/source-code-pro-latin-400.woff2", content: include_bytes!("../../ui/dist/fonts/source-code-pro-latin-400.woff2"), - ctype: WOFF2 + ctype: WOFF2, }; static FONTS_SOURCE_CODE_700: StaticContent = StaticContent { web_path: "/ui/fonts/source-code-pro-latin-700.woff", content: include_bytes!("../../ui/dist/fonts/source-code-pro-latin-700.woff"), - ctype: WOFF + ctype: WOFF, }; static FONTS_SOURCE_CODE_700_2: StaticContent = StaticContent { web_path: "/ui/fonts/source-code-pro-latin-700.woff2", content: include_bytes!("../../ui/dist/fonts/source-code-pro-latin-700.woff2"), - ctype: WOFF2 + ctype: WOFF2, }; static FONTS_SOURCE_CODE_900: StaticContent = StaticContent { web_path: "/ui/fonts/source-code-pro-latin-900.woff", content: include_bytes!("../../ui/dist/fonts/source-code-pro-latin-900.woff"), - ctype: WOFF + ctype: WOFF, }; static FONTS_SOURCE_CODE_900_2: StaticContent = StaticContent { web_path: "/ui/fonts/source-code-pro-latin-900.woff2", content: include_bytes!("../../ui/dist/fonts/source-code-pro-latin-900.woff2"), - ctype: WOFF2 + ctype: WOFF2, }; diff --git a/daemon/src/krillserver.rs b/daemon/src/krillserver.rs index 4e50648e..3a0ef8b4 100644 --- a/daemon/src/krillserver.rs +++ b/daemon/src/krillserver.rs @@ -3,34 +3,33 @@ use std::io; use std::path::PathBuf; use std::sync::Arc; -use bytes::Bytes; use bcder::Captured; +use bytes::Bytes; use rpki::uri; -use krill_commons::api::{publication, Entitlements, IssuanceRequest, IssuanceResponse}; use krill_commons::api::admin; -use krill_commons::api::admin::{Handle, Token, CertAuthInit, CertAuthPubMode, ParentCaContact, AddChildRequest, AddParentRequest}; -use krill_commons::api::ca::{TrustAnchorInfo, RcvdCert, CertAuthList, CertAuthInfo}; +use krill_commons::api::admin::{ + AddChildRequest, AddParentRequest, CertAuthInit, CertAuthPubMode, Handle, ParentCaContact, + Token, +}; +use krill_commons::api::ca::{CertAuthInfo, CertAuthList, RcvdCert, TrustAnchorInfo}; use krill_commons::api::publication::PublishRequest; -use krill_commons::util::softsigner::{OpenSslSigner, SignerError}; +use krill_commons::api::{publication, Entitlements, IssuanceRequest, IssuanceResponse}; use krill_commons::remote::api::ClientInfo; use krill_commons::remote::proxy; use krill_commons::remote::proxy::ProxyServer; use krill_commons::remote::rfc8181::ReplyMessage; -use krill_commons::remote::rfc8183::{RepositoryResponse, ChildRequest}; +use krill_commons::remote::rfc8183::{ChildRequest, RepositoryResponse}; use krill_commons::remote::sigmsg::SignedMessage; -use krill_pubd::PubServer; +use krill_commons::util::softsigner::{OpenSslSigner, SignerError}; use krill_pubd::publishers::Publisher; +use krill_pubd::PubServer; -use crate::ca::{ - self, - ta_handle, -}; use crate::auth::{Auth, Authorizer}; +use crate::ca::{self, ta_handle}; use crate::mq::EventQueueListener; use crate::scheduler::Scheduler; - //------------ KrillServer --------------------------------------------------- /// This is the master krill server that is doing all the orchestration @@ -66,8 +65,7 @@ pub struct KrillServer { // Responsible for background tasks, e.g. re-publishing #[allow(dead_code)] // just need to keep this in scope - scheduler: Scheduler - + scheduler: Scheduler, } /// # Set up and initialisation @@ -86,48 +84,32 @@ impl KrillServer { let authorizer = Authorizer::new(token); - let pubserver = Arc::new(PubServer::build( - base_uri.clone(), - rrdp_base_uri.clone(), - repo_dir, - work_dir - ).map_err(Error::PubServer)?); + let pubserver = Arc::new( + PubServer::build(base_uri.clone(), rrdp_base_uri.clone(), repo_dir, work_dir) + .map_err(Error::PubServer)?, + ); - - let proxy_server = ProxyServer::init( - work_dir, &service_uri - )?; + let proxy_server = ProxyServer::init(work_dir, &service_uri)?; let signer = OpenSslSigner::build(work_dir)?; let event_queue = Arc::new(EventQueueListener::in_mem()); - let caserver = Arc::new(ca::CaServer::build( - work_dir, - event_queue.clone(), - signer - )?); + let caserver = Arc::new(ca::CaServer::build(work_dir, event_queue.clone(), signer)?); - let scheduler = Scheduler::build( - event_queue, - caserver.clone(), - pubserver.clone() - ); + let scheduler = Scheduler::build(event_queue, caserver.clone(), pubserver.clone()); - Ok( - KrillServer { - service_uri, - work_dir: work_dir.clone(), - authorizer, - pubserver, - caserver, - proxy_server, - scheduler - } - ) + Ok(KrillServer { + service_uri, + work_dir: work_dir.clone(), + authorizer, + pubserver, + caserver, + proxy_server, + scheduler, + }) } - pub fn service_base_uri(&self) -> &uri::Https { &self.service_uri } @@ -138,21 +120,14 @@ impl KrillServer { self.authorizer.is_api_allowed(&token) } - pub fn is_api_allowed( - &self, - auth: &Auth - ) -> bool { + pub fn is_api_allowed(&self, auth: &Auth) -> bool { match auth { Auth::User(name) => name == "admin", - Auth::Bearer(token) => self.authorizer.is_api_allowed(&token) + Auth::Bearer(token) => self.authorizer.is_api_allowed(&token), } } - pub fn is_publication_api_allowed( - &self, - handle: &Handle, - auth: &Auth - ) -> bool { + pub fn is_publication_api_allowed(&self, handle: &Handle, auth: &Auth) -> bool { let allowed = match auth { Auth::User(name) => name == "admin", Auth::Bearer(token) => { @@ -169,46 +144,42 @@ impl KrillServer { if allowed { debug!("Access to publication api allowed") } else { - warn!("Access to publication api disallowed for handle: {}, and auth: {}", handle, auth); + warn!( + "Access to publication api disallowed for handle: {}, and auth: {}", + handle, auth + ); } allowed } - } /// # Configure publishers impl KrillServer { - /// Returns all currently configured publishers. (excludes deactivated) - pub fn publishers( - &self - ) -> Vec { + pub fn publishers(&self) -> Vec { self.pubserver.list_publishers() } /// Adds the publishers, blows up if it already existed. - pub fn add_publisher( - &mut self, - pbl_req: admin::PublisherRequest - ) -> EmptyRes { - self.pubserver.create_publisher(pbl_req).map_err(Error::PubServer) + pub fn add_publisher(&mut self, pbl_req: admin::PublisherRequest) -> EmptyRes { + self.pubserver + .create_publisher(pbl_req) + .map_err(Error::PubServer) } /// Removes a publisher, blows up if it didn't exist. - pub fn deactivate_publisher( - &mut self, - handle: &Handle - ) -> EmptyRes { - self.pubserver.deactivate_publisher(handle).map_err(Error::PubServer) + pub fn deactivate_publisher(&mut self, handle: &Handle) -> EmptyRes { + self.pubserver + .deactivate_publisher(handle) + .map_err(Error::PubServer) } /// Returns an option for a publisher. - pub fn publisher( - &self, - handle: &Handle - ) -> Result>, Error> { - self.pubserver.get_publisher(handle).map_err(Error::PubServer) + pub fn publisher(&self, handle: &Handle) -> Result>, Error> { + self.pubserver + .get_publisher(handle) + .map_err(Error::PubServer) } pub fn rrdp_base_path(&self) -> PathBuf { @@ -221,87 +192,75 @@ impl KrillServer { /// # Manage RFC8181 clients /// impl KrillServer { - pub fn rfc8181_clients(&self) ->Result, Error> { + pub fn rfc8181_clients(&self) -> Result, Error> { self.proxy_server.list_clients().map_err(Error::ProxyServer) } pub fn add_rfc8181_client(&self, client: ClientInfo) -> EmptyRes { - self.proxy_server.add_client(client).map_err(Error::ProxyServer) + self.proxy_server + .add_client(client) + .map_err(Error::ProxyServer) } pub fn repository_response(&self, handle: &Handle) -> Result { - let publisher = self.publisher(handle)? + let publisher = self + .publisher(handle)? .ok_or_else(|| Error::ProxyServer(proxy::Error::UnknownClient(handle.clone())))?; let sia_base = publisher.base_uri().clone(); - let service_uri = format!( - "{}rfc8181/{}", - self.service_uri.to_string(), - handle - ); + let service_uri = format!("{}rfc8181/{}", self.service_uri.to_string(), handle); let service_uri = uri::Https::from_string(service_uri).unwrap(); - let rrdp_notification_uri = format!( - "{}rrdp/notification.xml", - self.service_uri.to_string(), - ); + let rrdp_notification_uri = + format!("{}rrdp/notification.xml", self.service_uri.to_string(),); let rrdp_notification_uri = uri::Https::from_string(rrdp_notification_uri).unwrap(); - self.proxy_server.response( - handle, - service_uri, - sia_base, - rrdp_notification_uri - ).map_err(Error::ProxyServer) + self.proxy_server + .response(handle, service_uri, sia_base, rrdp_notification_uri) + .map_err(Error::ProxyServer) } pub fn handle_rfc8181_req( &self, msg: SignedMessage, - handle: Handle + handle: Handle, ) -> Result { debug!("Handling signed request for {}", &handle); match self.try_rfc8181_req(msg, handle) { Ok(captured) => Ok(captured), Err(Error::ProxyServer(e)) => { self.proxy_server.wrap_error(e).map_err(Error::ProxyServer) - }, - Err(e) => Err(e) + } + Err(e) => Err(e), } } /// Try to handle the rfc8181 request, and error out in case of /// issues. - fn try_rfc8181_req( - &self, - msg: SignedMessage, - handle: Handle - ) -> Result { + fn try_rfc8181_req(&self, msg: SignedMessage, handle: Handle) -> Result { let req = self.proxy_server.convert_rfc8181_req(msg, &handle)?; let reply = match req { - PublishRequest::List => { - ReplyMessage::ListReply( - self.pubserver.list(&handle)? - ) - }, + PublishRequest::List => ReplyMessage::ListReply(self.pubserver.list(&handle)?), PublishRequest::Delta(delta) => { self.pubserver.publish(&handle, delta)?; ReplyMessage::SuccessReply } }; - self.proxy_server.sign_reply(reply).map_err(Error::ProxyServer) + self.proxy_server + .sign_reply(reply) + .map_err(Error::ProxyServer) } } /// # Admin Trust Anchor /// impl KrillServer { - pub fn ta_info(&self) -> Option { + pub fn ta_info(&self) -> Option { match self.caserver.get_trust_anchor() { Ok(ta) => ta.as_ta_info().ok(), - _ => None + _ => None, } } @@ -310,7 +269,6 @@ impl KrillServer { } pub fn ta_init(&mut self) -> EmptyRes { - let ta_handle = ta_handle(); let repo_info = self.pubserver.repo_info_for(&ta_handle)?; @@ -331,11 +289,9 @@ impl KrillServer { self.add_publisher(req)?; // Add TA - self.caserver.init_ta( - repo_info, - ta_aia, - vec![ta_uri] - ).map_err(Error::CaServerError)?; + self.caserver + .init_ta(repo_info, ta_aia, vec![ta_uri]) + .map_err(Error::CaServerError)?; // Force initial publication self.caserver.republish(&ta_handle)?; @@ -345,10 +301,7 @@ impl KrillServer { /// Adds a child to the TA and returns the ParentCaInfo that the child /// will to contact this TA for resource requests. - pub fn ta_add_child( - &self, - req: AddChildRequest - ) -> Result { + pub fn ta_add_child(&self, req: AddChildRequest) -> Result { let contact = self.caserver.ta_add_child(req, &self.service_uri)?; Ok(contact) } @@ -373,15 +326,17 @@ impl KrillServer { /// Returns the child request for a CA, or NONE if the CA cannot be found. pub fn ca_child_req(&self, handle: &Handle) -> Option { - self.caserver.get_ca(handle).map(|ca| ca.child_request()).ok() + self.caserver + .get_ca(handle) + .map(|ca| ca.child_request()) + .ok() } pub fn ca_init(&mut self, init: CertAuthInit) -> EmptyRes { - let (handle, token, pub_mode) = init.unwrap(); let repo_info = match pub_mode { - CertAuthPubMode::Embedded => self.pubserver.repo_info_for(&handle)? + CertAuthPubMode::Embedded => self.pubserver.repo_info_for(&handle)?, }; let base_uri = repo_info.ca_repository(""); @@ -389,31 +344,18 @@ impl KrillServer { self.caserver.init_ca(&handle, token.clone(), repo_info)?; // Add publisher - let req = admin::PublisherRequest::new( - handle.clone(), - token.clone(), - base_uri, - ); + let req = admin::PublisherRequest::new(handle.clone(), token.clone(), base_uri); self.add_publisher(req)?; Ok(()) } - pub fn ca_add_parent( - &self, - handle: Handle, - parent: AddParentRequest - ) -> EmptyRes { + pub fn ca_add_parent(&self, handle: Handle, parent: AddParentRequest) -> EmptyRes { self.caserver.ca_add_parent(handle, parent)?; Ok(()) } - pub fn list( - &self, - parent: &Handle, - child: &Handle, - auth: Auth - ) -> KrillRes { + pub fn list(&self, parent: &Handle, child: &Handle, auth: Auth) -> KrillRes { Ok(self.caserver.list(parent, child, &auth.into())?) } @@ -422,24 +364,14 @@ impl KrillServer { parent: &Handle, child: &Handle, issue_req: IssuanceRequest, - auth: Auth + auth: Auth, ) -> KrillRes { - Ok(self.caserver.issue( - parent, - child, - issue_req, - auth.into() - )?) + Ok(self.caserver.issue(parent, child, issue_req, auth.into())?) } - pub fn rfc6492( - &self, - handle: Handle, - msg: SignedMessage - ) -> KrillRes { + pub fn rfc6492(&self, handle: Handle, msg: SignedMessage) -> KrillRes { Ok(self.caserver.rfc6492(&handle, msg)?) } - } /// # Handle publication requests @@ -448,24 +380,18 @@ impl KrillServer { /// Handles a publish delta request sent to the API, or.. through /// the CmsProxy. #[allow(clippy::needless_pass_by_value)] - pub fn handle_delta( - &self, - delta: publication::PublishDelta, - handle: &Handle - ) -> EmptyRes { - self.pubserver.publish(handle, delta).map_err(Error::PubServer) + pub fn handle_delta(&self, delta: publication::PublishDelta, handle: &Handle) -> EmptyRes { + self.pubserver + .publish(handle, delta) + .map_err(Error::PubServer) } /// Handles a list request sent to the API, or.. through the CmsProxy. - pub fn handle_list( - &self, - handle: &Handle - ) -> Result { + pub fn handle_list(&self, handle: &Handle) -> Result { self.pubserver.list(handle).map_err(Error::PubServer) } } - //------------ Response Aliases ---------------------------------------------- type KrillRes = Result; @@ -476,40 +402,50 @@ type EmptyRes = KrillRes<()>; #[derive(Debug, Display)] #[allow(clippy::large_enum_variant)] pub enum Error { - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] IoError(io::Error), - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] PubServer(krill_pubd::Error), - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] ProxyServer(proxy::Error), - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] SignerError(SignerError), - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] CaServerError(ca::ServerError), } impl From for Error { - fn from(e: io::Error) -> Self { Error::IoError(e) } + fn from(e: io::Error) -> Self { + Error::IoError(e) + } } impl From for Error { - fn from(e: krill_pubd::Error) -> Self { Error::PubServer(e) } + fn from(e: krill_pubd::Error) -> Self { + Error::PubServer(e) + } } impl From for Error { - fn from(e: proxy::Error) -> Self { Error::ProxyServer(e) } + fn from(e: proxy::Error) -> Self { + Error::ProxyServer(e) + } } impl From for Error { - fn from(e: SignerError) -> Self { Error::SignerError(e) } + fn from(e: SignerError) -> Self { + Error::SignerError(e) + } } impl From> for Error { - fn from(e: ca::ServerError) -> Self { Error::CaServerError(e) } + fn from(e: ca::ServerError) -> Self { + Error::CaServerError(e) + } } -// Tested through integration tests \ No newline at end of file +// Tested through integration tests diff --git a/daemon/src/lib.rs b/daemon/src/lib.rs index 47693afb..d4e4b899 100644 --- a/daemon/src/lib.rs +++ b/daemon/src/lib.rs @@ -1,23 +1,26 @@ extern crate actix_identity; -extern crate actix_web; extern crate actix_service; extern crate actix_session; +extern crate actix_web; extern crate base64; -extern crate bytes; extern crate bcder; +extern crate bytes; extern crate chrono; extern crate clap; extern crate clokwerk; extern crate core; -#[macro_use] extern crate derive_more; +#[macro_use] +extern crate derive_more; extern crate futures; extern crate hex; extern crate openssl; -#[macro_use] extern crate log; +#[macro_use] +extern crate log; extern crate rand; extern crate reqwest; extern crate rpki; -#[macro_use] extern crate serde; +#[macro_use] +extern crate serde; extern crate serde_json; extern crate syslog; extern crate tokio; @@ -25,21 +28,18 @@ extern crate toml; extern crate uuid; extern crate xml as xmlrs; +extern crate krill_client; extern crate krill_commons; extern crate krill_pubc; extern crate krill_pubd; -extern crate krill_client; - -pub mod ca; pub mod auth; +pub mod ca; pub mod config; pub mod endpoints; -pub mod krillserver; pub mod http; -pub mod test; +pub mod krillserver; pub mod scheduler; +pub mod test; mod mq; - - diff --git a/daemon/src/mq.rs b/daemon/src/mq.rs index 7b1f5b32..fb0d5641 100644 --- a/daemon/src/mq.rs +++ b/daemon/src/mq.rs @@ -7,20 +7,11 @@ use std::collections::VecDeque; use std::fmt; use std::sync::RwLock; -use krill_commons::api::admin::{ - Handle, - ParentCaContact -}; +use krill_commons::api::admin::{Handle, ParentCaContact}; use krill_commons::api::ca::PublicationDelta; use krill_commons::eventsourcing; -use crate::ca::{ - Signer, - Evt, - EvtDet, - CertAuth, - ParentHandle -}; +use crate::ca::{CertAuth, Evt, EvtDet, ParentHandle, Signer}; //------------ QueueEvent ---------------------------------------------------- @@ -35,12 +26,14 @@ pub enum QueueEvent { #[derive(Debug)] pub struct EventQueueListener { - q: RwLock> + q: RwLock>, } impl EventQueueListener { pub fn in_mem() -> Self { - EventQueueListener { q: RwLock::new(Box::new(MemoryEventQueue::new()))} + EventQueueListener { + q: RwLock::new(Box::new(MemoryEventQueue::new())), + } } } @@ -58,11 +51,9 @@ impl EventQueueListener { unsafe impl Send for EventQueueListener {} unsafe impl Sync for EventQueueListener {} - /// Implement listening for CertAuth Published events. impl eventsourcing::EventListener> for EventQueueListener { fn listen(&self, _ca: &CertAuth, event: &Evt) { - use krill_commons::eventsourcing::Event; let json = serde_json::to_string_pretty(&event).unwrap(); @@ -73,19 +64,15 @@ impl eventsourcing::EventListener> for EventQueueListener EvtDet::Published(_, _, _, delta) => { let evt = QueueEvent::Delta(handle.clone(), delta.clone()); self.push_back(evt); - }, + } EvtDet::TaPublished(delta) => { let evt = QueueEvent::Delta(handle.clone(), delta.clone()); self.push_back(evt); - }, + } EvtDet::ParentAdded(parent, contact) => { - let evt = QueueEvent::ParentAdded( - handle.clone(), - parent.clone(), - contact.clone() - ); + let evt = QueueEvent::ParentAdded(handle.clone(), parent.clone(), contact.clone()); self.push_back(evt); - }, + } _ => {} } } @@ -103,18 +90,19 @@ trait EventQueueStore: fmt::Debug { fn push_back(&self, evt: QueueEvent); } - //------------ MemoryEventQueue ---------------------------------------------- /// In memory event queue implementation. #[derive(Debug)] struct MemoryEventQueue { - q: RwLock> + q: RwLock>, } impl MemoryEventQueue { pub fn new() -> Self { - MemoryEventQueue { q: RwLock::new(VecDeque::new())} + MemoryEventQueue { + q: RwLock::new(VecDeque::new()), + } } } @@ -127,5 +115,3 @@ impl EventQueueStore for MemoryEventQueue { self.q.write().unwrap().push_back(evt); } } - - diff --git a/daemon/src/scheduler.rs b/daemon/src/scheduler.rs index f2efe100..a368d083 100644 --- a/daemon/src/scheduler.rs +++ b/daemon/src/scheduler.rs @@ -19,21 +19,21 @@ pub struct Scheduler { event_sh: ScheduleHandle, #[allow(dead_code)] // just need to keep this in scope - republish_sh: ScheduleHandle + republish_sh: ScheduleHandle, } impl Scheduler { pub fn build( event_queue: Arc, caserver: Arc>, - pubserver: Arc + pubserver: Arc, ) -> Self { - let event_sh = make_event_sh(event_queue, caserver.clone(), pubserver); let republish_sh = make_republish_sh(caserver); Scheduler { - event_sh, republish_sh + event_sh, + republish_sh, } } } @@ -41,7 +41,7 @@ impl Scheduler { fn make_event_sh( event_queue: Arc, caserver: Arc>, - pubserver: Arc + pubserver: Arc, ) -> ScheduleHandle { let mut scheduler = clokwerk::Scheduler::new(); scheduler.every(1.seconds()).run(move || { @@ -49,21 +49,18 @@ fn make_event_sh( match evt { QueueEvent::Delta(handle, delta) => { publish(&handle, delta, &pubserver); - }, + } QueueEvent::ParentAdded(handle, parent, contact) => { - if let Err(e) = caserver.get_updates_from_parent( - &handle, &parent, contact - ) { + if let Err(e) = caserver.get_updates_from_parent(&handle, &parent, contact) { error!("Getting updates for {}, error: {}", &handle, e); } - }, + } } } }); scheduler.watch_thread(Duration::from_millis(100)) } - fn make_republish_sh(caserver: Arc>) -> ScheduleHandle { let mut scheduler = clokwerk::Scheduler::new(); scheduler.every(1.hours()).run(move || { @@ -75,16 +72,10 @@ fn make_republish_sh(caserver: Arc>) -> ScheduleHandle { scheduler.watch_thread(Duration::from_millis(100)) } - -fn publish( - handle: &Handle, - delta: PublicationDelta, - pubserver: &PubServer -) { +fn publish(handle: &Handle, delta: PublicationDelta, pubserver: &PubServer) { debug!("Triggered publishing for CA: {}", handle); match pubserver.publish(handle, delta.into()) { Ok(()) => debug!("Published for CA: {}", handle), - Err(e) => error!("Failed to publish for CA: {}, error: {}", handle, e) + Err(e) => error!("Failed to publish for CA: {}, error: {}", handle, e), } } - diff --git a/daemon/src/test.rs b/daemon/src/test.rs index 349765ee..868d3ad0 100644 --- a/daemon/src/test.rs +++ b/daemon/src/test.rs @@ -1,18 +1,21 @@ //! Support for tests in other modules using a running krill server -use std::{thread, time}; use std::path::PathBuf; +use std::{thread, time}; -use krill_commons::util::test; -use krill_client::KrillClient; -use krill_client::Error; use krill_client::options::{Command, Options}; use krill_client::report::{ApiResponse, ReportFormat}; +use krill_client::Error; +use krill_client::KrillClient; +use krill_commons::util::test; use crate::config::Config; use crate::http::server; -pub fn test_with_krill_server(op: F) where F: FnOnce(PathBuf) -> () { +pub fn test_with_krill_server(op: F) +where + F: FnOnce(PathBuf) -> (), +{ test::test_under_tmp(|dir| { // Set up a test PubServer Config let server_conf = { @@ -22,13 +25,13 @@ pub fn test_with_krill_server(op: F) where F: FnOnce(PathBuf) -> () { }; // Start the server - thread::spawn(move || { server::start(&server_conf).unwrap() }); + thread::spawn(move || server::start(&server_conf).unwrap()); let mut tries = 0; loop { thread::sleep(time::Duration::from_millis(100)); if let Ok(_res) = health_check() { - break + break; } tries += 1; @@ -37,7 +40,6 @@ pub fn test_with_krill_server(op: F) where F: FnOnce(PathBuf) -> () { } } - op(dir) }) } @@ -51,24 +53,21 @@ fn health_check() -> Result { test::https("https://localhost:3000/"), "secret", ReportFormat::Default, - Command::Health + Command::Health, ); KrillClient::process(krillc_opts) } - pub fn krill_admin(command: Command) -> ApiResponse { let krillc_opts = Options::new( test::https("https://localhost:3000/"), "secret", ReportFormat::Json, - command + command, ); match KrillClient::process(krillc_opts) { Ok(res) => res, // ok - Err(e) => { - panic!("{}", e) - } + Err(e) => panic!("{}", e), } -} \ No newline at end of file +} diff --git a/daemon/tests/admin_publishers.rs b/daemon/tests/admin_publishers.rs index fc760342..7ce1c140 100644 --- a/daemon/tests/admin_publishers.rs +++ b/daemon/tests/admin_publishers.rs @@ -1,47 +1,36 @@ -extern crate krill_commons; extern crate krill_client; +extern crate krill_commons; extern crate krill_daemon; use krill_client::options::{AddPublisher, Command, PublishersCommand}; use krill_client::report::ApiResponse; +use krill_commons::api::admin::{Handle, Token}; use krill_commons::util::test; -use krill_commons::api::admin::{ - Handle, - Token -}; -use krill_daemon::test::{test_with_krill_server, krill_admin}; +use krill_daemon::test::{krill_admin, test_with_krill_server}; fn add_publisher(handle: &str, base_uri: &str, token: &str) { - let command = Command::Publishers(PublishersCommand::Add( - AddPublisher { - handle: Handle::from(handle), - base_uri: test::rsync(base_uri), - token: Token::from(token) - } - )); + let command = Command::Publishers(PublishersCommand::Add(AddPublisher { + handle: Handle::from(handle), + base_uri: test::rsync(base_uri), + token: Token::from(token), + })); krill_admin(command); } fn deactivate_publisher(handle: &str) { - let command = Command::Publishers( - PublishersCommand::Deactivate(handle.to_string()) - ); + let command = Command::Publishers(PublishersCommand::Deactivate(handle.to_string())); krill_admin(command); } fn list_publishers() -> ApiResponse { - let command = Command::Publishers( - PublishersCommand::List - ); + let command = Command::Publishers(PublishersCommand::List); krill_admin(command) } fn details_publisher(handle: &str) -> ApiResponse { - let command = Command::Publishers( - PublishersCommand::Details(handle.to_string()) - ); + let command = Command::Publishers(PublishersCommand::Details(handle.to_string())); krill_admin(command) } @@ -49,7 +38,6 @@ fn details_publisher(handle: &str) -> ApiResponse { #[test] fn admin_publishers() { test_with_krill_server(|_d| { - let handle = "alice"; let token = "secret"; let base_rsync_uri_alice = "rsync://localhost/repo/alice/"; @@ -65,8 +53,8 @@ fn admin_publishers() { assert_eq!(1, list.publishers().len()); let alice = &list.publishers().get(0).unwrap(); assert_eq!("alice", alice.id()); - }, - _ => panic!("Expected publisher list") + } + _ => panic!("Expected publisher list"), } // Find details for alice @@ -75,8 +63,8 @@ fn admin_publishers() { ApiResponse::PublisherDetails(details) => { assert_eq!("alice", details.handle()); assert_eq!(false, details.deactivated()); - }, - _ => panic!("Expected details") + } + _ => panic!("Expected details"), } // Remove alice @@ -88,10 +76,8 @@ fn admin_publishers() { ApiResponse::PublisherDetails(details) => { assert_eq!("alice", details.handle()); assert_eq!(true, details.deactivated()); - }, - _ => panic!("Expected details") + } + _ => panic!("Expected details"), } - }); } - diff --git a/daemon/tests/ca_under_ta.rs b/daemon/tests/ca_under_ta.rs index 88a257b0..3baf9a5e 100644 --- a/daemon/tests/ca_under_ta.rs +++ b/daemon/tests/ca_under_ta.rs @@ -1,93 +1,82 @@ -extern crate krill_daemon; extern crate krill_client; extern crate krill_commons; +extern crate krill_daemon; extern crate krill_pubc; -use krill_client::options::{ - CaCommand, - Command, - TrustAnchorCommand, -}; +use krill_client::options::{CaCommand, Command, TrustAnchorCommand}; use krill_client::report::ApiResponse; -use krill_commons::api::ca::{ResourceSet, CertAuthInfo, CaParentsInfo}; -use krill_commons::api::admin::{AddChildRequest, CertAuthInit, CertAuthPubMode, Handle, ParentCaContact, AddParentRequest, Token, ChildAuthRequest}; +use krill_commons::api::admin::{ + AddChildRequest, AddParentRequest, CertAuthInit, CertAuthPubMode, ChildAuthRequest, Handle, + ParentCaContact, Token, +}; +use krill_commons::api::ca::{CaParentsInfo, CertAuthInfo, ResourceSet}; use krill_commons::remote::rfc8183; use krill_daemon::ca::ta_handle; -use krill_daemon::test::{test_with_krill_server, krill_admin, wait_seconds}; - +use krill_daemon::test::{krill_admin, test_with_krill_server, wait_seconds}; fn init_ta() { krill_admin(Command::TrustAnchor(TrustAnchorCommand::Init)); } fn init_child(handle: &Handle, token: &Token) { - let init = CertAuthInit::new( - handle.clone(), token.clone(), CertAuthPubMode::Embedded - ); + let init = CertAuthInit::new(handle.clone(), token.clone(), CertAuthPubMode::Embedded); krill_admin(Command::CertAuth(CaCommand::Init(init))); } fn child_request(handle: &Handle) -> rfc8183::ChildRequest { - match krill_admin( - Command::CertAuth(CaCommand::ChildRequest(handle.clone())) - ) { + match krill_admin(Command::CertAuth(CaCommand::ChildRequest(handle.clone()))) { ApiResponse::Rfc8183ChildRequest(req) => req, - _ => panic!("Expected child request") + _ => panic!("Expected child request"), } - } fn add_child_to_ta_embedded( handle: &Handle, token: &Token, - resources: ResourceSet + resources: ResourceSet, ) -> ParentCaContact { let auth = ChildAuthRequest::Embedded(token.clone()); let req = AddChildRequest::new(handle.clone(), resources, auth); - let res = krill_admin( - Command::TrustAnchor(TrustAnchorCommand::AddChild(req)) - ); + let res = krill_admin(Command::TrustAnchor(TrustAnchorCommand::AddChild(req))); match res { ApiResponse::ParentCaInfo(info) => info, - _ => panic!("Expected ParentCaInfo response") + _ => panic!("Expected ParentCaInfo response"), } } fn add_child_to_ta_rfc6492( handle: &Handle, req: rfc8183::ChildRequest, - resources: ResourceSet + resources: ResourceSet, ) -> ParentCaContact { let auth = ChildAuthRequest::Rfc8183(req); let req = AddChildRequest::new(handle.clone(), resources, auth); - let res = krill_admin( - Command::TrustAnchor(TrustAnchorCommand::AddChild(req)) - ); + let res = krill_admin(Command::TrustAnchor(TrustAnchorCommand::AddChild(req))); match res { ApiResponse::ParentCaInfo(info) => info, - _ => panic!("Expected ParentCaInfo response") + _ => panic!("Expected ParentCaInfo response"), } } fn add_parent_to_ca(handle: &Handle, parent: AddParentRequest) { - krill_admin( - Command::CertAuth(CaCommand::AddParent(handle.clone(), parent)) - ); + krill_admin(Command::CertAuth(CaCommand::AddParent( + handle.clone(), + parent, + ))); } fn ca_details(handle: &Handle) -> CertAuthInfo { match krill_admin(Command::CertAuth(CaCommand::Show(handle.clone()))) { ApiResponse::CertAuthInfo(inf) => inf, - _ => panic!("Expected cert auth info") + _ => panic!("Expected cert auth info"), } - } fn wait_for_resources_on_current_key(handle: &Handle, resources: &ResourceSet) { let tries = 30; - for counter in 1..tries+1 { + for counter in 1..tries + 1 { if counter == tries { panic!("cms child did not get its resource certificate"); } @@ -99,7 +88,7 @@ fn wait_for_resources_on_current_key(handle: &Handle, resources: &ResourceSet) { if let Some(rc) = parent.resources().get("all") { if let Some(key) = rc.current_key() { assert_eq!(resources, key.resources()); - break + break; } } } @@ -109,29 +98,21 @@ fn wait_for_resources_on_current_key(handle: &Handle, resources: &ResourceSet) { } } - #[test] fn ca_under_ta() { - test_with_krill_server(|_d|{ - + test_with_krill_server(|_d| { let ta_handle = ta_handle(); init_ta(); let emb_child_handle = Handle::from("child"); let emb_child_token = Token::from("child"); - let emb_child_resources = ResourceSet::from_strs( - "", - "192.168.0.0/16", - "" - ).unwrap(); + let emb_child_resources = ResourceSet::from_strs("", "192.168.0.0/16", "").unwrap(); init_child(&emb_child_handle, &emb_child_token); - let parent = { - let parent_contact = add_child_to_ta_embedded( - &emb_child_handle, &emb_child_token, emb_child_resources - ); + let parent_contact = + add_child_to_ta_embedded(&emb_child_handle, &emb_child_token, emb_child_resources); AddParentRequest::new(ta_handle.clone(), parent_contact) }; @@ -139,11 +120,7 @@ fn ca_under_ta() { let cms_child_handle = Handle::from("rfc6492"); let cms_child_token = Token::from("rfc6492"); - let cms_child_resources = ResourceSet::from_strs( - "", - "10.0.0.0/16", - "" - ).unwrap(); + let cms_child_resources = ResourceSet::from_strs("", "10.0.0.0/16", "").unwrap(); init_child(&cms_child_handle, &cms_child_token); let req = child_request(&cms_child_handle); @@ -151,9 +128,8 @@ fn ca_under_ta() { eprintln!("Child Request: {}", req); let parent = { - let contact = add_child_to_ta_rfc6492( - &cms_child_handle, req, cms_child_resources.clone() - ); + let contact = + add_child_to_ta_rfc6492(&cms_child_handle, req, cms_child_resources.clone()); AddParentRequest::new(ta_handle.clone(), contact) }; diff --git a/daemon/tests/client_publish.rs b/daemon/tests/client_publish.rs index 5b6b26d8..6272fce4 100644 --- a/daemon/tests/client_publish.rs +++ b/daemon/tests/client_publish.rs @@ -3,32 +3,24 @@ extern crate krill_commons; extern crate krill_daemon; extern crate krill_pubc; -use std::collections::HashSet; -use std::path::PathBuf; -use krill_client::KrillClient; use krill_client::options::{ - AddPublisher, - AddRfc8181Client, - Command, - Options, - PublishersCommand, - Rfc8181Command, + AddPublisher, AddRfc8181Client, Command, Options, PublishersCommand, Rfc8181Command, }; use krill_client::report::ReportFormat; -use krill_commons::api::admin::{ - Handle, - Token -}; +use krill_client::KrillClient; +use krill_commons::api::admin::{Handle, Token}; use krill_commons::api::publication::ListReply; use krill_commons::remote::rfc8183::RepositoryResponse; -use krill_commons::util::file::CurrentFile; use krill_commons::util::file; +use krill_commons::util::file::CurrentFile; use krill_commons::util::httpclient; use krill_commons::util::test; -use krill_pubc::{ApiResponse, Format}; use krill_pubc::apiclient; use krill_pubc::cmsclient; use krill_pubc::cmsclient::PubClient; +use krill_pubc::{ApiResponse, Format}; +use std::collections::HashSet; +use std::path::PathBuf; fn list(server_uri: &str, handle: &str, token: &str) -> apiclient::Options { let conn = apiclient::Connection::build(server_uri, handle, token).unwrap(); @@ -43,7 +35,7 @@ fn sync( handle: &str, token: &str, syncdir: &PathBuf, - base_uri: &str + base_uri: &str, ) -> apiclient::Options { let conn = apiclient::Connection::build(server_uri, handle, token).unwrap(); let cmd = apiclient::Command::sync(syncdir.to_str().unwrap(), base_uri).unwrap(); @@ -57,31 +49,25 @@ fn execute_krillc_command(command: Command) { test::https("https://localhost:3000/"), "secret", ReportFormat::Default, - command + command, ); match KrillClient::process(krillc_opts) { - Ok(_res) => {}, // ok - Err(e) => { - panic!("{}", e) - } + Ok(_res) => {} // ok + Err(e) => panic!("{}", e), } } fn add_publisher(handle: &str, base_uri: &str, token: &str) { - let command = Command::Publishers(PublishersCommand::Add( - AddPublisher { - handle: Handle::from(handle), - base_uri: test::rsync(base_uri), - token: Token::from(token) - } - )); + let command = Command::Publishers(PublishersCommand::Add(AddPublisher { + handle: Handle::from(handle), + base_uri: test::rsync(base_uri), + token: Token::from(token), + })); execute_krillc_command(command); } fn remove_publisher(handle: &str) { - let command = Command::Publishers( - PublishersCommand::Deactivate(handle.to_string()) - ); + let command = Command::Publishers(PublishersCommand::Deactivate(handle.to_string())); execute_krillc_command(command); } @@ -91,18 +77,14 @@ fn rfc8181_client_init(handle: &str, state_dir: &PathBuf) { rfc8181_client_process_command(command, &state_dir); } -fn rfc8181_client_add(state_dir: &PathBuf) { +fn rfc8181_client_add(state_dir: &PathBuf) { let mut pr_path = state_dir.clone(); pr_path.push("request.xml"); let command = cmsclient::Command::publisher_request(pr_path.clone()); rfc8181_client_process_command(command, &state_dir); - let command = Command::Rfc8181( - Rfc8181Command::Add( - AddRfc8181Client { xml: pr_path } - ) - ); + let command = Command::Rfc8181(Rfc8181Command::Add(AddRfc8181Client { xml: pr_path })); execute_krillc_command(command); } @@ -119,7 +101,7 @@ fn rfc8181_client_list(state_dir: &PathBuf) -> ListReply { let api_response = rfc8181_client_process_command(command, &state_dir); match api_response { ApiResponse::Success => panic!("Expected list"), - ApiResponse::List(list) => list + ApiResponse::List(list) => list, } } @@ -137,13 +119,14 @@ fn rfc8181_client_process_command(command: cmsclient::Command, state_dir: &PathB #[allow(dead_code)] fn get_repository_response(handle: &str) -> RepositoryResponse { - let uri = format!("https://localhost:3000/api/v1/rfc8181/{}/response.xml", handle); + let uri = format!( + "https://localhost:3000/api/v1/rfc8181/{}/response.xml", + handle + ); let content_type = "application/xml"; let token = Token::from("secret"); - let xml = httpclient::get_text( - &uri, content_type, Some(&token) - ).unwrap(); + let xml = httpclient::get_text(&uri, content_type, Some(&token)).unwrap(); RepositoryResponse::validate(xml.as_bytes()).unwrap() } @@ -151,7 +134,6 @@ fn get_repository_response(handle: &str) -> RepositoryResponse { #[test] fn client_publish() { krill_daemon::test::test_with_krill_server(|d| { - let server_uri = "https://localhost:3000/"; let handle = "alice"; let token = "secret"; @@ -163,57 +145,46 @@ fn client_publish() { // Calls to api should require the correct token { - let res = apiclient::execute(list( - server_uri, - handle, - "wrong token" - )); + let res = apiclient::execute(list(server_uri, handle, "wrong token")); match res { - Err(apiclient::Error::HttpClientError - (httpclient::Error::Forbidden)) => {}, + Err(apiclient::Error::HttpClientError(httpclient::Error::Forbidden)) => {} Err(e) => panic!("Expected forbidden, got: {}", e), - _ => panic!("Expected forbidden") + _ => panic!("Expected forbidden"), } } // List files at server, expect no files { - let list = apiclient::execute(list( - server_uri, - handle, - token - )).unwrap(); + let list = apiclient::execute(list(server_uri, handle, token)).unwrap(); match list { ApiResponse::List(list) => { assert_eq!(0, list.elements().len()); - }, - _ => panic!("Expected list") + } + _ => panic!("Expected list"), } } - // Create files on disk to sync let sync_dir = test::sub_dir(&d); let file_a = CurrentFile::new( test::rsync("rsync://localhost/repo/alice/a.txt"), - &test::as_bytes("a") + &test::as_bytes("a"), ); let file_b = CurrentFile::new( test::rsync("rsync://localhost/repo/alice/b.txt"), - &test::as_bytes("b") + &test::as_bytes("b"), ); let file_c = CurrentFile::new( test::rsync("rsync://localhost/repo/alice/c.txt"), - &test::as_bytes("c") + &test::as_bytes("c"), ); file::save_in_dir(&file_a.to_bytes(), &sync_dir, "a.txt").unwrap(); file::save_in_dir(&file_b.to_bytes(), &sync_dir, "b.txt").unwrap(); file::save_in_dir(&file_c.to_bytes(), &sync_dir, "c.txt").unwrap(); - // Must refuse syncing files outside of publisher base dir { let api_res = apiclient::execute(sync( @@ -221,13 +192,12 @@ fn client_publish() { handle, token, &sync_dir, - base_rsync_uri_bob + base_rsync_uri_bob, )); assert!(api_res.is_err()) } - // Sync files { let api_res = apiclient::execute(sync( @@ -235,45 +205,37 @@ fn client_publish() { handle, token, &sync_dir, - base_rsync_uri_alice - )).unwrap(); + base_rsync_uri_alice, + )) + .unwrap(); assert_eq!(ApiResponse::Success, api_res); } // We should now see these files when we list { - let list = apiclient::execute(list( - server_uri, - handle, - token - )).unwrap(); + let list = apiclient::execute(list(server_uri, handle, token)).unwrap(); match list { ApiResponse::List(list) => { assert_eq!(3, list.elements().len()); - let returned_set: HashSet<_> = list.elements().iter().collect(); + let returned_set: HashSet<_> = list.elements().iter().collect(); let list_el_a = file_a.into_list_element(); let list_el_b = file_b.into_list_element(); let list_el_c = file_c.clone().into_list_element(); - let expected_elements = vec![ - &list_el_a, - &list_el_b, - &list_el_c - ]; + let expected_elements = vec![&list_el_a, &list_el_b, &list_el_c]; let expected_set: HashSet<_> = expected_elements.into_iter().collect(); assert_eq!(expected_set, returned_set); - }, - _ => panic!("Expected list") + } + _ => panic!("Expected list"), } } // XXX TODO We should also see these files in RRDP - // Now we should be able to delete it all again file::delete_in_dir(&sync_dir, "a.txt").unwrap(); file::delete_in_dir(&sync_dir, "b.txt").unwrap(); @@ -285,33 +247,30 @@ fn client_publish() { handle, token, &sync_dir, - base_rsync_uri_alice - )).unwrap(); + base_rsync_uri_alice, + )) + .unwrap(); assert_eq!(ApiResponse::Success, api_res); } // List files at server, expect 1 file (c.txt) { - let list = apiclient::execute(list( - server_uri, - handle, - token - )).unwrap(); + let list = apiclient::execute(list(server_uri, handle, token)).unwrap(); match list { ApiResponse::List(list) => { assert_eq!(1, list.elements().len()); - let returned_set: HashSet<_> = list.elements().iter().collect(); + let returned_set: HashSet<_> = list.elements().iter().collect(); let list_el_c = file_c.into_list_element(); let expected_elements = vec![&list_el_c]; let expected_set: HashSet<_> = expected_elements.into_iter().collect(); assert_eq!(expected_set, returned_set); - }, - _ => panic!("Expected list") + } + _ => panic!("Expected list"), } } @@ -354,15 +313,15 @@ fn client_publish() { let sync_dir = test::sub_dir(&d); let file_a = CurrentFile::new( test::rsync("rsync://localhost/repo/alice/a.txt"), - &test::as_bytes("a") + &test::as_bytes("a"), ); let file_b = CurrentFile::new( test::rsync("rsync://localhost/repo/alice/b.txt"), - &test::as_bytes("b") + &test::as_bytes("b"), ); let file_c = CurrentFile::new( test::rsync("rsync://localhost/repo/alice/c.txt"), - &test::as_bytes("c") + &test::as_bytes("c"), ); file::save_in_dir(&file_a.to_bytes(), &sync_dir, "a.txt").unwrap(); @@ -376,5 +335,4 @@ fn client_publish() { let list = rfc8181_client_list(&state_dir); assert_eq!(3, list.elements().len()); }); - -} \ No newline at end of file +} diff --git a/daemon/tests/embedded_trust_anchor.rs b/daemon/tests/embedded_trust_anchor.rs index b184a2f5..1432a696 100644 --- a/daemon/tests/embedded_trust_anchor.rs +++ b/daemon/tests/embedded_trust_anchor.rs @@ -1,21 +1,20 @@ -extern crate krill_daemon; extern crate krill_client; extern crate krill_commons; +extern crate krill_daemon; -use krill_daemon::test::{test_with_krill_server, krill_admin}; use krill_client::options::{Command, TrustAnchorCommand}; +use krill_daemon::test::{krill_admin, test_with_krill_server}; #[test] fn embedded_trust_anchor() { - test_with_krill_server(|_d|{ - + test_with_krill_server(|_d| { let command = Command::TrustAnchor(TrustAnchorCommand::Init); krill_admin(command); let command = Command::TrustAnchor(TrustAnchorCommand::Show); krill_admin(command); -// let command = Command::TrustAnchor(TrustAnchorCommand::Publish); -// let _res = execute_krillc_command(command); + // let command = Command::TrustAnchor(TrustAnchorCommand::Publish); + // let _res = execute_krillc_command(command); }); -} \ No newline at end of file +} diff --git a/pubc/src/apiclient.rs b/pubc/src/apiclient.rs index d298a59f..bd0056dc 100644 --- a/pubc/src/apiclient.rs +++ b/pubc/src/apiclient.rs @@ -7,7 +7,7 @@ use rpki::uri; use krill_commons::api::admin::Token; use krill_commons::api::publication; -use krill_commons::util::{httpclient, file}; +use krill_commons::util::{file, httpclient}; use crate::{create_delta, ApiResponse, Format}; @@ -16,7 +16,7 @@ use crate::{create_delta, ApiResponse, Format}; #[derive(Clone, Debug, Eq, PartialEq)] pub enum Command { List, - Sync(PathBuf, uri::Rsync) + Sync(PathBuf, uri::Rsync), } impl Command { @@ -25,7 +25,7 @@ impl Command { } pub fn sync(dir: &str, base_uri: &str) -> Result { let dir = PathBuf::from(dir); - if ! base_uri.ends_with('/') { + if !base_uri.ends_with('/') { Err(Error::InvalidBaseUri) } else { let uri = uri::Rsync::from_str(base_uri)?; @@ -34,8 +34,6 @@ impl Command { } } - - //------------ Connection --------------------------------------------------- pub struct Connection { @@ -50,28 +48,26 @@ pub struct Connection { } impl Connection { - pub fn build( - server_uri: &str, - handle: &str, - token: &str - ) -> Result { + pub fn build(server_uri: &str, handle: &str, token: &str) -> Result { let server_uri = uri::Https::from_str(server_uri)?; - let handle = handle.to_string(); - let token = Token::from(token); - Ok(Connection {server_uri, handle, token }) + let handle = handle.to_string(); + let token = Token::from(token); + Ok(Connection { + server_uri, + handle, + token, + }) } } - //------------ Options ------------------------------------------------------ pub struct Options { connection: Connection, cmd: Command, - format: Format + format: Format, } - impl Options { fn parts(self) -> (Connection, Command) { (self.connection, self.cmd) @@ -79,73 +75,81 @@ impl Options { } impl Options { - pub fn new( - connection: Connection, - cmd: Command, - format: Format - ) -> Self { - Options { connection, cmd, format } + pub fn new(connection: Connection, cmd: Command, format: Format) -> Self { + Options { + connection, + cmd, + format, + } } - pub fn format(&self) -> &Format { &self.format } + pub fn format(&self) -> &Format { + &self.format + } } - impl Options { pub fn create() -> Result { let m = App::new("NLnet Labs RRDP client (API)") .version("0.1b") - .arg(Arg::with_name("server") - .short("s") - .long("server") - .value_name("uri") - .help("Base server uri.") - .required(true) + .arg( + Arg::with_name("server") + .short("s") + .long("server") + .value_name("uri") + .help("Base server uri.") + .required(true), ) - .arg(Arg::with_name("handle") - .short("h") - .long("handle") - .value_name("name") - .help("Handle by which this client is known to the server.") - .required(true) + .arg( + Arg::with_name("handle") + .short("h") + .long("handle") + .value_name("name") + .help("Handle by which this client is known to the server.") + .required(true), ) - .arg(Arg::with_name("token") - .short("t") - .long("token") - .value_name("passphrase") - .help("Token for this particular client handle at the server") - .required(true) + .arg( + Arg::with_name("token") + .short("t") + .long("token") + .value_name("passphrase") + .help("Token for this particular client handle at the server") + .required(true), ) - .arg(Arg::with_name("format") - .short("f") - .long("format") - .value_name("text|json|none") - .help("Specify the output format. Defaults to 'text'.") - .required(false) + .arg( + Arg::with_name("format") + .short("f") + .long("format") + .value_name("text|json|none") + .help("Specify the output format. Defaults to 'text'.") + .required(false), ) .subcommand(SubCommand::with_name("list")) - .subcommand(SubCommand::with_name("sync") - .arg(Arg::with_name("dir") - .short("d") - .long("dir") - .value_name("directory") - .help("Directory to synchronise.") - .required(true) - ) - .arg(Arg::with_name("rsync_base") - .short("r") - .long("rsync_base") - .value_name("uri") - .help("Base rsync URI (name space) for this dir.") - .required(true) - ) + .subcommand( + SubCommand::with_name("sync") + .arg( + Arg::with_name("dir") + .short("d") + .long("dir") + .value_name("directory") + .help("Directory to synchronise.") + .required(true), + ) + .arg( + Arg::with_name("rsync_base") + .short("r") + .long("rsync_base") + .value_name("uri") + .help("Base rsync URI (name space) for this dir.") + .required(true), + ), ) .get_matches(); let connection = { let server_uri = m.value_of("server").unwrap(); - let handle = m.value_of("handle").unwrap(); - let token = m.value_of("token").unwrap(); + let handle = m.value_of("handle").unwrap(); + let token = m.value_of("token").unwrap(); Connection::build(server_uri, handle, token)? }; @@ -157,7 +161,7 @@ impl Options { let rsync_uri = m.value_of("rsync_base").unwrap(); Command::sync(dir, rsync_uri)? } else { - return Err(Error::NoCommand) + return Err(Error::NoCommand); } }; @@ -174,16 +178,11 @@ pub fn execute(options: Options) -> Result { let (connection, cmd) = options.parts(); match cmd { - Command::List => { - list_query(&connection).map(ApiResponse::List) - }, - Command::Sync(dir, rsync_uri) => { - sync(&connection, &dir, &rsync_uri) - } + Command::List => list_query(&connection).map(ApiResponse::List), + Command::Sync(dir, rsync_uri) => sync(&connection, &dir, &rsync_uri), } } - fn list_query(connection: &Connection) -> Result { let uri = format!( "{}publication/{}", @@ -191,31 +190,23 @@ fn list_query(connection: &Connection) -> Result &connection.handle ); - match httpclient::get_json::( - &uri, - Some(&connection.token) - ) { + match httpclient::get_json::(&uri, Some(&connection.token)) { Err(e) => Err(Error::HttpClientError(e)), - Ok(list) => Ok(list) + Ok(list) => Ok(list), } } fn sync( connection: &Connection, dir: &PathBuf, - base_rsync: &uri::Rsync + base_rsync: &uri::Rsync, ) -> Result { let list_reply = list_query(connection)?; - let delta = create_delta( - &list_reply, - dir, - base_rsync - )?; + let delta = create_delta(&list_reply, dir, base_rsync)?; let uri = format!( "{}publication/{}", - &connection.server_uri, - &connection.handle + &connection.server_uri, &connection.handle ); httpclient::post_json(&uri, delta, Some(&connection.token))?; @@ -239,36 +230,44 @@ pub enum Error { #[display(fmt = "Expected a response body, but got nothing.")] NoResponse, - #[display(fmt="HTTP client error: {}", _0)] + #[display(fmt = "HTTP client error: {}", _0)] HttpClientError(httpclient::Error), - #[display(fmt="Received invalid json response: {}", _0)] + #[display(fmt = "Received invalid json response: {}", _0)] JsonError(serde_json::Error), - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] FileError(file::Error), - #[display(fmt="Unsupported output format. Use text, json or none.")] + #[display(fmt = "Unsupported output format. Use text, json or none.")] UnsupportedOutputFormat, - #[display(fmt="Base URI must end with '/'.")] + #[display(fmt = "Base URI must end with '/'.")] InvalidBaseUri, } impl From for Error { - fn from(e: uri::Error) -> Self { Error::UriError(e) } + fn from(e: uri::Error) -> Self { + Error::UriError(e) + } } impl From for Error { - fn from(e: serde_json::Error) -> Self { Error::JsonError(e) } + fn from(e: serde_json::Error) -> Self { + Error::JsonError(e) + } } impl From for Error { - fn from(e: file::Error) -> Self { Error::FileError(e) } + fn from(e: file::Error) -> Self { + Error::FileError(e) + } } impl From for Error { - fn from(e: httpclient::Error) -> Self { Error::HttpClientError(e) } + fn from(e: httpclient::Error) -> Self { + Error::HttpClientError(e) + } } -// -- Tested in integration tests. \ No newline at end of file +// -- Tested in integration tests. diff --git a/pubc/src/bin/pubc.rs b/pubc/src/bin/pubc.rs index 3aa4d659..b5520b77 100644 --- a/pubc/src/bin/pubc.rs +++ b/pubc/src/bin/pubc.rs @@ -4,9 +4,8 @@ extern crate krill_pubc; use krill_pubc::apiclient; fn main() { - let options = match apiclient::Options::create() { - Ok(o) => o, + Ok(o) => o, Err(e) => { eprintln!("Error parsing options: {}", e); ::std::process::exit(1); @@ -22,5 +21,4 @@ fn main() { ::std::process::exit(1); } } - -} \ No newline at end of file +} diff --git a/pubc/src/bin/pubc_cms.rs b/pubc/src/bin/pubc_cms.rs index 0cc9fc57..f9fe15b1 100644 --- a/pubc/src/bin/pubc_cms.rs +++ b/pubc/src/bin/pubc_cms.rs @@ -5,9 +5,8 @@ use krill_pubc::cmsclient; use krill_pubc::cmsclient::PubClient; fn main() { - let options = match cmsclient::Options::create() { - Ok(o) => o, + Ok(o) => o, Err(e) => { eprintln!("{}", e); ::std::process::exit(1); @@ -23,5 +22,4 @@ fn main() { ::std::process::exit(1); } } - -} \ No newline at end of file +} diff --git a/pubc/src/cmsclient.rs b/pubc/src/cmsclient.rs index 2cefaa80..36cb89f0 100644 --- a/pubc/src/cmsclient.rs +++ b/pubc/src/cmsclient.rs @@ -1,17 +1,17 @@ -use std::io; -use std::path::PathBuf; +use crate::{create_delta, ApiResponse, Format}; use clap::{App, Arg, SubCommand}; -use rpki::crypto::PublicKeyFormat; -use rpki::crypto::Signer; use krill_commons::api::publication::ListReply; -use krill_commons::util::{softsigner, file}; -use krill_commons::util::softsigner::OpenSslSigner; use krill_commons::remote::builder::IdCertBuilder; +use krill_commons::remote::id::{MyIdentity, MyRepoInfo, ParentInfo}; +use krill_commons::remote::proxy::{ClientError, ClientProxy}; use krill_commons::remote::rfc8183; use krill_commons::remote::rfc8183::RepositoryResponse; -use krill_commons::remote::id::{MyIdentity, ParentInfo, MyRepoInfo}; -use krill_commons::remote::proxy::{ClientProxy, ClientError}; -use crate::{create_delta, ApiResponse, Format}; +use krill_commons::util::softsigner::OpenSslSigner; +use krill_commons::util::{file, softsigner}; +use rpki::crypto::PublicKeyFormat; +use rpki::crypto::Signer; +use std::io; +use std::path::PathBuf; #[derive(Debug, Deserialize, Eq, PartialEq)] pub enum Command { @@ -19,7 +19,7 @@ pub enum Command { PublisherRequest(PathBuf), RepoResponse(PathBuf), List, - Sync(PathBuf) + Sync(PathBuf), } impl Command { @@ -44,9 +44,8 @@ impl Command { } } - pub struct PubClient { - state_dir: PathBuf + state_dir: PathBuf, } impl PubClient { @@ -58,21 +57,21 @@ impl PubClient { let request = client.publisher_request()?; request.save(&path)?; Ok(ApiResponse::Success) - }, + } Command::RepoResponse(path) => { let xml = file::read(&path)?; let response = RepositoryResponse::validate(xml.as_ref())?; client.process_repo_response(&response)?; Ok(ApiResponse::Success) - }, + } Command::Init(name) => { client.init(&name)?; Ok(ApiResponse::Success) - }, + } Command::List => { let reply = client.list()?; Ok(ApiResponse::List(reply)) - }, + } Command::Sync(dir) => { client.sync(&dir)?; Ok(ApiResponse::Success) @@ -81,7 +80,9 @@ impl PubClient { } fn build(state_dir: &PathBuf) -> Result { - Ok(PubClient { state_dir: state_dir.clone() }) + Ok(PubClient { + state_dir: state_dir.clone(), + }) } /// Initialises a new publication client, using a new key pair, and @@ -98,31 +99,26 @@ impl PubClient { } /// Makes a publisher request, which can presented as an RFC8183 xml. - fn publisher_request( - &mut self - ) -> Result { + fn publisher_request(&mut self) -> Result { let id = self.my_identity()?; - Ok( - rfc8183::PublisherRequest::new( - None, - id.name(), - id.id_cert().clone() - ) - ) + Ok(rfc8183::PublisherRequest::new( + None, + id.name(), + id.id_cert().clone(), + )) } /// Process the publication server parent response. fn process_repo_response( &mut self, - response: &rfc8183::RepositoryResponse + response: &rfc8183::RepositoryResponse, ) -> Result<(), Error> { - // Store parent info { let parent_info = ParentInfo::new( response.publisher_handle().clone(), response.id_cert().clone(), - response.service_uri().clone() + response.service_uri().clone(), ); file::save_json(&parent_info, &self.path_my_parent())?; @@ -132,7 +128,7 @@ impl PubClient { { let repo_info = MyRepoInfo::new( response.sia_base().clone(), - response.rrdp_notification_uri().clone() + response.rrdp_notification_uri().clone(), ); file::save_json(&repo_info, &self.path_my_repo())?; @@ -153,11 +149,7 @@ impl PubClient { let repo = self.my_repo()?; let list_reply = self.list()?; - let delta = create_delta( - &list_reply, - dir, - repo.sia_base() - )?; + let delta = create_delta(&list_reply, dir, repo.sia_base())?; proxy.delta(delta).map_err(Error::ClientError) } @@ -200,20 +192,23 @@ impl PubClient { } } - //------------ Options -------------------------------------------------------- #[derive(Debug)] pub struct Options { state_dir: PathBuf, command: Command, - format: Format + format: Format, } /// # Accessors impl Options { pub fn new(state_dir: PathBuf, command: Command, format: Format) -> Self { - Options { state_dir, command, format } + Options { + state_dir, + command, + format, + } } pub fn state_dir(&self) -> &PathBuf { &self.state_dir @@ -223,7 +218,9 @@ impl Options { &self.command } - pub fn format(&self) -> &Format { &self.format } + pub fn format(&self) -> &Format { + &self.format + } } /// # Create @@ -232,69 +229,82 @@ impl Options { pub fn create() -> Result { let m = App::new("NLnet Labs RRDP Client (RFC8181)") .version("0.1b") - - .arg(Arg::with_name("state") - .short("s") - .long("state") - .value_name("FILE") - .help("Specify the directory where this publication client \ - maintains its state.") - .required(true)) - - .arg(Arg::with_name("format") - .short("f") - .long("format") - .value_name("text|json|none") - .help("Specify the output format. Defaults to 'none'.") - .required(false) - ) - - .subcommand(SubCommand::with_name("init") - .about("(Re-)Initialise the identity certificate and key \ - pair.") - .arg(Arg::with_name("name") - .short("n") - .long("name") - .value_name("NAME") - .help("Specify the name for this publication client.") - .required(true)) - ) - - .subcommand(SubCommand::with_name("request") - .about("Generate the publisher request XML") - .arg(Arg::with_name("xml") - .short("x") - .long("xml") + .arg( + Arg::with_name("state") + .short("s") + .long("state") .value_name("FILE") - .help("The name of the file to write the request to.") - .required(true)) + .help( + "Specify the directory where this publication client \ + maintains its state.", + ) + .required(true), ) - - .subcommand(SubCommand::with_name("response") - .about("Process the repository response XML") - .arg(Arg::with_name("xml") - .short("x") - .long("xml") - .value_name("FILE") - .help("The name of the file containing the response.") - .required(true)) + .arg( + Arg::with_name("format") + .short("f") + .long("format") + .value_name("text|json|none") + .help("Specify the output format. Defaults to 'none'.") + .required(false), + ) + .subcommand( + SubCommand::with_name("init") + .about( + "(Re-)Initialise the identity certificate and key \ + pair.", + ) + .arg( + Arg::with_name("name") + .short("n") + .long("name") + .value_name("NAME") + .help("Specify the name for this publication client.") + .required(true), + ), + ) + .subcommand( + SubCommand::with_name("request") + .about("Generate the publisher request XML") + .arg( + Arg::with_name("xml") + .short("x") + .long("xml") + .value_name("FILE") + .help("The name of the file to write the request to.") + .required(true), + ), + ) + .subcommand( + SubCommand::with_name("response") + .about("Process the repository response XML") + .arg( + Arg::with_name("xml") + .short("x") + .long("xml") + .value_name("FILE") + .help("The name of the file containing the response.") + .required(true), + ), ) - .subcommand(SubCommand::with_name("list")) - - .subcommand(SubCommand::with_name("sync") - .about("Synchronise the directory specified by '-d'.") - .arg(Arg::with_name("dir") - .short("d") - .long("dir") - .value_name("FILE") - .help("The directory that should be synced to the + .subcommand( + SubCommand::with_name("sync") + .about("Synchronise the directory specified by '-d'.") + .arg( + Arg::with_name("dir") + .short("d") + .long("dir") + .value_name("FILE") + .help( + "The directory that should be synced to the server. Note that entries here will be relative to the base rsync directory specified in the - repository response.") - .required(true)) + repository response.", + ) + .required(true), + ), ) - .get_matches(); let state_dir = { @@ -321,29 +331,30 @@ impl Options { let dir = PathBuf::from(dir); Command::Sync(dir) } else { - return Err(OptionsError::NoCommand) + return Err(OptionsError::NoCommand); } }; let format = Format::from(m.value_of("format").unwrap_or("none")) .map_err(|_| OptionsError::UnsupportedOutputFormat)?; - Ok(Options { state_dir, command, format }) + Ok(Options { + state_dir, + command, + format, + }) } } - - #[derive(Debug, Display)] pub enum OptionsError { - - #[display(fmt="Specify a sub-command. See --help")] + #[display(fmt = "Specify a sub-command. See --help")] NoCommand, - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] IoError(io::Error), - #[display(fmt="Unsupported output format. Use text, json or none.")] + #[display(fmt = "Unsupported output format. Use text, json or none.")] UnsupportedOutputFormat, } @@ -353,31 +364,29 @@ impl From for OptionsError { } } - //------------ Error --------------------------------------------------------- #[derive(Debug, Display)] pub enum Error { - - #[display(fmt="This client is uninitialised.")] + #[display(fmt = "This client is uninitialised.")] Uninitialised, - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] SignerError(softsigner::SignerError), - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] BuilderError(krill_commons::remote::builder::Error), - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] IoError(io::Error), - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] Rfc8183(rfc8183::Error), - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] ClientError(ClientError), - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] FileError(file::Error), } @@ -412,7 +421,9 @@ impl From for Error { } impl From for Error { - fn from(e: file::Error) -> Self { Error::FileError(e) } + fn from(e: file::Error) -> Self { + Error::FileError(e) + } } // For tests see main 'tests' folder diff --git a/pubc/src/lib.rs b/pubc/src/lib.rs index 9a9a9968..331cb8fa 100644 --- a/pubc/src/lib.rs +++ b/pubc/src/lib.rs @@ -1,22 +1,24 @@ extern crate clap; -#[macro_use] extern crate derive_more; +#[macro_use] +extern crate derive_more; extern crate rpki; -#[macro_use] extern crate serde; +#[macro_use] +extern crate serde; extern crate krill_commons; pub mod apiclient; pub mod cmsclient; -use std::path::PathBuf; -use rpki::uri; use krill_commons::api::publication; use krill_commons::util::file; +use rpki::uri; +use std::path::PathBuf; pub fn create_delta( list_reply: &publication::ListReply, dir: &PathBuf, - base_rsync: &uri::Rsync + base_rsync: &uri::Rsync, ) -> Result { let mut delta_builder = publication::PublishDeltaBuilder::new(); @@ -25,9 +27,7 @@ pub fn create_delta( // loop through what the server has and find the ones to withdraw for p in list_reply.elements() { if current.iter().find(|c| c.uri() == p.uri()).is_none() { - delta_builder.add_withdraw( - publication::Withdraw::from_list_element(p) - ); + delta_builder.add_withdraw(publication::Withdraw::from_list_element(p)); } } @@ -35,7 +35,11 @@ pub fn create_delta( // to be added to, which need to be updated at, or for which no change is // needed at the server. for f in current { - match list_reply.elements().iter().find(|pbl| pbl.uri() == f.uri()) { + match list_reply + .elements() + .iter() + .find(|pbl| pbl.uri() == f.uri()) + { None => delta_builder.add_publish(f.as_publish()), Some(pbl) => { if pbl.hash() != f.hash() { @@ -48,14 +52,13 @@ pub fn create_delta( Ok(delta_builder.finish()) } - //------------ Format -------------------------------------------------------- #[derive(Clone, Debug, Eq, PartialEq)] pub enum Format { Json, Text, - None + None, } impl Format { @@ -64,14 +67,13 @@ impl Format { "text" => Ok(Format::Text), "none" => Ok(Format::None), "json" => Ok(Format::Json), - _ => Err(UnsupportedFormat) + _ => Err(UnsupportedFormat), } } } pub struct UnsupportedFormat; - //------------ ApiResponse --------------------------------------------------- #[derive(Clone, Debug, Eq, PartialEq)] @@ -83,28 +85,23 @@ pub enum ApiResponse { impl ApiResponse { pub fn report(&self, format: &Format) { match format { - Format::None => {}, // done, + Format::None => {} // done, Format::Json => { match self { - ApiResponse::Success => {}, // nothing to report + ApiResponse::Success => {} // nothing to report ApiResponse::List(reply) => { println!("{}", serde_json::to_string(reply).unwrap()); } } - }, - Format::Text => { - match self { - ApiResponse::Success => println!("success"), - ApiResponse::List(list) => { - for el in list.elements() { - println!("{} {}", - el.hash().to_string(), - el.uri().to_string() - ); - } + } + Format::Text => match self { + ApiResponse::Success => println!("success"), + ApiResponse::List(list) => { + for el in list.elements() { + println!("{} {}", el.hash().to_string(), el.uri().to_string()); } } - } + }, } } } diff --git a/pubd/src/lib.rs b/pubd/src/lib.rs index ef0faf75..50e9e18e 100644 --- a/pubd/src/lib.rs +++ b/pubd/src/lib.rs @@ -1,14 +1,15 @@ extern crate bytes; -#[macro_use] extern crate derive_more; +#[macro_use] +extern crate derive_more; extern crate rand; extern crate rpki; -#[macro_use] extern crate serde; +#[macro_use] +extern crate serde; extern crate krill_commons; pub mod publishers; pub mod repo; mod pubserver; -pub use pubserver::PubServer; pub use pubserver::Error; - +pub use pubserver::PubServer; diff --git a/pubd/src/publishers.rs b/pubd/src/publishers.rs index 1bcd7c61..75208ccc 100644 --- a/pubd/src/publishers.rs +++ b/pubd/src/publishers.rs @@ -1,23 +1,8 @@ -use rpki::uri; +use krill_commons::api::admin::{Handle, PublisherDetails, PublisherRequest, Token}; use krill_commons::api::publication; -use krill_commons::api::admin::{ - Handle, - PublisherDetails, - PublisherRequest, - Token -}; -use krill_commons::api::rrdp::{ - CurrentObjects, - DeltaElements, - VerificationError -}; -use krill_commons::eventsourcing::{ - Aggregate, - CommandDetails, - StoredEvent, - SentCommand -}; - +use krill_commons::api::rrdp::{CurrentObjects, DeltaElements, VerificationError}; +use krill_commons::eventsourcing::{Aggregate, CommandDetails, SentCommand, StoredEvent}; +use rpki::uri; //------------ PublisherInit ------------------------------------------------- @@ -37,7 +22,6 @@ impl InitPublisherDetails { } } - //------------ PublisherEvent ------------------------------------------------ pub type PublisherEvent = StoredEvent; @@ -45,35 +29,19 @@ pub type PublisherEvent = StoredEvent; #[derive(Clone, Deserialize, Serialize)] pub enum PublisherEventDetails { Deactivated, - Published(DeltaElements) + Published(DeltaElements), } impl PublisherEventDetails { - pub fn deactivated( - handle: &Handle, - version: u64 - ) -> PublisherEvent { - PublisherEvent::new( - &handle, - version, - PublisherEventDetails::Deactivated - ) + pub fn deactivated(handle: &Handle, version: u64) -> PublisherEvent { + PublisherEvent::new(&handle, version, PublisherEventDetails::Deactivated) } - pub fn published( - handle: &Handle, - version: u64, - delta: DeltaElements - ) -> PublisherEvent { - PublisherEvent::new( - &handle, - version, - PublisherEventDetails::Published(delta) - ) + pub fn published(handle: &Handle, version: u64, delta: DeltaElements) -> PublisherEvent { + PublisherEvent::new(&handle, version, PublisherEventDetails::Published(delta)) } } - //------------ PublisherCommand ---------------------------------------------- pub type PublisherCommand = SentCommand; @@ -81,7 +49,7 @@ pub type PublisherCommand = SentCommand; #[derive(Clone, Deserialize, Serialize)] pub enum PublisherCommandDetails { Deactivate, - Publish(publication::PublishDelta) + Publish(publication::PublishDelta), } impl CommandDetails for PublisherCommandDetails { @@ -90,26 +58,14 @@ impl CommandDetails for PublisherCommandDetails { impl PublisherCommandDetails { pub fn deactivate(handle: &Handle) -> PublisherCommand { - PublisherCommand::new( - &handle, - None, - PublisherCommandDetails::Deactivate - ) + PublisherCommand::new(&handle, None, PublisherCommandDetails::Deactivate) } - pub fn publish( - handle: &Handle, - delta: publication::PublishDelta - ) -> PublisherCommand { - PublisherCommand::new( - &handle, - None, - PublisherCommandDetails::Publish(delta) - ) + pub fn publish(handle: &Handle, delta: publication::PublishDelta) -> PublisherCommand { + PublisherCommand::new(&handle, None, PublisherCommandDetails::Publish(delta)) } } - //------------ PublisherError ------------------------------------------------ #[derive(Clone, Debug, Display)] @@ -117,7 +73,7 @@ pub enum PublisherError { #[display(fmt = "Publisher is (already) de-activated")] Deactivated, - #[display(fmt="{}", _0)] + #[display(fmt = "{}", _0)] VerificationError(VerificationError), } @@ -129,25 +85,24 @@ impl From for PublisherError { impl std::error::Error for PublisherError {} - //------------ Publisher ----------------------------------------------------- /// This type defines Publisher CAs that are allowed to publish. #[derive(Clone, Debug, Deserialize, Serialize)] pub struct Publisher { /// Aggregate house keeping - handle: Handle, - version: u64, + handle: Handle, + version: u64, deactivated: bool, /// Publication jail for this publisher - base_uri: uri::Rsync, + base_uri: uri::Rsync, /// The token used by the API - token: Token, + token: Token, /// All objects currently published by this publisher, by hash - current_objects: CurrentObjects + current_objects: CurrentObjects, } /// # Accessors @@ -156,7 +111,9 @@ impl Publisher { &self.handle } - pub fn is_deactivated(&self) -> bool { self.deactivated } + pub fn is_deactivated(&self) -> bool { + self.deactivated + } pub fn token(&self) -> &Token { &self.token @@ -167,25 +124,22 @@ impl Publisher { } pub fn as_api_details(&self) -> PublisherDetails { - PublisherDetails::new( - self.handle.as_str(), self.deactivated, &self.base_uri - ) + PublisherDetails::new(self.handle.as_str(), self.deactivated, &self.base_uri) } } /// # Life cycle /// impl Publisher { - fn create(event: PublisherInit) -> Self { let (handle, _version, init) = event.unwrap(); Publisher { handle, - version: 1, - deactivated: false, - token: init.token, - base_uri: init.base_uri, - current_objects: CurrentObjects::default() + version: 1, + deactivated: false, + token: init.token, + base_uri: init.base_uri, + current_objects: CurrentObjects::default(), } } @@ -199,7 +153,6 @@ impl Publisher { } } - /// # Publication protocol /// impl Publisher { @@ -216,13 +169,16 @@ impl Publisher { /// provided that it's legitimate. fn process_delta_cmd( &self, - delta: publication::PublishDelta + delta: publication::PublishDelta, ) -> Result, PublisherError> { - let delta = DeltaElements::from(delta); self.current_objects.verify_delta(&delta, &self.base_uri)?; - Ok(vec![PublisherEventDetails::published(&self.handle, self.version, delta)]) + Ok(vec![PublisherEventDetails::published( + &self.handle, + self.version, + delta, + )]) } fn apply_delta(&mut self, delta: DeltaElements) { @@ -230,7 +186,6 @@ impl Publisher { } } - impl Aggregate for Publisher { type Command = PublisherCommand; type Event = PublisherEvent; @@ -248,7 +203,7 @@ impl Aggregate for Publisher { fn apply(&mut self, event: Self::Event) { match event.into_details() { PublisherEventDetails::Deactivated => self.deactivated = true, - PublisherEventDetails::Published(delta) => self.apply_delta(delta) + PublisherEventDetails::Published(delta) => self.apply_delta(delta), } self.version += 1; } @@ -256,7 +211,7 @@ impl Aggregate for Publisher { fn process_command(&self, command: Self::Command) -> Result, Self::Error> { match command.into_details() { PublisherCommandDetails::Deactivate => self.deactivate(), - PublisherCommandDetails::Publish(delta) => self.process_delta_cmd(delta) + PublisherCommandDetails::Publish(delta) => self.process_delta_cmd(delta), } } } diff --git a/pubd/src/pubserver.rs b/pubd/src/pubserver.rs index 4b34b137..f79b7d7a 100644 --- a/pubd/src/pubserver.rs +++ b/pubd/src/pubserver.rs @@ -1,39 +1,22 @@ +use crate::publishers::{ + InitPublisherDetails, Publisher, PublisherCommand, PublisherCommandDetails, PublisherError, + PublisherEventDetails, +}; +use crate::repo::{ + self, RetentionTime, RrdpCommandDetails, RrdpInitDetails, RrdpServer, RrdpServerError, + RsyncdStore, +}; +use krill_commons::api::admin::{Handle, PublisherRequest}; +use krill_commons::api::ca::RepoInfo; +use krill_commons::api::publication; +use krill_commons::api::rrdp::DeltaElements; +use krill_commons::eventsourcing::{ + Aggregate, AggregateStore, AggregateStoreError, Command, DiskAggregateStore, +}; +use rpki::uri; use std::io; use std::path::PathBuf; use std::sync::{Arc, Mutex}; -use rpki::uri; -use krill_commons::api::publication; -use krill_commons::api::admin::{ - Handle, - PublisherRequest -}; -use krill_commons::api::ca::RepoInfo; -use krill_commons::api::rrdp::DeltaElements; -use krill_commons::eventsourcing::{ - Aggregate, - AggregateStore, - AggregateStoreError, - Command, - DiskAggregateStore, -}; -use crate::publishers::{ - Publisher, - PublisherCommand, - PublisherCommandDetails, - PublisherError, - PublisherEventDetails, - InitPublisherDetails -}; -use crate::repo::{ - self, - RetentionTime, - RrdpCommandDetails, - RrdpInitDetails, - RrdpServer, - RrdpServerError, - RsyncdStore, -}; - //------------ PubServer ----------------------------------------------------- @@ -45,26 +28,32 @@ pub struct PubServer { rsyncd_store: RsyncdStore, store: Arc>, base_rsync_uri: uri::Rsync, // jail for the publishers, - command_lock: Mutex<()> // Only one command at the time. + command_lock: Mutex<()>, // Only one command at the time. } impl PubServer { pub fn build( base_rsync_uri: uri::Rsync, base_http_uri: uri::Https, // for the RRDP files - repo_dir: PathBuf, // for the RRDP and rsync files - work_dir: &PathBuf // for the aggregate stores + repo_dir: PathBuf, // for the RRDP and rsync files + work_dir: &PathBuf, // for the aggregate stores ) -> Result { - let rrdp_store = Arc::new(DiskAggregateStore::::new(work_dir, "repo-server")?); + let rrdp_store = Arc::new(DiskAggregateStore::::new( + work_dir, + "repo-server", + )?); let rsyncd_store = RsyncdStore::build(&repo_dir)?; - if ! rrdp_store.has(&repo::id()) { + if !rrdp_store.has(&repo::id()) { let init = RrdpInitDetails::init_new(base_http_uri, repo_dir); rrdp_store.add(init)?; } - let store = Arc::new(DiskAggregateStore::::new(work_dir, "publishers")?); + let store = Arc::new(DiskAggregateStore::::new( + work_dir, + "publishers", + )?); let command_lock = Mutex::new(()); @@ -73,7 +62,7 @@ impl PubServer { rsyncd_store, store, base_rsync_uri, - command_lock + command_lock, }; Ok(pubserver) @@ -92,21 +81,16 @@ impl PubServer { } } - /// # Publication Protocol support /// impl PubServer { - fn rrdp_server(&self) -> Result, Error> { - self.rrdp_store.get_latest(&repo::id()).map_err(Error::AggregateStoreError) + self.rrdp_store + .get_latest(&repo::id()) + .map_err(Error::AggregateStoreError) } - pub fn publish( - &self, - handle: &Handle, - delta: publication::PublishDelta - ) -> Result<(), Error> { - + pub fn publish(&self, handle: &Handle, delta: publication::PublishDelta) -> Result<(), Error> { // Only do one update at a time. let _lock = self.command_lock.lock().unwrap(); @@ -125,12 +109,16 @@ impl PubServer { let rrdp = self.rrdp_server()?; let add_cmd = RrdpCommandDetails::add_delta(delta); let rrdp_add_delta_events = rrdp.process_command(add_cmd)?; - let rrdp = self.rrdp_store.update(&repo_id, rrdp, rrdp_add_delta_events)?; + let rrdp = self + .rrdp_store + .update(&repo_id, rrdp, rrdp_add_delta_events)?; // Trigger publication of the RRDP files let publish_cmd = RrdpCommandDetails::publish(); let rrdp_publish_events = rrdp.process_command(publish_cmd)?; - let rrdp = self.rrdp_store.update(&repo_id, rrdp, rrdp_publish_events)?; + let rrdp = self + .rrdp_store + .update(&repo_id, rrdp, rrdp_publish_events)?; // Clean up old files let retention = RetentionTime::from_secs(0); @@ -142,31 +130,26 @@ impl PubServer { Ok(()) } - pub fn list( - &self, - handle: &Handle - ) -> Result { + pub fn list(&self, handle: &Handle) -> Result { match self.get_publisher(handle)? { Some(publisher) => Ok(publisher.list_current()), - None => Err(Error::UnknownPublisher(handle.to_string())) + None => Err(Error::UnknownPublisher(handle.to_string())), } } } - /// # Publishing /// impl PubServer { - fn verify_handle(&self, handle: &Handle) -> Result<(), Error> { let name = handle.as_str(); - if ! name.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'_') { - return Err(Error::InvalidHandle(name.to_string())) + if !name.bytes().all(|b| b.is_ascii_alphanumeric() || b == b'_') { + return Err(Error::InvalidHandle(name.to_string())); } if self.store.has(handle) { - return Err(Error::DuplicatePublisher(name.to_string())) + return Err(Error::DuplicatePublisher(name.to_string())); } Ok(()) @@ -186,12 +169,10 @@ impl PubServer { } } - pub fn get_publisher( - &self, - handle: &Handle - ) -> Result>, Error> { + pub fn get_publisher(&self, handle: &Handle) -> Result>, Error> { if self.store.has(handle) { - self.store.get_latest(handle) + self.store + .get_latest(handle) .map(Some) .map_err(Error::AggregateStoreError) } else { @@ -201,10 +182,7 @@ impl PubServer { /// Adds a publisher. Will complain if a publisher already exists for this /// handle. Will also verify that the base_uri is allowed. - pub fn create_publisher( - &self, - req: PublisherRequest - ) -> Result<(), Error> { + pub fn create_publisher(&self, req: PublisherRequest) -> Result<(), Error> { self.verify_handle(req.handle())?; self.verify_base_uri(req.base_uri())?; @@ -224,24 +202,16 @@ impl PubServer { /// re-activation in future. Reason is that we never forget the history /// of the old publisher, and if handles are re-used by different /// entities that would get confusing. - pub fn deactivate_publisher( - &self, - handle: &Handle - ) -> Result<(), Error> { + pub fn deactivate_publisher(&self, handle: &Handle) -> Result<(), Error> { let cmd = PublisherCommandDetails::deactivate(handle); self.command_publisher(cmd)?; Ok(()) } - /// Apply a command to a publisher. If this was a successful publication /// command, then return the delta so that it can be published by the /// RRDP server. - fn command_publisher( - &self, - command: PublisherCommand - ) -> Result, Error> { - + fn command_publisher(&self, command: PublisherCommand) -> Result, Error> { let handle = command.handle().clone(); match self.get_publisher(&handle)? { @@ -251,9 +221,7 @@ impl PubServer { if let Some(version) = command.version() { if version != pbl.version() { - return Err( - Error::ConcurrentModification(version, pbl.version()) - ) + return Err(Error::ConcurrentModification(version, pbl.version())); } } @@ -271,7 +239,6 @@ impl PubServer { } } } - } //------------ Error --------------------------------------------------------- @@ -281,10 +248,16 @@ pub enum Error { #[display(fmt = "{}", _0)] IoError(io::Error), - #[display(fmt = "The publisher handle may only contain a-ZA-Z0-9 and _. You sent: {}", _0)] + #[display( + fmt = "The publisher handle may only contain a-ZA-Z0-9 and _. You sent: {}", + _0 + )] InvalidHandle(String), - #[display(fmt = "Duplicate publisher with name: {} (note: might be de-activated).", _0)] + #[display( + fmt = "Duplicate publisher with name: {} (note: might be de-activated).", + _0 + )] DuplicatePublisher(String), #[display(fmt = "Unknown publisher with name: {}.", _0)] @@ -307,37 +280,44 @@ pub enum Error { } impl From for Error { - fn from(e: io::Error) -> Self { Error::IoError(e) } + fn from(e: io::Error) -> Self { + Error::IoError(e) + } } impl From for Error { - fn from(e: PublisherError) -> Self { Error::PublisherError(e) } + fn from(e: PublisherError) -> Self { + Error::PublisherError(e) + } } impl From for Error { - fn from(e: RrdpServerError) -> Self { Error::RrdpServerError(e) } + fn from(e: RrdpServerError) -> Self { + Error::RrdpServerError(e) + } } impl From for Error { - fn from(e: AggregateStoreError) -> Self { Error::AggregateStoreError(e) } + fn from(e: AggregateStoreError) -> Self { + Error::AggregateStoreError(e) + } } impl std::error::Error for Error {} - //------------ Tests --------------------------------------------------------- #[cfg(test)] mod tests { use super::*; - use std::path::PathBuf; use bytes::Bytes; use krill_commons::api::admin::Token; use krill_commons::api::publication::PublishDeltaBuilder; use krill_commons::api::rrdp::VerificationError; use krill_commons::util::file::CurrentFile; use krill_commons::util::test; + use std::path::PathBuf; fn server_base_uri() -> uri::Rsync { test::rsync("rsync://localhost/repo/") @@ -347,10 +327,7 @@ mod tests { test::https("https://localhost/rrdp/") } - fn make_publisher_req( - handle: &str, - uri: &str, - ) -> PublisherRequest { + fn make_publisher_req(handle: &str, uri: &str) -> PublisherRequest { let base_uri = test::rsync(uri); let handle = Handle::from(handle); let token = Token::from("secret"); @@ -366,17 +343,15 @@ mod tests { server_base_uri(), server_base_http_uri(), base_dir, - work_dir - ).unwrap() + work_dir, + ) + .unwrap() } #[test] fn should_add_publisher() { test::test_under_tmp(|d| { - let publisher_req = make_publisher_req( - "alice", - "rsync://localhost/repo/alice/", - ); + let publisher_req = make_publisher_req("alice", "rsync://localhost/repo/alice/"); let server = make_server(&d); server.create_publisher(publisher_req).unwrap(); @@ -391,17 +366,12 @@ mod tests { #[test] fn should_refuse_invalid_publisher_handle() { test::test_under_tmp(|d| { - let publisher_req = make_publisher_req( - "alice&", - "rsync://localhost/repo/alice/", - ); + let publisher_req = make_publisher_req("alice&", "rsync://localhost/repo/alice/"); let server = make_server(&d); match server.create_publisher(publisher_req) { - Err(Error::InvalidHandle(handle)) => { - assert_eq!(handle, "alice&".to_string()) - }, - _ => panic!("Expected error") + Err(Error::InvalidHandle(handle)) => assert_eq!(handle, "alice&".to_string()), + _ => panic!("Expected error"), } }) } @@ -409,15 +379,12 @@ mod tests { #[test] fn should_refuse_base_uri_not_ending_with_slash() { test::test_under_tmp(|d| { - let publisher_req = make_publisher_req( - "alice", - "rsync://localhost/repo/alice", - ); + let publisher_req = make_publisher_req("alice", "rsync://localhost/repo/alice"); let server = make_server(&d); match server.create_publisher(publisher_req) { - Err(Error::InvalidBaseUri) => { }, - _ => panic!("Expected error") + Err(Error::InvalidBaseUri) => {} + _ => panic!("Expected error"), } }) } @@ -425,15 +392,12 @@ mod tests { #[test] fn should_refuse_base_uri_outside_of_server_base() { test::test_under_tmp(|d| { - let publisher_req = make_publisher_req( - "alice", - "rsync://localhost/outside/alice/", - ); + let publisher_req = make_publisher_req("alice", "rsync://localhost/outside/alice/"); let server = make_server(&d); match server.create_publisher(publisher_req) { - Err(Error::InvalidBaseUri) => { }, - _ => panic!("Expected error") + Err(Error::InvalidBaseUri) => {} + _ => panic!("Expected error"), } }) } @@ -441,18 +405,13 @@ mod tests { #[test] fn should_not_add_publisher_twice() { test::test_under_tmp(|d| { - let publisher_req = make_publisher_req( - "alice", - "rsync://localhost/repo/alice/", - ); + let publisher_req = make_publisher_req("alice", "rsync://localhost/repo/alice/"); let server = make_server(&d); server.create_publisher(publisher_req.clone()).unwrap(); match server.create_publisher(publisher_req) { - Err(Error::DuplicatePublisher(name)) => { - assert_eq!(name, "alice".to_string()) - }, - _ => panic!("Expected error") + Err(Error::DuplicatePublisher(name)) => assert_eq!(name, "alice".to_string()), + _ => panic!("Expected error"), } }) } @@ -464,10 +423,8 @@ mod tests { let handle = Handle::from("alice"); // create publisher - let publisher_req = make_publisher_req( - handle.as_str(), - "rsync://localhost/repo/alice/", - ); + let publisher_req = + make_publisher_req(handle.as_str(), "rsync://localhost/repo/alice/"); server.create_publisher(publisher_req).unwrap(); // expect to see it in the list @@ -481,17 +438,13 @@ mod tests { // expect that it is now inactive let alice = server.get_publisher(&handle).unwrap().unwrap(); assert!(alice.is_deactivated()) - }) } #[test] fn should_list_files() { test::test_under_tmp(|d| { - let publisher_req = make_publisher_req( - "alice", - "rsync://localhost/repo/alice/", - ); + let publisher_req = make_publisher_req("alice", "rsync://localhost/repo/alice/"); let handle = Handle::from("alice"); let server = make_server(&d); @@ -510,15 +463,12 @@ mod tests { // get the file out of a list_reply fn find_in_reply<'a>( reply: &'a publication::ListReply, - uri: &uri::Rsync + uri: &uri::Rsync, ) -> Option<&'a publication::ListElement> { reply.elements().iter().find(|e| e.uri() == uri) } - let publisher_req = make_publisher_req( - "alice", - "rsync://localhost/repo/alice/", - ); + let publisher_req = make_publisher_req("alice", "rsync://localhost/repo/alice/"); let handle = Handle::from("alice"); let server = make_server(&d); @@ -527,12 +477,12 @@ mod tests { // Publish a single file let file1 = CurrentFile::new( test::rsync("rsync://localhost/repo/alice/file.txt"), - &Bytes::from("example content") + &Bytes::from("example content"), ); let file2 = CurrentFile::new( test::rsync("rsync://localhost/repo/alice/file2.txt"), - &Bytes::from("example content 2") + &Bytes::from("example content 2"), ); let mut builder = PublishDeltaBuilder::new(); @@ -549,11 +499,13 @@ mod tests { assert!(find_in_reply( &list_reply, &test::rsync("rsync://localhost/repo/alice/file.txt") - ).is_some()); + ) + .is_some()); assert!(find_in_reply( &list_reply, &test::rsync("rsync://localhost/repo/alice/file2.txt") - ).is_some()); + ) + .is_some()); // Update // - update file @@ -562,12 +514,12 @@ mod tests { let file1_update = CurrentFile::new( test::rsync("rsync://localhost/repo/alice/file.txt"), - &Bytes::from("example content - updated") + &Bytes::from("example content - updated"), ); let file3 = CurrentFile::new( test::rsync("rsync://localhost/repo/alice/file3.txt"), - &Bytes::from("example content 3") + &Bytes::from("example content 3"), ); let mut builder = PublishDeltaBuilder::new(); @@ -586,58 +538,54 @@ mod tests { assert!(find_in_reply( &list_reply, &test::rsync("rsync://localhost/repo/alice/file.txt") - ).is_some()); + ) + .is_some()); assert_eq!( find_in_reply( &list_reply, &test::rsync("rsync://localhost/repo/alice/file.txt") - ).unwrap().hash(), + ) + .unwrap() + .hash(), file1_update.hash() ); assert!(find_in_reply( &list_reply, &test::rsync("rsync://localhost/repo/alice/file3.txt") - ).is_some()); + ) + .is_some()); // Should reject publish outside of base uri let file_outside = CurrentFile::new( test::rsync("rsync://localhost/repo/bob/file.txt"), - &Bytes::from("irrelevant") + &Bytes::from("irrelevant"), ); let mut builder = PublishDeltaBuilder::new(); builder.add_publish(file_outside.as_publish()); let delta = builder.finish(); match server.publish(&handle, delta) { - Err( - Error::PublisherError( - PublisherError::VerificationError( - VerificationError::UriOutsideJail(_, _) - ) - ) - ) => {}, // ok - _ => panic!("Expected error publishing outside of base uri jail") + Err(Error::PublisherError(PublisherError::VerificationError( + VerificationError::UriOutsideJail(_, _), + ))) => {} // ok + _ => panic!("Expected error publishing outside of base uri jail"), } // Should reject update of file that does not exist let file2_update = CurrentFile::new( test::rsync("rsync://localhost/repo/alice/file2.txt"), - &Bytes::from("example content 2 updated") + &Bytes::from("example content 2 updated"), ); // file2 was removed let mut builder = PublishDeltaBuilder::new(); builder.add_update(file2_update.as_update(file2.hash())); let delta = builder.finish(); match server.publish(&handle, delta) { - Err( - Error::PublisherError( - PublisherError::VerificationError( - VerificationError::NoObjectForHashAndOrUri(_) - ) - ) - ) => {}, + Err(Error::PublisherError(PublisherError::VerificationError( + VerificationError::NoObjectForHashAndOrUri(_), + ))) => {} // ok - _ => panic!("Expected error when file for update can't be found") + _ => panic!("Expected error when file for update can't be found"), } // should reject withdraw for file that does not exist @@ -647,14 +595,10 @@ mod tests { let cmd = PublisherCommandDetails::publish(&handle, delta); match server.command_publisher(cmd) { - Err( - Error::PublisherError( - PublisherError::VerificationError( - VerificationError::NoObjectForHashAndOrUri(_) - ) - ) - ) => {}, // ok - _ => panic!("Expected error withdrawing file that does not exist") + Err(Error::PublisherError(PublisherError::VerificationError( + VerificationError::NoObjectForHashAndOrUri(_), + ))) => {} // ok + _ => panic!("Expected error withdrawing file that does not exist"), } // should reject publish for file that does exist @@ -663,18 +607,11 @@ mod tests { let delta = builder.finish(); match server.publish(&handle, delta) { - Err( - Error::PublisherError( - PublisherError::VerificationError - (VerificationError::ObjectAlreadyPresent(uri) - ) - ) - ) => { assert_eq!( - uri, - test::rsync("rsync://localhost/repo/alice/file3.txt") - )}, - _ => panic!("Expected error publishing file that already exists") + Err(Error::PublisherError(PublisherError::VerificationError( + VerificationError::ObjectAlreadyPresent(uri), + ))) => assert_eq!(uri, test::rsync("rsync://localhost/repo/alice/file3.txt")), + _ => panic!("Expected error publishing file that already exists"), } }); } -} \ No newline at end of file +} diff --git a/pubd/src/repo.rs b/pubd/src/repo.rs index 4b34d4ed..c69c9d74 100644 --- a/pubd/src/repo.rs +++ b/pubd/src/repo.rs @@ -1,29 +1,14 @@ -use std::{io, fs}; -use std::path::PathBuf; -use std::time::Duration; -use rpki::uri; use krill_commons::api::admin::Handle; use krill_commons::api::rrdp::{ - Delta, - DeltaElements, - DeltaRef, - FileRef, - Notification, - NotificationUpdate, - Snapshot, + Delta, DeltaElements, DeltaRef, FileRef, Notification, NotificationUpdate, Snapshot, SnapshotRef, }; -use krill_commons::eventsourcing::{ - Aggregate, - CommandDetails, - StoredEvent, - SentCommand, -}; -use krill_commons::util::{ - file, - Time -}; - +use krill_commons::eventsourcing::{Aggregate, CommandDetails, SentCommand, StoredEvent}; +use krill_commons::util::{file, Time}; +use rpki::uri; +use std::path::PathBuf; +use std::time::Duration; +use std::{fs, io}; const RRDP_FOLDER: &str = "rrdp"; const RSYNC_FOLDER: &str = "rsync"; @@ -33,7 +18,6 @@ pub fn id() -> Handle { Handle::from(ID) } - //------------ RrdpInit ------------------------------------------------------ pub type RrdpInit = StoredEvent; @@ -42,7 +26,7 @@ pub type RrdpInit = StoredEvent; pub struct RrdpInitDetails { session: String, base_uri: uri::Https, - repo_dir: PathBuf + repo_dir: PathBuf, } impl RrdpInitDetails { @@ -55,12 +39,15 @@ impl RrdpInitDetails { StoredEvent::new( &id(), 0, - RrdpInitDetails { session, base_uri, repo_dir } + RrdpInitDetails { + session, + base_uri, + repo_dir, + }, ) } } - //------------ RrdpEvent ------------------------------------------------------ pub type RrdpEvent = StoredEvent; @@ -70,7 +57,7 @@ pub type RrdpEvent = StoredEvent; pub enum RrdpEventDetails { AddedDelta(Delta), UpdatedNotification(NotificationUpdate), - CleanedUp(Time) + CleanedUp(Time), } impl RrdpEventDetails { @@ -78,24 +65,15 @@ impl RrdpEventDetails { StoredEvent::new(id, ver, RrdpEventDetails::AddedDelta(delta)) } - fn updated_notification( - id: &Handle, - ver: u64, - notif: NotificationUpdate - ) -> RrdpEvent { + fn updated_notification(id: &Handle, ver: u64, notif: NotificationUpdate) -> RrdpEvent { StoredEvent::new(id, ver, RrdpEventDetails::UpdatedNotification(notif)) } - fn cleaned_up( - id: &Handle, - ver: u64, - time: Time - ) -> RrdpEvent { + fn cleaned_up(id: &Handle, ver: u64, time: Time) -> RrdpEvent { StoredEvent::new(id, ver, RrdpEventDetails::CleanedUp(time)) } } - //------------ RrdpCommand --------------------------------------------------- pub type RrdpCommand = SentCommand; @@ -104,7 +82,7 @@ pub type RrdpCommand = SentCommand; pub enum RrdpCommandDetails { AddDelta(DeltaElements), Publish, - Cleanup(RetentionTime) + Cleanup(RetentionTime), } /// The retention time for snapshot and delta files no longer referenced. @@ -128,28 +106,26 @@ impl RrdpCommandDetails { } } - //------------ RrdpServerError ----------------------------------------------- #[derive(Debug, Display)] pub enum RrdpServerError { - #[display(fmt = "{}", _0)] IoError(io::Error), } impl From for RrdpServerError { - fn from(e: io::Error) -> Self { RrdpServerError::IoError(e) } + fn from(e: io::Error) -> Self { + RrdpServerError::IoError(e) + } } impl std::error::Error for RrdpServerError {} - //------------ RrdpResult ---------------------------------------------------- pub type RrdpResult = Result, RrdpServerError>; - //------------ RrdpServer ---------------------------------------------------- #[derive(Clone, Debug, Deserialize, Serialize)] @@ -169,20 +145,19 @@ pub struct RrdpServer { notification: Notification, snapshot: Snapshot, - deltas: Vec + deltas: Vec, } /// # Publishing /// impl RrdpServer { - fn process_published_delta(&mut self, delta: Delta) { self.snapshot.apply_delta(delta.clone()); self.deltas.insert(0, delta); - // Keep a minimum of 2 deltas, and a maximum for which the combined - // number of elements does not exceed the number of elements in the - // snapshot. + // Keep a minimum of 2 deltas, and a maximum for which the combined + // number of elements does not exceed the number of elements in the + // snapshot. { let size_snapshot = self.snapshot.len(); let mut total_deltas = 0; @@ -205,18 +180,19 @@ impl RrdpServer { let session = self.session.clone(); let delta = Delta::new(session, next, elements); - Ok(vec![RrdpEventDetails::added_delta(&id(), self.version, delta)]) + Ok(vec![RrdpEventDetails::added_delta( + &id(), + self.version, + delta, + )]) } /// Publishes the latest notification, snapshot and delta file to disk. /// Return event to move old files to clean-up list. fn publish(&self) -> RrdpResult { let snapshot_hash = self.snapshot.write_xml(&self.snapshot_path())?; - let snapshot_ref = SnapshotRef::new( - self.snapshot_uri(), - self.snapshot_path(), - snapshot_hash - ); + let snapshot_ref = + SnapshotRef::new(self.snapshot_uri(), self.snapshot_path(), snapshot_hash); // Note we always have at least 1 delta when publishing. let last_delta = &self.deltas[0]; @@ -226,8 +202,8 @@ impl RrdpServer { FileRef::new( self.delta_uri(last_delta.serial()), self.delta_path(last_delta.serial()), - delta_hash - ) + delta_hash, + ), ); let update = NotificationUpdate::new( @@ -235,20 +211,18 @@ impl RrdpServer { None, snapshot_ref, delta_ref, - self.deltas.last().unwrap().serial() + self.deltas.last().unwrap().serial(), ); let mut notification = self.notification.clone(); notification.update(update.clone()); notification.write_xml(&self.notification_path())?; - Ok(vec![ - RrdpEventDetails::updated_notification( - &id(), - self.version, - update - ) - ]) + Ok(vec![RrdpEventDetails::updated_notification( + &id(), + self.version, + update, + )]) } /// Cleans out old files on disk, returns event for cleaning up the state. @@ -261,13 +235,11 @@ impl RrdpServer { } } - Ok(vec![ - RrdpEventDetails::cleaned_up( - &id(), - self.version, - cut_off - ) - ]) + Ok(vec![RrdpEventDetails::cleaned_up( + &id(), + self.version, + cut_off, + )]) } } @@ -275,9 +247,7 @@ impl RrdpServer { /// impl RrdpServer { pub fn notification_uri(&self) -> uri::Https { - uri::Https::from_string( - format!("{}notifcation.xml", self.base_uri.to_string()) - ).unwrap() // Cannot fail. Config checked at startup. + uri::Https::from_string(format!("{}notifcation.xml", self.base_uri.to_string())).unwrap() // Cannot fail. Config checked at startup. } fn notification_path(&self) -> PathBuf { @@ -301,12 +271,12 @@ impl RrdpServer { } fn new_snapshot_uri(base: &uri::Https, session: &str, serial: u64) -> uri::Https { - uri::Https::from_string( - format!("{}{}", - base.to_string(), - Self::snapshot_rel(session, serial) - ) - ).unwrap() // Cannot fail. Config checked at startup. + uri::Https::from_string(format!( + "{}{}", + base.to_string(), + Self::snapshot_rel(session, serial) + )) + .unwrap() // Cannot fail. Config checked at startup. } fn snapshot_uri(&self) -> uri::Https { @@ -318,12 +288,12 @@ impl RrdpServer { } fn delta_uri(&self, serial: u64) -> uri::Https { - uri::Https::from_string( - format!("{}{}", - self.base_uri.to_string(), - Self::delta_rel(&self.session, serial) - ) - ).unwrap() // Cannot fail. Config checked at startup. + uri::Https::from_string(format!( + "{}{}", + self.base_uri.to_string(), + Self::delta_rel(&self.session, serial) + )) + .unwrap() // Cannot fail. Config checked at startup. } fn delta_path(&self, serial: u64) -> PathBuf { @@ -333,8 +303,6 @@ impl RrdpServer { } } - - impl Aggregate for RrdpServer { type Command = RrdpCommand; type Event = RrdpEvent; @@ -356,11 +324,7 @@ impl Aggregate for RrdpServer { let snapshot_uri = Self::new_snapshot_uri(&base_uri, &session, 0); let snapshot_hash = snapshot.write_xml(&snapshot_path)?; - let snapshot_ref = SnapshotRef::new( - snapshot_uri, - snapshot_path, - snapshot_hash - ); + let snapshot_ref = SnapshotRef::new(snapshot_uri, snapshot_path, snapshot_hash); let notification = Notification::create(session.clone(), snapshot_ref); let deltas = vec![]; @@ -373,7 +337,7 @@ impl Aggregate for RrdpServer { serial, notification, snapshot, - deltas + deltas, }) } @@ -383,15 +347,13 @@ impl Aggregate for RrdpServer { fn apply(&mut self, event: Self::Event) { match event.into_details() { - RrdpEventDetails::AddedDelta(delta) => - self.process_published_delta(delta), - RrdpEventDetails::UpdatedNotification(notification) => - self.notification.update(notification), - RrdpEventDetails::CleanedUp(time) => - self.notification.clean_up(time) + RrdpEventDetails::AddedDelta(delta) => self.process_published_delta(delta), + RrdpEventDetails::UpdatedNotification(notification) => { + self.notification.update(notification) + } + RrdpEventDetails::CleanedUp(time) => self.notification.clean_up(time), } self.version += 1; - } fn process_command(&self, command: Self::Command) -> RrdpResult { @@ -403,7 +365,6 @@ impl Aggregate for RrdpServer { } } - //------------ RsyncdStore --------------------------------------------------- /// This type is responsible for publishing files on disk in a structure so @@ -413,7 +374,7 @@ impl Aggregate for RrdpServer { /// base uri used. #[derive(Clone, Debug)] pub struct RsyncdStore { - rsync_dir: PathBuf + rsync_dir: PathBuf, } /// # Construct @@ -422,10 +383,10 @@ impl RsyncdStore { pub fn build(repo_dir: &PathBuf) -> Result { let mut rsync_dir = PathBuf::from(repo_dir); rsync_dir.push(RSYNC_FOLDER); - if ! rsync_dir.is_dir() { + if !rsync_dir.is_dir() { fs::create_dir_all(&rsync_dir)?; } - Ok ( RsyncdStore { rsync_dir } ) + Ok(RsyncdStore { rsync_dir }) } } @@ -434,29 +395,17 @@ impl RsyncdStore { impl RsyncdStore { /// Saves all the publishes and updates, deletes all the withdraws. pub fn publish(&self, delta: &DeltaElements) -> Result<(), io::Error> { - for p in delta.publishes() { - file::save_with_rsync_uri( - &p.base64().to_bytes(), - &self.rsync_dir, - p.uri() - )?; + file::save_with_rsync_uri(&p.base64().to_bytes(), &self.rsync_dir, p.uri())?; } for u in delta.updates() { - file::save_with_rsync_uri( - &u.base64().to_bytes(), - &self.rsync_dir, - u.uri() - )?; + file::save_with_rsync_uri(&u.base64().to_bytes(), &self.rsync_dir, u.uri())?; } for w in delta.withdraws() { - file::delete_with_rsync_uri( - &self.rsync_dir, - w.uri() - )?; + file::delete_with_rsync_uri(&self.rsync_dir, w.uri())?; } Ok(()) } -} \ No newline at end of file +}