Process repository response in publisher client.

This commit is contained in:
Tim Bruijnzeels
2018-11-20 15:27:02 +01:00
parent 200191839a
commit b3d73ade3d
7 changed files with 282 additions and 96 deletions
-56
View File
@@ -1,56 +0,0 @@
use ext_serde;
use rpki::remote::idcert::IdCert;
use rpki::signing::signer::KeyId;
//------------ MyIdentity ----------------------------------------------------
/// This type stores identity details for a client or server involved in RPKI
/// provisioning (up-down) or publication.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct MyIdentity {
name: String,
#[serde(
deserialize_with = "ext_serde::de_id_cert",
serialize_with = "ext_serde::ser_id_cert")]
id_cert: IdCert,
#[serde(
deserialize_with = "ext_serde::de_key_id",
serialize_with = "ext_serde::ser_key_id")]
key_id: KeyId
}
impl MyIdentity {
pub fn new(name: String, id_cert: IdCert, key_id: KeyId) -> Self {
MyIdentity {
name,
id_cert,
key_id
}
}
pub fn name(&self) -> &str {
self.name.as_str()
}
pub fn id_cert(&self) -> &IdCert {
&self.id_cert
}
pub fn key_id(&self) -> &KeyId {
&self.key_id
}
}
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
}
}
impl Eq for MyIdentity {}
+166
View File
@@ -0,0 +1,166 @@
use ext_serde;
use rpki::remote::idcert::IdCert;
use rpki::signing::signer::KeyId;
use rpki::uri;
//------------ MyIdentity ----------------------------------------------------
/// This type stores identity details for a client or server involved in RPKI
/// provisioning (up-down) or publication.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct MyIdentity {
name: String,
#[serde(
deserialize_with = "ext_serde::de_id_cert",
serialize_with = "ext_serde::ser_id_cert")]
id_cert: IdCert,
#[serde(
deserialize_with = "ext_serde::de_key_id",
serialize_with = "ext_serde::ser_key_id")]
key_id: KeyId
}
impl MyIdentity {
pub fn new(name: String, id_cert: IdCert, key_id: KeyId) -> Self {
MyIdentity {
name,
id_cert,
key_id
}
}
/// The name for this actor.
pub fn name(&self) -> &str {
self.name.as_str()
}
/// The identity certificate for this actor.
pub fn id_cert(&self) -> &IdCert {
&self.id_cert
}
/// The identifier that the Signer needs to use the key for the identity
/// certificate.
pub fn key_id(&self) -> &KeyId {
&self.key_id
}
}
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
}
}
impl Eq for MyIdentity {}
//------------ ParentInfo ----------------------------------------------------
/// This type stores details about a parent publication server: in
/// particular, its identity and where it may be contacted.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct ParentInfo {
publisher_handle: String,
#[serde(
deserialize_with = "ext_serde::de_id_cert",
serialize_with = "ext_serde::ser_id_cert")]
id_cert: IdCert,
#[serde(
deserialize_with = "ext_serde::de_http_uri",
serialize_with = "ext_serde::ser_http_uri")]
service_uri: uri::Http,
}
impl ParentInfo {
pub fn new(
publisher_handle: String,
id_cert: IdCert,
service_uri: uri::Http,
) -> Self {
ParentInfo {
publisher_handle,
id_cert,
service_uri,
}
}
/// The Identity Certificate used by the parent.
pub fn id_cert(&self) -> &IdCert {
&self.id_cert
}
/// The service URI where the client should send requests.
pub fn service_uri(&self) -> &uri::Http {
&self.service_uri
}
/// The name the publication server prefers to go by
pub fn publisher_handle(&self) -> &String {
&self.publisher_handle
}
}
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
}
}
impl Eq for ParentInfo {}
//------------ MyRepoInfo ----------------------------------------------------
/// This type stores details about the repository URIs available to a
/// publisher.
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct MyRepoInfo {
#[serde(
deserialize_with = "ext_serde::de_rsync_uri",
serialize_with = "ext_serde::ser_rsync_uri")]
sia_base: uri::Rsync,
#[serde(
deserialize_with = "ext_serde::de_http_uri",
serialize_with = "ext_serde::ser_http_uri")]
notify_sia: uri::Http
}
impl MyRepoInfo {
pub fn new(
sia_base: uri::Rsync,
notify_sia: uri::Http
) -> Self {
MyRepoInfo { sia_base, notify_sia }
}
/// The base rsync directory under which the publisher may publish.
// XXX TODO: Read whether standards allow sub-dirs
pub fn sia_base(&self) -> &uri::Rsync {
&self.sia_base
}
pub fn notify_sia(&self) -> &uri::Http {
&self.notify_sia
}
}
impl PartialEq for MyRepoInfo {
fn eq(&self, other: &MyRepoInfo) -> bool {
self.sia_base == other.sia_base &&
self.notify_sia == other.notify_sia
}
}
impl Eq for MyRepoInfo {}
+1 -1
View File
@@ -1,3 +1,3 @@
pub mod identity;
pub mod info;
pub mod publisher;
pub mod publisher_list;
+89 -8
View File
@@ -9,11 +9,14 @@ use rpki::oob::exchange::PublisherRequest;
use rpki::signing::PublicKeyAlgorithm;
use rpki::signing::builder::IdCertBuilder;
use rpki::signing::signer::{CreateKeyError, KeyUseError, Signer};
use provisioning::identity::MyIdentity;
use provisioning::info::MyIdentity;
use signing::softsigner;
use signing::softsigner::OpenSslSigner;
use storage::caching_ks::CachingDiskKeyStore;
use storage::keystore::{self, Info, Key, KeyStore};
use rpki::oob::exchange::RepositoryResponse;
use provisioning::info::ParentInfo;
use provisioning::info::MyRepoInfo;
/// # Some constants for naming resources in the keystore for clients.
@@ -25,10 +28,25 @@ fn my_id_key() -> Key {
Key::from_str("my_id")
}
fn my_parent_key() -> Key {
Key::from_str("my_parent")
}
fn my_repo_key() -> Key {
Key::from_str("my_repo")
}
fn my_id_msg() -> String {
"initialised identity".to_string()
}
fn my_parent_msg() -> String {
"updated parent info".to_string()
}
fn my_repo_msg() -> String {
"update repo info".to_string()
}
//------------ PubClient -----------------------------------------------------
@@ -40,11 +58,10 @@ pub struct PubClient {
// key value store
store: CachingDiskKeyStore,
// my_id -> MyIdentity
// -> my parent
// -> service uri
// -> parent id certificate
// -> my base uri
// my_id -> MyIdentity
// my_parent -> ParentInfo
// my_repo -> MyRepoInfo
// -> my directory of interest
// (note: we do not keep this state in client, truth is on disk)
// archive / log
@@ -85,8 +102,37 @@ impl PubClient {
}
/// Process the publication server parent response.
pub fn process_parent_id(&mut self) -> Result<(), Error> {
unimplemented!()
pub fn process_repo_response(
&mut self,
response: RepositoryResponse
) -> Result<(), Error> {
// Store parent info
{
let parent_val = ParentInfo::new(
response.publisher_handle().clone(),
response.id_cert().clone(),
response.service_uri().clone()
);
let parent_info = Info::now(actor(), my_parent_msg());
let parent_key = my_parent_key();
self.store.store(parent_key, parent_val, parent_info)?;
}
// Store repo info
{
let repo_val = MyRepoInfo::new(
response.sia_base().clone(),
response.rrdp_notification_uri().clone()
);
let repo_info = Info::now(actor(), my_repo_msg());
let repo_key = my_repo_key();
self.store.store(repo_key, repo_val, repo_info)?;
}
Ok(())
}
pub fn publisher_request(&self) -> Result<PublisherRequest, Error> {
@@ -175,6 +221,21 @@ impl From<KeyUseError> for Error {
mod tests {
use super::*;
use test;
use pubd::server::PubServer;
fn test_server(work_dir: &PathBuf, xml_dir: &PathBuf) -> PubServer {
// Start up a server
let uri = test::rsync_uri("rsync://host/module/");
let service = test::http_uri("http://host/publish");
let notify = test::http_uri("http://host/notify.xml");
PubServer::new(
work_dir.clone(),
xml_dir.clone(),
uri,
service,
notify
).unwrap()
}
#[test]
fn should_initialise_keep_state_and_reinitialise() {
@@ -199,7 +260,27 @@ mod tests {
assert_ne!(pr_1.id_cert().to_bytes(), pr_2.id_cert().to_bytes());
assert_ne!(client_1, client_2);
});
}
#[test]
fn should_process_repo_response() {
test::test_with_tmp_dir(|d| {
let xml_dir = test::create_sub_dir(&d);
let alice_dir = test::create_sub_dir(&d);
let mut alice = PubClient::new(alice_dir).unwrap();
alice.init("alice".to_string()).unwrap();
let pr_alice = alice.publisher_request().unwrap();
test::save_file(&xml_dir, "alice.xml", &pr_alice.encode_vec());
let mut server = test_server(&d, &xml_dir);
server.init_identity_if_empty().unwrap();
let response = server.repository_response("alice").unwrap();
alice.process_repo_response(response).unwrap();
});
}
}
+9 -21
View File
@@ -2,7 +2,7 @@
use std::path::PathBuf;
use std::sync::Arc;
use provisioning::identity::MyIdentity;
use provisioning::info::MyIdentity;
use provisioning::publisher_list;
use provisioning::publisher_list::PublisherList;
use rpki::uri;
@@ -213,20 +213,8 @@ impl From<KeyUseError> for Error {
#[cfg(test)]
mod tests {
use super::*;
use std::fs::File;
use std::io::Write;
use test;
use pubc::client::PubClient;
use rpki::oob::exchange::PublisherRequest;
fn save_pr(base_dir: &PathBuf, file_name: &str, pr: &PublisherRequest) {
let mut full_name = base_dir.clone();
full_name.push(PathBuf::from
(file_name));
let mut f = File::create(full_name).unwrap();
let xml = pr.encode_vec();
f.write(xml.as_ref()).unwrap();
}
fn test_server(work_dir: &PathBuf, xml_dir: &PathBuf) -> PubServer {
// Start up a server
@@ -280,8 +268,8 @@ mod tests {
bob.init("bob".to_string()).unwrap();
let pr_bob = bob.publisher_request().unwrap();
save_pr(&xml_dir, "alice.xml", &pr_alice);
save_pr(&xml_dir, "bob.xml", &pr_bob);
test::save_file(&xml_dir, "alice.xml", &pr_alice.encode_vec());
test::save_file(&xml_dir, "bob.xml", &pr_bob.encode_vec());
// Start up a server
let server = test_server(&d, &xml_dir);
@@ -292,7 +280,7 @@ mod tests {
// Create a new xml dir with only alice.xml
let xml_dir = PathBuf::from(test::create_sub_dir(&d));
save_pr(&xml_dir, "alice.xml", &pr_alice);
test::save_file(&xml_dir, "alice.xml", &pr_alice.encode_vec());
// Start a new server (so that it re-syncs)
let server = test_server(&d, &xml_dir);
@@ -321,8 +309,8 @@ mod tests {
carol.init("carol".to_string()).unwrap();
let pr_carol = carol.publisher_request().unwrap();
save_pr(&xml_dir, "alice.xml", &pr_alice);
save_pr(&xml_dir, "carol.xml", &pr_carol);
test::save_file(&xml_dir, "alice.xml", &pr_alice.encode_vec());
test::save_file(&xml_dir, "carol.xml", &pr_carol.encode_vec());
let server = test_server(&d, &xml_dir);
@@ -350,7 +338,7 @@ mod tests {
// However, initialising the server with two or more xml files
// for the same handle results in an error.
save_pr(&xml_dir, "alice-2.xml", &pr_alice);
test::save_file(&xml_dir, "alice-2.xml", &pr_alice.encode_vec());
let uri = test::rsync_uri("rsync://host/module/");
let service = test::http_uri("http://host/publish");
@@ -383,8 +371,8 @@ mod tests {
bob.init("bob".to_string()).unwrap();
let pr_bob = bob.publisher_request().unwrap();
save_pr(&xml_dir, "alice.xml", &pr_alice);
save_pr(&xml_dir, "bob.xml", &pr_bob);
test::save_file(&xml_dir, "alice.xml", &pr_alice.encode_vec());
test::save_file(&xml_dir, "bob.xml", &pr_bob.encode_vec());
let mut server = test_server(&d, &xml_dir);
server.init_identity_if_empty().unwrap();
+17 -9
View File
@@ -1,12 +1,13 @@
// Note: suppressing unused imports here, because this is only used with
#[allow(unused_imports)] use std::path::PathBuf;
#[allow(unused_imports)] use rpki::oob::exchange::PublisherRequest;
#[allow(unused_imports)] use rpki::uri;
#[allow(unused_imports)] use rpki::remote::idcert::IdCert;
#[allow(unused_imports)] use rpki::signing::builder::IdCertBuilder;
#[allow(unused_imports)] use rpki::signing::signer::Signer;
#[allow(unused_imports)] use rpki::signing::softsigner::OpenSslSigner;
#[allow(unused_imports)] use rpki::signing::PublicKeyAlgorithm;
use std::fs::File;
use std::io::Write;
use std::path::PathBuf;
use rpki::oob::exchange::PublisherRequest;
use rpki::uri;
use rpki::remote::idcert::IdCert;
use rpki::signing::builder::IdCertBuilder;
use rpki::signing::signer::Signer;
use rpki::signing::softsigner::OpenSslSigner;
use rpki::signing::PublicKeyAlgorithm;
pub fn test_with_tmp_dir<F>(op: F) where F: FnOnce(PathBuf) -> () {
use std::fs;
@@ -58,4 +59,11 @@ pub fn new_publisher_request(publisher_handle: &str) -> PublisherRequest {
publisher_handle,
id_cert
)
}
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(content).unwrap();
}
-1
View File
@@ -113,7 +113,6 @@ fn testing() {
println!("{}", e);
});
rt.block_on(fut).unwrap();