diff --git a/configuration/local.yaml b/configuration/local.yaml index c464c2f..8fd67fa 100644 --- a/configuration/local.yaml +++ b/configuration/local.yaml @@ -1,2 +1,4 @@ application: host: 127.0.0.1 +database: + require_ssl: false diff --git a/configuration/production.yaml b/configuration/production.yaml index b936a88..cd4608a 100644 --- a/configuration/production.yaml +++ b/configuration/production.yaml @@ -1,2 +1,4 @@ application: host: 0.0.0.0 +database: + require_ssl: true diff --git a/src/configuration.rs b/src/configuration.rs index 3f419b7..492c126 100644 --- a/src/configuration.rs +++ b/src/configuration.rs @@ -1,5 +1,8 @@ use secrecy::{ExposeSecret, Secret}; use serde_aux::field_attributes::deserialize_number_from_string; +use sqlx::postgres::PgConnectOptions; +use sqlx::postgres::PgSslMode; +use sqlx::ConnectOptions; #[derive(serde::Deserialize)] /// The setting collection. @@ -102,24 +105,24 @@ pub fn get_configuration() -> Result { } impl DatabaseSettings { - pub fn connection_string(&self) -> Secret { - Secret::new(format!( - "postgres://{}:{}@{}:{}/{}", - self.username, - self.password.expose_secret(), - self.host, - self.port, - self.name - )) + pub fn without_db(&self) -> PgConnectOptions { + let ssl_mode = if self.require_ssl { + PgSslMode::Require + } else { + // Try an encrypted connection, fallback to unencrypted if it fails + PgSslMode::Prefer + }; + PgConnectOptions::new() + .host(&self.host) + .username(&self.username) + .password(self.password.expose_secret()) + .port(self.port) + .ssl_mode(ssl_mode) } - pub fn connection_string_without_db(&self) -> Secret { - Secret::new(format!( - "postgres://{}:{}@{}:{}", - self.username, - self.password.expose_secret(), - self.host, - self.port - )) + pub fn with_db(&self) -> PgConnectOptions { + let mut options = self.without_db().database(&self.name); + options = options.log_statements(tracing::log::LevelFilter::Trace); + options } } diff --git a/src/main.rs b/src/main.rs index 5cc7ded..1dd1322 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ use learn_axum::configuration::get_configuration; use learn_axum::startup; use learn_axum::telemetry::{get_subscriber, init_subscriber}; -use secrecy::ExposeSecret; use sqlx::postgres::PgPoolOptions; use tokio::net::TcpListener; @@ -20,7 +19,6 @@ async fn main() { let listener = TcpListener::bind(addr).await.unwrap(); //.expect("Unable to bind to port"); let connection_pool = PgPoolOptions::new() .acquire_timeout(std::time::Duration::from_secs(2)) - .connect_lazy(configuration.database.connection_string().expose_secret()) - .expect("Failed to connect to Postgres."); + .connect_lazy_with(configuration.database.with_db()); startup::run(listener, connection_pool).await.unwrap(); } diff --git a/tests/health_check.rs b/tests/health_check.rs index c23b603..42d405c 100644 --- a/tests/health_check.rs +++ b/tests/health_check.rs @@ -1,7 +1,6 @@ use learn_axum::configuration::{get_configuration, DatabaseSettings}; use learn_axum::telemetry::{get_subscriber, init_subscriber}; use once_cell::sync::Lazy; -use secrecy::ExposeSecret; use sqlx::{Connection, Executor, PgConnection, PgPool}; use tokio::net::TcpListener; use uuid::Uuid; @@ -129,17 +128,16 @@ async fn spawn_app() -> TestApp { pub async fn configure_database(config: &DatabaseSettings) -> PgPool { // Create database - let mut connection = - PgConnection::connect(&config.connection_string_without_db().expose_secret()) - .await - .expect("Failed to connect to Postgres"); + let mut connection = PgConnection::connect_with(&config.without_db()) + .await + .expect("Failed to connect to Postgres"); connection .execute(format!(r#"CREATE DATABASE "{}";"#, config.name).as_str()) .await .expect("Failed to create database."); // Migrate database - let connection_pool = PgPool::connect(&config.connection_string().expose_secret()) + let connection_pool = PgPool::connect_with(config.with_db()) .await .expect("Failed to connect to Postgres."); sqlx::migrate!("./migrations")