extract config and encryption modules
This commit is contained in:
@@ -0,0 +1,26 @@
|
|||||||
|
use std::fs::read_to_string;
|
||||||
|
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct Config {
|
||||||
|
pub snapshot_tag: String,
|
||||||
|
pub snapshot_interval: String,
|
||||||
|
pub local_pool_name: String,
|
||||||
|
pub backup_pools: BackupPools,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
pub struct BackupPools {
|
||||||
|
pub backup1: String,
|
||||||
|
pub backup2: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
pub fn read(filename: &str) -> Result<Self> {
|
||||||
|
let content = read_to_string(filename).context("reading toml file")?;
|
||||||
|
let parsed: Self = toml::from_str(&content).context("parsing toml")?;
|
||||||
|
Ok(parsed)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use anyhow::{Result, bail};
|
||||||
|
|
||||||
|
use crate::cmd::cryptsetup;
|
||||||
|
use crate::config;
|
||||||
|
|
||||||
|
pub fn decrypt_backup(pools: &config::BackupPools) -> Result<(String, String)> {
|
||||||
|
let mut pathbuf = PathBuf::new();
|
||||||
|
let mut found = false;
|
||||||
|
|
||||||
|
let mut the_name = String::new();
|
||||||
|
let mut the_crypt_device = String::new();
|
||||||
|
|
||||||
|
for (device, name) in [&pools.backup1, &pools.backup2]
|
||||||
|
.iter()
|
||||||
|
.zip(["backup1", "backup2"])
|
||||||
|
{
|
||||||
|
pathbuf.push("/dev/disk/by-uuid/");
|
||||||
|
pathbuf.push(device);
|
||||||
|
|
||||||
|
if pathbuf.exists() {
|
||||||
|
found = true;
|
||||||
|
the_name = name.to_string();
|
||||||
|
|
||||||
|
the_crypt_device.push_str("crypt-");
|
||||||
|
the_crypt_device.push_str(name); // content is then e.g. "crypt-backup1"
|
||||||
|
|
||||||
|
println!("found backup disk {name}, will decrypt to {the_crypt_device}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if found {
|
||||||
|
cryptsetup::open(&pathbuf, &the_crypt_device)?;
|
||||||
|
Ok((the_name, the_crypt_device))
|
||||||
|
} else {
|
||||||
|
bail!("no backup disk found")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn encrypt_backup(crypt_device: String) -> Result<()> {
|
||||||
|
println!("encrypting {crypt_device}");
|
||||||
|
cryptsetup::close(&crypt_device)
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
pub mod cmd;
|
pub mod cmd;
|
||||||
|
pub mod config;
|
||||||
|
pub mod encryption;
|
||||||
pub mod todo;
|
pub mod todo;
|
||||||
pub mod zfs;
|
pub mod zfs;
|
||||||
|
|||||||
+5
-68
@@ -1,24 +1,22 @@
|
|||||||
use std::env;
|
use std::env;
|
||||||
use std::fs::read_to_string;
|
|
||||||
use std::io::stdin;
|
use std::io::stdin;
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use anyhow::{Context, Result, bail};
|
use anyhow::{Context, Result, bail};
|
||||||
use serde::Deserialize;
|
|
||||||
|
|
||||||
use zfs_backup::cmd::cryptsetup;
|
|
||||||
use zfs_backup::cmd::zfs::zpool_import;
|
use zfs_backup::cmd::zfs::zpool_import;
|
||||||
|
use zfs_backup::config;
|
||||||
|
use zfs_backup::encryption;
|
||||||
use zfs_backup::todo;
|
use zfs_backup::todo;
|
||||||
use zfs_backup::zfs::ZPool;
|
use zfs_backup::zfs::ZPool;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
fn main() -> Result<()> {
|
||||||
verify_running_as_root()?;
|
verify_running_as_root()?;
|
||||||
|
|
||||||
let config = Config::read("config.toml")?;
|
let config = config::Config::read("config.toml")?;
|
||||||
|
|
||||||
let local_pool = ZPool::new(&config.local_pool_name)?; // will error if pool does not exist
|
let local_pool = ZPool::new(&config.local_pool_name)?; // will error if pool does not exist
|
||||||
|
|
||||||
let (found_pool_name, crypt_device) = decrypt_backup(&config.backup_pools)?;
|
let (found_pool_name, crypt_device) = encryption::decrypt_backup(&config.backup_pools)?;
|
||||||
let backup_pool = import_backup_pool(&found_pool_name)?;
|
let backup_pool = import_backup_pool(&found_pool_name)?;
|
||||||
|
|
||||||
backup_pool.scrub()?;
|
backup_pool.scrub()?;
|
||||||
@@ -35,34 +33,12 @@ fn main() -> Result<()> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
backup_pool.export()?;
|
backup_pool.export()?;
|
||||||
encrypt_backup(crypt_device)?;
|
encryption::encrypt_backup(crypt_device)?;
|
||||||
|
|
||||||
println!("all done");
|
println!("all done");
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct Config {
|
|
||||||
snapshot_tag: String,
|
|
||||||
snapshot_interval: String,
|
|
||||||
local_pool_name: String,
|
|
||||||
backup_pools: BackupPools,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
|
||||||
struct BackupPools {
|
|
||||||
backup1: String,
|
|
||||||
backup2: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Config {
|
|
||||||
fn read(filename: &str) -> Result<Self> {
|
|
||||||
let content = read_to_string(filename).context("reading toml file")?;
|
|
||||||
let parsed: Self = toml::from_str(&content).context("parsing toml")?;
|
|
||||||
Ok(parsed)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Import the decrypted ZFS pool so that a backup can be sent.
|
/// Import the decrypted ZFS pool so that a backup can be sent.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
@@ -134,45 +110,6 @@ fn ask_user_confirmation(todos: &Vec<todo::Todo>) -> Result<bool> {
|
|||||||
Ok(false)
|
Ok(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn decrypt_backup(pools: &BackupPools) -> Result<(String, String)> {
|
|
||||||
let mut pathbuf = PathBuf::new();
|
|
||||||
let mut found = false;
|
|
||||||
|
|
||||||
let mut the_name = String::new();
|
|
||||||
let mut the_crypt_device = String::new();
|
|
||||||
|
|
||||||
for (device, name) in [&pools.backup1, &pools.backup2]
|
|
||||||
.iter()
|
|
||||||
.zip(["backup1", "backup2"])
|
|
||||||
{
|
|
||||||
pathbuf.push("/dev/disk/by-uuid/");
|
|
||||||
pathbuf.push(device);
|
|
||||||
|
|
||||||
if pathbuf.exists() {
|
|
||||||
found = true;
|
|
||||||
the_name = name.to_string();
|
|
||||||
|
|
||||||
the_crypt_device.push_str("crypt-");
|
|
||||||
the_crypt_device.push_str(name); // content is then e.g. "crypt-backup1"
|
|
||||||
|
|
||||||
println!("found backup disk {name}, will decrypt to {the_crypt_device}");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if found {
|
|
||||||
cryptsetup::open(&pathbuf, &the_crypt_device)?;
|
|
||||||
Ok((the_name, the_crypt_device))
|
|
||||||
} else {
|
|
||||||
bail!("no backup disk found")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn encrypt_backup(crypt_device: String) -> Result<()> {
|
|
||||||
println!("encrypting {crypt_device}");
|
|
||||||
cryptsetup::close(&crypt_device)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn verify_running_as_root() -> Result<()> {
|
fn verify_running_as_root() -> Result<()> {
|
||||||
let uid = env::var("USER")?;
|
let uid = env::var("USER")?;
|
||||||
if uid != "root" {
|
if uid != "root" {
|
||||||
|
|||||||
Reference in New Issue
Block a user