mirror of
https://github.com/NLnetLabs/krill.git
synced 2026-09-18 07:27:42 +02:00
Process repository response in publisher client.
This commit is contained in:
@@ -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 {}
|
||||
@@ -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,3 +1,3 @@
|
||||
pub mod identity;
|
||||
pub mod info;
|
||||
pub mod publisher;
|
||||
pub mod publisher_list;
|
||||
+89
-8
@@ -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
@@ -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
@@ -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();
|
||||
}
|
||||
@@ -113,7 +113,6 @@ fn testing() {
|
||||
println!("{}", e);
|
||||
});
|
||||
|
||||
|
||||
rt.block_on(fut).unwrap();
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user