LCOV - code coverage report
Current view: top level - proxy/src/auth/backend - hacks.rs (source / functions) Coverage Total Hit
Test: d0feeceb9d5ee9c8e73bee7d4ffcced539793178.info Lines: 90.9 % 55 50
Test Date: 2024-06-26 15:19:01 Functions: 25.0 % 16 4

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

Generated by: LCOV version 2.1-beta