From 93469a6e841d6aa98b111cabae902d6cc1fe9d7d Mon Sep 17 00:00:00 2001 From: h7x4 Date: Mon, 19 Aug 2024 00:11:11 +0200 Subject: [PATCH] Add more serverside logging --- src/server/config.rs | 7 +- src/server/sql/database_operations.rs | 34 +++++++- .../sql/database_privilege_operations.rs | 47 +++++++++-- src/server/sql/user_operations.rs | 78 ++++++++++++++++--- 4 files changed, 143 insertions(+), 23 deletions(-) diff --git a/src/server/config.rs b/src/server/config.rs index 7417b0d..e3639ca 100644 --- a/src/server/config.rs +++ b/src/server/config.rs @@ -102,8 +102,11 @@ pub async fn create_mysql_connection_from_config( config: &MysqlConfig, ) -> anyhow::Result { let mut display_config = config.clone(); - display_config.password = "".to_owned(); - log::debug!("Connecting to MySQL server with parameters: {:#?}", display_config); + "".clone_into(&mut display_config.password); + log::debug!( + "Connecting to MySQL server with parameters: {:#?}", + display_config + ); match tokio::time::timeout( Duration::from_secs(config.timeout.unwrap_or(DEFAULT_TIMEOUT)), diff --git a/src/server/sql/database_operations.rs b/src/server/sql/database_operations.rs index 9ddddda..2af32f5 100644 --- a/src/server/sql/database_operations.rs +++ b/src/server/sql/database_operations.rs @@ -26,9 +26,17 @@ pub(super) async fn unsafe_database_exists( sqlx::query("SELECT SCHEMA_NAME FROM information_schema.SCHEMATA WHERE SCHEMA_NAME = ?") .bind(database_name) .fetch_optional(connection) - .await?; + .await; - Ok(result.is_some()) + if let Err(err) = &result { + log::error!( + "Failed to check if database '{}' exists: {:?}", + &database_name, + err + ); + } + + Ok(result?.is_some()) } pub async fn create_databases( @@ -80,6 +88,10 @@ pub async fn create_databases( .map(|_| ()) .map_err(|err| CreateDatabaseError::MySqlError(err.to_string())); + if let Err(err) = &result { + log::error!("Failed to create database '{}': {:?}", &database_name, err); + } + results.insert(database_name, result); } @@ -135,6 +147,10 @@ pub async fn drop_databases( .map(|_| ()) .map_err(|err| DropDatabaseError::MySqlError(err.to_string())); + if let Err(err) = &result { + log::error!("Failed to drop database '{}': {:?}", &database_name, err); + } + results.insert(database_name, result); } @@ -145,7 +161,7 @@ pub async fn list_databases_for_user( unix_user: &UnixUser, connection: &mut MySqlConnection, ) -> Result, ListDatabasesError> { - sqlx::query( + let result = sqlx::query( r#" SELECT `SCHEMA_NAME` AS `database` FROM `information_schema`.`SCHEMATA` @@ -161,5 +177,15 @@ pub async fn list_databases_for_user( .map(|row| row.try_get::("database")) .collect::, sqlx::Error>>() }) - .map_err(|err| ListDatabasesError::MySqlError(err.to_string())) + .map_err(|err| ListDatabasesError::MySqlError(err.to_string())); + + if let Err(err) = &result { + log::error!( + "Failed to list databases for user '{}': {:?}", + unix_user.username, + err + ); + } + + result } diff --git a/src/server/sql/database_privilege_operations.rs b/src/server/sql/database_privilege_operations.rs index b5ba9a0..ec6b776 100644 --- a/src/server/sql/database_privilege_operations.rs +++ b/src/server/sql/database_privilege_operations.rs @@ -136,7 +136,7 @@ async fn unsafe_get_database_privileges( database_name: &str, connection: &mut MySqlConnection, ) -> Result, sqlx::Error> { - sqlx::query_as::<_, DatabasePrivilegeRow>(&format!( + let result = sqlx::query_as::<_, DatabasePrivilegeRow>(&format!( "SELECT {} FROM `db` WHERE `db` = ?", DATABASE_PRIVILEGE_FIELDS .iter() @@ -145,7 +145,17 @@ async fn unsafe_get_database_privileges( )) .bind(database_name) .fetch_all(connection) - .await + .await; + + if let Err(e) = &result { + log::error!( + "Failed to get database privileges for '{}': {}", + &database_name, + e + ); + } + + result } // NOTE: this function is unsafe because it does no input validation. @@ -155,7 +165,7 @@ pub async fn unsafe_get_database_privileges_for_db_user_pair( user_name: &str, connection: &mut MySqlConnection, ) -> Result, sqlx::Error> { - sqlx::query_as::<_, DatabasePrivilegeRow>(&format!( + let result = sqlx::query_as::<_, DatabasePrivilegeRow>(&format!( "SELECT {} FROM `db` WHERE `db` = ? AND `user` = ?", DATABASE_PRIVILEGE_FIELDS .iter() @@ -165,7 +175,18 @@ pub async fn unsafe_get_database_privileges_for_db_user_pair( .bind(database_name) .bind(user_name) .fetch_optional(connection) - .await + .await; + + if let Err(e) = &result { + log::error!( + "Failed to get database privileges for '{}.{}': {}", + &database_name, + &user_name, + e + ); + } + + result } pub async fn get_databases_privilege_data( @@ -220,7 +241,7 @@ pub async fn get_all_database_privileges( unix_user: &UnixUser, connection: &mut MySqlConnection, ) -> GetAllDatabasesPrivilegeData { - sqlx::query_as::<_, DatabasePrivilegeRow>(&format!( + let result = sqlx::query_as::<_, DatabasePrivilegeRow>(&format!( indoc! {r#" SELECT {} FROM `db` WHERE `db` IN (SELECT DISTINCT `SCHEMA_NAME` AS `database` @@ -236,14 +257,20 @@ pub async fn get_all_database_privileges( .bind(create_user_group_matching_regex(unix_user)) .fetch_all(connection) .await - .map_err(|e| GetAllDatabasesPrivilegeDataError::MySqlError(e.to_string())) + .map_err(|e| GetAllDatabasesPrivilegeDataError::MySqlError(e.to_string())); + + if let Err(e) = &result { + log::error!("Failed to get all database privileges: {:?}", e); + } + + result } async fn unsafe_apply_privilege_diff( database_privilege_diff: &DatabasePrivilegesDiff, connection: &mut MySqlConnection, ) -> Result<(), sqlx::Error> { - match database_privilege_diff { + let result = match database_privilege_diff { DatabasePrivilegesDiff::New(p) => { let tables = DATABASE_PRIVILEGE_FIELDS .iter() @@ -305,7 +332,13 @@ async fn unsafe_apply_privilege_diff( .await .map(|_| ()) } + }; + + if let Err(e) = &result { + log::error!("Failed to apply database privilege diff: {}", e); } + + result } async fn validate_diff( diff --git a/src/server/sql/user_operations.rs b/src/server/sql/user_operations.rs index 01e0c00..06da219 100644 --- a/src/server/sql/user_operations.rs +++ b/src/server/sql/user_operations.rs @@ -1,6 +1,6 @@ +use indoc::formatdoc; use itertools::Itertools; use std::collections::BTreeMap; -use indoc::formatdoc; use serde::{Deserialize, Serialize}; @@ -29,7 +29,7 @@ async fn unsafe_user_exists( db_user: &str, connection: &mut MySqlConnection, ) -> Result { - sqlx::query( + let result = sqlx::query( r#" SELECT EXISTS( SELECT 1 @@ -41,7 +41,13 @@ async fn unsafe_user_exists( .bind(db_user) .fetch_one(connection) .await - .map(|row| row.get::(0)) + .map(|row| row.get::(0)); + + if let Err(err) = &result { + log::error!("Failed to check if database user exists: {:?}", err); + } + + result } pub async fn create_database_users( @@ -80,6 +86,10 @@ pub async fn create_database_users( .map(|_| ()) .map_err(|err| CreateUserError::MySqlError(err.to_string())); + if let Err(err) = &result { + log::error!("Failed to create database user '{}': {:?}", &db_user, err); + } + results.insert(db_user, result); } @@ -122,6 +132,10 @@ pub async fn drop_database_users( .map(|_| ()) .map_err(|err| DropUserError::MySqlError(err.to_string())); + if let Err(err) = &result { + log::error!("Failed to drop database user '{}': {:?}", &db_user, err); + } + results.insert(db_user, result); } @@ -148,7 +162,7 @@ pub async fn set_password_for_database_user( _ => {} } - sqlx::query( + let result = sqlx::query( format!( "ALTER USER {}@'%' IDENTIFIED BY {}", quote_literal(db_user), @@ -159,7 +173,17 @@ pub async fn set_password_for_database_user( .execute(&mut *connection) .await .map(|_| ()) - .map_err(|err| SetPasswordError::MySqlError(err.to_string())) + .map_err(|err| SetPasswordError::MySqlError(err.to_string())); + + if let Err(err) = &result { + log::error!( + "Failed to set password for database user '{}': {:?}", + &db_user, + err + ); + } + + result } // NOTE: this function is unsafe because it does no input validation. @@ -167,7 +191,7 @@ async fn database_user_is_locked_unsafe( db_user: &str, connection: &mut MySqlConnection, ) -> Result { - sqlx::query( + let result = sqlx::query( r#" SELECT COALESCE( JSON_EXTRACT(`mysql`.`global_priv`.`priv`, "$.account_locked"), @@ -181,7 +205,17 @@ async fn database_user_is_locked_unsafe( .bind(db_user) .fetch_one(connection) .await - .map(|row| row.get::(0)) + .map(|row| row.get::(0)); + + if let Err(err) = &result { + log::error!( + "Failed to check if database user is locked '{}': {:?}", + &db_user, + err + ); + } + + result } pub async fn lock_database_users( @@ -234,6 +268,10 @@ pub async fn lock_database_users( .map(|_| ()) .map_err(|err| LockUserError::MySqlError(err.to_string())); + if let Err(err) = &result { + log::error!("Failed to lock database user '{}': {:?}", &db_user, err); + } + results.insert(db_user, result); } @@ -290,6 +328,10 @@ pub async fn unlock_database_users( .map(|_| ()) .map_err(|err| UnlockUserError::MySqlError(err.to_string())); + if let Err(err) = &result { + log::error!("Failed to unlock database user '{}': {:?}", &db_user, err); + } + results.insert(db_user, result); } @@ -374,6 +416,10 @@ pub async fn list_database_users( .fetch_optional(&mut *connection) .await; + if let Err(err) = &result { + log::error!("Failed to list database user '{}': {:?}", &db_user, err); + } + if let Ok(Some(user)) = result.as_mut() { append_databases_where_user_has_privileges(user, &mut *connection).await; } @@ -400,6 +446,10 @@ pub async fn list_all_database_users_for_unix_user( .await .map_err(|err| ListAllUsersError::MySqlError(err.to_string())); + if let Err(err) = &result { + log::error!("Failed to list all database users: {:?}", err); + } + if let Ok(users) = result.as_mut() { for user in users { append_databases_where_user_has_privileges(user, &mut *connection).await; @@ -410,7 +460,7 @@ pub async fn list_all_database_users_for_unix_user( } pub async fn append_databases_where_user_has_privileges( - database_user: &mut DatabaseUser, + db_user: &mut DatabaseUser, connection: &mut MySqlConnection, ) { let database_list = sqlx::query( @@ -427,11 +477,19 @@ pub async fn append_databases_where_user_has_privileges( ) .as_str(), ) - .bind(database_user.user.clone()) + .bind(db_user.user.clone()) .fetch_all(&mut *connection) .await; - database_user.databases = database_list + if let Err(err) = &database_list { + log::error!( + "Failed to list databases for user '{}': {:?}", + &db_user.user, + err + ); + } + + db_user.databases = database_list .map(|rows| { rows.into_iter() .map(|row| try_get_with_binary_fallback(&row, "database").unwrap())