163 lines
4.6 KiB
Rust
163 lines
4.6 KiB
Rust
use clap::{Parser, Subcommand};
|
|
|
|
#[derive(Parser)]
|
|
#[command(version, about, long_about = None)]
|
|
pub struct Cli {
|
|
/// Start the agent server
|
|
#[arg(short, long, group = "mode")]
|
|
pub serve: bool,
|
|
|
|
#[command(subcommand)]
|
|
pub command: Option<Commands>,
|
|
}
|
|
|
|
#[derive(Subcommand)]
|
|
pub enum Commands {
|
|
#[command(about = "Import certificates for agent from zip file or separate cert and key files")]
|
|
ImportCerts {
|
|
// Zip file input, mutually exclusive with separate cert and key file inputs
|
|
/// Zip file containing ca.pem cert.pem and key.pem
|
|
#[arg(value_name = "ZIP_FILE", group = "input_source")]
|
|
zip: Option<String>,
|
|
/// Certificate name in zip file, required if using zip input
|
|
#[arg(
|
|
long,
|
|
group = "input_source",
|
|
requires = "zip",
|
|
default_value = "cert.pem",
|
|
value_name = "CERT_NAME"
|
|
)]
|
|
cert_name: Option<String>,
|
|
/// Key name in zip file, required if using zip input
|
|
#[arg(
|
|
long,
|
|
group = "input_source",
|
|
requires = "zip",
|
|
default_value = "key.pem",
|
|
value_name = "KEY_NAME"
|
|
)]
|
|
key_name: Option<String>,
|
|
/// CA certificate name in zip file, required if using zip input
|
|
#[arg(
|
|
long,
|
|
group = "input_source",
|
|
requires = "zip",
|
|
default_value = "ca.pem",
|
|
value_name = "CA_NAME"
|
|
)]
|
|
ca_name: Option<String>,
|
|
|
|
// Separate cert and key file inputs, required if not using zip input
|
|
/// Certificate file path
|
|
#[arg(
|
|
long,
|
|
group = "input_source",
|
|
requires = "key",
|
|
conflicts_with = "zip",
|
|
value_name = "CERT_FILE"
|
|
)]
|
|
cert: Option<String>,
|
|
|
|
/// Key file path
|
|
#[arg(
|
|
long,
|
|
group = "input_source",
|
|
requires = "cert",
|
|
conflicts_with = "zip",
|
|
value_name = "KEY_FILE"
|
|
)]
|
|
key: Option<String>,
|
|
|
|
/// Master CA certificate file path for verifying master identity, optional if the CA certificate is already trusted by the system
|
|
/// This is required if the master server uses a self-signed certificate that is not trusted by the system
|
|
#[arg(
|
|
long,
|
|
group = "input_source",
|
|
conflicts_with = "zip",
|
|
value_name = "CA_CERT_FILE"
|
|
)]
|
|
ca_cert: Option<String>,
|
|
},
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use clap::Parser;
|
|
|
|
use super::{Cli, Commands};
|
|
|
|
#[test]
|
|
fn parses_serve_flag_without_subcommand() {
|
|
let parsed = Cli::try_parse_from(["nxmesh-agent", "--serve"]);
|
|
assert!(parsed.is_ok());
|
|
|
|
let parsed = parsed.ok();
|
|
assert!(parsed.is_some());
|
|
let parsed = parsed.unwrap_or_else(|| unreachable!());
|
|
|
|
assert!(parsed.serve);
|
|
assert!(parsed.command.is_none());
|
|
}
|
|
|
|
#[test]
|
|
fn parses_import_certs_with_zip_defaults() {
|
|
let parsed = Cli::try_parse_from(["nxmesh-agent", "import-certs", "bundle.zip"]);
|
|
assert!(parsed.is_ok());
|
|
|
|
let parsed = parsed.ok();
|
|
assert!(parsed.is_some());
|
|
let parsed = parsed.unwrap_or_else(|| unreachable!());
|
|
|
|
match parsed.command {
|
|
Some(Commands::ImportCerts {
|
|
zip,
|
|
cert_name,
|
|
key_name,
|
|
ca_name,
|
|
cert,
|
|
key,
|
|
ca_cert,
|
|
}) => {
|
|
assert_eq!(zip.as_deref(), Some("bundle.zip"));
|
|
assert_eq!(cert_name.as_deref(), Some("cert.pem"));
|
|
assert_eq!(key_name.as_deref(), Some("key.pem"));
|
|
assert_eq!(ca_name.as_deref(), Some("ca.pem"));
|
|
assert!(cert.is_none());
|
|
assert!(key.is_none());
|
|
assert!(ca_cert.is_none());
|
|
}
|
|
_ => unreachable!(),
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_import_certs_with_separate_files() {
|
|
let parsed = Cli::try_parse_from([
|
|
"nxmesh-agent",
|
|
"import-certs",
|
|
"--cert",
|
|
"agent.crt",
|
|
"--key",
|
|
"agent.key",
|
|
"--ca-cert",
|
|
"ca.crt",
|
|
]);
|
|
assert!(parsed.is_err());
|
|
}
|
|
|
|
#[test]
|
|
fn rejects_conflicting_zip_and_separate_inputs() {
|
|
let parsed = Cli::try_parse_from([
|
|
"nxmesh-agent",
|
|
"import-certs",
|
|
"bundle.zip",
|
|
"--cert",
|
|
"agent.crt",
|
|
"--key",
|
|
"agent.key",
|
|
]);
|
|
|
|
assert!(parsed.is_err());
|
|
}
|
|
}
|