TLA Line data Source code
1 : use super::{ComputeCredentials, ComputeUserInfo};
2 : use crate::{
3 : auth::{self, backend::ComputeCredentialKeys, AuthFlow},
4 : compute,
5 : config::AuthenticationConfig,
6 : console::AuthSecret,
7 : metrics::LatencyTimer,
8 : sasl,
9 : stream::{PqStream, Stream},
10 : };
11 : use tokio::io::{AsyncRead, AsyncWrite};
12 : use tracing::{info, warn};
13 :
14 CBC 36 : pub(super) async fn authenticate(
15 36 : creds: ComputeUserInfo,
16 36 : client: &mut PqStream<Stream<impl AsyncRead + AsyncWrite + Unpin>>,
17 36 : config: &'static AuthenticationConfig,
18 36 : latency_timer: &mut LatencyTimer,
19 36 : secret: AuthSecret,
20 36 : ) -> auth::Result<ComputeCredentials<ComputeCredentialKeys>> {
21 36 : let flow = AuthFlow::new(client);
22 36 : let scram_keys = match secret {
23 : #[cfg(feature = "testing")]
24 : AuthSecret::Md5(_) => {
25 UBC 0 : info!("auth endpoint chooses MD5");
26 0 : return Err(auth::AuthError::bad_auth_method("MD5"));
27 : }
28 CBC 36 : AuthSecret::Scram(secret) => {
29 36 : info!("auth endpoint chooses SCRAM");
30 36 : let scram = auth::Scram(&secret);
31 :
32 36 : let auth_outcome = tokio::time::timeout(
33 36 : config.scram_protocol_timeout,
34 36 : async {
35 36 : // pause the timer while we communicate with the client
36 36 : let _paused = latency_timer.pause();
37 36 :
38 36 : flow.begin(scram).await.map_err(|error| {
39 UBC 0 : warn!(?error, "error sending scram acknowledgement");
40 0 : error
41 CBC 68 : })?.authenticate().await.map_err(|error| {
42 UBC 0 : warn!(?error, "error processing scram messages");
43 0 : error
44 CBC 36 : })
45 36 : }
46 36 : )
47 68 : .await
48 36 : .map_err(|error| {
49 UBC 0 : warn!("error processing scram messages error = authentication timed out, execution time exeeded {} seconds", config.scram_protocol_timeout.as_secs());
50 0 : auth::io::Error::new(auth::io::ErrorKind::TimedOut, error)
51 CBC 36 : })??;
52 :
53 36 : let client_key = match auth_outcome {
54 33 : sasl::Outcome::Success(key) => key,
55 3 : sasl::Outcome::Failure(reason) => {
56 3 : info!("auth backend failed with an error: {reason}");
57 3 : return Err(auth::AuthError::auth_failed(&*creds.inner.user));
58 : }
59 : };
60 :
61 33 : compute::ScramKeys {
62 33 : client_key: client_key.as_bytes(),
63 33 : server_key: secret.server_key.as_bytes(),
64 33 : }
65 33 : }
66 33 : };
67 33 :
68 33 : Ok(ComputeCredentials {
69 33 : info: creds,
70 33 : keys: ComputeCredentialKeys::AuthKeys(tokio_postgres::config::AuthKeys::ScramSha256(
71 33 : scram_keys,
72 33 : )),
73 33 : })
74 36 : }
|