mirror of
https://github.com/neondatabase/neon.git
synced 2026-05-18 05:30:37 +00:00
## Problem 1. Hard to correlate startup parameters with the endpoint that provided them. 2. Some configurations are not needed in the `ProxyConfig` struct. ## Summary of changes Because of some borrow checker fun, I needed to switch to an interior-mutability implementation of our `RequestMonitoring` context system. Using https://docs.rs/try-lock/latest/try_lock/ as a cheap lock for such a use-case (needed to be thread safe). Removed the lock of each startup message, instead just logging only the startup params in a successful handshake. Also removed from values from `ProxyConfig` and kept as arguments. (needed for local-proxy config)
73 lines
2.5 KiB
Rust
73 lines
2.5 KiB
Rust
use super::{ComputeCredentials, ComputeUserInfo};
|
|
use crate::{
|
|
auth::{self, backend::ComputeCredentialKeys, AuthFlow},
|
|
compute,
|
|
config::AuthenticationConfig,
|
|
console::AuthSecret,
|
|
context::RequestMonitoring,
|
|
sasl,
|
|
stream::{PqStream, Stream},
|
|
};
|
|
use tokio::io::{AsyncRead, AsyncWrite};
|
|
use tracing::{info, warn};
|
|
|
|
pub(super) async fn authenticate(
|
|
ctx: &RequestMonitoring,
|
|
creds: ComputeUserInfo,
|
|
client: &mut PqStream<Stream<impl AsyncRead + AsyncWrite + Unpin>>,
|
|
config: &'static AuthenticationConfig,
|
|
secret: AuthSecret,
|
|
) -> auth::Result<ComputeCredentials> {
|
|
let flow = AuthFlow::new(client);
|
|
let scram_keys = match secret {
|
|
#[cfg(any(test, feature = "testing"))]
|
|
AuthSecret::Md5(_) => {
|
|
info!("auth endpoint chooses MD5");
|
|
return Err(auth::AuthError::bad_auth_method("MD5"));
|
|
}
|
|
AuthSecret::Scram(secret) => {
|
|
info!("auth endpoint chooses SCRAM");
|
|
let scram = auth::Scram(&secret, ctx);
|
|
|
|
let auth_outcome = tokio::time::timeout(
|
|
config.scram_protocol_timeout,
|
|
async {
|
|
|
|
flow.begin(scram).await.map_err(|error| {
|
|
warn!(?error, "error sending scram acknowledgement");
|
|
error
|
|
})?.authenticate().await.map_err(|error| {
|
|
warn!(?error, "error processing scram messages");
|
|
error
|
|
})
|
|
}
|
|
)
|
|
.await
|
|
.map_err(|e| {
|
|
warn!("error processing scram messages error = authentication timed out, execution time exceeded {} seconds", config.scram_protocol_timeout.as_secs());
|
|
auth::AuthError::user_timeout(e)
|
|
})??;
|
|
|
|
let client_key = match auth_outcome {
|
|
sasl::Outcome::Success(key) => key,
|
|
sasl::Outcome::Failure(reason) => {
|
|
info!("auth backend failed with an error: {reason}");
|
|
return Err(auth::AuthError::auth_failed(&*creds.user));
|
|
}
|
|
};
|
|
|
|
compute::ScramKeys {
|
|
client_key: client_key.as_bytes(),
|
|
server_key: secret.server_key.as_bytes(),
|
|
}
|
|
}
|
|
};
|
|
|
|
Ok(ComputeCredentials {
|
|
info: creds,
|
|
keys: ComputeCredentialKeys::AuthKeys(tokio_postgres::config::AuthKeys::ScramSha256(
|
|
scram_keys,
|
|
)),
|
|
})
|
|
}
|