parent
e11b73972c
commit
ddac328ae5
|
@ -9,8 +9,8 @@ use shared::{
|
||||||
interface_config::InterfaceConfig,
|
interface_config::InterfaceConfig,
|
||||||
prompts,
|
prompts,
|
||||||
wg::{DeviceExt, PeerInfoExt},
|
wg::{DeviceExt, PeerInfoExt},
|
||||||
AddAssociationOpts, AddCidrOpts, AddPeerOpts, Association, AssociationContents, Cidr, CidrTree,
|
AddCidrOpts, AddDeleteAssociationOpts, AddPeerOpts, Association, AssociationContents, Cidr,
|
||||||
DeleteCidrOpts, Endpoint, EndpointContents, InstallOpts, Interface, IoErrorContext,
|
CidrTree, DeleteCidrOpts, Endpoint, EndpointContents, InstallOpts, Interface, IoErrorContext,
|
||||||
ListenPortOpts, NatOpts, NetworkOpts, OverrideEndpointOpts, Peer, RedeemContents,
|
ListenPortOpts, NatOpts, NetworkOpts, OverrideEndpointOpts, Peer, RedeemContents,
|
||||||
RenamePeerOpts, State, WrappedIoError, REDEEM_TRANSITION_WAIT,
|
RenamePeerOpts, State, WrappedIoError, REDEEM_TRANSITION_WAIT,
|
||||||
};
|
};
|
||||||
|
@ -149,7 +149,13 @@ enum Command {
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Uninstall an innernet network.
|
/// Uninstall an innernet network.
|
||||||
Uninstall { interface: Interface },
|
Uninstall {
|
||||||
|
interface: Interface,
|
||||||
|
|
||||||
|
/// Bypass confirmation
|
||||||
|
#[clap(long)]
|
||||||
|
yes: bool,
|
||||||
|
},
|
||||||
|
|
||||||
/// Bring down the interface (equivalent to 'wg-quick down <interface>')
|
/// Bring down the interface (equivalent to 'wg-quick down <interface>')
|
||||||
Down { interface: Interface },
|
Down { interface: Interface },
|
||||||
|
@ -216,11 +222,16 @@ enum Command {
|
||||||
interface: Interface,
|
interface: Interface,
|
||||||
|
|
||||||
#[clap(flatten)]
|
#[clap(flatten)]
|
||||||
sub_opts: AddAssociationOpts,
|
sub_opts: AddDeleteAssociationOpts,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// Delete an association between CIDRs
|
/// Delete an association between CIDRs
|
||||||
DeleteAssociation { interface: Interface },
|
DeleteAssociation {
|
||||||
|
interface: Interface,
|
||||||
|
|
||||||
|
#[clap(flatten)]
|
||||||
|
sub_opts: AddDeleteAssociationOpts,
|
||||||
|
},
|
||||||
|
|
||||||
/// List existing assocations between CIDRs
|
/// List existing assocations between CIDRs
|
||||||
ListAssociations { interface: Interface },
|
ListAssociations { interface: Interface },
|
||||||
|
@ -628,7 +639,7 @@ fn fetch(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn uninstall(interface: &InterfaceName, opts: &Opts) -> Result<(), Error> {
|
fn uninstall(interface: &InterfaceName, opts: &Opts, yes: bool) -> Result<(), Error> {
|
||||||
let config = InterfaceConfig::get_path(&opts.config_dir, interface);
|
let config = InterfaceConfig::get_path(&opts.config_dir, interface);
|
||||||
let data = DataStore::get_path(&opts.data_dir, interface);
|
let data = DataStore::get_path(&opts.data_dir, interface);
|
||||||
|
|
||||||
|
@ -639,14 +650,15 @@ fn uninstall(interface: &InterfaceName, opts: &Opts) -> Result<(), Error> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if Confirm::with_theme(&*prompts::THEME)
|
if yes
|
||||||
.with_prompt(&format!(
|
|| Confirm::with_theme(&*prompts::THEME)
|
||||||
"Permanently delete network \"{}\"?",
|
.with_prompt(&format!(
|
||||||
interface.as_str_lossy().yellow()
|
"Permanently delete network \"{}\"?",
|
||||||
))
|
interface.as_str_lossy().yellow()
|
||||||
.default(false)
|
))
|
||||||
.wait_for_newline(true)
|
.default(false)
|
||||||
.interact()?
|
.wait_for_newline(true)
|
||||||
|
.interact()?
|
||||||
{
|
{
|
||||||
log::info!("bringing down interface (if up).");
|
log::info!("bringing down interface (if up).");
|
||||||
wg::down(interface, opts.network.backend).ok();
|
wg::down(interface, opts.network.backend).ok();
|
||||||
|
@ -821,7 +833,7 @@ fn enable_or_disable_peer(
|
||||||
fn add_association(
|
fn add_association(
|
||||||
interface: &InterfaceName,
|
interface: &InterfaceName,
|
||||||
opts: &Opts,
|
opts: &Opts,
|
||||||
sub_opts: AddAssociationOpts,
|
sub_opts: AddDeleteAssociationOpts,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let InterfaceConfig { server, .. } =
|
let InterfaceConfig { server, .. } =
|
||||||
InterfaceConfig::from_interface(&opts.config_dir, interface)?;
|
InterfaceConfig::from_interface(&opts.config_dir, interface)?;
|
||||||
|
@ -830,7 +842,8 @@ fn add_association(
|
||||||
log::info!("Fetching CIDRs");
|
log::info!("Fetching CIDRs");
|
||||||
let cidrs: Vec<Cidr> = api.http("GET", "/admin/cidrs")?;
|
let cidrs: Vec<Cidr> = api.http("GET", "/admin/cidrs")?;
|
||||||
|
|
||||||
let association = if let (Some(ref cidr1), Some(ref cidr2)) = (sub_opts.cidr1, sub_opts.cidr2) {
|
let association = if let (Some(ref cidr1), Some(ref cidr2)) = (&sub_opts.cidr1, &sub_opts.cidr2)
|
||||||
|
{
|
||||||
let cidr1 = cidrs
|
let cidr1 = cidrs
|
||||||
.iter()
|
.iter()
|
||||||
.find(|c| &c.name == cidr1)
|
.find(|c| &c.name == cidr1)
|
||||||
|
@ -840,7 +853,7 @@ fn add_association(
|
||||||
.find(|c| &c.name == cidr2)
|
.find(|c| &c.name == cidr2)
|
||||||
.ok_or_else(|| anyhow!("can't find cidr '{}'", cidr2))?;
|
.ok_or_else(|| anyhow!("can't find cidr '{}'", cidr2))?;
|
||||||
(cidr1, cidr2)
|
(cidr1, cidr2)
|
||||||
} else if let Some((cidr1, cidr2)) = prompts::add_association(&cidrs[..])? {
|
} else if let Some((cidr1, cidr2)) = prompts::add_association(&cidrs[..], &sub_opts)? {
|
||||||
(cidr1, cidr2)
|
(cidr1, cidr2)
|
||||||
} else {
|
} else {
|
||||||
log::info!("exiting without adding association.");
|
log::info!("exiting without adding association.");
|
||||||
|
@ -859,7 +872,11 @@ fn add_association(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete_association(interface: &InterfaceName, opts: &Opts) -> Result<(), Error> {
|
fn delete_association(
|
||||||
|
interface: &InterfaceName,
|
||||||
|
opts: &Opts,
|
||||||
|
sub_opts: AddDeleteAssociationOpts,
|
||||||
|
) -> Result<(), Error> {
|
||||||
let InterfaceConfig { server, .. } =
|
let InterfaceConfig { server, .. } =
|
||||||
InterfaceConfig::from_interface(&opts.config_dir, interface)?;
|
InterfaceConfig::from_interface(&opts.config_dir, interface)?;
|
||||||
let api = Api::new(&server);
|
let api = Api::new(&server);
|
||||||
|
@ -869,7 +886,9 @@ fn delete_association(interface: &InterfaceName, opts: &Opts) -> Result<(), Erro
|
||||||
log::info!("Fetching associations");
|
log::info!("Fetching associations");
|
||||||
let associations: Vec<Association> = api.http("GET", "/admin/associations")?;
|
let associations: Vec<Association> = api.http("GET", "/admin/associations")?;
|
||||||
|
|
||||||
if let Some(association) = prompts::delete_association(&associations[..], &cidrs[..])? {
|
if let Some(association) =
|
||||||
|
prompts::delete_association(&associations[..], &cidrs[..], &sub_opts)?
|
||||||
|
{
|
||||||
api.http("DELETE", &format!("/admin/associations/{}", association.id))?;
|
api.http("DELETE", &format!("/admin/associations/{}", association.id))?;
|
||||||
} else {
|
} else {
|
||||||
log::info!("exiting without adding association.");
|
log::info!("exiting without adding association.");
|
||||||
|
@ -1211,7 +1230,7 @@ fn run(opts: &Opts) -> Result<(), Error> {
|
||||||
&nat,
|
&nat,
|
||||||
)?,
|
)?,
|
||||||
Command::Down { interface } => wg::down(&interface, opts.network.backend)?,
|
Command::Down { interface } => wg::down(&interface, opts.network.backend)?,
|
||||||
Command::Uninstall { interface } => uninstall(&interface, opts)?,
|
Command::Uninstall { interface, yes } => uninstall(&interface, opts, yes)?,
|
||||||
Command::AddPeer {
|
Command::AddPeer {
|
||||||
interface,
|
interface,
|
||||||
sub_opts,
|
sub_opts,
|
||||||
|
@ -1235,7 +1254,10 @@ fn run(opts: &Opts) -> Result<(), Error> {
|
||||||
interface,
|
interface,
|
||||||
sub_opts,
|
sub_opts,
|
||||||
} => add_association(&interface, opts, sub_opts)?,
|
} => add_association(&interface, opts, sub_opts)?,
|
||||||
Command::DeleteAssociation { interface } => delete_association(&interface, opts)?,
|
Command::DeleteAssociation {
|
||||||
|
interface,
|
||||||
|
sub_opts,
|
||||||
|
} => delete_association(&interface, opts, sub_opts)?,
|
||||||
Command::ListAssociations { interface } => list_associations(&interface, opts)?,
|
Command::ListAssociations { interface } => list_associations(&interface, opts)?,
|
||||||
Command::SetListenPort {
|
Command::SetListenPort {
|
||||||
interface,
|
interface,
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
interface_config::{InterfaceConfig, InterfaceInfo, ServerInfo},
|
interface_config::{InterfaceConfig, InterfaceInfo, ServerInfo},
|
||||||
AddCidrOpts, AddPeerOpts, Association, Cidr, CidrContents, CidrTree, DeleteCidrOpts, Endpoint,
|
AddCidrOpts, AddDeleteAssociationOpts, AddPeerOpts, Association, Cidr, CidrContents, CidrTree,
|
||||||
Error, Hostname, ListenPortOpts, OverrideEndpointOpts, Peer, PeerContents, RenamePeerOpts,
|
DeleteCidrOpts, Endpoint, Error, Hostname, ListenPortOpts, OverrideEndpointOpts, Peer,
|
||||||
PERSISTENT_KEEPALIVE_INTERVAL_SECS,
|
PeerContents, RenamePeerOpts, PERSISTENT_KEEPALIVE_INTERVAL_SECS,
|
||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use colored::*;
|
use colored::*;
|
||||||
|
@ -151,41 +151,81 @@ pub fn choose_cidr<'a>(cidrs: &'a [Cidr], text: &'static str) -> Result<&'a Cidr
|
||||||
pub fn choose_association<'a>(
|
pub fn choose_association<'a>(
|
||||||
associations: &'a [Association],
|
associations: &'a [Association],
|
||||||
cidrs: &'a [Cidr],
|
cidrs: &'a [Cidr],
|
||||||
|
args: &AddDeleteAssociationOpts,
|
||||||
) -> Result<&'a Association, Error> {
|
) -> Result<&'a Association, Error> {
|
||||||
let names: Vec<_> = associations
|
match (&args.cidr1, &args.cidr2) {
|
||||||
.iter()
|
(Some(cidr1_name), Some(cidr2_name)) => {
|
||||||
.map(|association| {
|
let cidr1 = find_cidr(cidrs, cidr1_name)?;
|
||||||
format!(
|
let cidr2 = find_cidr(cidrs, cidr2_name)?;
|
||||||
"{}: {} <=> {}",
|
associations
|
||||||
association.id,
|
.iter()
|
||||||
&cidrs
|
.find(|association| {
|
||||||
.iter()
|
(association.cidr_id_1 == cidr1.id && association.cidr_id_2 == cidr2.id)
|
||||||
.find(|c| c.id == association.cidr_id_1)
|
|| (association.cidr_id_1 == cidr2.id && association.cidr_id_2 == cidr1.id)
|
||||||
.unwrap()
|
})
|
||||||
.name,
|
.ok_or_else(|| anyhow!("CIDR association does not exist"))
|
||||||
&cidrs
|
},
|
||||||
.iter()
|
_ => {
|
||||||
.find(|c| c.id == association.cidr_id_2)
|
let names: Vec<_> = associations
|
||||||
.unwrap()
|
.iter()
|
||||||
.name
|
.map(|association| {
|
||||||
)
|
format!(
|
||||||
})
|
"{}: {} <=> {}",
|
||||||
.collect();
|
association.id,
|
||||||
let (index, _) = select("Association", &names)?;
|
&cidrs
|
||||||
|
.iter()
|
||||||
|
.find(|c| c.id == association.cidr_id_1)
|
||||||
|
.unwrap()
|
||||||
|
.name,
|
||||||
|
&cidrs
|
||||||
|
.iter()
|
||||||
|
.find(|c| c.id == association.cidr_id_2)
|
||||||
|
.unwrap()
|
||||||
|
.name
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
let (index, _) = select("Association", &names)?;
|
||||||
|
|
||||||
Ok(&associations[index])
|
Ok(&associations[index])
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_association(cidrs: &[Cidr]) -> Result<Option<(&Cidr, &Cidr)>, Error> {
|
fn find_cidr<'a>(cidrs: &'a [Cidr], name: &str) -> Result<&'a Cidr, Error> {
|
||||||
let cidr1 = choose_cidr(cidrs, "First CIDR")?;
|
cidrs
|
||||||
let cidr2 = choose_cidr(cidrs, "Second CIDR")?;
|
.iter()
|
||||||
|
.find(|c| c.name == name)
|
||||||
|
.ok_or_else(|| anyhow!("can't find cidr '{}'", name))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_or_prompt_cidr<'a>(
|
||||||
|
cidrs: &'a [Cidr],
|
||||||
|
sub_opt: &Option<String>,
|
||||||
|
prompt: &'static str,
|
||||||
|
) -> Result<&'a Cidr, Error> {
|
||||||
|
if let Some(name) = sub_opt {
|
||||||
|
find_cidr(cidrs, name)
|
||||||
|
} else {
|
||||||
|
choose_cidr(cidrs, prompt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn add_association<'a>(
|
||||||
|
cidrs: &'a [Cidr],
|
||||||
|
args: &AddDeleteAssociationOpts,
|
||||||
|
) -> Result<Option<(&'a Cidr, &'a Cidr)>, Error> {
|
||||||
|
let cidr1 = find_or_prompt_cidr(cidrs, &args.cidr1, "First CIDR")?;
|
||||||
|
let cidr2 = find_or_prompt_cidr(cidrs, &args.cidr2, "Second CIDR")?;
|
||||||
|
|
||||||
Ok(
|
Ok(
|
||||||
if confirm(&format!(
|
if args.yes
|
||||||
"Add association: {} <=> {}?",
|
|| confirm(&format!(
|
||||||
cidr1.name.yellow().bold(),
|
"Add association: {} <=> {}?",
|
||||||
cidr2.name.yellow().bold()
|
cidr1.name.yellow().bold(),
|
||||||
))? {
|
cidr2.name.yellow().bold()
|
||||||
|
))?
|
||||||
|
{
|
||||||
Some((cidr1, cidr2))
|
Some((cidr1, cidr2))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
@ -196,11 +236,12 @@ pub fn add_association(cidrs: &[Cidr]) -> Result<Option<(&Cidr, &Cidr)>, Error>
|
||||||
pub fn delete_association<'a>(
|
pub fn delete_association<'a>(
|
||||||
associations: &'a [Association],
|
associations: &'a [Association],
|
||||||
cidrs: &'a [Cidr],
|
cidrs: &'a [Cidr],
|
||||||
|
args: &AddDeleteAssociationOpts,
|
||||||
) -> Result<Option<&'a Association>, Error> {
|
) -> Result<Option<&'a Association>, Error> {
|
||||||
let association = choose_association(associations, cidrs)?;
|
let association = choose_association(associations, cidrs, args)?;
|
||||||
|
|
||||||
Ok(
|
Ok(
|
||||||
if confirm(&format!("Delete association #{}?", association.id))? {
|
if args.yes || confirm(&format!("Delete association #{}?", association.id))? {
|
||||||
Some(association)
|
Some(association)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -379,12 +379,16 @@ pub struct DeleteCidrOpts {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Args)]
|
#[derive(Debug, Clone, PartialEq, Args)]
|
||||||
pub struct AddAssociationOpts {
|
pub struct AddDeleteAssociationOpts {
|
||||||
/// The first cidr to associate
|
/// The first cidr to associate
|
||||||
pub cidr1: Option<String>,
|
pub cidr1: Option<String>,
|
||||||
|
|
||||||
/// The second cidr to associate
|
/// The second cidr to associate
|
||||||
pub cidr2: Option<String>,
|
pub cidr2: Option<String>,
|
||||||
|
|
||||||
|
/// Bypass confirmation
|
||||||
|
#[clap(long)]
|
||||||
|
pub yes: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Args)]
|
#[derive(Debug, Clone, PartialEq, Args)]
|
||||||
|
|
Loading…
Reference in New Issue