Skip to content

Commit

Permalink
Some more work done to separate the CMS/XML protocol and JSON. Still …
Browse files Browse the repository at this point in the history
…some more cleanup coming. (see issue #34)
  • Loading branch information
Tim Bruijnzeels committed Jan 23, 2019
1 parent dea1958 commit c2ba03e
Show file tree
Hide file tree
Showing 17 changed files with 530 additions and 398 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ serde_json = "^1.0"
syslog = "^4.0"
toml = "^0.4"
tokio = "^0.1"
uuid = "0.7"
xml-rs = "0.8.0"

# XXX Temporarily
Expand Down
3 changes: 0 additions & 3 deletions defaults/krill.conf
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,6 @@
# in their certificates.
#rrdp_base_uri = "http://127.0.0.1:3000/rrdp/"

# Specify the base service URI where publishers can connect.
#service_uri = "http://127.0.0.1:3000/rfc8181/"

# Log level
#
# The maximum log level ("off", "error", "warn", "info", or "debug") for
Expand Down
63 changes: 45 additions & 18 deletions src/client/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,23 @@ impl PublisherSummary {
}
}


//------------ Rfc8181Details ------------------------------------------------

#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Rfc8181Details {
#[serde(
serialize_with = "ext_serde::ser_http_uri",
deserialize_with = "ext_serde::de_http_uri")]
service_uri: uri::Http,

#[serde(
serialize_with = "ext_serde::ser_id_cert",
deserialize_with = "ext_serde::de_id_cert")]
id_cert: IdCert
}


//------------ PublisherDetails ----------------------------------------------

/// This type defines the publisher details fro:
Expand All @@ -177,16 +194,7 @@ pub struct PublisherDetails {
)]
base_uri: uri::Rsync,

#[serde(
deserialize_with = "ext_serde::de_http_uri",
serialize_with = "ext_serde::ser_http_uri"
)]
service_uri: uri::Http,
#[serde(
deserialize_with = "ext_serde::de_id_cert",
serialize_with = "ext_serde::ser_id_cert"
)]
identity_certificate: IdCert,
rfc8181: Option<Rfc8181Details>,

links: Vec<Link>
}
Expand All @@ -195,8 +203,11 @@ impl PublisherDetails {
pub fn publisher_handle(&self) -> &str {
&self.publisher_handle
}
pub fn identity_cert(&self) -> &IdCert {
&self.identity_certificate
pub fn identity_cert(&self) -> Option<&IdCert> {
match self.rfc8181 {
None => None,
Some(ref details) => Some(&details.id_cert)
}
}
}

Expand All @@ -219,12 +230,28 @@ impl Report for PublisherDetails {
},
ReportFormat::Text => {

let res = format!(
"publisher_handle: {}\n\
base uri: {}\n\
service_uri: {}",
self.publisher_handle, self.base_uri, self.service_uri
);
let mut res = String::new();

res.push_str("handle: ");
res.push_str(self.publisher_handle.as_str());
res.push_str("\n");

res.push_str("base uri: ");
res.push_str(self.base_uri.to_string().as_str());
res.push_str("\n");

if let Some(ref rfc8181) = self.rfc8181 {
res.push_str("RFC8181 Details:\n");
res.push_str(" service uri: ");
res.push_str(rfc8181.service_uri.to_string().as_str());
res.push_str("\n");
res.push_str(" id cert (base64): ");
res.push_str(
base64::encode(
rfc8181.id_cert.to_bytes().as_ref()
).as_str());
res.push_str("\n");
}

Ok(res)
},
Expand Down
15 changes: 12 additions & 3 deletions src/client/krillc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,15 @@ impl KrillClient {
let uri = format!("api/v1/publishers/{}", handle);
let res = self.get(uri.as_str())?;
let details: PublisherDetails = serde_json::from_str(&res)?;
let bytes = details.identity_cert().to_bytes();
file::save(&bytes, &file)?;
Ok(ApiResponse::Empty)
match details.identity_cert() {
Some(cert) => {
let bytes = cert.to_bytes();
file::save(&bytes, &file)?;
Ok(ApiResponse::Empty)
},
None => Err(Error::NoIdCert)
}

}
}
}
Expand Down Expand Up @@ -271,6 +277,9 @@ pub enum Error {

#[display(fmt="Can't read file: {}", _0)]
IoError(io::Error),

#[display(fmt="There is no known IdCert for this publisher")]
NoIdCert
}

impl From<reqwest::Error> for Error {
Expand Down
130 changes: 89 additions & 41 deletions src/daemon/api/admin.rs → src/daemon/api/endpoints.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
//! Support for various admin API methods
//! Process requests received, delegate, and wrap up the responses.
use std::error;
use std::sync::{RwLockReadGuard, RwLockWriteGuard};
use actix_web::{HttpResponse, ResponseError};
Expand All @@ -8,7 +8,22 @@ use crate::daemon::api::responses::{PublisherDetails, PublisherList};
use crate::daemon::http::server::{HttpRequest, PublisherHandle};
use crate::daemon::publishers;
use crate::daemon::krillserver::{self, KrillServer};
use crate::remote::rfc8183::PublisherRequest;
use remote::sigmsg::SignedMessage;
use daemon::api::requests::PublishDelta;
use daemon::api::requests::PublisherRequestChoice;


//------------ Support Functions ---------------------------------------------

/// Returns a server in a read lock
pub fn ro_server(req: &HttpRequest) -> RwLockReadGuard<KrillServer> {
req.state().read().unwrap()
}

/// Returns a server in a write lock
pub fn rw_server(req: &HttpRequest) -> RwLockWriteGuard<KrillServer> {
req.state().write().unwrap()
}

/// Helper function to render json output.
fn render_json<O: Serialize>(object: O) -> HttpResponse {
Expand All @@ -29,26 +44,24 @@ fn server_error(error: Error) -> HttpResponse {
error.error_response()
}

/// Returns a server in a read lock
fn ro_server(req: &HttpRequest) -> RwLockReadGuard<KrillServer> {
req.state().read().unwrap()
}

/// Returns a server in a write lock
fn rw_server(req: &HttpRequest) -> RwLockWriteGuard<KrillServer> {
req.state().write().unwrap()
}

/// A clean 404 result for the API (no content, not for humans)
fn api_not_found() -> HttpResponse {
HttpResponse::build(StatusCode::NOT_FOUND).finish()
}

/// A clean 200 result for the API (no content, not for humans)
fn api_ok() -> HttpResponse {
pub fn api_ok() -> HttpResponse {
HttpResponse::Ok().finish()
}

/// Returns the server health. XXX TODO: do a real test!
pub fn health(_r: &HttpRequest) -> HttpResponse {
api_ok()
}


//------------ Admin: Publishers ---------------------------------------------

/// Returns a json structure with all publishers in it.
pub fn publishers(req: &HttpRequest) -> HttpResponse {
match ro_server(req).publishers() {
Expand All @@ -65,23 +78,23 @@ pub fn publishers(req: &HttpRequest) -> HttpResponse {
/// Request XML is posted.
pub fn add_publisher(
req: HttpRequest,
pr: PublisherRequest
prc: PublisherRequestChoice
) -> HttpResponse {
let mut server = rw_server(&req);
let handle = pr.handle().clone();
match server.add_publisher(pr, &handle) {
match server.add_publisher(prc, None) {
Ok(()) => api_ok(),
Err(e) => server_error(Error::ServerError(e))
}
}

/// Adds a an explicitly named publisher.
pub fn add_named_publisher(
req: HttpRequest,
pr: PublisherRequest,
prc: PublisherRequestChoice,
handle: PublisherHandle
) -> HttpResponse {
let mut server = rw_server(&req);
match server.add_publisher(pr, handle.as_ref()) {
match server.add_publisher(prc, Some(handle.as_ref())) {
Ok(()) => api_ok(),
Err(e) => server_error(Error::ServerError(e))
}
Expand All @@ -101,41 +114,26 @@ pub fn remove_publisher(
}
}


/// Returns a json structure with publisher details
pub fn publisher_details(
req: HttpRequest,
handle: PublisherHandle
) -> HttpResponse {
match ro_server(&req).publisher(handle) {
let server = ro_server(&req);
match server.publisher(handle) {
Ok(None) => api_not_found(),
Ok(Some(publisher)) => {
render_json(
PublisherDetails::from(&publisher, "/api/v1/publishers")
PublisherDetails::from(
&publisher,
"/api/v1/publishers",
server.service_base_uri())
)
},
Err(e) => server_error(Error::ServerError(e))
}
}


/// Returns the id.cer for a publisher
pub fn id_cert(
req: HttpRequest,
handle: PublisherHandle
) -> HttpResponse {
match ro_server(&req).publisher(handle) {
Ok(None) => api_not_found(),
Ok(Some(publisher)) => {
let bytes = publisher.id_cert().to_bytes();
HttpResponse::Ok()
.content_type("application/pkix-cert")
.body(bytes)
},
Err(e) => server_error(Error::ServerError(e))
}
}

/// Shows the server's RFC8183 section 5.2.4 Repository Response XML
/// file for a known publisher.
pub fn repository_response(
Expand All @@ -158,6 +156,55 @@ pub fn repository_response(
}
}


//------------ Publication ---------------------------------------------------

/// Processes an RFC8181 query and returns the appropriate response.
pub fn handle_rfc8181_request(
req: HttpRequest,
msg: SignedMessage,
handle: PublisherHandle
) -> HttpResponse {
let mut server: RwLockWriteGuard<KrillServer> = rw_server(&req);
match server.handle_rfc8181_request(&msg, handle.as_ref()) {
Ok(captured) => {
HttpResponse::build(StatusCode::OK)
.content_type("application/rpki-publication")
.body(captured.into_bytes())
}
Err(e) => {
server_error(Error::ServerError(e))
}
}
}

/// Processes a publishdelta request sent to the API.
pub fn handle_delta(
req: HttpRequest,
delta: PublishDelta,
handle: PublisherHandle
) -> HttpResponse {
match rw_server(&req).handle_delta(delta, handle.as_ref()) {
Ok(()) => api_ok(),
Err(e) => server_error(Error::ServerError(e))
}
}

/// Processes a list request sent to the API.
pub fn handle_list(
req: HttpRequest,
handle: PublisherHandle
) -> HttpResponse {
match ro_server(&req).handle_list(handle.as_ref()) {
Ok(list) => render_json(list),
Err(e) => server_error(Error::ServerError(e))
}
}





//------------ Error ---------------------------------------------------------

#[derive(Debug, Display)]
Expand Down Expand Up @@ -214,6 +261,7 @@ impl ErrorToStatus for krillserver::Error {
krillserver::Error::CmsProxy(_) => StatusCode::BAD_REQUEST,
krillserver::Error::PublisherStore(e) => e.status(),
krillserver::Error::Repository(_) => StatusCode::BAD_REQUEST,
krillserver::Error::NoIdCert => StatusCode::FORBIDDEN,
}
}
}
Expand All @@ -224,6 +272,8 @@ impl ErrorToCode for krillserver::Error {
krillserver::Error::PublisherStore(e) => e.code(),
krillserver::Error::Repository(_) => 3002,
krillserver::Error::CmsProxy(_) => 3003,
krillserver::Error::NoIdCert => 2001,

}
}
}
Expand Down Expand Up @@ -253,7 +303,6 @@ impl ErrorToStatus for publishers::Error {
}
}


#[derive(Debug, Serialize)]
struct ErrorResponse {
code: usize,
Expand All @@ -269,7 +318,6 @@ impl Error {
}
}


impl actix_web::ResponseError for Error {
fn error_response(&self) -> HttpResponse {
HttpResponse::build(self.status())
Expand Down
2 changes: 1 addition & 1 deletion src/daemon/api/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub mod admin;
pub mod endpoints;
pub mod auth;
pub mod responses;
pub mod requests;
Loading

0 comments on commit c2ba03e

Please sign in to comment.