parent
18343cc829
commit
37ae67bd1c
21 changed files with 240 additions and 188 deletions
@ -1,17 +1,18 @@ |
|||||||
set -ex |
set -ex |
||||||
DIR=. |
DIR=. |
||||||
V3_CFG=v3.ext |
V3_CFG=$DIR/v3.ext |
||||||
|
|
||||||
cat > $DIR/$V3_CFG << EOF |
cat > $V3_CFG << EOF |
||||||
authorityKeyIdentifier=keyid,issuer |
authorityKeyIdentifier=keyid,issuer |
||||||
basicConstraints=CA:FALSE |
basicConstraints=CA:FALSE |
||||||
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, cRLSign |
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment, keyAgreement, keyCertSign, cRLSign |
||||||
EOF |
EOF |
||||||
|
|
||||||
|
|
||||||
openssl req -x509 -newkey rsa:4096 -keyout $DIR/ca.key -out $DIR/ca.crt -nodes -days 365 -subj "/CN=root" |
openssl req -x509 -newkey rsa:4096 -keyout $DIR/ca.key -out $DIR/ca.crt -nodes -days 365 -subj "/CN=root" |
||||||
openssl req -newkey rsa:4096 -keyout $DIR/alice.key -out $DIR/alice.csr -nodes -days 365 -subj "/CN=alice" |
openssl req -newkey rsa:4096 -keyout $DIR/alice.key -out $DIR/alice.csr -nodes -days 365 -subj "/CN=alice" |
||||||
openssl req -newkey rsa:4096 -keyout $DIR/server.key -out $DIR/server.csr -nodes -days 365 -subj "/CN=u_server" |
openssl req -newkey rsa:4096 -keyout $DIR/server.key -out $DIR/server.csr -nodes -days 365 -subj "/CN=u_server" |
||||||
openssl x509 -req -in $DIR/alice.csr -CA $DIR/ca.crt -CAkey $DIR/ca.key -out $DIR/alice.crt -set_serial 01 -days 365 -extfile $DIR/$V3_CFG |
openssl x509 -req -in $DIR/alice.csr -CA $DIR/ca.crt -CAkey $DIR/ca.key -out $DIR/alice.crt -set_serial 01 -days 365 -extfile $V3_CFG |
||||||
openssl x509 -req -in $DIR/server.csr -CA $DIR/ca.crt -CAkey $DIR/ca.key -out $DIR/server.crt -set_serial 01 -days 365 -extfile $DIR/$V3_CFG |
openssl x509 -req -in $DIR/server.csr -CA $DIR/ca.crt -CAkey $DIR/ca.key -out $DIR/server.crt -set_serial 01 -days 365 -extfile $V3_CFG |
||||||
openssl pkcs12 -export -out $DIR/alice.p12 -inkey $DIR/alice.key -in $DIR/alice.crt -passin pass: -passout pass: |
openssl pkcs12 -export -out $DIR/alice.p12 -inkey $DIR/alice.key -in $DIR/alice.crt -passin pass: -passout pass: |
||||||
|
|
||||||
|
rm $V3_CFG |
@ -1 +1,46 @@ |
|||||||
|
use crate::fixtures::agent::*; |
||||||
|
use crate::helpers::Panel; |
||||||
|
|
||||||
|
use rstest::rstest; |
||||||
|
use std::error::Error; |
||||||
|
use std::thread::sleep; |
||||||
|
use std::time::Duration; |
||||||
|
use u_lib::models::*; |
||||||
|
use uuid::Uuid; |
||||||
|
|
||||||
|
type TestResult<R = ()> = Result<R, Box<dyn Error>>; |
||||||
|
|
||||||
|
#[rstest] |
||||||
|
#[tokio::test] |
||||||
|
async fn test_registration(#[future] register_agent: RegisteredAgent) -> TestResult { |
||||||
|
let agent = register_agent.await; |
||||||
|
let agents: Vec<Agent> = Panel::check_output("agents list"); |
||||||
|
let found = agents.iter().find(|v| v.id == agent.uid); |
||||||
|
assert!(found.is_some()); |
||||||
|
//teardown
|
||||||
|
Panel::check_status::<i32>(&format!("agents delete {}", agent.uid)); |
||||||
|
Ok(()) //TODO: ______^^^^^ REMOV
|
||||||
|
} |
||||||
|
|
||||||
|
#[tokio::test] |
||||||
|
async fn test_setup_tasks() -> TestResult { |
||||||
|
//some independent agents should present
|
||||||
|
let agents: Vec<Agent> = Panel::check_output("agents list"); |
||||||
|
let agent_uid = agents[0].id; |
||||||
|
let job_alias = "passwd_contents"; |
||||||
|
let cmd = format!("jobs add --alias {} 'cat /etc/passwd'", job_alias); |
||||||
|
Panel::check_status::<Empty>(&cmd); |
||||||
|
let cmd = format!("jobmap add {} {}", agent_uid, job_alias); |
||||||
|
let assigned_uids: Vec<Uuid> = Panel::check_output(cmd); |
||||||
|
for _ in 0..3 { |
||||||
|
let result: Vec<AssignedJob> = |
||||||
|
Panel::check_output(format!("jobmap list {}", assigned_uids[0])); |
||||||
|
if result[0].state == JobState::Finished { |
||||||
|
return Ok(()); |
||||||
|
} else { |
||||||
|
sleep(Duration::from_secs(5)); |
||||||
|
eprintln!("waiting for task"); |
||||||
|
} |
||||||
|
} |
||||||
|
panic!("Job didn't appear in the job map"); |
||||||
|
} |
||||||
|
@ -0,0 +1,36 @@ |
|||||||
|
use u_lib::{api::ClientHandler, models::*}; |
||||||
|
use uuid::Uuid; |
||||||
|
|
||||||
|
pub struct RegisteredAgent { |
||||||
|
pub uid: Uuid, |
||||||
|
} |
||||||
|
|
||||||
|
impl RegisteredAgent { |
||||||
|
pub async fn unregister(self) { |
||||||
|
let cli = ClientHandler::new(None); |
||||||
|
cli.del(Some(self.uid)).await.unwrap(); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
#[fixture] |
||||||
|
pub async fn register_agent() -> RegisteredAgent { |
||||||
|
let cli = ClientHandler::new(None); |
||||||
|
let agent_uid = Uuid::new_v4(); |
||||||
|
let resp = cli |
||||||
|
.get_personal_jobs(Some(agent_uid)) |
||||||
|
.await |
||||||
|
.unwrap() |
||||||
|
.pop() |
||||||
|
.unwrap(); |
||||||
|
let job_id = resp.job_id; |
||||||
|
let resp = cli.get_jobs(Some(job_id)).await.unwrap().pop().unwrap(); |
||||||
|
assert_eq!(resp.alias, Some("agent_hello".to_string())); |
||||||
|
let agent_data = Agent { |
||||||
|
id: agent_uid, |
||||||
|
..Default::default() |
||||||
|
}; |
||||||
|
cli.report(&vec![ExecResult::Agent(agent_data)]) |
||||||
|
.await |
||||||
|
.unwrap(); |
||||||
|
RegisteredAgent { uid: agent_uid } |
||||||
|
} |
@ -0,0 +1 @@ |
|||||||
|
pub mod agent; |
@ -1,48 +0,0 @@ |
|||||||
use reqwest::{Client, RequestBuilder, Url}; |
|
||||||
use serde::Serialize; |
|
||||||
use serde_json::{from_str, json, Value}; |
|
||||||
|
|
||||||
const SERVER: &str = "u_server"; |
|
||||||
const PORT: &str = "63714"; |
|
||||||
|
|
||||||
pub struct AgentClient { |
|
||||||
client: Client, |
|
||||||
base_url: Url, |
|
||||||
} |
|
||||||
|
|
||||||
impl AgentClient { |
|
||||||
pub fn new() -> Self { |
|
||||||
Self { |
|
||||||
client: Client::new(), |
|
||||||
base_url: Url::parse(&format!("http://{}:{}", SERVER, PORT)).unwrap(), |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
async fn process_request(&self, req: RequestBuilder, resp_needed: bool) -> Value { |
|
||||||
let resp = req.send().await.unwrap(); |
|
||||||
if let Err(e) = resp.error_for_status_ref() { |
|
||||||
panic!( |
|
||||||
"Server responded with code {}\nError: {}", |
|
||||||
e.status() |
|
||||||
.map(|s| s.to_string()) |
|
||||||
.unwrap_or(String::from("<none>")), |
|
||||||
e.to_string() |
|
||||||
); |
|
||||||
} |
|
||||||
if !resp_needed { |
|
||||||
return json!([]); |
|
||||||
} |
|
||||||
let resp: Value = from_str(&resp.text().await.unwrap()).unwrap(); |
|
||||||
resp.get("inner").unwrap().get(0).unwrap().clone() |
|
||||||
} |
|
||||||
|
|
||||||
pub async fn get<S: AsRef<str>>(&self, url: S) -> Value { |
|
||||||
let req = self.client.get(self.base_url.join(url.as_ref()).unwrap()); |
|
||||||
self.process_request(req, true).await |
|
||||||
} |
|
||||||
|
|
||||||
pub async fn post<S: AsRef<str>, B: Serialize>(&self, url: S, body: &B) -> Value { |
|
||||||
let req = self.client.post(self.base_url.join(url.as_ref()).unwrap()); |
|
||||||
self.process_request(req.json(body), false).await |
|
||||||
} |
|
||||||
} |
|
@ -1,67 +1,6 @@ |
|||||||
|
mod behaviour; |
||||||
|
mod fixtures; |
||||||
mod helpers; |
mod helpers; |
||||||
|
|
||||||
use helpers::Panel; |
#[macro_use] |
||||||
|
extern crate rstest; |
||||||
use std::error::Error; |
|
||||||
use std::thread::sleep; |
|
||||||
use std::time::Duration; |
|
||||||
use u_lib::{api::ClientHandler, models::*}; |
|
||||||
use uuid::Uuid; |
|
||||||
|
|
||||||
type TestResult<R = ()> = Result<R, Box<dyn Error>>; |
|
||||||
|
|
||||||
async fn register_agent() -> Uuid { |
|
||||||
let cli = ClientHandler::new(None); |
|
||||||
let agent_uid = Uuid::new_v4(); |
|
||||||
let resp = cli |
|
||||||
.get_personal_jobs(Some(agent_uid)) |
|
||||||
.await |
|
||||||
.unwrap() |
|
||||||
.pop() |
|
||||||
.unwrap(); |
|
||||||
let job_id = resp.job_id; |
|
||||||
let resp = cli.get_jobs(Some(job_id)).await.unwrap().pop().unwrap(); |
|
||||||
assert_eq!(resp.alias, Some("agent_hello".to_string())); |
|
||||||
let agent_data = Agent { |
|
||||||
id: agent_uid, |
|
||||||
..Default::default() |
|
||||||
}; |
|
||||||
cli.report(&vec![ExecResult::Agent(agent_data)]) |
|
||||||
.await |
|
||||||
.unwrap(); |
|
||||||
agent_uid |
|
||||||
} |
|
||||||
|
|
||||||
#[tokio::test] |
|
||||||
async fn test_registration() -> TestResult { |
|
||||||
let agent_uid = register_agent().await; |
|
||||||
let agents: Vec<Agent> = Panel::check_output("agents list"); |
|
||||||
let found = agents.iter().find(|v| v.id == agent_uid); |
|
||||||
assert!(found.is_some()); |
|
||||||
//teardown
|
|
||||||
Panel::check_status::<i32>(&format!("agents delete {}", agent_uid)); |
|
||||||
Ok(()) |
|
||||||
} |
|
||||||
|
|
||||||
#[tokio::test] |
|
||||||
async fn test_setup_tasks() -> TestResult { |
|
||||||
//some independent agents should present
|
|
||||||
let agents: Vec<Agent> = Panel::check_output("agents list"); |
|
||||||
let agent_uid = agents[0].id; |
|
||||||
let job_alias = "passwd_contents"; |
|
||||||
let cmd = format!("jobs add --alias {} 'cat /etc/passwd'", job_alias); |
|
||||||
Panel::check_status::<Empty>(&cmd); |
|
||||||
let cmd = format!("jobmap add {} {}", agent_uid, job_alias); |
|
||||||
let assigned_uids: Vec<Uuid> = Panel::check_output(cmd); |
|
||||||
for _ in 0..3 { |
|
||||||
let result: Vec<AssignedJob> = |
|
||||||
Panel::check_output(format!("jobmap list {}", assigned_uids[0])); |
|
||||||
if result[0].state == JobState::Finished { |
|
||||||
return Ok(()); |
|
||||||
} else { |
|
||||||
sleep(Duration::from_secs(5)); |
|
||||||
eprintln!("waiting for task"); |
|
||||||
} |
|
||||||
} |
|
||||||
panic!() |
|
||||||
} |
|
||||||
|
@ -0,0 +1,8 @@ |
|||||||
|
use serde::{Deserialize, Serialize}; |
||||||
|
use uuid::Uuid; |
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Debug, Default)] |
||||||
|
pub struct DownloadInfo { |
||||||
|
hashsum: String, |
||||||
|
dl_fid: Uuid, |
||||||
|
} |
@ -0,0 +1,29 @@ |
|||||||
|
mod base; |
||||||
|
mod files; |
||||||
|
|
||||||
|
use crate::models::*; |
||||||
|
pub use base::{AsMsg, BaseMessage}; |
||||||
|
pub use files::*; |
||||||
|
use serde::{Deserialize, Serialize}; |
||||||
|
use std::fmt; |
||||||
|
use uuid::Uuid; |
||||||
|
|
||||||
|
impl AsMsg for Agent {} |
||||||
|
impl AsMsg for AssignedJob {} |
||||||
|
impl AsMsg for DownloadInfo {} |
||||||
|
impl AsMsg for ExecResult {} |
||||||
|
impl AsMsg for JobMeta {} |
||||||
|
impl AsMsg for String {} |
||||||
|
impl AsMsg for Uuid {} |
||||||
|
impl AsMsg for Empty {} |
||||||
|
impl AsMsg for i32 {} |
||||||
|
impl AsMsg for u8 {} |
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Clone, Default, Debug)] |
||||||
|
pub struct Empty; |
||||||
|
|
||||||
|
impl fmt::Display for Empty { |
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||||
|
write!(f, "<empty>") |
||||||
|
} |
||||||
|
} |
@ -1,29 +1,13 @@ |
|||||||
mod agent; |
mod agent; |
||||||
pub mod jobs; |
pub mod jobs; |
||||||
mod result; |
|
||||||
pub mod schema; |
pub mod schema; |
||||||
|
|
||||||
use crate::messaging::AsMsg; |
|
||||||
pub use crate::models::result::ExecResult; |
|
||||||
pub use crate::models::{agent::*, jobs::*}; |
pub use crate::models::{agent::*, jobs::*}; |
||||||
use serde::{Deserialize, Serialize}; |
use serde::{Deserialize, Serialize}; |
||||||
use std::fmt; |
|
||||||
use uuid::Uuid; |
|
||||||
|
|
||||||
impl AsMsg for Agent {} |
#[derive(Serialize, Deserialize, Clone, PartialEq)] |
||||||
impl AsMsg for AssignedJob {} |
pub enum ExecResult { |
||||||
impl AsMsg for ExecResult {} |
Assigned(AssignedJob), |
||||||
impl AsMsg for JobMeta {} |
Agent(Agent), |
||||||
impl AsMsg for String {} |
Dummy, |
||||||
impl AsMsg for Uuid {} |
|
||||||
impl AsMsg for Empty {} |
|
||||||
impl AsMsg for i32 {} |
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Default, Debug)] |
|
||||||
pub struct Empty; |
|
||||||
|
|
||||||
impl fmt::Display for Empty { |
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
|
||||||
write!(f, "<empty>") |
|
||||||
} |
|
||||||
} |
} |
||||||
|
@ -1,9 +0,0 @@ |
|||||||
use crate::models::{Agent, AssignedJob}; |
|
||||||
use serde::{Deserialize, Serialize}; |
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, PartialEq)] |
|
||||||
pub enum ExecResult { |
|
||||||
Assigned(AssignedJob), |
|
||||||
Agent(Agent), |
|
||||||
Dummy, |
|
||||||
} |
|
@ -0,0 +1,12 @@ |
|||||||
|
use std::fmt; |
||||||
|
|
||||||
|
pub struct Hexlify<'b>(pub &'b [u8]); |
||||||
|
|
||||||
|
impl<'a> fmt::LowerHex for Hexlify<'a> { |
||||||
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
||||||
|
for byte in self.0.iter() { |
||||||
|
write!(f, "{:02x}", byte)?; |
||||||
|
} |
||||||
|
Ok(()) |
||||||
|
} |
||||||
|
} |
@ -1,11 +1,15 @@ |
|||||||
pub mod combined_result; |
mod combined_result; |
||||||
pub mod conv; |
mod conv; |
||||||
pub mod misc; |
mod hexlify; |
||||||
pub mod tempfile; |
mod misc; |
||||||
pub mod vec_display; |
mod storage; |
||||||
|
mod tempfile; |
||||||
|
mod vec_display; |
||||||
|
|
||||||
pub use combined_result::*; |
pub use combined_result::*; |
||||||
pub use conv::*; |
pub use conv::*; |
||||||
|
pub use hexlify::*; |
||||||
pub use misc::*; |
pub use misc::*; |
||||||
|
pub use storage::*; |
||||||
pub use tempfile::*; |
pub use tempfile::*; |
||||||
pub use vec_display::*; |
pub use vec_display::*; |
||||||
|
@ -0,0 +1,39 @@ |
|||||||
|
use once_cell::sync::Lazy; |
||||||
|
use std::cmp::Eq; |
||||||
|
use std::collections::HashMap; |
||||||
|
use std::hash::Hash; |
||||||
|
use std::ops::Deref; |
||||||
|
use std::sync::Arc; |
||||||
|
use std::sync::{Mutex, MutexGuard}; |
||||||
|
|
||||||
|
//improve this later, replace job cacher with it
|
||||||
|
//possibly add different backends (memory, disk)
|
||||||
|
pub struct SharedStorage<Key, Val>(Arc<Mutex<HashMap<Key, Val>>>); |
||||||
|
|
||||||
|
impl<Key: Eq + Hash, Val> SharedStorage<Key, Val> { |
||||||
|
pub fn new() -> Lazy<SharedStorage<Key, Val>> { |
||||||
|
Lazy::new(|| SharedStorage(Arc::new(Mutex::new(HashMap::new())))) |
||||||
|
} |
||||||
|
|
||||||
|
pub fn lock(&self) -> MutexGuard<'_, HashMap<Key, Val>> { |
||||||
|
self.0.lock().unwrap() |
||||||
|
} |
||||||
|
|
||||||
|
pub fn get<'get, 'slf: 'get>(&'slf self, key: &'get Key) -> Option<RefHolder<'get, Key, Val>> { |
||||||
|
if !self.lock().contains_key(key) { |
||||||
|
return None; |
||||||
|
} |
||||||
|
let lock = self.lock(); |
||||||
|
Some(RefHolder(lock, key)) |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pub struct RefHolder<'h, Key, Val>(pub MutexGuard<'h, HashMap<Key, Val>>, pub &'h Key); |
||||||
|
|
||||||
|
impl<'h, Key: Eq + Hash, Val> Deref for RefHolder<'h, Key, Val> { |
||||||
|
type Target = Val; |
||||||
|
|
||||||
|
fn deref(&self) -> &Self::Target { |
||||||
|
self.0.get(self.1).unwrap() |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue