diff --git a/proxy/src/auth/backend.rs b/proxy/src/auth/backend.rs index 5bc2f2ff65..4e9f4591ad 100644 --- a/proxy/src/auth/backend.rs +++ b/proxy/src/auth/backend.rs @@ -444,7 +444,7 @@ impl<'a> Backend<'a, ComputeUserInfoMaybeEndpoint, &()> { Self::Web(url, ()) => { info!("performing web authentication"); - let info = web::authenticate(ctx, &url, client).await?; + let info = web::authenticate(ctx, config, &url, client).await?; Backend::Web(url, info) } diff --git a/proxy/src/auth/backend/web.rs b/proxy/src/auth/backend/web.rs index 58a4bef62e..05f437355e 100644 --- a/proxy/src/auth/backend/web.rs +++ b/proxy/src/auth/backend/web.rs @@ -1,5 +1,6 @@ use crate::{ auth, compute, + config::AuthenticationConfig, console::{self, provider::NodeInfo}, context::RequestMonitoring, error::{ReportableError, UserFacingError}, @@ -58,6 +59,7 @@ pub(crate) fn new_psql_session_id() -> String { pub(super) async fn authenticate( ctx: &RequestMonitoring, + auth_config: &'static AuthenticationConfig, link_uri: &reqwest::Url, client: &mut PqStream, ) -> auth::Result { @@ -89,6 +91,14 @@ pub(super) async fn authenticate( info!(parent: &span, "waiting for console's reply..."); let db_info = waiter.await.map_err(WebAuthError::from)?; + if auth_config.ip_allowlist_check_enabled { + if let Some(allowed_ips) = &db_info.allowed_ips { + if !auth::check_peer_addr_is_in_list(&ctx.peer_addr(), allowed_ips) { + return Err(auth::AuthError::ip_address_not_allowed(ctx.peer_addr())); + } + } + } + client.write_message_noflush(&Be::NoticeResponse("Connecting to database."))?; // This config should be self-contained, because we won't diff --git a/proxy/src/console/messages.rs b/proxy/src/console/messages.rs index 9b66333cd4..85683acb82 100644 --- a/proxy/src/console/messages.rs +++ b/proxy/src/console/messages.rs @@ -284,6 +284,8 @@ pub(crate) struct DatabaseInfo { /// be inconvenient for debug with local PG instance. pub(crate) password: Option>, pub(crate) aux: MetricsAuxInfo, + #[serde(default)] + pub(crate) allowed_ips: Option>, } // Manually implement debug to omit sensitive info. @@ -294,6 +296,7 @@ impl fmt::Debug for DatabaseInfo { .field("port", &self.port) .field("dbname", &self.dbname) .field("user", &self.user) + .field("allowed_ips", &self.allowed_ips) .finish_non_exhaustive() } } @@ -432,6 +435,22 @@ mod tests { "aux": dummy_aux(), }))?; + // with allowed_ips + let dbinfo = serde_json::from_value::(json!({ + "host": "localhost", + "port": 5432, + "dbname": "postgres", + "user": "john_doe", + "password": "password", + "aux": dummy_aux(), + "allowed_ips": ["127.0.0.1"], + }))?; + + assert_eq!( + dbinfo.allowed_ips, + Some(vec![IpPattern::Single("127.0.0.1".parse()?)]) + ); + Ok(()) }