LCOV - code coverage report
Current view: top level - proxy/src - auth.rs (source / functions) Coverage Total Hit
Test: c639aa5f7ab62b43d647b10f40d15a15686ce8a9.info Lines: 54.5 % 55 30
Test Date: 2024-02-12 20:26:03 Functions: 59.3 % 27 16

            Line data    Source code
       1              : //! Client authentication mechanisms.
       2              : 
       3              : pub mod backend;
       4              : pub use backend::BackendType;
       5              : 
       6              : mod credentials;
       7              : pub use credentials::{
       8              :     check_peer_addr_is_in_list, endpoint_sni, ComputeUserInfoMaybeEndpoint,
       9              :     ComputeUserInfoParseError, IpPattern,
      10              : };
      11              : 
      12              : mod password_hack;
      13              : pub use password_hack::parse_endpoint_param;
      14              : use password_hack::PasswordHackPayload;
      15              : 
      16              : mod flow;
      17              : pub use flow::*;
      18              : use tokio::time::error::Elapsed;
      19              : 
      20              : use crate::{
      21              :     console,
      22              :     error::{ReportableError, UserFacingError},
      23              : };
      24              : use std::io;
      25              : use thiserror::Error;
      26              : 
      27              : /// Convenience wrapper for the authentication error.
      28              : pub type Result<T> = std::result::Result<T, AuthError>;
      29              : 
      30              : /// Common authentication error.
      31          116 : #[derive(Debug, Error)]
      32              : pub enum AuthErrorImpl {
      33              :     #[error(transparent)]
      34              :     Link(#[from] backend::LinkAuthError),
      35              : 
      36              :     #[error(transparent)]
      37              :     GetAuthInfo(#[from] console::errors::GetAuthInfoError),
      38              : 
      39              :     #[error(transparent)]
      40              :     WakeCompute(#[from] console::errors::WakeComputeError),
      41              : 
      42              :     /// SASL protocol errors (includes [SCRAM](crate::scram)).
      43              :     #[error(transparent)]
      44              :     Sasl(#[from] crate::sasl::Error),
      45              : 
      46              :     #[error("Unsupported authentication method: {0}")]
      47              :     BadAuthMethod(Box<str>),
      48              : 
      49              :     #[error("Malformed password message: {0}")]
      50              :     MalformedPassword(&'static str),
      51              : 
      52              :     #[error(
      53              :         "Endpoint ID is not specified. \
      54              :         Either please upgrade the postgres client library (libpq) for SNI support \
      55              :         or pass the endpoint ID (first part of the domain name) as a parameter: '?options=endpoint%3D<endpoint-id>'. \
      56              :         See more at https://neon.tech/sni"
      57              :     )]
      58              :     MissingEndpointName,
      59              : 
      60              :     #[error("password authentication failed for user '{0}'")]
      61              :     AuthFailed(Box<str>),
      62              : 
      63              :     /// Errors produced by e.g. [`crate::stream::PqStream`].
      64              :     #[error(transparent)]
      65              :     Io(#[from] io::Error),
      66              : 
      67              :     #[error(
      68              :         "This IP address is not allowed to connect to this endpoint. \
      69              :         Please add it to the allowed list in the Neon console."
      70              :     )]
      71              :     IpAddressNotAllowed,
      72              : 
      73              :     #[error("Too many connections to this endpoint. Please try again later.")]
      74              :     TooManyConnections,
      75              : 
      76              :     #[error("Authentication timed out")]
      77              :     UserTimeout(Elapsed),
      78              : }
      79              : 
      80          116 : #[derive(Debug, Error)]
      81              : #[error(transparent)]
      82              : pub struct AuthError(Box<AuthErrorImpl>);
      83              : 
      84              : impl AuthError {
      85            0 :     pub fn bad_auth_method(name: impl Into<Box<str>>) -> Self {
      86            0 :         AuthErrorImpl::BadAuthMethod(name.into()).into()
      87            0 :     }
      88              : 
      89            5 :     pub fn auth_failed(user: impl Into<Box<str>>) -> Self {
      90            5 :         AuthErrorImpl::AuthFailed(user.into()).into()
      91            5 :     }
      92              : 
      93            4 :     pub fn ip_address_not_allowed() -> Self {
      94            4 :         AuthErrorImpl::IpAddressNotAllowed.into()
      95            4 :     }
      96              : 
      97            0 :     pub fn too_many_connections() -> Self {
      98            0 :         AuthErrorImpl::TooManyConnections.into()
      99            0 :     }
     100              : 
     101            3 :     pub fn is_auth_failed(&self) -> bool {
     102            3 :         matches!(self.0.as_ref(), AuthErrorImpl::AuthFailed(_))
     103            3 :     }
     104              : 
     105            0 :     pub fn user_timeout(elapsed: Elapsed) -> Self {
     106            0 :         AuthErrorImpl::UserTimeout(elapsed).into()
     107            0 :     }
     108              : }
     109              : 
     110              : impl<E: Into<AuthErrorImpl>> From<E> for AuthError {
     111           26 :     fn from(e: E) -> Self {
     112           26 :         Self(Box::new(e.into()))
     113           26 :     }
     114              : }
     115              : 
     116              : impl UserFacingError for AuthError {
     117           11 :     fn to_string_client(&self) -> String {
     118           11 :         use AuthErrorImpl::*;
     119           11 :         match self.0.as_ref() {
     120            0 :             Link(e) => e.to_string_client(),
     121            4 :             GetAuthInfo(e) => e.to_string_client(),
     122            0 :             WakeCompute(e) => e.to_string_client(),
     123            0 :             Sasl(e) => e.to_string_client(),
     124            3 :             AuthFailed(_) => self.to_string(),
     125            0 :             BadAuthMethod(_) => self.to_string(),
     126            0 :             MalformedPassword(_) => self.to_string(),
     127            1 :             MissingEndpointName => self.to_string(),
     128            0 :             Io(_) => "Internal error".to_string(),
     129            3 :             IpAddressNotAllowed => self.to_string(),
     130            0 :             TooManyConnections => self.to_string(),
     131            0 :             UserTimeout(_) => self.to_string(),
     132              :         }
     133           11 :     }
     134              : }
     135              : 
     136              : impl ReportableError for AuthError {
     137           11 :     fn get_error_kind(&self) -> crate::error::ErrorKind {
     138           11 :         use AuthErrorImpl::*;
     139           11 :         match self.0.as_ref() {
     140            0 :             Link(e) => e.get_error_kind(),
     141            4 :             GetAuthInfo(e) => e.get_error_kind(),
     142            0 :             WakeCompute(e) => e.get_error_kind(),
     143            0 :             Sasl(e) => e.get_error_kind(),
     144            3 :             AuthFailed(_) => crate::error::ErrorKind::User,
     145            0 :             BadAuthMethod(_) => crate::error::ErrorKind::User,
     146            0 :             MalformedPassword(_) => crate::error::ErrorKind::User,
     147            1 :             MissingEndpointName => crate::error::ErrorKind::User,
     148            0 :             Io(_) => crate::error::ErrorKind::ClientDisconnect,
     149            3 :             IpAddressNotAllowed => crate::error::ErrorKind::User,
     150            0 :             TooManyConnections => crate::error::ErrorKind::RateLimit,
     151            0 :             UserTimeout(_) => crate::error::ErrorKind::User,
     152              :         }
     153           11 :     }
     154              : }
        

Generated by: LCOV version 2.1-beta