TLA 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::ClientCredentials;
8 :
9 : mod password_hack;
10 : pub use password_hack::parse_endpoint_param;
11 : use password_hack::PasswordHackPayload;
12 :
13 : mod flow;
14 : pub use flow::*;
15 :
16 : use crate::{console, error::UserFacingError};
17 : use std::io;
18 : use thiserror::Error;
19 :
20 : /// Convenience wrapper for the authentication error.
21 : pub type Result<T> = std::result::Result<T, AuthError>;
22 :
23 : /// Common authentication error.
24 CBC 18 : #[derive(Debug, Error)]
25 : pub enum AuthErrorImpl {
26 : #[error(transparent)]
27 : Link(#[from] backend::LinkAuthError),
28 :
29 : #[error(transparent)]
30 : GetAuthInfo(#[from] console::errors::GetAuthInfoError),
31 :
32 : #[error(transparent)]
33 : WakeCompute(#[from] console::errors::WakeComputeError),
34 :
35 : /// SASL protocol errors (includes [SCRAM](crate::scram)).
36 : #[error(transparent)]
37 : Sasl(#[from] crate::sasl::Error),
38 :
39 : #[error("Unsupported authentication method: {0}")]
40 : BadAuthMethod(Box<str>),
41 :
42 : #[error("Malformed password message: {0}")]
43 : MalformedPassword(&'static str),
44 :
45 : #[error(
46 : "Endpoint ID is not specified. \
47 : Either please upgrade the postgres client library (libpq) for SNI support \
48 : or pass the endpoint ID (first part of the domain name) as a parameter: '?options=endpoint%3D<endpoint-id>'. \
49 : See more at https://neon.tech/sni"
50 : )]
51 : MissingEndpointName,
52 :
53 : #[error("password authentication failed for user '{0}'")]
54 : AuthFailed(Box<str>),
55 :
56 : /// Errors produced by e.g. [`crate::stream::PqStream`].
57 : #[error(transparent)]
58 : Io(#[from] io::Error),
59 : }
60 :
61 12 : #[derive(Debug, Error)]
62 : #[error(transparent)]
63 : pub struct AuthError(Box<AuthErrorImpl>);
64 :
65 : impl AuthError {
66 UBC 0 : pub fn bad_auth_method(name: impl Into<Box<str>>) -> Self {
67 0 : AuthErrorImpl::BadAuthMethod(name.into()).into()
68 0 : }
69 :
70 CBC 3 : pub fn auth_failed(user: impl Into<Box<str>>) -> Self {
71 3 : AuthErrorImpl::AuthFailed(user.into()).into()
72 3 : }
73 : }
74 :
75 : impl<E: Into<AuthErrorImpl>> From<E> for AuthError {
76 4 : fn from(e: E) -> Self {
77 4 : Self(Box::new(e.into()))
78 4 : }
79 : }
80 :
81 : impl UserFacingError for AuthError {
82 4 : fn to_string_client(&self) -> String {
83 4 : use AuthErrorImpl::*;
84 4 : match self.0.as_ref() {
85 UBC 0 : Link(e) => e.to_string_client(),
86 0 : GetAuthInfo(e) => e.to_string_client(),
87 0 : WakeCompute(e) => e.to_string_client(),
88 0 : Sasl(e) => e.to_string_client(),
89 CBC 3 : AuthFailed(_) => self.to_string(),
90 UBC 0 : BadAuthMethod(_) => self.to_string(),
91 0 : MalformedPassword(_) => self.to_string(),
92 CBC 1 : MissingEndpointName => self.to_string(),
93 UBC 0 : Io(_) => "Internal error".to_string(),
94 : }
95 CBC 4 : }
96 : }
|