phase 4
This commit is contained in:
@@ -106,6 +106,13 @@ I'm going to add some test data to the project under `tests/` but it's just rand
|
||||
|
||||
As a minor improvement, make the `perform_close` method also gzip the contents of the tarball.
|
||||
|
||||
### Phase 4
|
||||
|
||||
For phase 4, add encryption. We'll have to add a new error type for the given key not being a valid key for `age`.
|
||||
|
||||
Now, after we create the tar but before we write it to disk, we need to encrypt the array, so that plaintext is never
|
||||
written to disk.
|
||||
|
||||
## Commands
|
||||
|
||||
```bash
|
||||
|
||||
@@ -13,6 +13,8 @@ pub enum DrawerError {
|
||||
DrawerInsideTarget,
|
||||
TarFailed,
|
||||
WriteFailed(PathBuf),
|
||||
KeyNotValidSsh,
|
||||
EncryptFailed,
|
||||
}
|
||||
|
||||
impl fmt::Display for DrawerError {
|
||||
@@ -28,6 +30,8 @@ impl fmt::Display for DrawerError {
|
||||
DrawerError::DrawerInsideTarget => write!(f, "drawer file is inside the target directory"),
|
||||
DrawerError::TarFailed => write!(f, "failed to create tarball"),
|
||||
DrawerError::WriteFailed(p) => write!(f, "failed to write drawer file: {}", p.display()),
|
||||
DrawerError::KeyNotValidSsh => write!(f, "key is not a valid SSH key"),
|
||||
DrawerError::EncryptFailed => write!(f, "encryption failed"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+37
-9
@@ -1,4 +1,5 @@
|
||||
use std::ffi::OsString;
|
||||
use std::io::Write;
|
||||
use std::path::{Path, PathBuf};
|
||||
use flate2::Compression;
|
||||
use flate2::write::GzEncoder;
|
||||
@@ -119,7 +120,26 @@ impl DrawerOperation {
|
||||
gz.finish()
|
||||
.map_err(|_| DrawerError::TarFailed)?;
|
||||
}
|
||||
std::fs::write(&self.drawer_file, &buf)
|
||||
|
||||
let key_path = self.key_path()?;
|
||||
let file = std::fs::File::open(&key_path)
|
||||
.map_err(|_| DrawerError::KeyInvalid(key_path.clone()))?;
|
||||
let reader = std::io::BufReader::new(file);
|
||||
let identity = age::ssh::Identity::from_buffer(reader, None)
|
||||
.map_err(|_| DrawerError::EncryptFailed)?;
|
||||
let recipient = age::ssh::Recipient::try_from(identity)
|
||||
.map_err(|_| DrawerError::EncryptFailed)?;
|
||||
|
||||
let mut encrypted: Vec<u8> = Vec::new();
|
||||
let encryptor = age::Encryptor::with_recipients(
|
||||
std::iter::once(&recipient as &dyn age::Recipient)
|
||||
).map_err(|_| DrawerError::EncryptFailed)?;
|
||||
let mut writer = encryptor.wrap_output(&mut encrypted)
|
||||
.map_err(|_| DrawerError::EncryptFailed)?;
|
||||
writer.write_all(&buf).map_err(|_| DrawerError::EncryptFailed)?;
|
||||
writer.finish().map_err(|_| DrawerError::EncryptFailed)?;
|
||||
|
||||
std::fs::write(&self.drawer_file, &encrypted)
|
||||
.map_err(|_| DrawerError::WriteFailed(self.drawer_file.clone()))
|
||||
}
|
||||
|
||||
@@ -134,20 +154,28 @@ impl DrawerOperation {
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_key(&self) -> Result<(), DrawerError> {
|
||||
let key_path = match &self.key {
|
||||
fn key_path(&self) -> Result<PathBuf, DrawerError> {
|
||||
match &self.key {
|
||||
EnvVar => {
|
||||
let val = std::env::var("DRAWER_KEY").map_err(|_| DrawerError::NoKeyPath)?;
|
||||
PathBuf::from(val)
|
||||
Ok(PathBuf::from(val))
|
||||
}
|
||||
Path(p) => p.clone(),
|
||||
};
|
||||
match std::fs::File::open(&key_path) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(_) => Err(DrawerError::KeyInvalid(key_path)),
|
||||
Path(p) => Ok(p.clone()),
|
||||
}
|
||||
}
|
||||
|
||||
fn validate_key(&self) -> Result<(), DrawerError> {
|
||||
let key_path = self.key_path()?;
|
||||
let file = std::fs::File::open(&key_path)
|
||||
.map_err(|_| DrawerError::KeyInvalid(key_path.clone()))?;
|
||||
let reader = std::io::BufReader::new(file);
|
||||
let identity = age::ssh::Identity::from_buffer(reader, None)
|
||||
.map_err(|_| DrawerError::KeyNotValidSsh)?;
|
||||
age::ssh::Recipient::try_from(identity)
|
||||
.map_err(|_| DrawerError::KeyNotValidSsh)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn validate_open(&self) -> Result<(), DrawerError> {
|
||||
if !self.drawer_file.exists() {
|
||||
return Err(DrawerError::DrawerFileNotFound(self.drawer_file.clone()));
|
||||
|
||||
Reference in New Issue
Block a user