LCOV - code coverage report
Current view: top level - proxy/src/control_plane - mod.rs (source / functions) Coverage Total Hit
Test: 1d18b743246dcf78c27c0bad0234a4c0da6fde89.info Lines: 36.8 % 19 7
Test Date: 2025-02-14 00:11:37 Functions: 50.0 % 4 2

            Line data    Source code
       1              : //! Various stuff for dealing with the Neon Console.
       2              : //! Later we might move some API wrappers here.
       3              : 
       4              : /// Payloads used in the console's APIs.
       5              : pub mod messages;
       6              : 
       7              : /// Wrappers for console APIs and their mocks.
       8              : pub mod client;
       9              : 
      10              : pub(crate) mod errors;
      11              : 
      12              : use std::sync::Arc;
      13              : 
      14              : use crate::auth::backend::jwt::AuthRule;
      15              : use crate::auth::backend::{ComputeCredentialKeys, ComputeUserInfo};
      16              : use crate::auth::IpPattern;
      17              : use crate::cache::project_info::ProjectInfoCacheImpl;
      18              : use crate::cache::{Cached, TimedLru};
      19              : use crate::config::ComputeConfig;
      20              : use crate::context::RequestContext;
      21              : use crate::control_plane::messages::{ControlPlaneErrorMessage, MetricsAuxInfo};
      22              : use crate::intern::AccountIdInt;
      23              : use crate::intern::ProjectIdInt;
      24              : use crate::types::{EndpointCacheKey, EndpointId};
      25              : use crate::{compute, scram};
      26              : 
      27              : /// Various cache-related types.
      28              : pub mod caches {
      29              :     pub use super::client::ApiCaches;
      30              : }
      31              : 
      32              : /// Various cache-related types.
      33              : pub mod locks {
      34              :     pub use super::client::ApiLocks;
      35              : }
      36              : 
      37              : /// Console's management API.
      38              : pub mod mgmt;
      39              : 
      40              : /// Auth secret which is managed by the cloud.
      41              : #[derive(Clone, Eq, PartialEq, Debug)]
      42              : pub(crate) enum AuthSecret {
      43              :     #[cfg(any(test, feature = "testing"))]
      44              :     /// Md5 hash of user's password.
      45              :     Md5([u8; 16]),
      46              : 
      47              :     /// [SCRAM](crate::scram) authentication info.
      48              :     Scram(scram::ServerSecret),
      49              : }
      50              : 
      51              : #[derive(Default)]
      52              : pub(crate) struct AuthInfo {
      53              :     pub(crate) secret: Option<AuthSecret>,
      54              :     /// List of IP addresses allowed for the autorization.
      55              :     pub(crate) allowed_ips: Vec<IpPattern>,
      56              :     /// List of VPC endpoints allowed for the autorization.
      57              :     pub(crate) allowed_vpc_endpoint_ids: Vec<String>,
      58              :     /// Project ID. This is used for cache invalidation.
      59              :     pub(crate) project_id: Option<ProjectIdInt>,
      60              :     /// Account ID. This is used for cache invalidation.
      61              :     pub(crate) account_id: Option<AccountIdInt>,
      62              :     /// Are public connections or VPC connections blocked?
      63              :     pub(crate) access_blocker_flags: AccessBlockerFlags,
      64              : }
      65              : 
      66              : /// Info for establishing a connection to a compute node.
      67              : /// This is what we get after auth succeeded, but not before!
      68              : #[derive(Clone)]
      69              : pub(crate) struct NodeInfo {
      70              :     /// Compute node connection params.
      71              :     /// It's sad that we have to clone this, but this will improve
      72              :     /// once we migrate to a bespoke connection logic.
      73              :     pub(crate) config: compute::ConnCfg,
      74              : 
      75              :     /// Labels for proxy's metrics.
      76              :     pub(crate) aux: MetricsAuxInfo,
      77              : }
      78              : 
      79              : impl NodeInfo {
      80            0 :     pub(crate) async fn connect(
      81            0 :         &self,
      82            0 :         ctx: &RequestContext,
      83            0 :         config: &ComputeConfig,
      84            0 :         user_info: ComputeUserInfo,
      85            0 :     ) -> Result<compute::PostgresConnection, compute::ConnectionError> {
      86            0 :         self.config
      87            0 :             .connect(ctx, self.aux.clone(), config, user_info)
      88            0 :             .await
      89            0 :     }
      90              : 
      91            4 :     pub(crate) fn reuse_settings(&mut self, other: Self) {
      92            4 :         self.config.reuse_password(other.config);
      93            4 :     }
      94              : 
      95            6 :     pub(crate) fn set_keys(&mut self, keys: &ComputeCredentialKeys) {
      96            6 :         match keys {
      97              :             #[cfg(any(test, feature = "testing"))]
      98            6 :             ComputeCredentialKeys::Password(password) => self.config.password(password),
      99            0 :             ComputeCredentialKeys::AuthKeys(auth_keys) => self.config.auth_keys(*auth_keys),
     100            0 :             ComputeCredentialKeys::JwtPayload(_) | ComputeCredentialKeys::None => &mut self.config,
     101              :         };
     102            6 :     }
     103              : }
     104              : 
     105              : #[derive(Clone, Default, Eq, PartialEq, Debug)]
     106              : pub(crate) struct AccessBlockerFlags {
     107              :     pub public_access_blocked: bool,
     108              :     pub vpc_access_blocked: bool,
     109              : }
     110              : 
     111              : pub(crate) type NodeInfoCache =
     112              :     TimedLru<EndpointCacheKey, Result<NodeInfo, Box<ControlPlaneErrorMessage>>>;
     113              : pub(crate) type CachedNodeInfo = Cached<&'static NodeInfoCache, NodeInfo>;
     114              : pub(crate) type CachedRoleSecret = Cached<&'static ProjectInfoCacheImpl, Option<AuthSecret>>;
     115              : pub(crate) type CachedAllowedIps = Cached<&'static ProjectInfoCacheImpl, Arc<Vec<IpPattern>>>;
     116              : pub(crate) type CachedAllowedVpcEndpointIds =
     117              :     Cached<&'static ProjectInfoCacheImpl, Arc<Vec<String>>>;
     118              : pub(crate) type CachedAccessBlockerFlags =
     119              :     Cached<&'static ProjectInfoCacheImpl, AccessBlockerFlags>;
     120              : 
     121              : /// This will allocate per each call, but the http requests alone
     122              : /// already require a few allocations, so it should be fine.
     123              : pub(crate) trait ControlPlaneApi {
     124              :     /// Get the client's auth secret for authentication.
     125              :     /// Returns option because user not found situation is special.
     126              :     /// We still have to mock the scram to avoid leaking information that user doesn't exist.
     127              :     async fn get_role_secret(
     128              :         &self,
     129              :         ctx: &RequestContext,
     130              :         user_info: &ComputeUserInfo,
     131              :     ) -> Result<CachedRoleSecret, errors::GetAuthInfoError>;
     132              : 
     133              :     async fn get_allowed_ips(
     134              :         &self,
     135              :         ctx: &RequestContext,
     136              :         user_info: &ComputeUserInfo,
     137              :     ) -> Result<CachedAllowedIps, errors::GetAuthInfoError>;
     138              : 
     139              :     async fn get_allowed_vpc_endpoint_ids(
     140              :         &self,
     141              :         ctx: &RequestContext,
     142              :         user_info: &ComputeUserInfo,
     143              :     ) -> Result<CachedAllowedVpcEndpointIds, errors::GetAuthInfoError>;
     144              : 
     145              :     async fn get_block_public_or_vpc_access(
     146              :         &self,
     147              :         ctx: &RequestContext,
     148              :         user_info: &ComputeUserInfo,
     149              :     ) -> Result<CachedAccessBlockerFlags, errors::GetAuthInfoError>;
     150              : 
     151              :     async fn get_endpoint_jwks(
     152              :         &self,
     153              :         ctx: &RequestContext,
     154              :         endpoint: EndpointId,
     155              :     ) -> Result<Vec<AuthRule>, errors::GetEndpointJwksError>;
     156              : 
     157              :     /// Wake up the compute node and return the corresponding connection info.
     158              :     async fn wake_compute(
     159              :         &self,
     160              :         ctx: &RequestContext,
     161              :         user_info: &ComputeUserInfo,
     162              :     ) -> Result<CachedNodeInfo, errors::WakeComputeError>;
     163              : }
        

Generated by: LCOV version 2.1-beta