LCOV - code coverage report
Current view: top level - proxy/src/auth/backend - hacks.rs (source / functions) Coverage Total Hit
Test: 32f4a56327bc9da697706839ed4836b2a00a408f.info Lines: 50.0 % 42 21
Test Date: 2024-02-07 07:37:29 Functions: 16.7 % 24 4

            Line data    Source code
       1              : use super::{
       2              :     ComputeCredentialKeys, ComputeCredentials, ComputeUserInfo, ComputeUserInfoNoEndpoint,
       3              : };
       4              : use crate::{
       5              :     auth::{self, AuthFlow},
       6              :     console::AuthSecret,
       7              :     metrics::LatencyTimer,
       8              :     sasl,
       9              :     stream::{self, Stream},
      10              : };
      11              : use tokio::io::{AsyncRead, AsyncWrite};
      12              : use tracing::{info, warn};
      13              : 
      14              : /// Compared to [SCRAM](crate::scram), cleartext password auth saves
      15              : /// one round trip and *expensive* computations (>= 4096 HMAC iterations).
      16              : /// These properties are benefical for serverless JS workers, so we
      17              : /// use this mechanism for websocket connections.
      18            0 : pub async fn authenticate_cleartext(
      19            0 :     info: ComputeUserInfo,
      20            0 :     client: &mut stream::PqStream<Stream<impl AsyncRead + AsyncWrite + Unpin>>,
      21            0 :     latency_timer: &mut LatencyTimer,
      22            0 :     secret: AuthSecret,
      23            0 : ) -> auth::Result<ComputeCredentials<ComputeCredentialKeys>> {
      24            0 :     warn!("cleartext auth flow override is enabled, proceeding");
      25              : 
      26              :     // pause the timer while we communicate with the client
      27            0 :     let _paused = latency_timer.pause();
      28              : 
      29            0 :     let auth_outcome = AuthFlow::new(client)
      30            0 :         .begin(auth::CleartextPassword(secret))
      31            0 :         .await?
      32            0 :         .authenticate()
      33            0 :         .await?;
      34              : 
      35            0 :     let keys = match auth_outcome {
      36            0 :         sasl::Outcome::Success(key) => key,
      37            0 :         sasl::Outcome::Failure(reason) => {
      38            0 :             info!("auth backend failed with an error: {reason}");
      39            0 :             return Err(auth::AuthError::auth_failed(&*info.user));
      40              :         }
      41              :     };
      42              : 
      43            0 :     Ok(ComputeCredentials { info, keys })
      44            0 : }
      45              : 
      46              : /// Workaround for clients which don't provide an endpoint (project) name.
      47              : /// Similar to [`authenticate_cleartext`], but there's a specific password format,
      48              : /// and passwords are not yet validated (we don't know how to validate them!)
      49            3 : pub async fn password_hack_no_authentication(
      50            3 :     info: ComputeUserInfoNoEndpoint,
      51            3 :     client: &mut stream::PqStream<Stream<impl AsyncRead + AsyncWrite + Unpin>>,
      52            3 :     latency_timer: &mut LatencyTimer,
      53            3 : ) -> auth::Result<ComputeCredentials<Vec<u8>>> {
      54            3 :     warn!("project not specified, resorting to the password hack auth flow");
      55              : 
      56              :     // pause the timer while we communicate with the client
      57            3 :     let _paused = latency_timer.pause();
      58              : 
      59            3 :     let payload = AuthFlow::new(client)
      60            3 :         .begin(auth::PasswordHack)
      61            0 :         .await?
      62            3 :         .get_password()
      63            3 :         .await?;
      64              : 
      65            2 :     info!(project = &*payload.endpoint, "received missing parameter");
      66              : 
      67              :     // Report tentative success; compute node will check the password anyway.
      68            2 :     Ok(ComputeCredentials {
      69            2 :         info: ComputeUserInfo {
      70            2 :             user: info.user,
      71            2 :             options: info.options,
      72            2 :             endpoint: payload.endpoint,
      73            2 :         },
      74            2 :         keys: payload.password,
      75            2 :     })
      76            3 : }
        

Generated by: LCOV version 2.1-beta