From 520fc35ce0269df2963a5b53112f614257b08bc6 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Sat, 6 Feb 2021 09:54:26 +0200 Subject: feat: client verifies server's TLS certificate by default Configuration setting can disable it. --- client.yaml | 1 + obnam.md | 26 ++++++++++++++++++++++++++ src/backup_run.rs | 2 +- src/client.rs | 8 +++++--- src/cmd/get_chunk.rs | 2 +- src/cmd/list.rs | 2 +- src/cmd/list_files.rs | 2 +- src/cmd/restore.rs | 2 +- src/cmd/show_gen.rs | 2 +- subplot/client.py | 1 + 10 files changed, 39 insertions(+), 9 deletions(-) diff --git a/client.yaml b/client.yaml index dd60c9c..f985fae 100644 --- a/client.yaml +++ b/client.yaml @@ -1,3 +1,4 @@ server_url: https://localhost:8888 +verify_tls_cert: false root: /home/liw/tmp/Foton log: obnam.log diff --git a/obnam.md b/obnam.md index 47839c7..b41a118 100644 --- a/obnam.md +++ b/obnam.md @@ -998,6 +998,7 @@ then stdout, as JSON, matches file config.json ~~~{#config.yaml .file .yaml .numberLines} root: live server_url: https://backup.example.com +verify_tls_cert: true ~~~ @@ -1018,8 +1019,31 @@ then stderr contains "https:" ~~~{#http.yaml .file .yaml .numberLines} root: live server_url: http://backup.example.com +verify_tls_cert: true ~~~ +## Client refuses a self-signed certificate + +This scenario verifies that the client refuses to connect to a server +if the server's TLS certificate is self-signed. The test server set up +by the scenario uses self-signed certificates. + +~~~scenario +given an installed obnam +and a running chunk server +and a client config based on ca-required.yaml +and a file live/data.dat containing some random data +when I try to run obnam --config ca-required.yaml backup +then command fails +then stderr contains "self signed certificate" +~~~ + +~~~{#ca-required.yaml .file .yaml .numberLines} +verify_tls_cert: true +root: live +~~~ + + # Acceptance criteria for Obnam as a whole The scenarios in this chapter apply to Obnam as a whole: the client @@ -1048,6 +1072,7 @@ then files live.yaml and rest.yaml match ~~~ ~~~{#smoke.yaml .file .yaml .numberLines} +verify_tls_cert: false root: live ~~~ @@ -1062,6 +1087,7 @@ anything. All these scenarios use the following configuration file. ~~~{#metadata.yaml .file .yaml .numberLines} +verify_tls_cert: false root: live ~~~ diff --git a/src/backup_run.rs b/src/backup_run.rs index ae3731d..05d5988 100644 --- a/src/backup_run.rs +++ b/src/backup_run.rs @@ -31,7 +31,7 @@ pub type BackupResult = Result; impl BackupRun { pub fn new(config: &ClientConfig, buffer_size: usize) -> BackupResult { - let client = BackupClient::new(&config.server_url)?; + let client = BackupClient::new(config)?; let policy = BackupPolicy::new(); let progress = BackupProgress::new(); Ok(Self { diff --git a/src/client.rs b/src/client.rs index 3d3b2a5..7cd6df7 100644 --- a/src/client.rs +++ b/src/client.rs @@ -20,6 +20,7 @@ use std::path::{Path, PathBuf}; #[derive(Debug, Serialize, Deserialize, Clone)] pub struct ClientConfig { pub server_url: String, + pub verify_tls_cert: bool, pub root: PathBuf, pub log: Option, } @@ -105,13 +106,14 @@ pub struct BackupClient { } impl BackupClient { - pub fn new(base_url: &str) -> ClientResult { + pub fn new(config: &ClientConfig) -> ClientResult { + info!("creating backup client with config: {:#?}", config); let client = Client::builder() - .danger_accept_invalid_certs(true) + .danger_accept_invalid_certs(!config.verify_tls_cert) .build()?; Ok(Self { client, - base_url: base_url.to_string(), + base_url: config.server_url.to_string(), }) } diff --git a/src/cmd/get_chunk.rs b/src/cmd/get_chunk.rs index c1d7590..385c4d5 100644 --- a/src/cmd/get_chunk.rs +++ b/src/cmd/get_chunk.rs @@ -5,7 +5,7 @@ use crate::error::ObnamError; use std::io::{stdout, Write}; pub fn get_chunk(config: &ClientConfig, chunk_id: &str) -> Result<(), ObnamError> { - let client = BackupClient::new(&config.server_url)?; + let client = BackupClient::new(config)?; let chunk_id: ChunkId = chunk_id.parse().unwrap(); let chunk = client.fetch_chunk(&chunk_id)?; diff --git a/src/cmd/list.rs b/src/cmd/list.rs index ce19a72..a3f059b 100644 --- a/src/cmd/list.rs +++ b/src/cmd/list.rs @@ -2,7 +2,7 @@ use crate::client::{BackupClient, ClientConfig}; use crate::error::ObnamError; pub fn list(config: &ClientConfig) -> Result<(), ObnamError> { - let client = BackupClient::new(&config.server_url)?; + let client = BackupClient::new(config)?; let generations = client.list_generations()?; for finished in generations.iter() { diff --git a/src/cmd/list_files.rs b/src/cmd/list_files.rs index b240d5a..38048ec 100644 --- a/src/cmd/list_files.rs +++ b/src/cmd/list_files.rs @@ -14,7 +14,7 @@ pub fn list_files(config: &ClientConfig, gen_ref: &str) -> Result<(), ObnamError dbname }; - let client = BackupClient::new(&config.server_url)?; + let client = BackupClient::new(config)?; let genlist = client.list_generations()?; let gen_id: String = genlist.resolve(gen_ref)?; diff --git a/src/cmd/restore.rs b/src/cmd/restore.rs index 16d5320..a0f5ec0 100644 --- a/src/cmd/restore.rs +++ b/src/cmd/restore.rs @@ -25,7 +25,7 @@ pub fn restore(config: &ClientConfig, gen_ref: &str, to: &Path) -> Result<(), Ob dbname }; - let client = BackupClient::new(&config.server_url)?; + let client = BackupClient::new(config)?; let genlist = client.list_generations()?; let gen_id: String = genlist.resolve(gen_ref)?; diff --git a/src/cmd/show_gen.rs b/src/cmd/show_gen.rs index 3dcdbf2..c7a4bdd 100644 --- a/src/cmd/show_gen.rs +++ b/src/cmd/show_gen.rs @@ -14,7 +14,7 @@ pub fn show_generation(config: &ClientConfig, gen_ref: &str) -> Result<(), Obnam dbname }; - let client = BackupClient::new(&config.server_url)?; + let client = BackupClient::new(config)?; let genlist = client.list_generations()?; let gen_id: String = genlist.resolve(gen_ref)?; diff --git a/subplot/client.py b/subplot/client.py index d450b4c..0e724b8 100644 --- a/subplot/client.py +++ b/subplot/client.py @@ -20,6 +20,7 @@ def configure_client(ctx, filename=None): config = yaml.safe_load(config) config["server_url"] = ctx["server_url"] + logging.debug(f"client config {filename}: {config}") with open(filename, "w") as f: yaml.safe_dump(config, stream=f) -- cgit v1.2.1