diff --git a/dnapi-rs/src/client_blocking.rs b/dnapi-rs/src/client_blocking.rs index 780cc32..f568f8e 100644 --- a/dnapi-rs/src/client_blocking.rs +++ b/dnapi-rs/src/client_blocking.rs @@ -3,11 +3,13 @@ use std::error::Error; use chrono::Local; use log::{debug, error}; +use reqwest::StatusCode; use url::Url; use trifid_pki::cert::serialize_ed25519_public; +use trifid_pki::ed25519_dalek::{Signer, SigningKey}; use crate::credentials::{Credentials, ed25519_public_keys_from_pem}; use crate::crypto::new_keys; -use crate::message::{ENROLL_ENDPOINT, EnrollRequest, EnrollResponse}; +use crate::message::{ENDPOINT_V1, ENROLL_ENDPOINT, EnrollRequest, EnrollResponse, RequestV1, RequestWrapper}; /// A type alias to abstract return types pub type NebulaConfig = Vec; @@ -98,5 +100,44 @@ impl Client { Ok((r.config, dh_privkey_pem, creds, meta)) } + /// Wraps and signs the given req_type and value, and then makes the API call. + /// On success, returns the response body. + /// # Errors + /// This function will return an error if: + /// - serialization in any step fails + /// - if the server_url is invalid + /// - if the request could not be sent + pub fn post_dnclient(&self, req_type: &str, value: &[u8], host_id: &str, counter: u32, ed_privkey: SigningKey) -> Result, Box> { + let encoded_msg = serde_json::to_string(&RequestWrapper { + message_type: req_type.to_string(), + value: value.to_vec(), + timestamp: Local::now().format("%Y-%m-%dT%H:%M:%S.%f%:z").to_string(), + })?; + let encoded_msg_bytes = encoded_msg.into_bytes(); + let signature = ed_privkey.sign(&encoded_msg_bytes).to_vec(); + let body = RequestV1 { + version: 1, + host_id: host_id.to_string(), + counter, + message: encoded_msg_bytes, + signature, + }; + let post_body = serde_json::to_string(&body)?; + + let resp = self.http_client.post(self.server_url.join(ENDPOINT_V1)?).body(post_body).send()?; + + match resp.status() { + StatusCode::OK => { + Ok(resp.bytes()?.to_vec()) + }, + StatusCode::FORBIDDEN => { + Err("Forbidden".into()) + }, + _ => { + error!("dnclient endpoint returned bad status code {}", resp.status()); + Err("dnclient endpoint returned error".into()) + } + } + } } \ No newline at end of file