rename u_panel server -> gui, use doh to resolve u_server addr

master
plazmoid 2 years ago
parent 699896f335
commit 7eb15b33be
  1. 2
      Makefile.toml
  2. 3
      bin/u_agent/Cargo.toml
  3. 39
      bin/u_agent/src/lib.rs
  4. 2
      bin/u_panel/src/argparse.rs
  5. 0
      bin/u_panel/src/gui/error.rs
  6. 16
      bin/u_panel/src/gui/fe/.browserslistrc
  7. 16
      bin/u_panel/src/gui/fe/.editorconfig
  8. 0
      bin/u_panel/src/gui/fe/.gitignore
  9. 0
      bin/u_panel/src/gui/fe/README.md
  10. 0
      bin/u_panel/src/gui/fe/angular.json
  11. 0
      bin/u_panel/src/gui/fe/karma.conf.js
  12. 0
      bin/u_panel/src/gui/fe/package.json
  13. 0
      bin/u_panel/src/gui/fe/src/app/app-routing.module.ts
  14. 0
      bin/u_panel/src/gui/fe/src/app/app.component.html
  15. 0
      bin/u_panel/src/gui/fe/src/app/app.component.less
  16. 0
      bin/u_panel/src/gui/fe/src/app/app.component.spec.ts
  17. 0
      bin/u_panel/src/gui/fe/src/app/app.component.ts
  18. 0
      bin/u_panel/src/gui/fe/src/app/app.module.ts
  19. 0
      bin/u_panel/src/gui/fe/src/app/core/index.ts
  20. 0
      bin/u_panel/src/gui/fe/src/app/core/models/agent.model.ts
  21. 0
      bin/u_panel/src/gui/fe/src/app/core/models/index.ts
  22. 0
      bin/u_panel/src/gui/fe/src/app/core/models/job.model.ts
  23. 0
      bin/u_panel/src/gui/fe/src/app/core/models/result.model.ts
  24. 0
      bin/u_panel/src/gui/fe/src/app/core/services/api.service.ts
  25. 0
      bin/u_panel/src/gui/fe/src/app/core/services/index.ts
  26. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/agent.component.html
  27. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/agent.component.ts
  28. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/dialogs/agent-info-dialog.html
  29. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/dialogs/agent_info.component.ts
  30. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/dialogs/assign-job-dialog.html
  31. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/dialogs/assign_job.component.ts
  32. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/dialogs/index.ts
  33. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/dialogs/info-dialog.component.less
  34. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/dialogs/job-info-dialog.html
  35. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/dialogs/job_info.component.ts
  36. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/dialogs/result-info-dialog.html
  37. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/dialogs/result_info.component.ts
  38. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/index.ts
  39. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/job.component.html
  40. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/job.component.ts
  41. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/result.component.html
  42. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/result.component.ts
  43. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/table.component.less
  44. 0
      bin/u_panel/src/gui/fe/src/app/core/tables/table.component.ts
  45. 0
      bin/u_panel/src/gui/fe/src/app/core/utils.ts
  46. 0
      bin/u_panel/src/gui/fe/src/environments/environment.prod.ts
  47. 0
      bin/u_panel/src/gui/fe/src/environments/environment.ts
  48. 0
      bin/u_panel/src/gui/fe/src/favicon.ico
  49. 0
      bin/u_panel/src/gui/fe/src/index.html
  50. 0
      bin/u_panel/src/gui/fe/src/main.ts
  51. 0
      bin/u_panel/src/gui/fe/src/polyfills.ts
  52. 0
      bin/u_panel/src/gui/fe/src/styles.less
  53. 0
      bin/u_panel/src/gui/fe/src/test.ts
  54. 0
      bin/u_panel/src/gui/fe/tsconfig.app.json
  55. 0
      bin/u_panel/src/gui/fe/tsconfig.json
  56. 0
      bin/u_panel/src/gui/fe/tsconfig.spec.json
  57. 2
      bin/u_panel/src/gui/mod.rs
  58. 4
      bin/u_panel/src/main.rs
  59. 3
      bin/u_server/src/handlers.rs
  60. 19
      bin/u_server/src/u_server.rs
  61. 1
      deploy/podman-compose.yml
  62. 1
      integration/docker-compose.yml
  63. 4
      integration/tests/fixtures/agent.rs
  64. 5
      integration/tests/helpers/panel.rs
  65. 40
      integration/tests/integration/behaviour.rs
  66. 2
      integration/tests/integration/connection.rs
  67. 9
      lib/u_lib/Cargo.toml
  68. 68
      lib/u_lib/src/api.rs
  69. 2
      lib/u_lib/src/combined_result.rs
  70. 0
      lib/u_lib/src/conv.rs
  71. 0
      lib/u_lib/src/error/chan.rs
  72. 0
      lib/u_lib/src/error/mod.rs
  73. 16
      lib/u_lib/src/lib.rs
  74. 2
      lib/u_lib/src/messaging/base.rs
  75. 0
      lib/u_lib/src/misc.rs
  76. 23
      lib/u_lib/src/models/agent.rs
  77. 2
      lib/u_lib/src/models/jobs/meta.rs
  78. 1
      lib/u_lib/src/models/jobs/misc.rs
  79. 0
      lib/u_lib/src/platform.rs
  80. 2
      lib/u_lib/src/proc_output.rs
  81. 8
      lib/u_lib/src/runner.rs
  82. 0
      lib/u_lib/src/storage.rs
  83. 4
      lib/u_lib/src/tempfile.rs
  84. 7
      lib/u_lib/src/unix.rs
  85. 20
      lib/u_lib/src/utils/mod.rs
  86. 40
      lib/u_lib/src/utils/vec_display.rs
  87. 2
      migrations/2020-10-24-111622_create_all/up.sql
  88. 2
      scripts/deploy.sh
  89. 2
      spec.txt

@ -35,7 +35,7 @@ script = "./scripts/build_musl_libs.sh"
[tasks.build_frontend]
script = '''
cd ./bin/u_panel/src/server/fe
cd ./bin/u_panel/src/gui/fe
ng build
'''

@ -7,8 +7,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
daemonize = "0.4.1"
log = "^0.4"
log = { version = "0.4", features = ["release_max_level_off"] }
reqwest = { workspace = true }
sysinfo = "0.10.5"
tokio = { workspace = true, features = ["macros", "rt-multi-thread", "process", "time"] }

@ -5,14 +5,18 @@
#[macro_use]
extern crate log;
use daemonize::Daemonize;
use std::sync::Arc;
use std::process::exit;
use tokio::runtime::Builder;
use tokio::time::{sleep, Duration};
use u_lib::config;
use u_lib::{
api::ClientHandler, cache::JobCache, config::get_self_uid, errors::ErrChan,
executor::pop_completed, logging::init_logger, messaging::Reportable, models::AssignedJobById,
api::ClientHandler,
cache::JobCache,
config::{endpoints, get_self_uid},
error::ErrChan,
executor::pop_completed,
logging::init_logger,
messaging::Reportable,
models::AssignedJobById,
runner::JobRunner,
};
@ -53,7 +57,7 @@ pub async fn process_request(jobs: Vec<AssignedJobById>, client: &ClientHandler)
}
}
async fn error_reporting(client: Arc<ClientHandler>) -> ! {
async fn error_reporting(client: ClientHandler) -> ! {
loop {
match ErrChan::recv().await {
Some(err) => {
@ -72,7 +76,7 @@ async fn error_reporting(client: Arc<ClientHandler>) -> ! {
}
}
async fn agent_loop(client: Arc<ClientHandler>) -> ! {
async fn agent_loop(client: ClientHandler) -> ! {
loop {
match client.get_personal_jobs(get_self_uid()).await {
Ok(jobs) => {
@ -97,9 +101,8 @@ async fn agent_loop(client: Arc<ClientHandler>) -> ! {
}
}
pub fn run_forever() {
let env = config::endpoints::load().unwrap();
let client = Arc::new(ClientHandler::new(&env.u_server, None));
pub fn run_forever() -> ! {
let env = endpoints::load().unwrap();
if cfg!(debug_assertions) {
init_logger(Some(format!(
@ -112,8 +115,10 @@ pub fn run_forever() {
.unwrap()
)));
} else {
Daemonize::new().start().unwrap();
#[cfg(unix)]
u_lib::unix::daemonize()
}
info!("Starting agent {}", get_self_uid());
Builder::new_multi_thread()
@ -121,7 +126,15 @@ pub fn run_forever() {
.build()
.unwrap()
.block_on(async {
tokio::spawn(error_reporting(client.clone()));
agent_loop(client).await
match ClientHandler::new(&env.u_server, None).await {
Ok(client) => {
tokio::spawn(error_reporting(client.clone()));
agent_loop(client).await
}
Err(e) => {
error!("client init failed: {}", e);
exit(7)
}
}
})
}

@ -113,7 +113,7 @@ pub async fn process_cmd(client: ClientHandler, args: Args) -> PanelResult<Value
},
Cmd::Ping => into_value(client.ping().await?),
Cmd::Serve => {
crate::server::serve(client)
crate::gui::serve(client)
.await
.map_err(|e| UError::PanelError(format!("{e:?}")))?;
Value::Null

@ -0,0 +1,16 @@
# This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
# For additional information regarding the format and rule options, please see:
# https://github.com/browserslist/browserslist#queries
# For the full list of supported browsers by the Angular framework, please see:
# https://angular.io/guide/browser-support
# You can see what browsers were selected by your queries by running:
# npx browserslist
last 1 Chrome version
last 1 Firefox version
last 2 Edge major versions
last 2 Safari major versions
last 2 iOS major versions
Firefox ESR

@ -0,0 +1,16 @@
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.ts]
quote_type = single
[*.md]
max_line_length = off
trim_trailing_whitespace = false

Before

Width:  |  Height:  |  Size: 948 B

After

Width:  |  Height:  |  Size: 948 B

@ -11,7 +11,7 @@ use structopt::StructOpt;
use u_lib::{api::ClientHandler, unwrap_enum};
#[derive(RustEmbed)]
#[folder = "./src/server/fe/dist/fe/"]
#[folder = "./src/gui/fe/dist/fe/"]
struct Files;
impl Files {

@ -1,5 +1,5 @@
mod argparse;
mod server;
mod gui;
#[macro_use]
extern crate tracing;
@ -14,7 +14,7 @@ use u_lib::logging::init_logger;
#[actix_web::main]
async fn main() -> AnyResult<()> {
let env = admin::load()?;
let client = ClientHandler::new(&env.u_server, Some(env.admin_auth_token));
let client = ClientHandler::new(&env.u_server, Some(env.admin_auth_token)).await?;
let args = Args::from_args();
init_logger(None::<&str>);

@ -4,8 +4,8 @@ use crate::db::{PgRepo, UDB};
use crate::error::Error;
use u_lib::{
messaging::{AsMsg, BaseMessage, Reportable},
misc::OneOrVec,
models::*,
utils::OneOrVec,
};
use uuid::Uuid;
use warp::Rejection;
@ -147,6 +147,7 @@ impl Endpoints {
None => warn!("Empty agent data"),
},
JobType::Shell => (),
JobType::Service => (),
JobType::Terminate => todo!(),
JobType::Update => todo!(),
}

@ -12,7 +12,7 @@ mod handlers;
use db::PgRepo;
use error::{Error as ServerError, RejResponse};
use serde::de::DeserializeOwned;
use std::{convert::Infallible, path::PathBuf, sync::Arc};
use std::{convert::Infallible, sync::Arc};
use u_lib::{
config,
db::async_pool,
@ -47,8 +47,10 @@ pub fn init_endpoints(
let path = |p: &'static str| warp::post().and(warp::path(p));
let infallible_none = |_| async { Ok::<_, Infallible>((None::<Uuid>,)) };
let adb = Arc::new(db);
let with_db = warp::any().map(move || adb.clone());
let with_db = {
let adb = Arc::new(db);
warp::any().map(move || adb.clone())
};
let get_agents = path("get_agents")
.and(with_db.clone())
@ -179,17 +181,20 @@ pub async fn serve() -> Result<(), ServerError> {
preload_jobs(&db).await?;
let certs_dir = PathBuf::from("certs");
let env = config::admin::load().map_err(|e| ServerError::Other(e.to_string()))?;
let routes = init_endpoints(&env.admin_auth_token, db)
.recover(handle_rejection)
.with(custom(logger));
let server_cert = include_bytes!("../../../certs/server.crt");
let server_key = include_bytes!("../../../certs/server.key");
let ca = include_bytes!("../../../certs/ca.crt");
warp::serve(routes)
.tls()
.cert_path(certs_dir.join("server.crt"))
.key_path(certs_dir.join("server.key"))
.client_auth_required_path(certs_dir.join("ca.crt"))
.cert(server_cert)
.key(server_key)
.client_auth_required(ca)
.run(([0, 0, 0, 0], config::MASTER_PORT))
.await;
Ok(())

@ -11,7 +11,6 @@ services:
- u_net
volumes:
- ./u_server:/unki/u_server
- ./certs:/unki/certs
- ./logs:/unki/logs:rw
working_dir: /unki
command: /unki/u_server

@ -16,7 +16,6 @@ services:
- u_net
volumes:
- ../target/x86_64-unknown-linux-musl/${PROFILE:-debug}/u_server:/unki/u_server
- ../certs:/unki/certs
- ../logs:/unki/logs:rw
working_dir: /unki
command: /unki/u_server

@ -8,14 +8,14 @@ pub struct RegisteredAgent {
impl RegisteredAgent {
pub async fn unregister(self) {
let cli = ClientHandler::new(&ENV.u_server, None);
let cli = ClientHandler::new(&ENV.u_server, None).await.unwrap();
cli.del(self.uid).await.unwrap();
}
}
#[fixture]
pub async fn register_agent() -> RegisteredAgent {
let cli = ClientHandler::new(&ENV.u_server, None);
let cli = ClientHandler::new(&ENV.u_server, None).await.unwrap();
let agent_uid = Uuid::new_v4();
println!("registering agent {agent_uid}");
let resp = cli

@ -2,10 +2,7 @@ use serde::de::DeserializeOwned;
use serde_json::{from_slice, Value};
use std::fmt::{Debug, Display};
use std::process::{Command, Output};
use u_lib::{
datatypes::PanelResult,
utils::{bytes_to_string, ProcOutput},
};
use u_lib::{conv::bytes_to_string, datatypes::PanelResult, proc_output::ProcOutput};
const PANEL_BINARY: &str = "/u_panel";

@ -4,6 +4,7 @@ use crate::helpers::Panel;
use rstest::rstest;
use serde_json::{json, to_string};
use std::error::Error;
use std::fs;
use std::time::Duration;
use tokio::time::sleep;
use u_lib::models::*;
@ -13,7 +14,7 @@ type TestResult<R = ()> = Result<R, Box<dyn Error>>;
#[rstest]
#[tokio::test]
async fn test_registration(#[future] register_agent: RegisteredAgent) -> TestResult {
async fn registration(#[future] register_agent: RegisteredAgent) -> TestResult {
let agent = register_agent.await;
let agents: Vec<Agent> = Panel::check_output("agents read");
let found = agents.iter().find(|v| v.id == agent.uid);
@ -23,20 +24,47 @@ async fn test_registration(#[future] register_agent: RegisteredAgent) -> TestRes
}
#[tokio::test]
async fn test_setup_tasks() -> TestResult {
async fn setup_tasks() -> TestResult {
let agents: Vec<Agent> = Panel::check_output("agents read");
let agent_uid = match agents.get(0) {
Some(a) => a.id,
None => panic!("Some independent agents should present"),
};
let agent_uid = agents[0].id;
let job_alias = "passwd_contents";
let job = json!(
{"alias": job_alias, "payload": b"cat /etc/passwd", "argv": "/bin/bash {}" }
);
let cmd = format!("jobs create '{}'", to_string(&job).unwrap());
Panel::check_status(cmd);
let cmd = format!("map create {} {}", 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!("map read {}", assigned_uids[0]));
if result[0].state == JobState::Finished {
return Ok(());
} else {
sleep(Duration::from_secs(5)).await;
eprintln!("waiting for task");
}
}
panic!("Job didn't appear in the job map");
}
#[tokio::test]
async fn large_payload() -> TestResult {
let agent_uid = Panel::check_output::<Vec<Agent>>("agents read")[0].id;
let job_alias = "large_payload";
let payload = fs::read("./tests/bin/echoer").unwrap();
let job = json!(
{"alias": job_alias, "payload": payload, "argv": "/bin/bash {}" }
);
let cmd = format!("jobs create '{}'", to_string(&job).unwrap());
Panel::check_status(cmd);
let cmd = format!("map create {} {}", 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!("map read {}", assigned_uids[0]));

@ -2,7 +2,7 @@ use crate::helpers::ENV;
use u_lib::config::MASTER_PORT;
#[tokio::test]
async fn test_non_auth_connection_dropped() {
async fn non_auth_connection_dropped() {
let client = reqwest::ClientBuilder::new()
.danger_accept_invalid_certs(true)
.build()

@ -18,21 +18,24 @@ futures = "0.3.5"
guess_host_triple = "0.1.2"
libc = "^0.2"
lazy_static = "1.4.0"
log = "*"
nix = "0.17"
once_cell = "1.7.2"
platforms = "3.0.1"
reqwest = { workspace = true, features = ["native-tls"] }
reqwest = { workspace = true, features = ["native-tls", "blocking"] }
shlex = "1.0.0"
serde = { workspace = true }
serde_json = { workspace = true }
strum = { version = "0.20", features = ["derive"] }
thiserror = { workspace = true }
tokio = { workspace = true, features = ["rt-multi-thread", "sync", "macros", "process", "time"] }
tracing = { workspace = true }
tracing-appender = { workspace = true }
tracing-subscriber = { workspace = true, features = ["env-filter"] }
uuid = { workspace = true, features = ["serde", "v4"] }
[target.'cfg(unix)'.dependencies]
daemonize = "0.4.1"
nix = "0.17"
[features]
panel = []
server = ["dep:diesel", "dep:diesel-derive-enum", "dep:deadpool-diesel"]

@ -1,18 +1,21 @@
use std::collections::HashMap;
use std::fmt::Debug;
use std::net::SocketAddr;
use anyhow::{Context, Result};
use reqwest::{header, header::HeaderMap, Certificate, Client, Identity, Method, Url};
use serde::de::DeserializeOwned;
use serde_json::{from_str, Value};
use uuid::Uuid;
use crate::{
config::{get_self_uid, MASTER_PORT},
conv::opt_to_string,
messaging::{self, AsMsg, BaseMessage},
misc::OneOrVec,
models::{self},
utils::{opt_to_string, OneOrVec},
UError,
UError, UResult,
};
use anyhow::{Context, Result};
use reqwest::{header::HeaderMap, Certificate, Client, Identity, Url};
use serde::de::DeserializeOwned;
use serde_json::from_str;
use uuid::Uuid;
const AGENT_IDENTITY: &[u8] = include_bytes!("../../../certs/alice.p12");
const ROOT_CA_CERT: &[u8] = include_bytes!("../../../certs/ca.crt");
@ -24,28 +27,51 @@ pub struct ClientHandler {
}
impl ClientHandler {
pub fn new(server: &str, password: Option<String>) -> Self {
pub async fn new(server: &str, password: Option<String>) -> UResult<Self> {
let identity = Identity::from_pkcs12_der(AGENT_IDENTITY, "").unwrap();
let mut default_headers = HashMap::from([(
"user-agent".to_string(),
get_self_uid().hyphenated().to_string(),
)]);
let mut default_headers =
HashMap::from([(header::USER_AGENT, get_self_uid().hyphenated().to_string())]);
if let Some(pwd) = password {
default_headers.insert("authorization".to_string(), format!("Bearer {pwd}"));
default_headers.insert(header::AUTHORIZATION, format!("Bearer {pwd}"));
}
let client = Client::builder()
.identity(identity)
.default_headers(HeaderMap::try_from(&default_headers).unwrap())
.add_root_certificate(Certificate::from_pem(ROOT_CA_CERT).unwrap())
.build()
.unwrap();
let dns_response = Client::new()
.request(
Method::GET,
format!("https://1.1.1.1/dns-query?name={server}&type=A"),
)
.header(header::ACCEPT, "application/dns-json")
.send()
.await?
.text()
.await?;
let client = {
let client = Client::builder()
.identity(identity)
.default_headers(HeaderMap::try_from(&default_headers).unwrap())
.add_root_certificate(Certificate::from_pem(ROOT_CA_CERT).unwrap());
match from_str::<Value>(&dns_response).unwrap()["Answer"]
.get(0)
.and_then(|a| a.get("data"))
{
Some(ip) => {
let raw_addr = format!("{}:{MASTER_PORT}", ip.as_str().unwrap());
let addr: SocketAddr = raw_addr.parse().unwrap();
client.resolve(server, addr)
}
None => client,
}
}
.build()
.unwrap();
Self {
Ok(Self {
client,
base_url: Url::parse(&format!("https://{}:{}", server, MASTER_PORT)).unwrap(),
}
})
}
async fn req<R: AsMsg + DeserializeOwned + Default>(&self, url: impl AsRef<str>) -> Result<R> {

@ -1,6 +1,6 @@
use std::fmt::Debug;
use crate::utils::OneOrVec;
use crate::misc::OneOrVec;
use anyhow::Error;
pub struct CombinedResult<T, E: Debug = Error> {

@ -1,19 +1,27 @@
#![allow(non_upper_case_globals)]
pub mod api;
pub mod cache;
pub mod combined_result;
pub mod config;
pub mod conv;
pub mod datatypes;
#[cfg(feature = "server")]
pub mod db;
pub mod errors;
pub mod error;
pub mod executor;
pub mod logging;
pub mod messaging;
pub mod misc;
pub mod models;
pub mod platform;
pub mod proc_output;
pub mod runner;
pub mod utils;
pub mod storage;
pub mod tempfile;
#[cfg(unix)]
pub mod unix;
pub use errors::{UError, UResult};
pub use error::{UError, UResult};
#[cfg(feature = "server")]
pub mod schema_exports {
@ -25,7 +33,7 @@ pub mod schema_exports {
extern crate diesel;
#[macro_use]
extern crate log;
extern crate tracing;
#[cfg(test)]
#[macro_use]

@ -1,8 +1,6 @@
use crate::config::get_self_uid;
//use crate::utils::VecDisplay;
use serde::{Deserialize, Serialize};
use std::borrow::Cow;
//use std::fmt::Display;
use uuid::Uuid;
pub struct Moo<'cow, T: AsMsg + Clone>(pub Cow<'cow, T>);

@ -11,7 +11,9 @@ mod server {
#[cfg(feature = "server")]
use self::server::*;
use crate::{config::get_self_uid, executor::ExecResult, runner::NamedJobRunner, utils::Platform};
use crate::{
config::get_self_uid, executor::ExecResult, platform::Platform, runner::NamedJobRunner,
};
use uuid::Uuid;
@ -63,17 +65,24 @@ impl Agent {
self.last_active = SystemTime::now();
}
#[cfg(unix)]
pub async fn gather() -> Self {
let mut builder = NamedJobRunner::from_shell(vec![
#[cfg(unix)]
let cmds = vec![
("hostname", "uname -a"),
("host_info", "hostnamectl --json=pretty"),
("is_root", "id -u"),
("username", "id -un"),
])
.unwrap_one()
.wait()
.await;
];
#[cfg(windows)]
let cmds = vec![
("hostname", "uname -a"),
("host_info", "hostnamectl --json=pretty"),
("is_root", "id -u"),
("username", "id -un"),
];
let mut builder = NamedJobRunner::from_shell(cmds).unwrap_one().wait().await;
let decoder =
|job_result: ExecResult| job_result.unwrap().to_str_result().trim().to_string();

@ -1,7 +1,7 @@
use super::JobType;
#[cfg(feature = "server")]
use crate::models::schema::*;
use crate::utils::Platform;
use crate::platform::Platform;
use crate::{UError, UResult};
#[cfg(feature = "server")]
use diesel::{Identifiable, Insertable, Queryable};

@ -34,6 +34,7 @@ pub enum JobState {
)]
pub enum JobType {
Init,
Service,
#[default]
Shell,
Terminate,

@ -63,7 +63,7 @@ impl ProcOutput {
#[cfg(test)]
mod tests {
use crate::utils::{bytes_to_string, ProcOutput};
use crate::{conv::bytes_to_string, proc_output::ProcOutput};
use std::str;
const STDERR_DELIMETER: &'static str =

@ -1,9 +1,12 @@
use crate::{
cache::JobCache,
combined_result::CombinedResult,
executor::{ExecResult, Waiter},
misc::OneOrVec,
models::{Agent, AssignedJob, AssignedJobById, JobMeta, JobType},
utils::{CombinedResult, OneOrVec, Platform},
utils::{ProcOutput, TempFile},
platform::Platform,
proc_output::ProcOutput,
tempfile::TempFile,
UError, UResult,
};
use std::collections::HashMap;
@ -128,6 +131,7 @@ pub async fn run_assigned_job(mut job: AssignedJob) -> ExecResult {
job.set_result(&Agent::run().await);
job.retcode = Some(0);
}
JobType::Service => todo!(),
JobType::Update => todo!(),
JobType::Terminate => exit(0),
};

@ -49,13 +49,13 @@ impl Drop for TempFile {
#[cfg(test)]
mod tests {
use super::*;
use crate::utils::bytes_to_string;
use crate::conv::bytes_to_string;
use std::path::Path;
use std::process::Command;
#[test]
fn test_file_is_not_busy() {
let binary = include_bytes!("../../tests/fixtures/echoer");
let binary = include_bytes!("../tests/fixtures/echoer");
for _ in 0..100 {
let executable = TempFile::write_exec(binary).unwrap();
let path = executable.get_path();

@ -1,10 +1,11 @@
use daemonize::Daemonize;
use nix::{
sys::signal::{signal, SigHandler, Signal},
unistd::{chdir, close as fdclose, fork, getppid, setsid, ForkResult},
};
use std::process::exit;
pub fn daemonize() {
fn _daemonize() {
if getppid().as_raw() != 1 {
setsig(Signal::SIGTTOU, SigHandler::SigIgn);
setsig(Signal::SIGTTIN, SigHandler::SigIgn);
@ -30,6 +31,10 @@ pub fn daemonize() {
}
}
pub fn daemonize() {
Daemonize::new().start().unwrap()
}
pub fn setsig(sig: Signal, hnd: SigHandler) {
unsafe {
signal(sig, hnd).unwrap();

@ -1,20 +0,0 @@
pub mod combined_result;
pub mod conv;
pub mod misc;
pub mod platform;
pub mod proc_output;
pub mod storage;
pub mod tempfile;
#[cfg(unix)]
pub mod unix;
pub use combined_result::*;
pub use conv::*;
pub use misc::*;
pub use platform::*;
pub use proc_output::*;
pub use storage::*;
pub use tempfile::*;
#[cfg(unix)]
pub use unix::*;

@ -1,40 +0,0 @@
use crate::{messaging::AsMsg, utils::OneOrVec};
use serde::{Deserialize, Serialize};
use std::fmt::{self, Display, Formatter};
use std::ops::{Deref, DerefMut};
#[derive(Serialize, Deserialize, Clone, Default)]
pub struct VecDisplay<T: AsMsg + Display>(pub Vec<T>);
impl<T: AsMsg + Display> VecDisplay<T> {
pub fn new(inner: impl OneOrVec<T>) -> Self {
VecDisplay(inner.into_vec())
}
pub fn into_builtin_vec(self) -> Vec<T> {
self.0
}
}
impl<T: AsMsg + Display> Deref for VecDisplay<T> {
type Target = Vec<T>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T: AsMsg + Display> DerefMut for VecDisplay<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<T: AsMsg + Display> Display for VecDisplay<T> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
for (i, itm) in self.0.iter().enumerate() {
writeln!(f, "### {}:\n{}\n", i, itm)?;
}
Ok(())
}
}

@ -1,5 +1,5 @@
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TYPE JobType AS ENUM ('shell', 'init', 'python');
CREATE TYPE JobType AS ENUM ('shell', 'init', 'python', 'service');
CREATE TYPE JobState AS ENUM ('queued', 'running', 'finished');
CREATE TYPE AgentState AS ENUM ('new', 'active', 'banned');

@ -10,8 +10,6 @@ RSYNC="rsync -arzh --progress"
ssh $SERVER mkdir -p $REMOTE_DIR/data
$RSYNC $ROOTDIR/target/x86_64-unknown-linux-musl/release/{u_server,migrator} $REMOTE_PATH/
$RSYNC $ROOTDIR/certs/server.{crt,key} $REMOTE_PATH/certs/
$RSYNC $ROOTDIR/certs/ca.crt $REMOTE_PATH/certs/
$RSYNC $ROOTDIR/.env* $REMOTE_PATH/
$RSYNC $ROOTDIR/deploy/* $REMOTE_PATH/
$RSYNC $ROOTDIR/images/{u_server,u_db}.Dockerfile $REMOTE_PATH/

@ -2,8 +2,6 @@ todos:
Upload/download files
More tests
Agent update (use more JobType's)
Erase log macros in release mode
Bump wine version to test agent on windows
Store downloaded payload on disk instead of ram
Improve web interface
Migrator binary

Loading…
Cancel
Save