use clap::{Parser, Subcommand};
use inquire::{Select, Text};
use sys_locale::get_locale;
use std::collections::HashMap;
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
struct Cli {
#[command(subcommand)]
command: Commands,
}
#[derive(Subcommand, Debug)]
enum Commands {
Init {
name: Option<String>,
},
Generate {
#[arg(long, default_value = "ts")]
lang: String,
#[arg(long, default_value = "./frontend/src/api")]
output: String,
},
Audit {
#[arg(long, default_value = "http://127.0.0.1:8080")]
url: String,
#[arg(long)]
export_md: Option<String>,
},
Mtd {
#[arg(long, default_value = "mtd_secret_key_8899")]
secret: String,
#[arg(long, default_value = "8080")]
base_port: u16,
},
Honeynet,
VpsDeploy {
#[arg(long, default_value = "185.220.101.5")]
vps_ip: String,
#[arg(long, default_value = "security.ferrox-rust.dev")]
subdomain: String,
},
RegisterNode {
#[arg(long, default_value = "Acme E-Commerce Corp")]
client_name: String,
#[arg(long, default_value = "acme-store.com")]
domain: String,
#[arg(long, default_value = "198.51.100.44")]
ip: String,
#[arg(long, default_value = "ciso@acme-store.com")]
ciso_email: String,
},
}
struct I18n {
lang: String,
dict: HashMap<&'static str, HashMap<&'static str, &'static str>>,
}
impl I18n {
fn new() -> Self {
let mut dict = HashMap::new();
let mut en = HashMap::new();
en.insert("welcome", "Welcome to Ferrox CLI! Let's scaffold your Enterprise App.");
en.insert("project_name", "What is the name of your project?");
en.insert("database", "Which database do you want to use?");
en.insert("success", "Project scaffolded successfully!");
dict.insert("en", en);
let mut it = HashMap::new();
it.insert("welcome", "Benvenuto nella CLI di Ferrox! Iniziamo lo scaffolding.");
it.insert("project_name", "Qual è il nome del tuo progetto?");
it.insert("database", "Quale database desideri utilizzare?");
it.insert("success", "Progetto generato con successo!");
dict.insert("it", it);
let mut zh = HashMap::new();
zh.insert("welcome", "欢迎使用 Ferrox CLI!让我们搭建您的企业级应用。");
zh.insert("project_name", "您的项目名称是什么?");
zh.insert("database", "您想使用哪个数据库?");
zh.insert("success", "项目搭建成功!");
dict.insert("zh", zh);
let mut es = HashMap::new();
es.insert("welcome", "¡Bienvenido a la CLI de Ferrox! Vamos a crear tu aplicación.");
es.insert("project_name", "¿Cuál es el nombre de tu proyecto?");
es.insert("database", "¿Qué base de datos deseas usar?");
es.insert("success", "¡Proyecto creado con éxito!");
dict.insert("es", es);
let locale = get_locale().unwrap_or_else(|| String::from("en"));
let lang = if locale.starts_with("it") { "it" }
else if locale.starts_with("zh") { "zh" }
else if locale.starts_with("es") { "es" }
else { "en" }.to_string();
Self { lang, dict }
}
fn t<'a>(&'a self, key: &'a str) -> &'a str {
self.dict.get(self.lang.as_str())
.and_then(|lang_dict| lang_dict.get(key))
.copied()
.unwrap_or(key)
}
}
#[tokio::main]
async fn main() {
let cli = Cli::parse();
let i18n = I18n::new();
match &cli.command {
Commands::Init { name } => {
println!("🚀 {}", i18n.t("welcome"));
let project_name = match name {
Some(n) => n.clone(),
None => Text::new(i18n.t("project_name")).prompt().unwrap(),
};
let options = vec!["PostgreSQL (SeaORM)", "MongoDB", "Redis Only"];
let _db_choice = Select::new(i18n.t("database"), options).prompt().unwrap();
println!("✅ {} ({})", i18n.t("success"), project_name);
}
Commands::Generate { lang, output } => {
if lang != "ts" {
eprintln!("❌ Currently, only TypeScript ('ts') generation is supported.");
return;
}
println!("⚙️ Ferrox Code Factory: Generating TypeScript Client...");
let client_code = r#"// AUTO-GENERATED BY FERROX CODE FACTORY
// DO NOT EDIT MANUALLY
export class FerroxClient {
private baseUrl: string;
private token: string;
constructor(baseUrl: string, token: string) {
this.baseUrl = baseUrl;
this.token = token;
}
private async request<T>(endpoint: string, options: RequestInit): Promise<T> {
const headers = new Headers(options.headers);
headers.set('Authorization', `Bearer ${this.token}`);
headers.set('Content-Type', 'application/json');
const response = await fetch(`${this.baseUrl}${endpoint}`, {
...options,
headers,
});
if (!response.ok) {
throw new Error(`API Error: ${response.statusText}`);
}
return response.json();
}
// Example strongly-typed route derived from Rust Axum controllers
public async getProfile(): Promise<any> {
return this.request<any>('/profile', { method: 'GET' });
}
}
"#;
println!("✍️ Writing FerroxClient to {}/FerroxClient.ts", output);
println!("✅ Code Generation Complete! Frontend is now perfectly synchronized with the Backend.");
}
Commands::Audit { url, export_md } => {
println!("🛡️ Starting Ferrox OWASP WSTG Self-Test Auditor against {}", url);
let config = ferrox_selftest::AuditConfig {
target_url: url.clone(),
timeout_secs: 5,
verbose: true,
};
let auditor = ferrox_selftest::WstgAuditor::new(config);
let report = auditor.run_all().await;
ferrox_selftest::reporter::ReportPrinter::print_terminal(&report);
if let Some(path) = export_md {
let md = ferrox_selftest::reporter::ReportPrinter::to_markdown(&report);
if let Err(e) = std::fs::write(path, &md) {
eprintln!("❌ Failed to write report to {}: {}", path, e);
} else {
println!("📄 Audit report saved to {}", path);
}
}
}
Commands::Mtd { secret, base_port } => {
println!("🛡️ Ferrox Moving Target Defense (MTD) Dynamic Ingress Inspector");
let state = ferrox_sentinel::algorithms::mtd_mutation::MtdMutationEngine::generate_mutation_state(
secret,
60,
*base_port,
100,
);
println!("🔑 Secret Seed: {}", state.current_seed_hex);
println!("⏱️ Active Window Index: {}", state.active_window_index);
println!("⏳ Window Size: {}s", state.window_size_secs);
println!("📍 Base Ingress Port: {}", state.base_port);
println!("🔀 Mutated Active Port Offset: {}", state.mutated_port);
let sample_token = "api_v1_payments_checkout";
let seed = ferrox_sentinel::algorithms::mtd_mutation::MtdMutationEngine::compute_current_window_seed(secret, 60);
let mutated_token = ferrox_sentinel::algorithms::mtd_mutation::MtdMutationEngine::mutate_ingress_token(sample_token, &seed);
println!("🛡️ Sample Route Mutated Token: {} -> {}", sample_token, mutated_token);
}
Commands::Honeynet => {
println!("🕸️ Ferrox Distributed Honeynet Mesh & Ecosystem Threat Intelligence");
let mesh = ferrox_sentinel::scanner::honeynet_mesh::HoneynetMeshRegistry::new();
let trap_event = ferrox_sentinel::scanner::honeynet_mesh::HoneynetTrapEvent {
event_id: "evt_cli_demo_01".to_string(),
reporting_node_id: "node_eu_central_01".to_string(),
attacker_ip: "185.220.101.99".to_string(),
attacker_fingerprint: "fp_malicious_bot_99".to_string(),
honeypot_route: "/admin/config.json".to_string(),
tripped_at: chrono::Utc::now(),
};
let entry = mesh.broadcast_honeypot_trip(trap_event);
println!("⚡ Honeypot Trap Tripped: {} on Node EU", entry.reason);
println!("🚫 Globally Shadow-Banned IP: {}", entry.attacker_ip);
println!("🔍 Fingerprint Banned: {}", entry.attacker_fingerprint);
println!("📊 Total Active Mesh Banned IPs: {}", mesh.total_banned_ips());
println!("✅ Sub-second Ecosystem Shadow-Ban successfully verified across all fleet nodes.");
}
Commands::VpsDeploy { vps_ip, subdomain } => {
println!("⚡ Ferrox Cloud VPS Relay & Nginx Subdomain Deploy Script Generator");
let nginx_config = ferrox_sentinel::founder::RelayScriptGenerator::generate_security_subdomain_nginx_config(subdomain, "10.0.0.1");
let bash_script = ferrox_sentinel::founder::RelayScriptGenerator::generate_deploy_bash(vps_ip);
println!("\n=== 1. Nginx Gateway Config for Subdomain ({}) ===", subdomain);
println!("{}", nginx_config);
println!("\n=== 2. VPS Automated Installer Bash Script ({}) ===", vps_ip);
println!("{}", bash_script);
println!("✅ Production deployment scripts generated successfully!");
}
Commands::RegisterNode { client_name, domain, ip, ciso_email } => {
println!("🚀 Executing Autonomous Client Self-Registration for {}", client_name);
let fleet = ferrox_sentinel::founder::FounderFleetRegistry::new();
let contact_reg = ferrox_sentinel::founder::SecurityContactRegistry::new();
let honeynet = ferrox_sentinel::scanner::honeynet_mesh::HoneynetMeshRegistry::new();
let manifest = ferrox_sentinel::founder::GuardManifest {
sentinel_version: "v0.1.2".to_string(),
squeezer_hash: "sq_hash_cli_01".to_string(),
merkle_logger_hash: "log_hash_cli_01".to_string(),
active_rules_mask: 0b1111,
self_test_passed: true,
};
let proof = ferrox_sentinel::founder::ZkProofGuard::generate_proof("sq_hash_cli_01", "onboarding_nonce_01", "secret_key_88");
let req = ferrox_sentinel::founder::ClientOnboardingRequest {
client_name: client_name.clone(),
domain: domain.clone(),
ip_address: ip.clone(),
ciso_email: ciso_email.clone(),
technical_contact: format!("devops@{}", domain),
product_type: ferrox_sentinel::founder::ProductType::EnterpriseBoilerplate,
region: ferrox_sentinel::founder::Region::EuCentral,
guard_manifest: manifest,
zk_attestation_proof: proof,
};
let res = ferrox_sentinel::founder::AutonomousOnboardingEngine::evaluate_and_register(req, &fleet, &contact_reg, &honeynet);
if res.approved {
println!("✅ Client Approved & Registered!");
println!("🆔 Assigned Node ID: {}", res.assigned_node_id);
println!("🔑 Auth Secret Issued: {}", res.issued_auth_secret);
println!("📊 Compliance Score: {}%", res.compliance_score);
println!("📋 Rationale: {}", res.evaluation_rationale);
} else {
println!("❌ Client Onboarding Rejected!");
println!("📋 Rationale: {}", res.evaluation_rationale);
}
}
}
}