feat: use openssl for tls connections, add CA_ROOT_FILE support (#268) (h/t @kapcsandi)

This commit is contained in:
Stepan Kuzmin 2021-10-18 14:35:08 +03:00 committed by GitHub
parent d4d101c7f9
commit 7ad7f1ab8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 60 additions and 127 deletions

118
Cargo.lock generated
View File

@ -545,22 +545,6 @@ version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536"
[[package]]
name = "core-foundation"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6888e10551bb93e424d8df1d07f1a8b4fceb0001a3a4b048bfc47554946f47b3"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]]
name = "core-foundation-sys"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5827cebf4670468b8772dd191856768aedcb1b0278a04f989f7766351917b9dc"
[[package]] [[package]]
name = "cpufeatures" name = "cpufeatures"
version = "0.2.1" version = "0.2.1"
@ -1244,11 +1228,11 @@ dependencies = [
"env_logger", "env_logger",
"itertools", "itertools",
"log", "log",
"native-tls",
"num_cpus", "num_cpus",
"openssl",
"postgis", "postgis",
"postgres", "postgres",
"postgres-native-tls", "postgres-openssl",
"postgres-protocol", "postgres-protocol",
"r2d2", "r2d2",
"r2d2_postgres", "r2d2_postgres",
@ -1384,24 +1368,6 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "native-tls"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d"
dependencies = [
"lazy_static",
"libc",
"log",
"openssl",
"openssl-probe",
"openssl-sys",
"schannel",
"security-framework",
"security-framework-sys",
"tempfile",
]
[[package]] [[package]]
name = "net2" name = "net2"
version = "0.2.37" version = "0.2.37"
@ -1473,12 +1439,6 @@ dependencies = [
"openssl-sys", "openssl-sys",
] ]
[[package]]
name = "openssl-probe"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a"
[[package]] [[package]]
name = "openssl-sys" name = "openssl-sys"
version = "0.9.67" version = "0.9.67"
@ -1668,15 +1628,15 @@ dependencies = [
] ]
[[package]] [[package]]
name = "postgres-native-tls" name = "postgres-openssl"
version = "0.5.0" version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d442770e2b1e244bb5eb03b31c79b65bb2568f413b899eaba850fa945a65954" checksum = "1de0ea6504e07ca78355a6fb88ad0f36cafe9e696cbc6717f16a207f3a60be72"
dependencies = [ dependencies = [
"futures", "futures",
"native-tls", "openssl",
"tokio 1.12.0", "tokio 1.12.0",
"tokio-native-tls", "tokio-openssl",
"tokio-postgres", "tokio-postgres",
] ]
@ -1914,15 +1874,6 @@ version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b" checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "remove_dir_all"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7"
dependencies = [
"winapi 0.3.9",
]
[[package]] [[package]]
name = "resolv-conf" name = "resolv-conf"
version = "0.7.0" version = "0.7.0"
@ -1975,16 +1926,6 @@ dependencies = [
"winapi-util", "winapi-util",
] ]
[[package]]
name = "schannel"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75"
dependencies = [
"lazy_static",
"winapi 0.3.9",
]
[[package]] [[package]]
name = "scheduled-thread-pool" name = "scheduled-thread-pool"
version = "0.2.5" version = "0.2.5"
@ -2000,29 +1941,6 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "security-framework"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87"
dependencies = [
"bitflags",
"core-foundation",
"core-foundation-sys",
"libc",
"security-framework-sys",
]
[[package]]
name = "security-framework-sys"
version = "2.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e"
dependencies = [
"core-foundation-sys",
"libc",
]
[[package]] [[package]]
name = "semver" name = "semver"
version = "0.9.0" version = "0.9.0"
@ -2298,20 +2216,6 @@ dependencies = [
"unicode-xid", "unicode-xid",
] ]
[[package]]
name = "tempfile"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [
"cfg-if 1.0.0",
"libc",
"rand 0.8.4",
"redox_syscall",
"remove_dir_all",
"winapi 0.3.9",
]
[[package]] [[package]]
name = "termcolor" name = "termcolor"
version = "1.1.2" version = "1.1.2"
@ -2469,12 +2373,14 @@ dependencies = [
] ]
[[package]] [[package]]
name = "tokio-native-tls" name = "tokio-openssl"
version = "0.3.0" version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" checksum = "f24cddc8445a4dc8359cdd9e91c19d544fc95f672e32afe8945852b9381a09fe"
dependencies = [ dependencies = [
"native-tls", "futures",
"openssl",
"openssl-sys",
"tokio 1.12.0", "tokio 1.12.0",
] ]

View File

@ -24,12 +24,12 @@ docopt = "1"
env_logger = "0.9" env_logger = "0.9"
itertools = "0.10" itertools = "0.10"
log = "0.4" log = "0.4"
native-tls = "0.2"
num_cpus = "1.13" num_cpus = "1.13"
postgres = { version = "0.19.1", features = ["with-time-0_2", "with-uuid-0_8", "with-serde_json-1"] } openssl = "0.10.36"
postgres-native-tls = "0.5.0"
postgres-protocol = "0.6.2"
postgis = "0.9.0" postgis = "0.9.0"
postgres = { version = "0.19.1", features = ["with-time-0_2", "with-uuid-0_8", "with-serde_json-1"] }
postgres-openssl = "0.5.0"
postgres-protocol = "0.6.2"
r2d2 = "0.8" r2d2 = "0.8"
r2d2_postgres = "0.18" r2d2_postgres = "0.18"
semver = "1.0" semver = "1.0"

View File

@ -366,6 +366,7 @@ Options:
--pool-size=<n> Maximum connections pool size [default: 20]. --pool-size=<n> Maximum connections pool size [default: 20].
--watch Scan for new sources on sources list requests. --watch Scan for new sources on sources list requests.
--workers=<n> Number of web server workers. --workers=<n> Number of web server workers.
--ca-root-file=<path> Loads trusted root certificates from a file. The file should contain a sequence of PEM-formatted CA certificates.
--danger-accept-invalid-certs Trust invalid certificates. This introduces significant vulnerabilities, and should only be used as a last resort. --danger-accept-invalid-certs Trust invalid certificates. This introduces significant vulnerabilities, and should only be used as a last resort.
``` ```
@ -373,11 +374,12 @@ Options:
You can also configure martin using environment variables You can also configure martin using environment variables
| Environment variable | Example | Description | | Environment variable | Example | Description |
| --------------------------- | -------------------------------- | ---------------------------- | | ----------------------------- | ---------------------------------- | --------------------------------------------- |
| DATABASE_URL | postgres://postgres@localhost/db | postgres database connection | | `DATABASE_URL` | `postgres://postgres@localhost/db` | Postgres database connection |
| WATCH_MODE | true | scan for new sources | | `WATCH_MODE` | `true` | Scan for new sources on sources list requests |
| DANGER_ACCEPT_INVALID_CERTS | false | Trust invalid certificates | | `CA_ROOT_FILE` | `./ca-certificate.crt` | Loads trusted root certificates from a file |
| `DANGER_ACCEPT_INVALID_CERTS` | `false` | Trust invalid certificates |
## Configuration File ## Configuration File

View File

@ -32,6 +32,7 @@ Options:
--pool-size=<n> Maximum connections pool size [default: 20]. --pool-size=<n> Maximum connections pool size [default: 20].
--watch Scan for new sources on sources list requests. --watch Scan for new sources on sources list requests.
--workers=<n> Number of web server workers. --workers=<n> Number of web server workers.
--ca-root-file=<path> Loads trusted root certificates from a file. The file should contain a sequence of PEM-formatted CA certificates.
--danger-accept-invalid-certs Trust invalid certificates. This introduces significant vulnerabilities, and should only be used as a last resort. --danger-accept-invalid-certs Trust invalid certificates. This introduces significant vulnerabilities, and should only be used as a last resort.
"; ";
@ -46,6 +47,7 @@ pub struct Args {
pub flag_watch: bool, pub flag_watch: bool,
pub flag_version: bool, pub flag_version: bool,
pub flag_workers: Option<usize>, pub flag_workers: Option<usize>,
pub flag_ca_root_file: Option<String>,
pub flag_danger_accept_invalid_certs: bool, pub flag_danger_accept_invalid_certs: bool,
} }
@ -70,6 +72,7 @@ pub fn generate_config(args: Args, pool: &Pool) -> io::Result<Config> {
worker_processes: args.flag_workers, worker_processes: args.flag_workers,
table_sources: Some(table_sources), table_sources: Some(table_sources),
function_sources: Some(function_sources), function_sources: Some(function_sources),
ca_root_file: None,
danger_accept_invalid_certs: Some(args.flag_danger_accept_invalid_certs), danger_accept_invalid_certs: Some(args.flag_danger_accept_invalid_certs),
}; };
@ -82,6 +85,7 @@ fn setup_from_config(file_name: String) -> io::Result<(Config, Pool)> {
let pool = setup_connection_pool( let pool = setup_connection_pool(
&config.connection_string, &config.connection_string,
&config.ca_root_file,
Some(config.pool_size), Some(config.pool_size),
config.danger_accept_invalid_certs, config.danger_accept_invalid_certs,
) )
@ -124,6 +128,7 @@ fn setup_from_args(args: Args) -> io::Result<(Config, Pool)> {
info!("Connecting to database"); info!("Connecting to database");
let pool = setup_connection_pool( let pool = setup_connection_pool(
&connection_string, &connection_string,
&args.flag_ca_root_file,
args.flag_pool_size, args.flag_pool_size,
args.flag_danger_accept_invalid_certs, args.flag_danger_accept_invalid_certs,
) )
@ -141,6 +146,10 @@ fn parse_env(args: Args) -> Args {
env::var_os("DATABASE_URL").and_then(|connection| connection.into_string().ok()) env::var_os("DATABASE_URL").and_then(|connection| connection.into_string().ok())
}); });
let flag_ca_root_file = args.flag_ca_root_file.or_else(|| {
env::var_os("CA_ROOT_FILE").and_then(|connection| connection.into_string().ok())
});
let flag_danger_accept_invalid_certs = args.flag_danger_accept_invalid_certs let flag_danger_accept_invalid_certs = args.flag_danger_accept_invalid_certs
|| env::var_os("DANGER_ACCEPT_INVALID_CERTS").is_some(); || env::var_os("DANGER_ACCEPT_INVALID_CERTS").is_some();
@ -149,6 +158,7 @@ fn parse_env(args: Args) -> Args {
Args { Args {
arg_connection, arg_connection,
flag_watch, flag_watch,
flag_ca_root_file,
flag_danger_accept_invalid_certs, flag_danger_accept_invalid_certs,
..args ..args
} }

View File

@ -17,6 +17,7 @@ pub struct Config {
pub connection_string: String, pub connection_string: String,
pub table_sources: Option<TableSources>, pub table_sources: Option<TableSources>,
pub function_sources: Option<FunctionSources>, pub function_sources: Option<FunctionSources>,
pub ca_root_file: Option<String>,
pub danger_accept_invalid_certs: bool, pub danger_accept_invalid_certs: bool,
} }
@ -30,6 +31,7 @@ pub struct ConfigBuilder {
pub connection_string: String, pub connection_string: String,
pub table_sources: Option<TableSources>, pub table_sources: Option<TableSources>,
pub function_sources: Option<FunctionSources>, pub function_sources: Option<FunctionSources>,
pub ca_root_file: Option<String>,
pub danger_accept_invalid_certs: Option<bool>, pub danger_accept_invalid_certs: Option<bool>,
} }
@ -46,6 +48,7 @@ impl ConfigBuilder {
connection_string: self.connection_string, connection_string: self.connection_string,
table_sources: self.table_sources, table_sources: self.table_sources,
function_sources: self.function_sources, function_sources: self.function_sources,
ca_root_file: self.ca_root_file,
danger_accept_invalid_certs: self.danger_accept_invalid_certs.unwrap_or(false), danger_accept_invalid_certs: self.danger_accept_invalid_certs.unwrap_or(false),
} }
} }

View File

@ -1,8 +1,8 @@
use std::io; use std::io;
use std::str::FromStr; use std::str::FromStr;
use native_tls::TlsConnector; use openssl::ssl::{SslConnector, SslMethod, SslVerifyMode};
use postgres_native_tls::MakeTlsConnector; use postgres_openssl::MakeTlsConnector;
use r2d2::PooledConnection; use r2d2::PooledConnection;
use r2d2_postgres::PostgresConnectionManager; use r2d2_postgres::PostgresConnectionManager;
use semver::Version; use semver::Version;
@ -14,25 +14,37 @@ pub type ConnectionManager = PostgresConnectionManager<MakeTlsConnector>;
pub type Pool = r2d2::Pool<ConnectionManager>; pub type Pool = r2d2::Pool<ConnectionManager>;
pub type Connection = PooledConnection<ConnectionManager>; pub type Connection = PooledConnection<ConnectionManager>;
fn make_tls_connector(danger_accept_invalid_certs: bool) -> io::Result<MakeTlsConnector> { fn make_tls_connector(
let connector = TlsConnector::builder() ca_root_file: &Option<String>,
.danger_accept_invalid_certs(danger_accept_invalid_certs) danger_accept_invalid_certs: bool,
.build() ) -> io::Result<MakeTlsConnector> {
.map_err(prettify_error("Can't build TLS connection".to_owned()))?; let mut builder = SslConnector::builder(SslMethod::tls())?;
let tls_connector = MakeTlsConnector::new(connector); if danger_accept_invalid_certs {
builder.set_verify(SslVerifyMode::NONE);
}
if let Some(ca_root_file) = ca_root_file {
info!("Using {} as trusted root certificate", ca_root_file);
builder.set_ca_file(ca_root_file)?;
}
let tls_connector = MakeTlsConnector::new(builder.build());
Ok(tls_connector) Ok(tls_connector)
} }
pub fn setup_connection_pool( pub fn setup_connection_pool(
cn_str: &str, connection_string: &str,
ca_root_file: &Option<String>,
pool_size: Option<u32>, pool_size: Option<u32>,
danger_accept_invalid_certs: bool, danger_accept_invalid_certs: bool,
) -> io::Result<Pool> { ) -> io::Result<Pool> {
let config = postgres::config::Config::from_str(cn_str) let config = postgres::config::Config::from_str(connection_string)
.map_err(prettify_error("Can't parse connection string".to_owned()))?; .map_err(prettify_error("Can't parse connection string".to_owned()))?;
let tls_connector = make_tls_connector(danger_accept_invalid_certs)?; let tls_connector = make_tls_connector(ca_root_file, danger_accept_invalid_certs)
.map_err(prettify_error("Can't build TLS connection".to_owned()))?;
let manager = PostgresConnectionManager::new(config, tls_connector); let manager = PostgresConnectionManager::new(config, tls_connector);
let pool = r2d2::Pool::builder() let pool = r2d2::Pool::builder()

View File

@ -128,7 +128,7 @@ pub fn make_pool() -> Pool {
let connection_string: String = env::var("DATABASE_URL").unwrap(); let connection_string: String = env::var("DATABASE_URL").unwrap();
info!("Connecting to {}", connection_string); info!("Connecting to {}", connection_string);
let pool = setup_connection_pool(&connection_string, Some(1), false).unwrap(); let pool = setup_connection_pool(&connection_string, &None, Some(1), false).unwrap();
info!("Connected to {}", connection_string); info!("Connected to {}", connection_string);
pool pool