Add more configuration tests

This commit is contained in:
Pierre HUBERT 2022-09-02 15:01:34 +02:00
parent a5e48cf9d0
commit 59aadeacd4
12 changed files with 463 additions and 97 deletions

View File

@ -3,7 +3,7 @@ use std::io::ErrorKind;
/// Encapsulate errors in [`std::io::Error`] with a message
pub fn encpasulate_error<E: Display, F: ToString>(e: E, msg: F) -> std::io::Error {
std::io::Error::new(ErrorKind::Other, format!("{}: {}", msg.to_string(), e))
std::io::Error::new(ErrorKind::Other, format!("{}:\n* {}", msg.to_string(), e))
}
/// Create a new [`std::io::Error`]

View File

@ -36,3 +36,14 @@ async fn main() -> std::io::Result<()> {
SubCommands::Client(c) => tcp_over_http::tcp_relay_client::run_app(c).await,
}
}
#[cfg(test)]
mod test {
use crate::CliArgs;
#[test]
fn verify_cli() {
use clap::CommandFactory;
CliArgs::command().debug_assert()
}
}

View File

@ -7,7 +7,7 @@ use std::sync::Arc;
use futures::future::join_all;
use reqwest::{Certificate, Identity};
use crate::base::err_utils::new_err;
use crate::base::err_utils::{encpasulate_error, new_err};
use crate::base::RemoteConfig;
use crate::tcp_relay_client::client_config::ClientConfig;
use crate::tcp_relay_client::relay_client::relay_client;
@ -29,7 +29,8 @@ async fn get_server_config(conf: &ClientConfig) -> Result<RemoteConfig, Box<dyn
// Specify client certificate, if any
if let Some(kp) = conf.get_merged_client_keypair() {
let identity = Identity::from_pem(&kp).expect("Failed to load certificates for reqwest!");
let identity = Identity::from_pem(&kp)
.map_err(|e| encpasulate_error(e, "Failed to load certificates for reqwest!"))?;
client = client.identity(identity).use_rustls_tls();
}
@ -93,7 +94,7 @@ pub async fn run_app(mut args: ClientConfig) -> std::io::Result<()> {
port.id,
urlencoding::encode(args.get_auth_token())
)
.replace("http", "ws"),
.replace("http", "ws"),
listen_address,
args.clone(),
));

View File

@ -0,0 +1,159 @@
use tokio::task;
use crate::tcp_relay_client::client_config::ClientConfig;
use crate::tcp_relay_server::server_config::ServerConfig;
use crate::test::{BAD_PATH, get_port_number, LOCALHOST_IP, PortsAllocation};
use crate::test::dummy_tcp_sockets::wait_for_port;
use crate::test::pki::Pki;
use crate::test::test_files_utils::create_temp_file_with_random_content;
fn port(index: u16) -> u16 {
get_port_number(PortsAllocation::ClientInvalidTlsConfiguration, index)
}
#[tokio::test()]
async fn random_file_for_cert() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
let random_file = create_temp_file_with_random_content();
crate::tcp_relay_client::run_app(ClientConfig {
token: Some("token".to_string()),
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
listen_address: LOCALHOST_IP.to_string(),
tls_cert: Some(random_file.to_string_lossy().to_string()),
tls_key: Some(pki.valid_client_key.file_path()),
..Default::default()
})
.await
.unwrap_err();
}
#[tokio::test()]
async fn random_file_for_key() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
let random_file = create_temp_file_with_random_content();
crate::tcp_relay_client::run_app(ClientConfig {
token: Some("token".to_string()),
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
listen_address: LOCALHOST_IP.to_string(),
tls_cert: Some(pki.valid_client_crt.file_path()),
tls_key: Some(random_file.to_string_lossy().to_string()),
..Default::default()
})
.await
.unwrap_err();
}
#[tokio::test()]
async fn bad_pem_file_for_cert() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
crate::tcp_relay_client::run_app(ClientConfig {
token: Some("token".to_string()),
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
listen_address: LOCALHOST_IP.to_string(),
tls_cert: Some(pki.root_ca_crl.file_path()),
tls_key: Some(pki.valid_client_key.file_path()),
..Default::default()
})
.await
.unwrap_err();
}
#[tokio::test()]
async fn bad_pem_file_for_key() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
crate::tcp_relay_client::run_app(ClientConfig {
token: Some("token".to_string()),
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
listen_address: LOCALHOST_IP.to_string(),
tls_cert: Some(pki.valid_client_crt.file_path()),
tls_key: Some(pki.root_ca_crl.file_path()),
..Default::default()
})
.await
.unwrap_err();
}
#[tokio::test()]
async fn non_existing_cert() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
crate::tcp_relay_client::run_app(ClientConfig {
token: Some("token".to_string()),
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
listen_address: LOCALHOST_IP.to_string(),
tls_cert: Some(BAD_PATH.to_string()),
tls_key: Some(pki.valid_client_key.file_path()),
..Default::default()
})
.await
.unwrap_err();
}
#[tokio::test()]
async fn non_existing_key() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
crate::tcp_relay_client::run_app(ClientConfig {
token: Some("token".to_string()),
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
listen_address: LOCALHOST_IP.to_string(),
tls_cert: Some(pki.valid_client_crt.file_path()),
tls_key: Some(BAD_PATH.to_string()),
..Default::default()
})
.await
.unwrap_err();
}
#[tokio::test()]
async fn unmatched_key_cert_pair() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
let local_set = task::LocalSet::new();
local_set
.run_until(async move {
// Start server relay
task::spawn_local(crate::tcp_relay_server::run_app(ServerConfig {
tokens: vec!["dqsd".to_string()],
tokens_file: None,
ports: vec![port(1)],
upstream_server: "127.0.0.1".to_string(),
listen_address: format!("127.0.0.1:{}", port(0)),
increment_ports: 1,
tls_cert: Some(pki.localhost_crt.file_path()),
tls_key: Some(pki.localhost_key.file_path()),
tls_client_auth_root_cert: Some(pki.root_ca_crt.file_path()),
tls_revocation_list: None,
}));
wait_for_port(port(0)).await;
crate::tcp_relay_client::run_app(ClientConfig {
token: Some("token".to_string()),
relay_url: format!("https://localhost:{}", port(0)),
listen_address: LOCALHOST_IP.to_string(),
tls_cert: Some(pki.valid_client_crt.file_path()),
tls_key: Some(pki.revoked_client_key.file_path()),
root_certificate: Some(pki.root_ca_crt.file_path()),
..Default::default()
})
.await
.unwrap_err();
}).await;
}

View File

@ -1,6 +1,7 @@
use crate::tcp_relay_client::client_config::ClientConfig;
use crate::test::{BAD_PATH, get_port_number, LOCALHOST_IP, PortsAllocation};
use crate::test::pki::Pki;
use crate::test::{get_port_number, PortsAllocation, LOCALHOST_IP};
use crate::test::test_files_utils::create_temp_file_with_random_content;
const VALID_TOKEN: &str = "AvalidTOKEN";
@ -21,8 +22,8 @@ async fn invalid_file_type() {
root_certificate: Some(pki.expired_client_key.file_path()),
..Default::default()
})
.await
.unwrap_err();
.await
.unwrap_err();
}
#[tokio::test()]
@ -33,9 +34,26 @@ async fn non_existing_file() {
token: Some(VALID_TOKEN.to_string()),
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
listen_address: LOCALHOST_IP.to_string(),
root_certificate: Some("/bad/path/to/file".to_string()),
root_certificate: Some(BAD_PATH.to_string()),
..Default::default()
})
.await
.unwrap_err();
.await
.unwrap_err();
}
#[tokio::test()]
async fn random_file() {
let _ = env_logger::builder().is_test(true).try_init();
let random_file = create_temp_file_with_random_content();
crate::tcp_relay_client::run_app(ClientConfig {
token: Some(VALID_TOKEN.to_string()),
relay_url: format!("https://{}:{}", LOCALHOST_IP, port(0)),
listen_address: LOCALHOST_IP.to_string(),
root_certificate: Some(random_file.to_string_lossy().to_string()),
..Default::default()
})
.await
.unwrap_err();
}

View File

@ -16,6 +16,7 @@ enum PortsAllocation {
TlsAuthExpiredClientCertificate,
TlsAuthRevokedClientCertificate,
TlsAuthInvalidClientCertificate,
ClientInvalidTlsConfiguration,
}
fn get_port_number(alloc: PortsAllocation, index: u16) -> u16 {
@ -23,6 +24,7 @@ fn get_port_number(alloc: PortsAllocation, index: u16) -> u16 {
}
const LOCALHOST_IP: &str = "127.0.0.1";
const BAD_PATH: &str = "/bad/path/to/key/file";
mod dummy_tcp_sockets;
mod pki;
@ -30,11 +32,12 @@ mod test_files_utils;
mod client_invalid_tls_root_certificate_file;
mod client_try_tls_while_there_is_no_tls;
mod client_invalid_tls_configuration;
mod invalid_with_token_auth;
mod server_invalid_tls_config_invalid_cert;
mod server_invalid_tls_config_invalid_client_crl;
mod server_invalid_tls_config_invalid_client_root_cert;
mod server_invalid_tls_config_invalid_key;
mod server_invalid_tls_config_invalid_paths;
mod server_invalid_tls_config_missing_key;
mod server_invalid_token_file;
mod server_missing_auth;
mod tls_auth_expired_certificate;

View File

@ -1,6 +1,7 @@
use crate::tcp_relay_server::server_config::ServerConfig;
use crate::test::pki::Pki;
use crate::test::{get_port_number, PortsAllocation};
use crate::test::test_files_utils::create_temp_file_with_random_content;
use crate::test::{get_port_number, PortsAllocation, BAD_PATH};
const TOKEN: &str = "mytok";
@ -9,7 +10,29 @@ fn port(index: u16) -> u16 {
}
#[tokio::test]
async fn test() {
async fn unspecified() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
crate::tcp_relay_server::run_app(ServerConfig {
tokens: vec![TOKEN.to_string()],
tokens_file: None,
ports: vec![port(1)],
upstream_server: "127.0.0.1".to_string(),
listen_address: format!("127.0.0.1:{}", port(0)),
increment_ports: 1,
tls_cert: None,
tls_key: Some(pki.localhost_key.file_path()),
tls_client_auth_root_cert: None,
tls_revocation_list: None,
})
.await
.unwrap_err();
}
#[tokio::test]
async fn incorrect_pem_type() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
@ -29,3 +52,49 @@ async fn test() {
.await
.unwrap_err();
}
#[tokio::test]
async fn random_contents() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
let random_file = create_temp_file_with_random_content();
crate::tcp_relay_server::run_app(ServerConfig {
tokens: vec![TOKEN.to_string()],
tokens_file: None,
ports: vec![port(1)],
upstream_server: "127.0.0.1".to_string(),
listen_address: format!("127.0.0.1:{}", port(0)),
increment_ports: 1,
tls_cert: Some(random_file.to_string_lossy().to_string()),
tls_key: Some(pki.localhost_key.file_path()),
tls_client_auth_root_cert: None,
tls_revocation_list: None,
})
.await
.unwrap_err();
}
#[tokio::test]
async fn invalid_path() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
crate::tcp_relay_server::run_app(ServerConfig {
tokens: vec![TOKEN.to_string()],
tokens_file: None,
ports: vec![port(1)],
upstream_server: "127.0.0.1".to_string(),
listen_address: format!("127.0.0.1:{}", port(0)),
increment_ports: 1,
tls_cert: Some(BAD_PATH.to_string()),
tls_key: Some(pki.localhost_key.file_path()),
tls_client_auth_root_cert: None,
tls_revocation_list: None,
})
.await
.unwrap_err();
}

View File

@ -0,0 +1,78 @@
use crate::tcp_relay_server::server_config::ServerConfig;
use crate::test::pki::Pki;
use crate::test::test_files_utils::create_temp_file_with_random_content;
use crate::test::{get_port_number, PortsAllocation, BAD_PATH};
const TOKEN: &str = "mytok";
fn port(index: u16) -> u16 {
get_port_number(PortsAllocation::TestsWithoutPortOpened, index)
}
#[tokio::test]
async fn bad_path() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
crate::tcp_relay_server::run_app(ServerConfig {
tokens: vec![TOKEN.to_string()],
tokens_file: None,
ports: vec![port(1)],
upstream_server: "127.0.0.1".to_string(),
listen_address: format!("127.0.0.1:{}", port(0)),
increment_ports: 1,
tls_cert: Some(pki.localhost_crt.file_path()),
tls_key: Some(pki.localhost_key.file_path()),
tls_client_auth_root_cert: Some(pki.root_ca_crl.file_path()),
tls_revocation_list: Some(BAD_PATH.to_string()),
})
.await
.unwrap_err();
}
#[tokio::test]
async fn random_content() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
let random_file = create_temp_file_with_random_content();
crate::tcp_relay_server::run_app(ServerConfig {
tokens: vec![TOKEN.to_string()],
tokens_file: None,
ports: vec![port(1)],
upstream_server: "127.0.0.1".to_string(),
listen_address: format!("127.0.0.1:{}", port(0)),
increment_ports: 1,
tls_cert: Some(pki.localhost_crt.file_path()),
tls_key: Some(pki.localhost_key.file_path()),
tls_client_auth_root_cert: Some(pki.root_ca_crl.file_path()),
tls_revocation_list: Some(random_file.to_string_lossy().to_string()),
})
.await
.unwrap_err();
}
#[tokio::test]
async fn invalid_pem() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
crate::tcp_relay_server::run_app(ServerConfig {
tokens: vec![TOKEN.to_string()],
tokens_file: None,
ports: vec![port(1)],
upstream_server: "127.0.0.1".to_string(),
listen_address: format!("127.0.0.1:{}", port(0)),
increment_ports: 1,
tls_cert: Some(pki.localhost_crt.file_path()),
tls_key: Some(pki.localhost_key.file_path()),
tls_client_auth_root_cert: Some(pki.root_ca_crl.file_path()),
tls_revocation_list: Some(pki.root_ca_crt.file_path()),
})
.await
.unwrap_err();
}

View File

@ -1,61 +1,16 @@
use crate::tcp_relay_server::server_config::ServerConfig;
use crate::test::pki::Pki;
use crate::test::{get_port_number, PortsAllocation};
use crate::test::test_files_utils::create_temp_file_with_random_content;
use crate::test::{get_port_number, PortsAllocation, BAD_PATH};
const TOKEN: &str = "mytok";
const BAD_PATH: &str = "/bad/path/to/key/file";
fn port(index: u16) -> u16 {
get_port_number(PortsAllocation::TestsWithoutPortOpened, index)
}
#[tokio::test]
async fn invalid_key_path() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
crate::tcp_relay_server::run_app(ServerConfig {
tokens: vec![TOKEN.to_string()],
tokens_file: None,
ports: vec![port(1)],
upstream_server: "127.0.0.1".to_string(),
listen_address: format!("127.0.0.1:{}", port(0)),
increment_ports: 1,
tls_cert: Some(pki.localhost_crt.file_path()),
tls_key: Some(BAD_PATH.to_string()),
tls_client_auth_root_cert: None,
tls_revocation_list: None,
})
.await
.unwrap_err();
}
#[tokio::test]
async fn invalid_cert_path() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
crate::tcp_relay_server::run_app(ServerConfig {
tokens: vec![TOKEN.to_string()],
tokens_file: None,
ports: vec![port(1)],
upstream_server: "127.0.0.1".to_string(),
listen_address: format!("127.0.0.1:{}", port(0)),
increment_ports: 1,
tls_cert: Some(BAD_PATH.to_string()),
tls_key: Some(pki.localhost_key.file_path()),
tls_client_auth_root_cert: None,
tls_revocation_list: None,
})
.await
.unwrap_err();
}
#[tokio::test]
async fn invalid_client_root_cert_path() {
async fn invalid_path() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
@ -77,7 +32,7 @@ async fn invalid_client_root_cert_path() {
}
#[tokio::test]
async fn invalid_client_root_crl_path() {
async fn other_pem_file_type() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
@ -92,7 +47,31 @@ async fn invalid_client_root_crl_path() {
tls_cert: Some(pki.localhost_crt.file_path()),
tls_key: Some(pki.localhost_key.file_path()),
tls_client_auth_root_cert: Some(pki.root_ca_crl.file_path()),
tls_revocation_list: Some(BAD_PATH.to_string()),
tls_revocation_list: None,
})
.await
.unwrap_err();
}
#[tokio::test]
async fn random_content() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
let random_file = create_temp_file_with_random_content();
crate::tcp_relay_server::run_app(ServerConfig {
tokens: vec![TOKEN.to_string()],
tokens_file: None,
ports: vec![port(1)],
upstream_server: "127.0.0.1".to_string(),
listen_address: format!("127.0.0.1:{}", port(0)),
increment_ports: 1,
tls_cert: Some(pki.localhost_crt.file_path()),
tls_key: Some(pki.localhost_key.file_path()),
tls_client_auth_root_cert: Some(random_file.to_string_lossy().to_string()),
tls_revocation_list: None,
})
.await
.unwrap_err();

View File

@ -1,6 +1,7 @@
use crate::tcp_relay_server::server_config::ServerConfig;
use crate::test::pki::Pki;
use crate::test::{get_port_number, PortsAllocation};
use crate::test::test_files_utils::create_temp_file_with_random_content;
use crate::test::{get_port_number, PortsAllocation, BAD_PATH};
const TOKEN: &str = "mytok";
@ -9,7 +10,7 @@ fn port(index: u16) -> u16 {
}
#[tokio::test]
async fn test() {
async fn invalid_pem_file_type() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
@ -29,3 +30,71 @@ async fn test() {
.await
.unwrap_err();
}
#[tokio::test()]
async fn unspecified() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
crate::tcp_relay_server::run_app(ServerConfig {
tokens: vec![TOKEN.to_string()],
tokens_file: None,
ports: vec![port(1)],
upstream_server: "127.0.0.1".to_string(),
listen_address: format!("127.0.0.1:{}", port(0)),
increment_ports: 1,
tls_cert: Some(pki.root_ca_crt.file_path()),
tls_key: None,
tls_client_auth_root_cert: None,
tls_revocation_list: None,
})
.await
.unwrap_err();
}
#[tokio::test]
async fn random_content() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
let random_content = create_temp_file_with_random_content();
crate::tcp_relay_server::run_app(ServerConfig {
tokens: vec![TOKEN.to_string()],
tokens_file: None,
ports: vec![port(1)],
upstream_server: "127.0.0.1".to_string(),
listen_address: format!("127.0.0.1:{}", port(0)),
increment_ports: 1,
tls_cert: Some(pki.root_ca_crt.file_path()),
tls_key: Some(random_content.to_string_lossy().to_string()),
tls_client_auth_root_cert: None,
tls_revocation_list: None,
})
.await
.unwrap_err();
}
#[tokio::test]
async fn invalid_path() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
crate::tcp_relay_server::run_app(ServerConfig {
tokens: vec![TOKEN.to_string()],
tokens_file: None,
ports: vec![port(1)],
upstream_server: "127.0.0.1".to_string(),
listen_address: format!("127.0.0.1:{}", port(0)),
increment_ports: 1,
tls_cert: Some(pki.localhost_crt.file_path()),
tls_key: Some(BAD_PATH.to_string()),
tls_client_auth_root_cert: None,
tls_revocation_list: None,
})
.await
.unwrap_err();
}

View File

@ -1,31 +0,0 @@
use crate::tcp_relay_server::server_config::ServerConfig;
use crate::test::pki::Pki;
use crate::test::{get_port_number, PortsAllocation};
const TOKEN: &str = "mytok";
fn port(index: u16) -> u16 {
get_port_number(PortsAllocation::TestsWithoutPortOpened, index)
}
#[tokio::test()]
async fn test() {
let _ = env_logger::builder().is_test(true).try_init();
let pki = Pki::load();
crate::tcp_relay_server::run_app(ServerConfig {
tokens: vec![TOKEN.to_string()],
tokens_file: None,
ports: vec![port(1)],
upstream_server: "127.0.0.1".to_string(),
listen_address: format!("127.0.0.1:{}", port(0)),
increment_ports: 1,
tls_cert: Some(pki.root_ca_crt.file_path()),
tls_key: None,
tls_client_auth_root_cert: None,
tls_revocation_list: None,
})
.await
.unwrap_err();
}

View File

@ -1,7 +1,17 @@
use mktemp::Temp;
use rand::Rng;
/// Create a temporary file and feed it with some specified content
pub fn create_temp_file_with_content(content: &[u8]) -> Temp {
let temp = Temp::new_file().unwrap();
std::fs::write(&temp, content).unwrap();
temp
}
/// Generate a temporary file with some random content
pub fn create_temp_file_with_random_content() -> Temp {
let random_bytes = rand::thread_rng().gen::<[u8; 10]>();
let temp = Temp::new_file().unwrap();
std::fs::write(&temp, random_bytes).unwrap();
temp
}