Skip to content

Commit 2f3300b

Browse files
committed
♻️ refactor: add test config constructors and update Context instantiation
- Add TandemConfig::for_testing() for environment-independent unit tests - Add DatabaseConfig::for_testing() to handle private password field - Update Context::new_for_test() to use new testing constructors - Update Context::new_with_proxy() to extract schema and config from Proxy - Rename Proxy fields: encrypt_config → encrypt_config_manager, schema → schema_manager - Remove environment variable dependency from Context tests - Add integration test for schema reload with mapping disabled
1 parent 91d1740 commit 2f3300b

File tree

6 files changed

+93
-43
lines changed

6 files changed

+93
-43
lines changed

packages/cipherstash-proxy-integration/src/schema_change.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,30 @@ mod tests {
2222

2323
assert!(rows.is_empty());
2424
}
25+
26+
#[tokio::test]
27+
async fn disable_mapping_disables_schema_reload() {
28+
let client = connect_with_tls(PROXY).await;
29+
30+
let sql = "SET CIPHERSTASH.UNSAFE_DISABLE_MAPPING = true";
31+
client.query(sql, &[]).await.unwrap();
32+
33+
let id = random_id();
34+
35+
let sql = format!(
36+
"CREATE TABLE table_{id} (
37+
id bigint,
38+
PRIMARY KEY(id)
39+
);"
40+
);
41+
42+
let _ = client.execute(&sql, &[]).await.unwrap();
43+
44+
let sql = "SET CIPHERSTASH.UNSAFE_DISABLE_MAPPING = false";
45+
client.query(sql, &[]).await.unwrap();
46+
47+
let sql = format!("SELECT id FROM table_{id}");
48+
let result = client.query(&sql, &[]).await;
49+
assert!(result.is_err());
50+
}
2551
}

packages/cipherstash-proxy/src/config/database.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,21 @@ impl DatabaseConfig {
8181
})?;
8282
Ok(name)
8383
}
84+
85+
#[cfg(test)]
86+
pub fn for_testing() -> Self {
87+
Self {
88+
host: Self::default_host(),
89+
port: Self::default_port(),
90+
name: "test".to_string(),
91+
username: "test".to_string(),
92+
password: Protected::new("test".to_string()),
93+
connection_timeout: None,
94+
with_tls_verification: false,
95+
config_reload_interval: Self::default_config_reload_interval(),
96+
schema_reload_interval: Self::default_schema_reload_interval(),
97+
}
98+
}
8499
}
85100

86101
///

packages/cipherstash-proxy/src/config/tandem.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,29 @@ impl TandemConfig {
273273

274274
DEFAULT_THREAD_STACK_SIZE
275275
}
276+
277+
#[cfg(test)]
278+
pub fn for_testing() -> Self {
279+
Self {
280+
server: ServerConfig::default(),
281+
database: DatabaseConfig::for_testing(),
282+
auth: AuthConfig {
283+
workspace_crn: "crn:ap-southeast-2.aws:IJGECSCWKREECNBS".parse().unwrap(),
284+
client_access_key: "test".to_string(),
285+
},
286+
encrypt: EncryptConfig {
287+
client_id: "test".to_string(),
288+
client_key: "test".to_string(),
289+
default_keyset_id: Some(
290+
Uuid::parse_str("00000000-0000-0000-0000-000000000000").unwrap(),
291+
),
292+
},
293+
tls: None,
294+
log: LogConfig::default(),
295+
prometheus: PrometheusConfig::default(),
296+
development: None,
297+
}
298+
}
276299
}
277300

278301
impl PrometheusConfig {

packages/cipherstash-proxy/src/postgresql/context/mod.rs

Lines changed: 18 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::{
1313
error::{EncryptError, Error},
1414
log::CONTEXT,
1515
prometheus::{STATEMENTS_EXECUTION_DURATION_SECONDS, STATEMENTS_SESSION_DURATION_SECONDS},
16+
proxy::EncryptConfig,
1617
services::{EncryptionService, SchemaService},
1718
};
1819
use cipherstash_client::IdentifiedBy;
@@ -105,6 +106,7 @@ impl Context {
105106
client_id: i32,
106107
schema: Arc<Schema>,
107108
config: Arc<TandemConfig>,
109+
_encrypt_config: Arc<EncryptConfig>,
108110
encryption: Arc<dyn EncryptionService>,
109111
schema_service: Arc<dyn SchemaService>,
110112
) -> Context {
@@ -570,17 +572,18 @@ impl Context {
570572
}
571573

572574
/// Helper function for gradual migration - creates Context with Proxy implementing services
573-
pub fn new_with_proxy(
574-
client_id: i32,
575-
schema: Arc<Schema>,
576-
proxy: crate::proxy::Proxy,
577-
) -> Context {
575+
pub fn new_with_proxy(client_id: i32, proxy: crate::proxy::Proxy) -> Context {
578576
let config = Arc::new(proxy.config.clone());
577+
let encrypt_config = proxy.encrypt_config_manager.load();
578+
let schema = proxy.schema_manager.load();
579+
579580
let proxy = Arc::new(proxy);
581+
580582
Self::new(
581583
client_id,
582584
schema,
583585
config,
586+
encrypt_config,
584587
proxy.clone(), // as EncryptionService
585588
proxy, // as SchemaService
586589
)
@@ -633,36 +636,20 @@ impl Context {
633636
}
634637
}
635638

636-
// Set up minimal environment variables for testing
637-
std::env::set_var("CS_DATABASE__USERNAME", "test");
638-
std::env::set_var("CS_DATABASE__PASSWORD", "test");
639-
std::env::set_var("CS_DATABASE__NAME", "test");
640-
std::env::set_var("CS_DATABASE__HOST", "localhost");
641-
std::env::set_var("CS_DATABASE__PORT", "5432");
642-
std::env::set_var(
643-
"CS_AUTH__WORKSPACE_CRN",
644-
"crn:ap-southeast-2.aws:3KISDURL3ZCWYZ2O",
645-
);
646-
std::env::set_var("CS_AUTH__CLIENT_ACCESS_KEY", "test");
647-
std::env::set_var(
648-
"CS_ENCRYPT__CLIENT_ID",
649-
"e40f1692-6bb7-4bbd-a552-4c0f155be073",
650-
);
651-
std::env::set_var("CS_ENCRYPT__CLIENT_KEY", "a4627031a16b7065726d75746174696f6e90090e0805000b0d0c0106040f0a0302076770325f66726f6da16b7065726d75746174696f6e9007060a0b02090d080c00040f0305010e6570325f746fa16b7065726d75746174696f6e900a0206090b04050c070f0e010d030800627033a16b7065726d75746174696f6e98210514181d0818200a18190b1112181809130f15181a0717181e000e0103181f0d181c1602040c181b1006");
652-
std::env::set_var(
653-
"CS_ENCRYPT__KEYSET_ID",
654-
"c50d8463-60e9-41a5-86cd-5782e03a503c",
655-
);
656-
657-
let config = Arc::new(
658-
crate::config::TandemConfig::build("tests/config/unknown.toml")
659-
.expect("Failed to create test config"),
660-
);
639+
let config = Arc::new(TandemConfig::for_testing());
640+
let encrypt_config = Arc::new(EncryptConfig::default());
661641

662642
let encryption = Arc::new(MockEncryptionService) as Arc<dyn EncryptionService>;
663643
let schema_service = Arc::new(MockSchemaService) as Arc<dyn SchemaService>;
664644

665-
Self::new(client_id, schema, config, encryption, schema_service)
645+
Self::new(
646+
client_id,
647+
schema,
648+
config,
649+
encrypt_config,
650+
encryption,
651+
schema_service,
652+
)
666653
}
667654
}
668655

packages/cipherstash-proxy/src/postgresql/handler.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -218,8 +218,7 @@ pub async fn handler(
218218

219219
let channel_writer = ChannelWriter::new(client_writer, client_id);
220220

221-
let schema = proxy.schema.load();
222-
let context = Context::new_with_proxy(client_id, schema, proxy.clone());
221+
let context = Context::new_with_proxy(client_id, proxy.clone());
223222

224223
let mut frontend = Frontend::new(
225224
client_reader,

packages/cipherstash-proxy/src/proxy/mod.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ const AGGREGATE_QUERY: &str = include_str!("./sql/select_aggregates.sql");
3030
#[derive(Clone)]
3131
pub struct Proxy {
3232
pub config: TandemConfig,
33-
pub encrypt_config: EncryptConfigManager,
34-
pub schema: SchemaManager,
33+
pub encrypt_config_manager: EncryptConfigManager,
34+
pub schema_manager: SchemaManager,
3535
/// The EQL version installed in the database or `None` if it was not present
3636
pub eql_version: Option<String>,
3737
zerokms: ZeroKms,
@@ -70,8 +70,8 @@ impl Proxy {
7070
Ok(Proxy {
7171
config,
7272
zerokms,
73-
encrypt_config,
74-
schema,
73+
encrypt_config_manager: encrypt_config,
74+
schema_manager: schema,
7575
eql_version,
7676
})
7777
}
@@ -119,21 +119,21 @@ impl Proxy {
119119
}
120120

121121
pub fn get_column_config(&self, identifier: &eql::Identifier) -> Option<ColumnConfig> {
122-
let encrypt_config = self.encrypt_config.load();
122+
let encrypt_config = self.encrypt_config_manager.load();
123123
encrypt_config.get_column_config(identifier)
124124
}
125125

126126
pub async fn reload_schema(&self) {
127-
self.schema.reload().await;
128-
self.encrypt_config.reload().await;
127+
self.schema_manager.reload().await;
128+
self.encrypt_config_manager.reload().await;
129129
}
130130

131131
pub fn is_passthrough(&self) -> bool {
132-
self.encrypt_config.is_empty() || self.config.mapping_disabled()
132+
self.encrypt_config_manager.is_empty() || self.config.mapping_disabled()
133133
}
134134

135135
pub fn is_empty_config(&self) -> bool {
136-
self.encrypt_config.is_empty()
136+
self.encrypt_config_manager.is_empty()
137137
}
138138
}
139139

@@ -172,7 +172,7 @@ impl crate::services::SchemaService for Proxy {
172172
}
173173

174174
fn get_table_resolver(&self) -> std::sync::Arc<eql_mapper::TableResolver> {
175-
self.schema.get_table_resolver()
175+
self.schema_manager.get_table_resolver()
176176
}
177177

178178
fn is_passthrough(&self) -> bool {

0 commit comments

Comments
 (0)