diff options
-rw-r--r-- | src/backup_run.rs | 2 | ||||
-rw-r--r-- | src/bin/obnam.rs | 39 | ||||
-rw-r--r-- | src/cmd/backup.rs | 2 | ||||
-rw-r--r-- | src/cmd/init.rs | 8 | ||||
-rw-r--r-- | src/cmd/show_config.rs | 2 | ||||
-rw-r--r-- | src/config.rs | 92 | ||||
-rw-r--r-- | subplot/client.py | 11 | ||||
-rw-r--r-- | subplot/client.yaml | 5 |
8 files changed, 63 insertions, 98 deletions
diff --git a/src/backup_run.rs b/src/backup_run.rs index 23c97f6..16d6700 100644 --- a/src/backup_run.rs +++ b/src/backup_run.rs @@ -41,7 +41,6 @@ pub type BackupResult<T> = Result<T, BackupError>; impl<'a> InitialBackup<'a> { pub fn new(config: &ClientConfig, client: &'a BackupClient) -> BackupResult<Self> { let progress = BackupProgress::initial(); - let config = config.config(); Ok(Self { client, buffer_size: config.chunk_size, @@ -81,7 +80,6 @@ impl<'a> InitialBackup<'a> { impl<'a> IncrementalBackup<'a> { pub fn new(config: &ClientConfig, client: &'a BackupClient) -> BackupResult<Self> { - let config = config.config(); let policy = BackupPolicy::default(); Ok(Self { client, diff --git a/src/bin/obnam.rs b/src/bin/obnam.rs index cdb5179..c8da6c2 100644 --- a/src/bin/obnam.rs +++ b/src/bin/obnam.rs @@ -3,6 +3,7 @@ use log::{debug, error, info, LevelFilter}; use log4rs::append::file::FileAppender; use log4rs::config::{Appender, Logger, Root}; use obnam::cmd::backup::Backup; +use obnam::cmd::chunk::{DecryptChunk, EncryptChunk}; use obnam::cmd::get_chunk::GetChunk; use obnam::cmd::init::Init; use obnam::cmd::list::List; @@ -20,28 +21,24 @@ const APPLICATION: &str = "obnam"; fn main() -> anyhow::Result<()> { let opt = Opt::from_args(); - let config = load_config_without_passwords(&opt)?; - setup_logging(&config.config().log)?; + let config = ClientConfig::read(&config_filename(&opt))?; + setup_logging(&config.log)?; info!("client starts"); debug!("{:?}", opt); debug!("configuration: {:#?}", config); let result = match opt.cmd { - Command::Init(x) => x.run(config.config()), - _ => { - let config = load_config_with_passwords(&opt)?; - match opt.cmd { - Command::Init(_) => panic!("this can't happen"), - Command::Backup(x) => x.run(&config), - Command::List(x) => x.run(&config), - Command::ShowGeneration(x) => x.run(&config), - Command::ListFiles(x) => x.run(&config), - Command::Restore(x) => x.run(&config), - Command::GetChunk(x) => x.run(&config), - Command::Config(x) => x.run(&config), - } - } + Command::Init(x) => x.run(&config), + Command::Backup(x) => x.run(&config), + Command::List(x) => x.run(&config), + Command::ShowGeneration(x) => x.run(&config), + Command::ListFiles(x) => x.run(&config), + Command::Restore(x) => x.run(&config), + Command::GetChunk(x) => x.run(&config), + Command::Config(x) => x.run(&config), + Command::EncryptChunk(x) => x.run(&config), + Command::DecryptChunk(x) => x.run(&config), }; if let Err(ref e) = result { @@ -66,14 +63,6 @@ fn setup_logging(filename: &Path) -> anyhow::Result<()> { Ok(()) } -fn load_config_with_passwords(opt: &Opt) -> Result<ClientConfig, anyhow::Error> { - Ok(ClientConfig::read_with_passwords(&config_filename(opt))?) -} - -fn load_config_without_passwords(opt: &Opt) -> Result<ClientConfig, anyhow::Error> { - Ok(ClientConfig::read_without_passwords(&config_filename(opt))?) -} - fn config_filename(opt: &Opt) -> PathBuf { match opt.config { None => default_config(), @@ -109,4 +98,6 @@ enum Command { ShowGeneration(ShowGeneration), GetChunk(GetChunk), Config(ShowConfig), + EncryptChunk(EncryptChunk), + DecryptChunk(DecryptChunk), } diff --git a/src/cmd/backup.rs b/src/cmd/backup.rs index 0479844..22afd6e 100644 --- a/src/cmd/backup.rs +++ b/src/cmd/backup.rs @@ -60,7 +60,6 @@ fn initial_backup( info!("fresh backup without a previous generation"); let newtemp = NamedTempFile::new()?; let run = InitialBackup::new(config, &client)?; - let config = config.config(); let mut all_warnings = vec![]; let count = { let mut new = NascentGeneration::create(newtemp.path())?; @@ -87,7 +86,6 @@ fn incremental_backup( info!("incremental backup based on {}", old_ref); let newtemp = NamedTempFile::new()?; let mut run = IncrementalBackup::new(config, &client)?; - let config = config.config(); let mut all_warnings = vec![]; let count = { let oldtemp = NamedTempFile::new()?; diff --git a/src/cmd/init.rs b/src/cmd/init.rs index cb61fba..08060f7 100644 --- a/src/cmd/init.rs +++ b/src/cmd/init.rs @@ -1,4 +1,4 @@ -use crate::config::ClientConfigWithoutPasswords; +use crate::config::ClientConfig; use crate::error::ObnamError; use crate::passwords::{passwords_filename, Passwords}; use structopt::StructOpt; @@ -12,11 +12,7 @@ pub struct Init { } impl Init { - pub fn run(&self, config: &ClientConfigWithoutPasswords) -> Result<(), ObnamError> { - if !config.encrypt { - panic!("no encryption specified"); - } - + pub fn run(&self, config: &ClientConfig) -> Result<(), ObnamError> { let passphrase = match &self.insecure_passphrase { Some(x) => x.to_string(), None => rpassword::read_password_from_tty(Some(PROMPT)).unwrap(), diff --git a/src/cmd/show_config.rs b/src/cmd/show_config.rs index 424e2ed..05e83c1 100644 --- a/src/cmd/show_config.rs +++ b/src/cmd/show_config.rs @@ -7,7 +7,7 @@ pub struct ShowConfig {} impl ShowConfig { pub fn run(&self, config: &ClientConfig) -> Result<(), ObnamError> { - println!("{}", serde_json::to_string_pretty(&config.config())?); + println!("{}", serde_json::to_string_pretty(config)?); Ok(()) } } diff --git a/src/config.rs b/src/config.rs index 33e08a2..0d4e9de 100644 --- a/src/config.rs +++ b/src/config.rs @@ -16,78 +16,22 @@ struct TentativeClientConfig { chunk_size: Option<usize>, roots: Vec<PathBuf>, log: Option<PathBuf>, - encrypt: Option<bool>, exclude_cache_tag_directories: Option<bool>, } #[derive(Debug, Serialize, Clone)] -pub enum ClientConfig { - Plain(ClientConfigWithoutPasswords), - WithPasswords(ClientConfigWithoutPasswords, Passwords), -} - -impl ClientConfig { - pub fn read_without_passwords(filename: &Path) -> Result<Self, ClientConfigError> { - let config = ClientConfigWithoutPasswords::read_config(filename)?; - Ok(ClientConfig::Plain(config)) - } - - pub fn read_with_passwords(filename: &Path) -> Result<Self, ClientConfigError> { - let config = ClientConfigWithoutPasswords::read_config(filename)?; - if config.encrypt { - let passwords = Passwords::load(&passwords_filename(filename)) - .map_err(ClientConfigError::PasswordsMissing)?; - Ok(ClientConfig::WithPasswords(config, passwords)) - } else { - Ok(ClientConfig::Plain(config)) - } - } - - pub fn config(&self) -> &ClientConfigWithoutPasswords { - match self { - Self::Plain(config) => &config, - Self::WithPasswords(config, _) => &config, - } - } -} - -#[derive(Debug, Serialize, Clone)] -pub struct ClientConfigWithoutPasswords { +pub struct ClientConfig { pub filename: PathBuf, pub server_url: String, pub verify_tls_cert: bool, pub chunk_size: usize, pub roots: Vec<PathBuf>, pub log: PathBuf, - pub encrypt: bool, pub exclude_cache_tag_directories: bool, } -#[derive(Debug, thiserror::Error)] -pub enum ClientConfigError { - #[error("server_url is empty")] - ServerUrlIsEmpty, - - #[error("No backup roots in config; at least one is needed")] - NoBackupRoot, - - #[error("server URL doesn't use https: {0}")] - NotHttps(String), - - #[error("No passwords are set: you may need to run 'obnam init': {0}")] - PasswordsMissing(PasswordError), - - #[error("failed to read configuration file {0}: {1}")] - Read(PathBuf, std::io::Error), - - #[error("failed to parse configuration file {0} as YAML: {1}")] - YamlParse(PathBuf, serde_yaml::Error), -} - -pub type ClientConfigResult<T> = Result<T, ClientConfigError>; - -impl ClientConfigWithoutPasswords { - pub fn read_config(filename: &Path) -> ClientConfigResult<Self> { +impl ClientConfig { + pub fn read(filename: &Path) -> ClientConfigResult<Self> { trace!("read_config: filename={:?}", filename); let config = std::fs::read_to_string(filename) .map_err(|err| ClientConfigError::Read(filename.to_path_buf(), err))?; @@ -102,12 +46,10 @@ impl ClientConfigWithoutPasswords { .log .map(|path| expand_tilde(&path)) .unwrap_or_else(|| PathBuf::from(DEVNULL)); - let encrypt = tentative.encrypt.or(Some(false)).unwrap(); let exclude_cache_tag_directories = tentative.exclude_cache_tag_directories.unwrap_or(true); let config = Self { chunk_size: tentative.chunk_size.or(Some(DEFAULT_CHUNK_SIZE)).unwrap(), - encrypt, filename: filename.to_path_buf(), roots, server_url: tentative.server_url, @@ -132,8 +74,36 @@ impl ClientConfigWithoutPasswords { } Ok(()) } + + pub fn passwords(&self) -> Result<Passwords, ClientConfigError> { + Passwords::load(&passwords_filename(&self.filename)) + .map_err(ClientConfigError::PasswordsMissing) + } } +#[derive(Debug, thiserror::Error)] +pub enum ClientConfigError { + #[error("server_url is empty")] + ServerUrlIsEmpty, + + #[error("No backup roots in config; at least one is needed")] + NoBackupRoot, + + #[error("server URL doesn't use https: {0}")] + NotHttps(String), + + #[error("No passwords are set: you may need to run 'obnam init': {0}")] + PasswordsMissing(PasswordError), + + #[error("failed to read configuration file {0}: {1}")] + Read(PathBuf, std::io::Error), + + #[error("failed to parse configuration file {0} as YAML: {1}")] + YamlParse(PathBuf, serde_yaml::Error), +} + +pub type ClientConfigResult<T> = Result<T, ClientConfigError>; + fn expand_tilde(path: &Path) -> PathBuf { if path.starts_with("~/") { if let Some(home) = std::env::var_os("HOME") { diff --git a/subplot/client.py b/subplot/client.py index be0a6d6..d0beba5 100644 --- a/subplot/client.py +++ b/subplot/client.py @@ -16,7 +16,7 @@ def uninstall_obnam(ctx): runcmd_run(ctx, ["chmod", "-R", "u+rwX", "."]) -def configure_client(ctx, filename=None): +def configure_client_without_init(ctx, filename=None): get_file = globals()["get_file"] assert ctx.get("server_url") is not None @@ -35,6 +35,15 @@ def configure_client(ctx, filename=None): yaml.safe_dump(config, stream=f) +def configure_client_with_init(ctx, filename=None): + runcmd_run = globals()["runcmd_run"] + runcmd_exit_code_is_zero = globals()["runcmd_exit_code_is_zero"] + + configure_client_without_init(ctx, filename=filename) + runcmd_run(ctx, ["obnam", "init", "--insecure-passphrase=hunter2"]) + runcmd_exit_code_is_zero(ctx) + + def run_obnam_restore(ctx, genid=None, todir=None): runcmd_run = globals()["runcmd_run"] diff --git a/subplot/client.yaml b/subplot/client.yaml index 6de04c9..d660089 100644 --- a/subplot/client.yaml +++ b/subplot/client.yaml @@ -3,7 +3,10 @@ cleanup: uninstall_obnam - given: "a client config based on {filename}" - function: configure_client + function: configure_client_with_init + +- given: "a client config, without passphrase, based on {filename}" + function: configure_client_without_init - when: "I invoke obnam restore <{genid}> {todir}" function: run_obnam_restore |