Save tokens for each machine
This commit is contained in:
parent
4e62839513
commit
6c6d5a51a8
3 changed files with 83 additions and 27 deletions
43
src/dirs.rs
43
src/dirs.rs
|
|
@ -1,7 +1,8 @@
|
||||||
use directories::ProjectDirs;
|
use directories::ProjectDirs;
|
||||||
|
use gethostname::gethostname;
|
||||||
|
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
use std::path::PathBuf;
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
const QUALIFIER: &str = "com";
|
const QUALIFIER: &str = "com";
|
||||||
const ORGANIZATION: &str = "Ero-sennin";
|
const ORGANIZATION: &str = "Ero-sennin";
|
||||||
|
|
@ -16,3 +17,43 @@ pub(crate) fn get_data_dir() -> PathBuf {
|
||||||
});
|
});
|
||||||
project_dirs.data_dir().to_path_buf()
|
project_dirs.data_dir().to_path_buf()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) struct MachineConfig {
|
||||||
|
path: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl MachineConfig {
|
||||||
|
pub(crate) fn new(machine_name: Option<&PathBuf>) -> anyhow::Result<Self> {
|
||||||
|
let hostname: PathBuf;
|
||||||
|
let machine: &PathBuf = if let Some(machine_name) = machine_name {
|
||||||
|
machine_name
|
||||||
|
} else {
|
||||||
|
hostname = PathBuf::from(gethostname());
|
||||||
|
&hostname
|
||||||
|
};
|
||||||
|
let path = get_data_dir().join("machines").join(machine);
|
||||||
|
std::fs::create_dir_all(&path)?;
|
||||||
|
Ok(Self { path })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn destroy(self) -> anyhow::Result<()> {
|
||||||
|
std::fs::remove_dir_all(self.path)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn path(&self) -> &Path {
|
||||||
|
&self.path
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn username_path(&self) -> PathBuf {
|
||||||
|
self.path().join("username")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn token_path(&self) -> PathBuf {
|
||||||
|
self.path().join("token")
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn key_path(&self) -> PathBuf {
|
||||||
|
self.path().join("key")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
27
src/keys.rs
27
src/keys.rs
|
|
@ -1,14 +1,10 @@
|
||||||
use base64::prelude::{Engine as _, BASE64_STANDARD};
|
use base64::prelude::{Engine as _, BASE64_STANDARD};
|
||||||
use gethostname::gethostname;
|
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use x25519_dalek::{PublicKey, StaticSecret};
|
use x25519_dalek::{PublicKey, StaticSecret};
|
||||||
|
|
||||||
use std::{
|
use std::{io::Write, path::Path};
|
||||||
io::Write,
|
|
||||||
path::{Path, PathBuf},
|
|
||||||
};
|
|
||||||
|
|
||||||
use crate::dirs::get_data_dir;
|
use crate::dirs::MachineConfig;
|
||||||
|
|
||||||
const KEY_SIZE: usize = 32;
|
const KEY_SIZE: usize = 32;
|
||||||
|
|
||||||
|
|
@ -46,24 +42,15 @@ pub(crate) struct WireguardKeyPair {
|
||||||
pub private_key: Key,
|
pub private_key: Key,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn get_keys(machine: Option<&PathBuf>) -> Result<WireguardKeyPair, anyhow::Error> {
|
pub(crate) fn get_keys(machine_config: &MachineConfig) -> Result<WireguardKeyPair, anyhow::Error> {
|
||||||
let hostname: PathBuf;
|
let key_path = machine_config.key_path();
|
||||||
let machine_subdir: &PathBuf = if let Some(machine) = machine {
|
|
||||||
machine
|
|
||||||
} else {
|
|
||||||
hostname = PathBuf::from(gethostname());
|
|
||||||
&hostname
|
|
||||||
};
|
|
||||||
let key_path = get_data_dir().join("keys");
|
|
||||||
debug!("key path = {:?}", &key_path);
|
debug!("key path = {:?}", &key_path);
|
||||||
std::fs::create_dir_all(&key_path)?;
|
|
||||||
|
|
||||||
let private_key_path = key_path.join(machine_subdir);
|
let private_key = if key_path.is_file() {
|
||||||
let private_key = if private_key_path.is_file() {
|
Key::load(&key_path)?
|
||||||
Key::load(&private_key_path)?
|
|
||||||
} else {
|
} else {
|
||||||
let key = generate_private_key();
|
let key = generate_private_key();
|
||||||
key.save(&private_key_path)?;
|
key.save(&key_path)?;
|
||||||
key
|
key
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
40
src/main.rs
40
src/main.rs
|
|
@ -1,15 +1,15 @@
|
||||||
mod api;
|
mod api;
|
||||||
use std::net::IpAddr;
|
|
||||||
mod dirs;
|
mod dirs;
|
||||||
mod keys;
|
mod keys;
|
||||||
|
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
|
use std::net::IpAddr;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
|
||||||
use crate::keys::{get_keys, WireguardKeyPair};
|
use crate::{keys::{get_keys, WireguardKeyPair}, dirs::MachineConfig};
|
||||||
|
|
||||||
/// AzireVPN client
|
/// AzireVPN client
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
|
|
@ -27,10 +27,14 @@ struct Opts {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Parser, Debug)]
|
#[derive(Parser, Debug)]
|
||||||
struct ConfigOpts {
|
struct LoginOpts {
|
||||||
location: String,
|
|
||||||
username: String,
|
username: String,
|
||||||
token: String,
|
token: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Parser, Debug)]
|
||||||
|
struct ConfigOpts {
|
||||||
|
location: String,
|
||||||
|
|
||||||
#[arg(short, long)]
|
#[arg(short, long)]
|
||||||
no_dns: bool,
|
no_dns: bool,
|
||||||
|
|
@ -41,6 +45,12 @@ struct ConfigOpts {
|
||||||
|
|
||||||
#[derive(Subcommand, Debug)]
|
#[derive(Subcommand, Debug)]
|
||||||
enum Command {
|
enum Command {
|
||||||
|
/// Add machine token
|
||||||
|
Login(LoginOpts),
|
||||||
|
|
||||||
|
/// Logout
|
||||||
|
Logout,
|
||||||
|
|
||||||
/// Checks connection status
|
/// Checks connection status
|
||||||
Check,
|
Check,
|
||||||
|
|
||||||
|
|
@ -55,6 +65,8 @@ fn main() -> Result<(), anyhow::Error> {
|
||||||
env_logger::init();
|
env_logger::init();
|
||||||
let opts = Opts::parse();
|
let opts = Opts::parse();
|
||||||
match &opts.command {
|
match &opts.command {
|
||||||
|
Command::Login(login_opts) => login(&opts, login_opts)?,
|
||||||
|
Command::Logout => logout(&opts)?,
|
||||||
Command::Check => check(&opts)?,
|
Command::Check => check(&opts)?,
|
||||||
Command::Locations => list_locations(&opts)?,
|
Command::Locations => list_locations(&opts)?,
|
||||||
Command::Config(get_config_opts) => get_config(&opts, get_config_opts)?,
|
Command::Config(get_config_opts) => get_config(&opts, get_config_opts)?,
|
||||||
|
|
@ -62,6 +74,19 @@ fn main() -> Result<(), anyhow::Error> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn login(opts: &Opts, login_opts: &LoginOpts) -> Result<(), anyhow::Error> {
|
||||||
|
let machine_config = dirs::MachineConfig::new(opts.machine.as_ref())?;
|
||||||
|
std::fs::write(machine_config.username_path(), &login_opts.username)?;
|
||||||
|
std::fs::write(machine_config.token_path(), &login_opts.token)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn logout(opts: &Opts) -> Result<(), anyhow::Error> {
|
||||||
|
let machine_config = dirs::MachineConfig::new(opts.machine.as_ref())?;
|
||||||
|
machine_config.destroy()?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn check(opts: &Opts) -> Result<(), anyhow::Error> {
|
fn check(opts: &Opts) -> Result<(), anyhow::Error> {
|
||||||
let check_result = api::check()?;
|
let check_result = api::check()?;
|
||||||
if opts.json {
|
if opts.json {
|
||||||
|
|
@ -97,6 +122,7 @@ fn list_locations(opts: &Opts) -> Result<(), anyhow::Error> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_config(opts: &Opts, config_opts: &ConfigOpts) -> Result<(), anyhow::Error> {
|
fn get_config(opts: &Opts, config_opts: &ConfigOpts) -> Result<(), anyhow::Error> {
|
||||||
|
let machine_config = MachineConfig::new(opts.machine.as_ref())?;
|
||||||
let locations = api::get_locations()?;
|
let locations = api::get_locations()?;
|
||||||
let location = locations
|
let location = locations
|
||||||
.locations
|
.locations
|
||||||
|
|
@ -104,9 +130,11 @@ fn get_config(opts: &Opts, config_opts: &ConfigOpts) -> Result<(), anyhow::Error
|
||||||
.find(|location| location.name == config_opts.location)
|
.find(|location| location.name == config_opts.location)
|
||||||
.ok_or_else(|| anyhow::anyhow!("no such location: {}", config_opts.location))?;
|
.ok_or_else(|| anyhow::anyhow!("no such location: {}", config_opts.location))?;
|
||||||
debug!("location = {:?}", &location);
|
debug!("location = {:?}", &location);
|
||||||
let keys = get_keys(opts.machine.as_ref())?;
|
let keys = get_keys(&machine_config)?;
|
||||||
|
let username = std::fs::read_to_string(machine_config.username_path())?;
|
||||||
|
let token = std::fs::read_to_string(machine_config.token_path())?;
|
||||||
debug!("keys = {:?}", &keys);
|
debug!("keys = {:?}", &keys);
|
||||||
let addresses = api::add_ip(&config_opts.username, &config_opts.token, &keys.public_key)?;
|
let addresses = api::add_ip(&username, &token, &keys.public_key)?;
|
||||||
|
|
||||||
write_config(
|
write_config(
|
||||||
&mut std::io::stdout().lock(),
|
&mut std::io::stdout().lock(),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue