feat(secret): hide db password

This commit is contained in:
Kristofers Solo 2024-03-24 15:17:19 +02:00
parent f814772599
commit 9ef6b9430c
5 changed files with 35 additions and 20 deletions

11
Cargo.lock generated
View File

@ -1653,6 +1653,16 @@ dependencies = [
"untrusted", "untrusted",
] ]
[[package]]
name = "secrecy"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9bd1c54ea06cfd2f6b63219704de0b9b4f72dcc2b8fdef820be6cd799780e91e"
dependencies = [
"serde",
"zeroize",
]
[[package]] [[package]]
name = "security-framework" name = "security-framework"
version = "2.9.2" version = "2.9.2"
@ -2867,6 +2877,7 @@ dependencies = [
"config", "config",
"once_cell", "once_cell",
"reqwest", "reqwest",
"secrecy",
"serde", "serde",
"sqlx", "sqlx",
"tokio", "tokio",

View File

@ -34,6 +34,7 @@ tracing-subscriber = { version = "0.3", features = ["registry", "env-filter"] }
tower-http = { version = "0.5", features = ["trace"] } tower-http = { version = "0.5", features = ["trace"] }
tracing-bunyan-formatter = "0.3" tracing-bunyan-formatter = "0.3"
tracing-log = "0.2" tracing-log = "0.2"
secrecy = { version = "0.8", features = ["serde"] }
[dev-dependencies] [dev-dependencies]
reqwest = "0.12" reqwest = "0.12"

View File

@ -1,5 +1,4 @@
use std::fmt::Display; use secrecy::{ExposeSecret, Secret};
use serde::Deserialize; use serde::Deserialize;
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
@ -11,28 +10,31 @@ pub struct Settings {
#[derive(Debug, Deserialize)] #[derive(Debug, Deserialize)]
pub struct DatabaseSettings { pub struct DatabaseSettings {
pub username: String, pub username: String,
pub password: String, pub password: Secret<String>,
pub port: u16, pub port: u16,
pub host: String, pub host: String,
pub database_name: String, pub database_name: String,
} }
impl DatabaseSettings { impl DatabaseSettings {
pub fn to_string_no_db(&self) -> String { pub fn to_string_no_db(&self) -> Secret<String> {
format!( Secret::new(format!(
"postgres://{}:{}@{}:{}", "postgres://{}:{}@{}:{}",
self.username, self.password, self.host, self.port self.username,
) self.password.expose_secret(),
self.host,
self.port
))
} }
} pub fn to_string(&self) -> Secret<String> {
Secret::new(format!(
impl Display for DatabaseSettings {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"postgres://{}:{}@{}:{}/{}", "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
))
} }
} }

View File

@ -1,5 +1,6 @@
use std::net::SocketAddr; use std::net::SocketAddr;
use secrecy::ExposeSecret;
use sqlx::postgres::PgPoolOptions; use sqlx::postgres::PgPoolOptions;
use tokio::net::TcpListener; use tokio::net::TcpListener;
use zero2prod::{ use zero2prod::{
@ -14,7 +15,7 @@ async fn main() -> Result<(), std::io::Error> {
init_subscriber(subscriber); init_subscriber(subscriber);
let configuation = get_configuration().expect("Failed to read configuation."); let configuation = get_configuration().expect("Failed to read configuation.");
let pool = PgPoolOptions::new() let pool = PgPoolOptions::new()
.connect(&configuation.database.to_string()) .connect(&configuation.database.to_string().expose_secret())
.await .await
.expect("Failed to connect to Postgres."); .expect("Failed to connect to Postgres.");
let addr = SocketAddr::from(([127, 0, 0, 1], configuation.application_port)); let addr = SocketAddr::from(([127, 0, 0, 1], configuation.application_port));

View File

@ -1,5 +1,6 @@
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use reqwest::Client; use reqwest::Client;
use secrecy::ExposeSecret;
use sqlx::{postgres::PgPoolOptions, Connection, Executor, PgConnection, PgPool}; use sqlx::{postgres::PgPoolOptions, Connection, Executor, PgConnection, PgPool};
use tokio::net::TcpListener; use tokio::net::TcpListener;
use uuid::Uuid; use uuid::Uuid;
@ -28,8 +29,7 @@ async fn health_check() {
async fn subscribe_returns_200_for_valid_form_data() { async fn subscribe_returns_200_for_valid_form_data() {
let app = spawn_app().await; let app = spawn_app().await;
let configuration = get_configuration().expect("Failed to read configuration."); let configuration = get_configuration().expect("Failed to read configuration.");
let db_url = configuration.database.to_string(); let mut connection = PgConnection::connect(&configuration.database.to_string().expose_secret())
let mut connection = PgConnection::connect(&db_url)
.await .await
.expect("Failed to connect to Postgres."); .expect("Failed to connect to Postgres.");
let client = Client::new(); let client = Client::new();
@ -120,7 +120,7 @@ async fn spawn_app() -> TestApp {
} }
async fn configure_database(config: &DatabaseSettings) -> PgPool { async fn configure_database(config: &DatabaseSettings) -> PgPool {
let mut connection = PgConnection::connect(&config.to_string_no_db()) let mut connection = PgConnection::connect(&config.to_string_no_db().expose_secret())
.await .await
.expect("Failed to connect to Postgres."); .expect("Failed to connect to Postgres.");
@ -138,7 +138,7 @@ async fn configure_database(config: &DatabaseSettings) -> PgPool {
.expect("Failed to create database."); .expect("Failed to create database.");
let pool = PgPoolOptions::new() let pool = PgPoolOptions::new()
.connect(&config.to_string()) .connect(&config.to_string().expose_secret())
.await .await
.expect("Failed to connect to Postgres."); .expect("Failed to connect to Postgres.");