LCOV - code coverage report
Current view: top level - proxy/src/auth/backend - classic.rs (source / functions) Coverage Total Hit
Test: 20b6afc7b7f34578dcaab2b3acdaecfe91cd8bf1.info Lines: 75.5 % 53 40
Test Date: 2024-11-25 17:48:16 Functions: 12.5 % 24 3

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

Generated by: LCOV version 2.1-beta