From 7ea02d6ba6fa6f2756cb1c12df5a1e65a740f297 Mon Sep 17 00:00:00 2001 From: Yago Iglesias Date: Wed, 30 Aug 2023 13:07:05 +0200 Subject: [PATCH] feat: Wrap db password in a Secret --- Cargo.lock | 17 +++++++++++++++++ Cargo.toml | 1 + src/configurations.rs | 27 ++++++++++++++++++--------- src/main.rs | 12 +++++++++--- tests/health_check.rs | 10 ++++++---- 5 files changed, 51 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c474cee..e48ce96 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1589,6 +1589,16 @@ dependencies = [ "untrusted", ] +[[package]] +name = "secrecy" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e" +dependencies = [ + "serde", + "zeroize", +] + [[package]] name = "security-framework" version = "2.9.2" @@ -2469,6 +2479,7 @@ dependencies = [ "config", "once_cell", "reqwest", + "secrecy", "serde", "sqlx", "tokio", @@ -2479,6 +2490,12 @@ dependencies = [ "uuid", ] +[[package]] +name = "zeroize" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a0956f1ba7c7909bfb66c2e9e4124ab6f6482560f6628b5aaeba39207c9aad9" + [[package]] name = "zstd" version = "0.12.4" diff --git a/Cargo.toml b/Cargo.toml index 80604a1..7ed5e58 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,6 +25,7 @@ tracing-subscriber = { version = "0.3", features = ["registry", "env-filter"] } tracing-bunyan-formatter = "0.3" tracing-log = "0.1" once_cell = "1" +secrecy = { version = "0.8", features = ["serde"] } [dev-dependencies] reqwest = { version = "0.11", features = ["json"] } diff --git a/src/configurations.rs b/src/configurations.rs index e811b4a..3fd4c1e 100644 --- a/src/configurations.rs +++ b/src/configurations.rs @@ -1,3 +1,5 @@ +use secrecy::{ExposeSecret, Secret}; + #[derive(serde::Deserialize)] pub struct Settings { pub database: DatabaseSettings, @@ -7,25 +9,32 @@ pub struct Settings { #[derive(serde::Deserialize)] pub struct DatabaseSettings { pub username: String, - pub password: String, + pub password: Secret, pub port: u16, pub host: String, pub database_name: String, } impl DatabaseSettings { - pub fn get_connnection_string(&self) -> String { - format!( + pub fn get_connnection_string(&self) -> Secret { + Secret::new(format!( "postgres://{}:{}@{}:{}/{}", - self.username, self.password, self.host, self.port, self.database_name - ) + self.username, + self.password.expose_secret(), + self.host, + self.port, + self.database_name + )) } - pub fn get_connnection_string_without_db(&self) -> String { - format!( + pub fn get_connnection_string_without_db(&self) -> Secret { + Secret::new(format!( "postgres://{}:{}@{}:{}", - self.username, self.password, self.host, self.port - ) + self.username, + self.password.expose_secret(), + self.host, + self.port + )) } } diff --git a/src/main.rs b/src/main.rs index 432c7e1..3ebf8f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use secrecy::ExposeSecret; use sqlx::PgPool; use std::net::TcpListener; use tracing::subscriber::set_global_default; @@ -14,9 +15,14 @@ async fn main() -> Result<(), std::io::Error> { // We want to panic if we cannot read the configuration let configuration = get_configuration().expect("Failed to read configurations"); - let connection = PgPool::connect(&configuration.database.get_connnection_string()) - .await - .expect("Failed to connect to Postgresf"); + let connection = PgPool::connect( + &configuration + .database + .get_connnection_string() + .expose_secret(), + ) + .await + .expect("Failed to connect to Postgresf"); // Bind the TCP listener socket address with the configuration port let address = format!("127.0.0.1:{}", configuration.application_port); let listener = TcpListener::bind(address).expect("Failed to bind random port"); diff --git a/tests/health_check.rs b/tests/health_check.rs index d1e2955..7b35179 100644 --- a/tests/health_check.rs +++ b/tests/health_check.rs @@ -1,4 +1,5 @@ use once_cell::sync::Lazy; +use secrecy::ExposeSecret; use sqlx::{Connection, Executor, PgConnection, PgPool}; use std::net::TcpListener; use uuid::Uuid; @@ -53,16 +54,17 @@ async fn spawn_app() -> TestApp { /// This is important in order to avoid polluting an existing database with test data. pub async fn configure_database(config: &zero2prod::configurations::DatabaseSettings) -> PgPool { // Create database - let mut connection = PgConnection::connect(&config.get_connnection_string_without_db()) - .await - .expect("Failed to connect to Postgres"); + let mut connection = + PgConnection::connect(&config.get_connnection_string_without_db().expose_secret()) + .await + .expect("Failed to connect to Postgres"); connection .execute(format!(r#"CREATE DATABASE "{}";"#, config.database_name).as_str()) .await .expect("Failed to create database"); // Migrate database - let connection_pool = PgPool::connect(&config.get_connnection_string()) + let connection_pool = PgPool::connect(&config.get_connnection_string().expose_secret()) .await .expect("Failed to connect to Postgres"); sqlx::migrate!("./migrations")