From 49b92cde7a2dc94a200c31c236549d3891ec02c7 Mon Sep 17 00:00:00 2001 From: Eugene Pankov Date: Tue, 8 Aug 2023 09:39:22 +0200 Subject: [PATCH] fixed #855 - log client IPs and credentials used --- warpgate-common/src/auth/cred.rs | 10 ++++++++++ warpgate-common/src/auth/state.rs | 18 +++++++++++++++--- warpgate-protocol-http/src/common.rs | 1 - warpgate-protocol-http/src/logging.rs | 10 ++++++++-- warpgate-protocol-mysql/src/lib.rs | 4 ++-- warpgate-protocol-mysql/src/session.rs | 15 +++++++++------ warpgate-protocol-ssh/src/server/session.rs | 9 +++++---- 7 files changed, 49 insertions(+), 18 deletions(-) diff --git a/warpgate-common/src/auth/cred.rs b/warpgate-common/src/auth/cred.rs index 68ecfb1..0b3d8f8 100644 --- a/warpgate-common/src/auth/cred.rs +++ b/warpgate-common/src/auth/cred.rs @@ -43,4 +43,14 @@ impl AuthCredential { Self::WebUserApproval => CredentialKind::WebUserApproval, } } + + pub fn safe_description(&self) -> String { + match self { + Self::Password { .. } => "password".to_string(), + Self::PublicKey { .. } => "public key".to_string(), + Self::Otp { .. } => "one-time password".to_string(), + Self::Sso { provider, .. } => format!("SSO ({provider})"), + Self::WebUserApproval => "in-browser auth".to_string(), + } + } } diff --git a/warpgate-common/src/auth/state.rs b/warpgate-common/src/auth/state.rs index 0fe7dc3..6fb6d51 100644 --- a/warpgate-common/src/auth/state.rs +++ b/warpgate-common/src/auth/state.rs @@ -2,6 +2,7 @@ use std::collections::HashSet; use chrono::{DateTime, Utc}; use rand::Rng; +use tracing::info; use uuid::Uuid; use super::{AuthCredential, CredentialKind, CredentialPolicy, CredentialPolicyResponse}; @@ -96,9 +97,20 @@ impl AuthState { .policy .is_sufficient(&self.protocol, &self.valid_credentials[..]) { - CredentialPolicyResponse::Ok => AuthResult::Accepted { - username: self.username.clone(), - }, + CredentialPolicyResponse::Ok => { + info!( + username=%self.username, + credentials=%self.valid_credentials + .iter() + .map(|x| x.safe_description()) + .collect::>() + .join(", "), + "Authenticated", + ); + AuthResult::Accepted { + username: self.username.clone(), + } + } CredentialPolicyResponse::Need(kinds) => AuthResult::Need(kinds), } } diff --git a/warpgate-protocol-http/src/common.rs b/warpgate-protocol-http/src/common.rs index 325a842..8fa12bd 100644 --- a/warpgate-protocol-http/src/common.rs +++ b/warpgate-protocol-http/src/common.rs @@ -222,7 +222,6 @@ pub async fn authorize_session(req: &Request, username: String) -> poem::Result< .await .set_username(username.clone()) .await?; - info!(%username, "Authenticated"); session.set_auth(SessionAuthorization::User(username)); Ok(()) diff --git a/warpgate-protocol-http/src/logging.rs b/warpgate-protocol-http/src/logging.rs index a13b974..a0202c2 100644 --- a/warpgate-protocol-http/src/logging.rs +++ b/warpgate-protocol-http/src/logging.rs @@ -7,15 +7,21 @@ use crate::session_handle::WarpgateServerHandleFromRequest; pub async fn span_for_request(req: &Request) -> poem::Result { let handle = WarpgateServerHandleFromRequest::from_request_without_body(req).await; + let client_ip = req + .remote_addr() + .as_socket_addr() + .map(|x| x.ip().to_string()) + .unwrap_or("".into()); + Ok(match handle { Ok(ref handle) => { let handle = handle.lock().await; let ss = handle.session_state().lock().await; match { ss.username.clone() } { Some(ref username) => { - info_span!("HTTP", session=%handle.id(), session_username=%username) + info_span!("HTTP", session=%handle.id(), session_username=%username, %client_ip) } - None => info_span!("HTTP", session=%handle.id()), + None => info_span!("HTTP", session=%handle.id(), %client_ip), } } Err(_) => info_span!("HTTP"), diff --git a/warpgate-protocol-mysql/src/lib.rs b/warpgate-protocol-mysql/src/lib.rs index 63b0174..e976727 100644 --- a/warpgate-protocol-mysql/src/lib.rs +++ b/warpgate-protocol-mysql/src/lib.rs @@ -86,13 +86,13 @@ impl ProtocolServer for MySQLProtocolServer { .register_session( &crate::common::PROTOCOL_NAME, SessionStateInit { - remote_address: Some(remote_address), + remote_address: Some(remote_address.clone()), handle: Box::new(session_handle), }, ) .await?; - let session = MySqlSession::new(server_handle, services, stream, tls_config).await; + let session = MySqlSession::new(server_handle, services, stream, tls_config, remote_address).await; let span = session.make_logging_span(); tokio::select! { result = session.run().instrument(span) => match result { diff --git a/warpgate-protocol-mysql/src/session.rs b/warpgate-protocol-mysql/src/session.rs index 49366dc..2c6c6c6 100644 --- a/warpgate-protocol-mysql/src/session.rs +++ b/warpgate-protocol-mysql/src/session.rs @@ -1,3 +1,4 @@ +use std::net::SocketAddr; use std::sync::Arc; use bytes::{Buf, Bytes, BytesMut}; @@ -34,6 +35,7 @@ pub struct MySqlSession { server_handle: Arc>, id: Uuid, services: Services, + remote_address: SocketAddr, } impl MySqlSession { @@ -42,6 +44,7 @@ impl MySqlSession { services: Services, stream: TcpStream, tls_config: ServerConfig, + remote_address: SocketAddr, ) -> Self { let id = server_handle.lock().await.id(); Self { @@ -67,13 +70,17 @@ impl MySqlSession { database: None, server_handle, id, + remote_address, } } pub fn make_logging_span(&self) -> tracing::Span { + let client_ip = self.remote_address.ip().to_string(); match self.username { - Some(ref username) => info_span!("MySQL", session=%self.id, session_username=%username), - None => info_span!("MySQL", session=%self.id), + Some(ref username) => { + info_span!("MySQL", session=%self.id, session_username=%username, %client_ip) + } + None => info_span!("MySQL", session=%self.id, %client_ip), } } @@ -269,8 +276,6 @@ impl MySqlSession { )?; self.stream.flush().await?; - info!(%username, "Authenticated"); - let target = { self.services .config_provider @@ -307,9 +312,7 @@ impl MySqlSession { handle.set_target(&target).await?; } - let span = self.make_logging_span(); self.run_authorized_inner(handshake, mysql_options) - .instrument(span) .await } diff --git a/warpgate-protocol-ssh/src/server/session.rs b/warpgate-protocol-ssh/src/server/session.rs index 23a44da..a20f236 100644 --- a/warpgate-protocol-ssh/src/server/session.rs +++ b/warpgate-protocol-ssh/src/server/session.rs @@ -238,9 +238,12 @@ impl ServerSession { } pub fn make_logging_span(&self) -> tracing::Span { + let client_ip = self.remote_address.ip().to_string(); match self.username { - Some(ref username) => info_span!("SSH", session=%self.id, session_username=%username), - None => info_span!("SSH", session=%self.id), + Some(ref username) => { + info_span!("SSH", session=%self.id, session_username=%username, %client_ip) + } + None => info_span!("SSH", session=%self.id, %client_ip), } } @@ -1437,8 +1440,6 @@ impl ServerSession { username: &str, target_name: &str, ) -> Result<(), WarpgateError> { - info!(%username, "Authenticated"); - let _ = self .server_handle .lock()