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 : }
|