From 2c59e1aba6b36943ad6eb1f98dd657f694f55acd Mon Sep 17 00:00:00 2001 From: Jin Dong Date: Tue, 26 Mar 2024 22:26:05 -0700 Subject: [PATCH] ch4: wrap secret data with secrecy::Secret Signed-off-by: Jin Dong --- Cargo.lock | 11 +++++++++++ Cargo.toml | 3 ++- src/configuration.rs | 27 ++++++++++++++++++--------- src/main.rs | 8 +++++--- tests/health_check.rs | 10 ++++++---- 5 files changed, 42 insertions(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 2bd4678..c6e6405 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1931,6 +1931,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" @@ -3124,6 +3134,7 @@ dependencies = [ "log", "once_cell", "reqwest", + "secrecy", "serde", "sqlx", "tokio", diff --git a/Cargo.toml b/Cargo.toml index 95b42bf..cfcbe8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ actix-web = "4.5.1" chrono = { version = "0.4.35", default-features = false, features = ["clock"] } config = "0.14.0" log = "0.4.21" +secrecy = { version = "0.8.0", features = ["serde"] } serde = { version = "1.0.197", features = ["derive"] } tokio = { version = "1.36.0", features = ["macros", "rt-multi-thread"] } tracing = { version = "0.1.40", features = ["log"] } @@ -41,4 +42,4 @@ features = [ [dev-dependencies] reqwest = "0.12.1" -once_cell = "1" \ No newline at end of file +once_cell = "1" diff --git a/src/configuration.rs b/src/configuration.rs index c771c96..70992f2 100644 --- a/src/configuration.rs +++ b/src/configuration.rs @@ -1,3 +1,5 @@ +use secrecy::{ExposeSecret, Secret}; + #[derive(serde::Deserialize)] pub struct Settings { pub database: DatabseSettings, @@ -7,25 +9,32 @@ pub struct Settings { #[derive(serde::Deserialize)] pub struct DatabseSettings { pub username: String, - pub password: String, + pub password: Secret, pub host: String, pub port: u16, pub database_name: String, } impl DatabseSettings { - pub fn connection_string(&self) -> String { - format!( + pub fn connection_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 connection_string_without_db(&self) -> String { - format!( + pub fn connection_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 1f67df2..85b9450 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use secrecy::ExposeSecret; use sqlx::PgPool; use std::net::TcpListener; use zero2prod::configuration::get_configuration; @@ -12,9 +13,10 @@ async fn main() -> Result<(), std::io::Error> { let configuration = get_configuration().expect("Failed to read configuration"); let address = format!("127.0.0.1:{}", configuration.application_port); let listener = TcpListener::bind(address)?; - let connection_pool = PgPool::connect(&configuration.database.connection_string()) - .await - .expect("Failed to connect to Postgres."); + let connection_pool = + PgPool::connect(&configuration.database.connection_string().expose_secret()) + .await + .expect("Failed to connect to Postgres."); run(listener, connection_pool)?.await } diff --git a/tests/health_check.rs b/tests/health_check.rs index 9fc56eb..ac182fe 100644 --- a/tests/health_check.rs +++ b/tests/health_check.rs @@ -1,6 +1,7 @@ use std::net::TcpListener; use once_cell::sync::Lazy; +use secrecy::ExposeSecret; use sqlx::{Connection, Executor, PgConnection, PgPool}; use uuid::Uuid; use zero2prod::configuration::{get_configuration, DatabseSettings}; @@ -50,9 +51,10 @@ async fn spawn_app() -> TestApp { async fn configure_database(config: &DatabseSettings) -> PgPool { // Create database - let mut connection = PgConnection::connect(&config.connection_string_without_db()) - .await - .expect("Failed to connect to Postgres."); + let mut connection = + PgConnection::connect(&config.connection_string_without_db().expose_secret()) + .await + .expect("Failed to connect to Postgres."); // Migrate database connection @@ -60,7 +62,7 @@ async fn configure_database(config: &DatabseSettings) -> PgPool { .await .expect("Failed to create database."); - let connection_pool = PgPool::connect(&config.connection_string()) + let connection_pool = PgPool::connect(&config.connection_string().expose_secret()) .await .expect("Failed to connect to Postgres.");