mz_sql_server_util/config.rs
1// Copyright Materialize, Inc. and contributors. All rights reserved.
2//
3// Use of this software is governed by the Business Source License
4// included in the LICENSE file.
5//
6// As of the Change Date specified in that file, in accordance with
7// the Business Source License, use of this software will be governed
8// by the Apache License, Version 2.0.
9
10use anyhow::Context;
11use mz_ore::future::InTask;
12use mz_repr::CatalogItemId;
13use mz_ssh_util::tunnel::{SshTimeoutConfig, SshTunnelConfig};
14use mz_ssh_util::tunnel_manager::SshTunnelManager;
15use proptest_derive::Arbitrary;
16use serde::{Deserialize, Serialize};
17
18/// Materialize specific configuration for SQL Server connections.
19///
20/// This wraps a [`tiberius::Config`] so we can configure a tunnel over SSH, AWS
21/// PrivateLink, or various other techniques, via a [`TunnelConfig`]
22#[derive(Clone, Debug)]
23pub struct Config {
24 /// SQL Server specific configuration.
25 pub(crate) inner: tiberius::Config,
26 /// Details of how we'll connect to the upstream SQL Server instance.
27 pub(crate) tunnel: TunnelConfig,
28 /// If all of the I/O for this connection will be done in a separate task.
29 ///
30 /// Note: This is used to prevent accidentally doing I/O in timely threads.
31 pub(crate) in_task: InTask,
32}
33
34impl Config {
35 pub fn new(inner: tiberius::Config, tunnel: TunnelConfig, in_task: InTask) -> Self {
36 Config {
37 inner,
38 tunnel,
39 in_task,
40 }
41 }
42
43 /// Create a new [`Config`] from an ActiveX Data Object.
44 ///
45 /// Generally this is only used in test environments, see [`Config::new`]
46 /// for regular/production use cases.
47 pub fn from_ado_string(s: &str) -> Result<Self, anyhow::Error> {
48 let inner = tiberius::Config::from_ado_string(s).context("tiberius config")?;
49 Ok(Config {
50 inner,
51 tunnel: TunnelConfig::Direct,
52 in_task: InTask::No,
53 })
54 }
55}
56
57/// Configures an optional tunnel for use when connecting to a SQL Server database.
58///
59/// TODO(sql_server2): De-duplicate this with MySQL and Postgres sources.
60#[derive(Debug, Clone)]
61pub enum TunnelConfig {
62 /// No tunnelling.
63 Direct,
64 /// Establish a TCP connection to the database via an SSH tunnel.
65 Ssh {
66 /// Config for opening the SSH tunnel.
67 config: SshTunnelConfig,
68 /// Global manager of SSH tunnels.
69 manager: SshTunnelManager,
70 /// Timeout config for the SSH tunnel.
71 timeout: SshTimeoutConfig,
72 // TODO(sql_server3): Remove these fields by forking the `tiberius`
73 // crate and expose the `get_host` and `get_port` methods.
74 //
75 // See: <https://github.com/MaterializeInc/tiberius/blob/406ad2780d206617bd41689b1b638bddf4538f89/src/client/config.rs#L174-L191>
76 host: String,
77 port: u16,
78 },
79 /// Establish a TCP connection to the database via an AWS PrivateLink service.
80 AwsPrivatelink {
81 /// The ID of the AWS PrivateLink service.
82 connection_id: CatalogItemId,
83 port: u16,
84 },
85}
86
87/// Level of encryption to use with a SQL Server connection.
88///
89/// Mirror of [`tiberius::EncryptionLevel`] but we define our own so we can
90/// implement traits like [`Serialize`].
91#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Arbitrary, Serialize, Deserialize)]
92pub enum EncryptionLevel {
93 /// Do not use encryption at all.
94 None,
95 /// Only use encryption for the login procedure.
96 Login,
97 /// Use encryption for everything, if possible.
98 Preferred,
99 /// Require encryption, failing if not possible.
100 Required,
101}
102
103impl From<tiberius::EncryptionLevel> for EncryptionLevel {
104 fn from(value: tiberius::EncryptionLevel) -> Self {
105 match value {
106 tiberius::EncryptionLevel::NotSupported => EncryptionLevel::None,
107 tiberius::EncryptionLevel::Off => EncryptionLevel::Login,
108 tiberius::EncryptionLevel::On => EncryptionLevel::Preferred,
109 tiberius::EncryptionLevel::Required => EncryptionLevel::Required,
110 }
111 }
112}
113
114impl From<EncryptionLevel> for tiberius::EncryptionLevel {
115 fn from(value: EncryptionLevel) -> Self {
116 match value {
117 EncryptionLevel::None => tiberius::EncryptionLevel::NotSupported,
118 EncryptionLevel::Login => tiberius::EncryptionLevel::Off,
119 EncryptionLevel::Preferred => tiberius::EncryptionLevel::On,
120 EncryptionLevel::Required => tiberius::EncryptionLevel::Required,
121 }
122 }
123}
124
125/// Policy that dictates validation of the SQL-SERVER certificate.
126#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Arbitrary, Serialize, Deserialize)]
127pub enum CertificateValidationPolicy {
128 /// Don't validate the server's certificate; trust all certificates.
129 TrustAll,
130 /// Validate server's certificate using system certificates.
131 VerifySystem,
132 /// Validate server's certifiacte using provided CA certificate.
133 VerifyCA,
134}