summaryrefslogtreecommitdiff
path: root/src/client.rs
diff options
context:
space:
mode:
authorLars Wirzenius <liw@liw.fi>2021-04-09 11:54:19 +0300
committerLars Wirzenius <liw@liw.fi>2021-04-09 17:17:35 +0300
commitd0b0245edbb2f6ed8285358d83b98f3334bf1b12 (patch)
tree988f72832b8a5015f4dbfb49473eba022d089666 /src/client.rs
parent2d6c1c81bfb1c0be8dfaced1c70e825e46c66430 (diff)
downloadobnam2-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.rs47
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()?;