cli to run nebula and nebula-cert, and remove cache dirs
This commit is contained in:
parent
a4fda57da8
commit
2d7626317d
|
@ -295,6 +295,17 @@ version = "1.1.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b"
|
||||
|
||||
[[package]]
|
||||
name = "colored"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b3616f750b84d8f0de8a58bda93e08e2a81ad3f523089b05f1dffecab48c6cbd"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"lazy_static",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.9.1"
|
||||
|
@ -554,7 +565,16 @@ version = "4.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059"
|
||||
dependencies = [
|
||||
"dirs-sys",
|
||||
"dirs-sys 0.3.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs"
|
||||
version = "5.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dece029acd3353e3a58ac2e3eb3c8d6c35827a892edc6cc4138ef9c33df46ecd"
|
||||
dependencies = [
|
||||
"dirs-sys 0.4.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -568,6 +588,17 @@ dependencies = [
|
|||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dirs-sys"
|
||||
version = "0.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "04414300db88f70d74c5ff54e50f9e1d1737d9a5b90f53fcf2e95ca2a9ab554b"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"redox_users",
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dotenvy"
|
||||
version = "0.15.6"
|
||||
|
@ -1393,6 +1424,15 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_threads"
|
||||
version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2819ce041d2ee131036f4fc9d6ae7ae125a3a40e97ba64d04fe799ad9dabbb44"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.17.0"
|
||||
|
@ -2094,6 +2134,19 @@ version = "2.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fe458c98333f9c8152221191a77e2a44e8325d0193484af2e9421a53019e57d"
|
||||
|
||||
[[package]]
|
||||
name = "simple_logger"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e78beb34673091ccf96a8816fce8bfd30d1292c7621ca2bcb5f2ba0fae4f558d"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"colored",
|
||||
"log",
|
||||
"time 0.3.17",
|
||||
"windows-sys 0.42.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "slab"
|
||||
version = "0.4.7"
|
||||
|
@ -2170,7 +2223,7 @@ dependencies = [
|
|||
"bytes",
|
||||
"crc",
|
||||
"crossbeam-queue",
|
||||
"dirs",
|
||||
"dirs 4.0.0",
|
||||
"dotenvy",
|
||||
"either",
|
||||
"event-listener",
|
||||
|
@ -2349,11 +2402,14 @@ name = "tfclient"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"dirs 5.0.0",
|
||||
"flate2",
|
||||
"hex",
|
||||
"log",
|
||||
"reqwest",
|
||||
"serde",
|
||||
"sha2",
|
||||
"simple_logger",
|
||||
"tar",
|
||||
"tempfile",
|
||||
"trifid-pki",
|
||||
|
@ -2406,6 +2462,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"libc",
|
||||
"num_threads",
|
||||
"serde",
|
||||
"time-core",
|
||||
"time-macros",
|
||||
|
|
|
@ -9,6 +9,11 @@ description = "An open-source reimplementation of a Defined Networking-compatibl
|
|||
[dependencies]
|
||||
clap = { version = "4.1.10", features = ["derive"] }
|
||||
trifid-pki = { version = "0.1.5", path = "../trifid-pki" }
|
||||
dirs = "5.0.0"
|
||||
log = "0.4.17"
|
||||
simple_logger = "4.1.0"
|
||||
sha2 = "0.10.6"
|
||||
hex = "0.4.3"
|
||||
|
||||
[build-dependencies]
|
||||
serde = { version = "1.0.157", features = ["derive"] }
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
use std::path::PathBuf;
|
||||
|
||||
pub fn get_data_dir() -> Option<PathBuf> {
|
||||
dirs::data_dir().map(|f| f.join("tfclient/"))
|
||||
}
|
|
@ -0,0 +1,104 @@
|
|||
use std::error::Error;
|
||||
use std::fs;
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
use std::path::PathBuf;
|
||||
use std::process::{Child, Command, Output};
|
||||
use log::debug;
|
||||
use crate::dirs::get_data_dir;
|
||||
use crate::util::sha256;
|
||||
|
||||
pub fn extract_embedded_nebula() -> Result<PathBuf, Box<dyn Error>> {
|
||||
let data_dir = get_data_dir().ok_or("Unable to get platform-specific data dir")?;
|
||||
if !data_dir.exists() {
|
||||
fs::create_dir_all(&data_dir)?;
|
||||
debug!("Created data directory {}", data_dir.as_path().display());
|
||||
}
|
||||
|
||||
let bin_dir = data_dir.join("cache/");
|
||||
let hash_dir = bin_dir.join(format!("{}/", sha256(crate::nebula_bin::NEBULA_BIN)));
|
||||
|
||||
if !hash_dir.exists() {
|
||||
fs::create_dir_all(&hash_dir)?;
|
||||
debug!("Created directory {}", hash_dir.as_path().display());
|
||||
}
|
||||
|
||||
let executable_postfix = if cfg!(windows) { ".exe" } else { "" };
|
||||
let executable_name = format!("nebula-{}{}", crate::nebula_bin::NEBULA_VERSION, executable_postfix);
|
||||
|
||||
let file_path = hash_dir.join(executable_name);
|
||||
|
||||
if file_path.exists() {
|
||||
// Already extracted
|
||||
return Ok(file_path);
|
||||
}
|
||||
let mut file = File::create(&file_path)?;
|
||||
file.write_all(crate::nebula_bin::NEBULA_BIN)?;
|
||||
|
||||
debug!("Extracted nebula to {}", file_path.as_path().display());
|
||||
|
||||
Ok(file_path)
|
||||
}
|
||||
|
||||
pub fn extract_embedded_nebula_cert() -> Result<PathBuf, Box<dyn Error>> {
|
||||
let data_dir = get_data_dir().ok_or("Unable to get platform-specific data dir")?;
|
||||
if !data_dir.exists() {
|
||||
fs::create_dir_all(&data_dir)?;
|
||||
debug!("Created data directory {}", data_dir.as_path().display());
|
||||
}
|
||||
|
||||
let bin_dir = data_dir.join("cache/");
|
||||
let hash_dir = bin_dir.join(format!("{}/", sha256(crate::nebula_cert_bin::NEBULA_CERT_BIN)));
|
||||
|
||||
if !hash_dir.exists() {
|
||||
fs::create_dir_all(&hash_dir)?;
|
||||
debug!("Created directory {}", hash_dir.as_path().display());
|
||||
}
|
||||
|
||||
let executable_postfix = if cfg!(windows) { ".exe" } else { "" };
|
||||
let executable_name = format!("nebula-cert-{}{}", crate::nebula_cert_bin::NEBULA_CERT_VERSION, executable_postfix);
|
||||
|
||||
let file_path = hash_dir.join(executable_name);
|
||||
|
||||
if file_path.exists() {
|
||||
// Already extracted
|
||||
return Ok(file_path);
|
||||
}
|
||||
|
||||
let mut file = File::create(&file_path)?;
|
||||
file.write_all(crate::nebula_cert_bin::NEBULA_CERT_BIN)?;
|
||||
|
||||
debug!("Extracted nebula-cert to {}", file_path.as_path().display());
|
||||
|
||||
Ok(file_path)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn _setup_permissions(path: &PathBuf) -> Result<(), Box<dyn Error>> {
|
||||
let meta = path.metadata()?;
|
||||
let mut perms = meta.permissions();
|
||||
perms.set_mode(0o0755);
|
||||
debug!("Setting permissions on {} to 755", path.as_path().display());
|
||||
fs::set_permissions(path, perms)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn _setup_permissions() -> Result<(), Box<dyn Error>> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn run_embedded_nebula(args: &[String]) -> Result<Child, Box<dyn Error>> {
|
||||
let path = extract_embedded_nebula()?;
|
||||
debug!("Running {} with args {:?}", path.as_path().display(), args);
|
||||
_setup_permissions(&path)?;
|
||||
Ok(Command::new(path).args(args).spawn()?)
|
||||
}
|
||||
|
||||
pub fn run_embedded_nebula_cert(args: &[String]) -> Result<Child, Box<dyn Error>> {
|
||||
let path = extract_embedded_nebula_cert()?;
|
||||
debug!("Running {} with args {:?}", path.as_path().display(), args);
|
||||
_setup_permissions(&path)?;
|
||||
Ok(Command::new(path).args(args).spawn()?)
|
||||
}
|
|
@ -14,6 +14,10 @@
|
|||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
pub mod embedded_nebula;
|
||||
pub mod dirs;
|
||||
pub mod util;
|
||||
|
||||
pub mod nebula_bin {
|
||||
include!(concat!(env!("OUT_DIR"), "/nebula.bin.rs"));
|
||||
}
|
||||
|
@ -21,7 +25,14 @@ pub mod nebula_cert_bin {
|
|||
include!(concat!(env!("OUT_DIR"), "/nebula_cert.bin.rs"));
|
||||
}
|
||||
|
||||
use clap::{Parser, ArgAction};
|
||||
use std::error::Error;
|
||||
use std::fs;
|
||||
use std::process::Child;
|
||||
use clap::{Parser, ArgAction, Subcommand};
|
||||
use log::{error, info};
|
||||
use simple_logger::SimpleLogger;
|
||||
use crate::dirs::get_data_dir;
|
||||
use crate::embedded_nebula::{run_embedded_nebula, run_embedded_nebula_cert};
|
||||
|
||||
#[derive(Parser)]
|
||||
#[command(author = "c0repwn3r", version, about, long_about = None)]
|
||||
|
@ -29,17 +40,121 @@ use clap::{Parser, ArgAction};
|
|||
struct Cli {
|
||||
#[arg(short = 'v', long = "version", action = ArgAction::SetTrue)]
|
||||
#[clap(global = true)]
|
||||
version: bool
|
||||
version: bool,
|
||||
|
||||
#[command(subcommand)]
|
||||
subcommand: Commands
|
||||
}
|
||||
|
||||
#[derive(Subcommand)]
|
||||
enum Commands {
|
||||
/// Run the `nebula` binary. This is useful if you want to do debugging with tfclient's internal nebula.
|
||||
RunNebula {
|
||||
/// Arguments to pass to the `nebula` binary
|
||||
#[clap(trailing_var_arg=true, allow_hyphen_values=true)]
|
||||
args: Vec<String>
|
||||
},
|
||||
/// Run the `nebula-cert` binary. This is useful if you want to mess with certificates. Note: tfclient does not actually use nebula-cert for certificate operations, and instead uses trifid-pki internally
|
||||
RunNebulaCert {
|
||||
/// Arguments to pass to the `nebula-cert` binary
|
||||
#[clap(trailing_var_arg=true, allow_hyphen_values=true)]
|
||||
args: Vec<String>
|
||||
},
|
||||
/// Clear any cached data that tfclient may have added
|
||||
ClearCache {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
SimpleLogger::new().init().unwrap();
|
||||
|
||||
let args = Cli::parse();
|
||||
|
||||
if args.version {
|
||||
print_version();
|
||||
}
|
||||
|
||||
match args.subcommand {
|
||||
Commands::RunNebula { args } => {
|
||||
match run_embedded_nebula(&args) {
|
||||
Ok(mut c) => {
|
||||
match c.wait() {
|
||||
Ok(stat) => {
|
||||
match stat.code() {
|
||||
Some(code) => {
|
||||
if code != 0 {
|
||||
error!("Nebula process exited with nonzero status code {}", code);
|
||||
}
|
||||
std::process::exit(code);
|
||||
},
|
||||
None => {
|
||||
info!("Nebula process terminated by signal");
|
||||
std::process::exit(0);
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Unable to wait for child to exit: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Unable to start nebula binary: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
},
|
||||
Commands::ClearCache { .. } => {
|
||||
let data_dir = match get_data_dir() {
|
||||
Some(dir) => dir,
|
||||
None => {
|
||||
error!("Unable to get platform-specific data dir");
|
||||
std::process::exit(1);
|
||||
}
|
||||
};
|
||||
match fs::remove_dir_all(&data_dir) {
|
||||
Ok(_) => (),
|
||||
Err(e) => {
|
||||
error!("Unable to delete data dir: {}", e);
|
||||
std::process::exit(0);
|
||||
}
|
||||
}
|
||||
info!("Removed data dir {}", data_dir.as_path().display());
|
||||
|
||||
info!("Removed all cached data.");
|
||||
std::process::exit(0);
|
||||
},
|
||||
Commands::RunNebulaCert { args } => {
|
||||
match run_embedded_nebula_cert(&args) {
|
||||
Ok(mut c) => {
|
||||
match c.wait() {
|
||||
Ok(stat) => {
|
||||
match stat.code() {
|
||||
Some(code) => {
|
||||
if code != 0 {
|
||||
error!("nebula-cert process exited with nonzero status code {}", code);
|
||||
}
|
||||
std::process::exit(code);
|
||||
},
|
||||
None => {
|
||||
info!("nebula-cert process terminated by signal");
|
||||
std::process::exit(0);
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Unable to wait for child to exit: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(e) => {
|
||||
error!("Unable to start nebula-cert binary: {}", e);
|
||||
std::process::exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn print_version() {
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
use sha2::Sha256;
|
||||
use sha2::Digest;
|
||||
|
||||
pub fn sha256(bytes: &[u8]) -> String {
|
||||
let mut hasher = Sha256::new();
|
||||
hasher.update(bytes);
|
||||
let digest = hasher.finalize();
|
||||
hex::encode(digest)
|
||||
}
|
Loading…
Reference in New Issue