diff options
author | Lars Wirzenius <liw@liw.fi> | 2021-04-09 11:54:19 +0300 |
---|---|---|
committer | Lars Wirzenius <liw@liw.fi> | 2021-04-09 17:17:35 +0300 |
commit | d0b0245edbb2f6ed8285358d83b98f3334bf1b12 (patch) | |
tree | 988f72832b8a5015f4dbfb49473eba022d089666 /src/client.rs | |
parent | 2d6c1c81bfb1c0be8dfaced1c70e825e46c66430 (diff) | |
download | obnam2-d0b0245edbb2f6ed8285358d83b98f3334bf1b12.tar.gz |
feat: add "obnam init" subcommand
This reads a passphrase and derives two passwords from that, and
stores them next to the configuration file. The passwords aren't yet
used for anything, that will come later.
Diffstat (limited to 'src/client.rs')
-rw-r--r-- | src/client.rs | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/src/client.rs b/src/client.rs index d513011..37bfe91 100644 --- a/src/client.rs +++ b/src/client.rs @@ -7,6 +7,7 @@ use crate::chunkmeta::ChunkMeta; use crate::fsentry::{FilesystemEntry, FilesystemKind}; use crate::generation::{FinishedGeneration, LocalGeneration, LocalGenerationError}; use crate::genlist::GenerationList; +use crate::passwords::{passwords_filename, PasswordError, Passwords}; use bytesize::MIB; use chrono::{DateTime, Local}; @@ -29,15 +30,48 @@ struct TentativeClientConfig { chunk_size: Option<usize>, roots: Vec<PathBuf>, log: Option<PathBuf>, + encrypt: Option<bool>, } #[derive(Debug, Serialize, Clone)] -pub struct ClientConfig { +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 server_url: String, pub verify_tls_cert: bool, pub chunk_size: usize, pub roots: Vec<PathBuf>, pub log: PathBuf, + pub encrypt: bool, } #[derive(Debug, thiserror::Error)] @@ -51,6 +85,9 @@ pub enum ClientConfigError { #[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(transparent)] IoError(#[from] std::io::Error), @@ -60,13 +97,15 @@ pub enum ClientConfigError { pub type ClientConfigResult<T> = Result<T, ClientConfigError>; -impl ClientConfig { +impl ClientConfigWithoutPasswords { pub fn read_config(filename: &Path) -> ClientConfigResult<Self> { trace!("read_config: filename={:?}", filename); let config = std::fs::read_to_string(filename)?; let tentative: TentativeClientConfig = serde_yaml::from_str(&config)?; - let config = ClientConfig { + let encrypt = tentative.encrypt.or(Some(false)).unwrap(); + + let config = Self { server_url: tentative.server_url, roots: tentative.roots, verify_tls_cert: tentative.verify_tls_cert.or(Some(false)).unwrap(), @@ -75,6 +114,7 @@ impl ClientConfig { .log .or_else(|| Some(PathBuf::from(DEVNULL))) .unwrap(), + encrypt, }; config.check()?; @@ -147,6 +187,7 @@ pub struct BackupClient { impl BackupClient { pub fn new(config: &ClientConfig) -> ClientResult<Self> { info!("creating backup client with config: {:#?}", config); + let config = config.config(); let client = Client::builder() .danger_accept_invalid_certs(!config.verify_tls_cert) .build()?; |