trifid/tfcli/src/main.rs

255 lines
7.5 KiB
Rust
Raw Normal View History

2023-06-16 00:49:06 +00:00
use std::error::Error;
use std::fs;
2023-06-21 01:23:28 +00:00
use std::net::{Ipv4Addr, SocketAddrV4};
2023-06-16 00:49:06 +00:00
use clap::{Parser, Subcommand};
use ipnet::Ipv4Net;
use url::Url;
use crate::account::account_main;
2023-06-21 01:23:28 +00:00
use crate::host::host_main;
2023-06-16 00:49:06 +00:00
use crate::network::network_main;
use crate::org::org_main;
2023-06-16 02:00:09 +00:00
use crate::role::role_main;
2023-06-16 00:49:06 +00:00
pub mod account;
pub mod api;
pub mod network;
pub mod org;
2023-06-16 02:00:09 +00:00
pub mod role;
2023-06-21 01:23:28 +00:00
pub mod host;
2023-06-16 00:49:06 +00:00
#[derive(Parser, Debug)]
#[command(author, version, about, long_about = None)]
#[command(propagate_version = true)]
pub struct Args {
#[command(subcommand)]
command: Commands,
#[clap(short, long, env = "TFCLI_SERVER")]
/// The base URL of your trifid-api instance. Defaults to the value in $XDG_CONFIG_HOME/tfcli-server-url.conf or the TFCLI_SERVER environment variable.
server: Option<Url>
}
#[derive(Subcommand, Debug)]
pub enum Commands {
/// Manage your trifid account
Account {
#[command(subcommand)]
command: AccountCommands
},
/// Manage the networks associated with your trifid account
Network {
#[command(subcommand)]
command: NetworkCommands
},
/// Manage the organization associated with your trifid account
Org {
#[command(subcommand)]
command: OrgCommands
2023-06-16 02:00:09 +00:00
},
/// Manage the roles associated with your trifid organization
Role {
#[command(subcommand)]
command: RoleCommands
2023-06-21 01:23:28 +00:00
},
/// Manage the hosts associated with your trifid network
Host {
#[command(subcommand)]
command: HostCommands
2023-06-16 00:49:06 +00:00
}
}
#[derive(Subcommand, Debug)]
pub enum AccountCommands {
/// Create a new trifid account on the designated server
Create {
#[clap(short, long)]
email: String
},
2023-06-21 01:23:28 +00:00
/// Log into an existing account on the designated server
Login {
#[clap(short, long)]
email: String
},
2023-06-16 00:49:06 +00:00
/// Log in to your account with a magic-link token acquired via email or the trifid-api logs.
MagicLink {
#[clap(short, long)]
magic_link_token: String
},
/// Create a new TOTP authenticator on this account to enable authorizing with 2fa and performing all management tasks.
MfaSetup {},
/// Finish creating a new TOTP authenticator by inputting the code shown on your authenticator app.
MfaSetupFinish {
#[clap(short, long)]
code: String,
#[clap(short, long)]
token: String
},
/// Create a new short-lived authentication token by inputting the code shown on your authenticator app.
Mfa {
#[clap(short, long)]
code: String
}
}
#[derive(Subcommand, Debug)]
pub enum NetworkCommands {
/// List all networks associated with your trifid account.
List {},
/// Lookup a specific network by ID.
Lookup {
#[clap(short, long)]
id: String
}
}
#[derive(Subcommand, Debug)]
pub enum OrgCommands {
/// Create an organization on your trifid-api server. NOTE: This command ONLY works on trifid-api servers. It will NOT work on original DN servers.
Create {
#[clap(short, long)]
cidr: Ipv4Net
}
}
2023-06-16 02:00:09 +00:00
#[derive(Subcommand, Debug)]
pub enum RoleCommands {
/// Create a role on your organization
Create {
#[clap(short, long)]
name: String,
#[clap(short, long)]
description: String,
/// A JSON string containing the firewall rules to add to this host
#[clap(short, long)]
rules_json: String
},
/// List all roles attached to your organization
List {},
/// Lookup a specific role by it's ID
Lookup {
#[clap(short, long)]
id: String
},
/// Delete a specific role by it's ID
Delete {
#[clap(short, long)]
id: String
},
/// Update a specific role by it's ID. Warning: any data not provided in this update will be removed - include all data you wish to remain
Update {
#[clap(short, long)]
id: String,
#[clap(short, long)]
description: String,
/// A JSON string containing the firewall rules to add to this host
#[clap(short, long)]
rules_json: String
}
}
2023-06-21 01:23:28 +00:00
#[derive(Subcommand, Debug)]
pub enum HostCommands {
/// Create a host on your network
Create {
#[clap(short, long)]
name: String,
#[clap(short = 'N', long)]
network_id: String,
#[clap(short, long)]
role_id: String,
#[clap(short, long)]
ip_address: Ipv4Addr,
#[clap(short, long)]
listen_port: Option<u16>,
#[clap(short = 'L', long)]
lighthouse: bool,
#[clap(short = 'R', long)]
relay: bool,
#[clap(short, long)]
static_address: Option<SocketAddrV4>
},
/// List all hosts on your network
List {},
/// Lookup a specific host by it's ID
Lookup {
#[clap(short, long)]
id: String
},
/// Delete a specific host by it's ID
Delete {
#[clap(short, long)]
id: String
},
/// Update a specific host by it's ID, changing the listen port and static addresses, as well as the name, ip and role. The name, ip and role updates will only work on trifid-api compatible servers.
Update {
#[clap(short, long)]
id: String,
#[clap(short, long)]
listen_port: Option<u16>,
#[clap(short, long)]
static_address: Option<SocketAddrV4>,
#[clap(short, long)]
name: Option<String>,
#[clap(short, long)]
role: Option<String>,
#[clap(short = 'I', long)]
ip: Option<Ipv4Addr>
},
/// Blocks the specified host from the network
Block {
#[clap(short, long)]
id: String
},
/// Enroll or re-enroll the host by generating an enrollment code
Enroll {
#[clap(short, long)]
id: String
}
}
2023-06-16 00:49:06 +00:00
#[tokio::main]
async fn main() {
match main2().await {
Ok(_) => (),
Err(e) => {
eprintln!("There was an error during execution: {}", e);
std::process::exit(1);
}
}
}
async fn main2() -> Result<(), Box<dyn Error>> {
let args = Args::parse();
// find server
let server;
if let Some(srv) = args.server {
server = srv; // Environment variable or CLI takes precedence over config file
} else {
let srv_url_file = dirs::config_dir().unwrap().join("tfcli-server-url.conf");
if !srv_url_file.exists() {
eprintln!("[error] no server URL available: '-s/--server' not provided, TFCLI_SERVER not set, and {} does not exist", srv_url_file.display());
eprintln!("[error] please set a server url via any of these mechanisms and try again");
std::process::exit(1);
}
let url_s = fs::read_to_string(&srv_url_file)?;
let url = match Url::parse(&url_s) {
Ok(u) => u,
Err(e) => {
eprintln!("[error] unable to parse the URL in {}", srv_url_file.display());
eprintln!("[error] urlparse returned error '{}'", e);
eprintln!("[error] please correct the error and try again");
std::process::exit(1);
}
};
server = url;
}
match args.command {
Commands::Account { command } => account_main(command, server).await,
Commands::Network { command } => network_main(command, server).await,
2023-06-16 02:00:09 +00:00
Commands::Org { command } => org_main(command, server).await,
2023-06-21 01:23:28 +00:00
Commands::Role { command } => role_main(command, server).await,
Commands::Host { command } => host_main(command, server).await
2023-06-16 00:49:06 +00:00
}
}