phase 6
This commit is contained in:
+61
-6
@@ -6,6 +6,7 @@ use flate2::Compression;
|
||||
use flate2::read::GzDecoder;
|
||||
use flate2::write::GzEncoder;
|
||||
use clap::{Parser, Subcommand};
|
||||
use ssh_key::{Algorithm, LineEnding, PrivateKey};
|
||||
use crate::error::DrawerError;
|
||||
use crate::parsing::KeyType::*;
|
||||
|
||||
@@ -13,6 +14,7 @@ use crate::parsing::KeyType::*;
|
||||
pub enum OperationType {
|
||||
Open,
|
||||
Close,
|
||||
Key,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@@ -22,6 +24,7 @@ pub struct DrawerOperation {
|
||||
pub key: KeyType,
|
||||
pub target_path: PathBuf,
|
||||
pub force: bool,
|
||||
pub target_inferred: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
@@ -52,6 +55,9 @@ enum Command {
|
||||
#[arg(short = 'i')]
|
||||
key: Option<PathBuf>,
|
||||
},
|
||||
Key {
|
||||
filename: PathBuf,
|
||||
},
|
||||
}
|
||||
|
||||
pub fn parse_args<I, T>(args: I) -> Result<DrawerOperation, DrawerError>
|
||||
@@ -65,15 +71,17 @@ where
|
||||
match cli.command {
|
||||
Command::Open { drawer_file, target_path, key, force } => {
|
||||
let key = resolve_key(key);
|
||||
let target = target_path.unwrap_or_else(|| {
|
||||
PathBuf::from(drawer_file.file_stem().unwrap_or_default())
|
||||
});
|
||||
let (target, target_inferred) = match target_path {
|
||||
Some(p) => (p, false),
|
||||
None => (PathBuf::from(drawer_file.file_stem().unwrap_or_default()), true),
|
||||
};
|
||||
Ok(DrawerOperation {
|
||||
operation_type: OperationType::Open,
|
||||
drawer_file,
|
||||
key,
|
||||
target_path: target,
|
||||
force,
|
||||
target_inferred,
|
||||
})
|
||||
}
|
||||
Command::Close { drawer_file, target_path, key } => {
|
||||
@@ -85,6 +93,17 @@ where
|
||||
key,
|
||||
target_path: target,
|
||||
force: false,
|
||||
target_inferred: false,
|
||||
})
|
||||
}
|
||||
Command::Key { filename } => {
|
||||
Ok(DrawerOperation {
|
||||
operation_type: OperationType::Key,
|
||||
drawer_file: filename,
|
||||
key: KeyType::EnvVar,
|
||||
target_path: PathBuf::from("."),
|
||||
force: false,
|
||||
target_inferred: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -103,10 +122,14 @@ impl DrawerOperation {
|
||||
match self.operation_type {
|
||||
OperationType::Open => self.perform_open(),
|
||||
OperationType::Close => self.perform_close(),
|
||||
OperationType::Key => self.perform_key(),
|
||||
}
|
||||
}
|
||||
|
||||
fn perform_open(&self) -> Result<(), DrawerError> {
|
||||
if self.target_inferred {
|
||||
println!("(assuming into {})", self.target_path.display());
|
||||
}
|
||||
let encrypted = std::fs::read(&self.drawer_file)
|
||||
.map_err(|_| DrawerError::DrawerFileNotFound(self.drawer_file.clone()))?;
|
||||
|
||||
@@ -179,16 +202,39 @@ impl DrawerOperation {
|
||||
}
|
||||
|
||||
pub fn validate(&self) -> Result<(), DrawerError> {
|
||||
if self.drawer_file.extension().and_then(|e| e.to_str()) != Some("drawer") {
|
||||
return Err(DrawerError::DrawerFileInvalidExtension(self.drawer_file.clone()));
|
||||
if self.operation_type != OperationType::Key {
|
||||
if self.drawer_file.extension().and_then(|e| e.to_str()) != Some("drawer") {
|
||||
return Err(DrawerError::DrawerFileInvalidExtension(self.drawer_file.clone()));
|
||||
}
|
||||
self.validate_key()?;
|
||||
}
|
||||
self.validate_key()?;
|
||||
match self.operation_type {
|
||||
OperationType::Open => self.validate_open(),
|
||||
OperationType::Close => self.validate_close(),
|
||||
OperationType::Key => self.validate_key_gen(),
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_key_gen(&self) -> Result<(), DrawerError> {
|
||||
if self.drawer_file.exists() {
|
||||
return Err(DrawerError::KeyOutputFailed(self.drawer_file.clone()));
|
||||
}
|
||||
let parent = match self.drawer_file.parent() {
|
||||
None => Path::new("."),
|
||||
Some(p) => {
|
||||
if p == Path::new("") {
|
||||
Path::new(".")
|
||||
} else {
|
||||
p
|
||||
}
|
||||
},
|
||||
};
|
||||
if !parent.exists() {
|
||||
return Err(DrawerError::KeyOutputFailed(self.drawer_file.clone()));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn key_path(&self) -> Result<PathBuf, DrawerError> {
|
||||
match &self.key {
|
||||
EnvVar => {
|
||||
@@ -225,6 +271,15 @@ impl DrawerOperation {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn perform_key(&self) -> Result<(), DrawerError> {
|
||||
let private_key = PrivateKey::random(&mut rand::rngs::OsRng, Algorithm::Ed25519)
|
||||
.map_err(|_| DrawerError::KeyGenerateFailed)?;
|
||||
let pem = private_key.to_openssh(LineEnding::LF)
|
||||
.map_err(|_| DrawerError::KeyGenerateFailed)?;
|
||||
std::fs::write(&self.drawer_file, pem.as_bytes())
|
||||
.map_err(|_| DrawerError::KeyOutputFailed(self.drawer_file.clone()))
|
||||
}
|
||||
|
||||
fn validate_close(&self) -> Result<(), DrawerError> {
|
||||
let meta = std::fs::metadata(&self.target_path)
|
||||
.map_err(|_| DrawerError::TargetInvalid(self.target_path.clone()))?;
|
||||
|
||||
Reference in New Issue
Block a user