Skip to content

Commit e7ac897

Browse files
authored
RUST-1536: tidy the client-side encryption API (#768)
1 parent 41795da commit e7ac897

File tree

10 files changed

+924
-709
lines changed

10 files changed

+924
-709
lines changed

src/client/csfle.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
pub(crate) mod client_builder;
12
pub mod client_encryption;
23
pub mod options;
34
mod state_machine;
@@ -47,7 +48,7 @@ impl ClientState {
4748
const MONGOCRYPTD_DEFAULT_URI: &'static str = "mongodb://localhost:27020";
4849
const MONGOCRYPTD_SERVER_SELECTION_TIMEOUT: Duration = Duration::from_millis(10_000);
4950

50-
pub(super) async fn new(client: &Client, mut opts: AutoEncryptionOptions) -> Result<Self> {
51+
pub(super) async fn new(client: &Client, opts: AutoEncryptionOptions) -> Result<Self> {
5152
let crypt = Self::make_crypt(&opts)?;
5253
let mongocryptd_opts = Self::make_mongocryptd_opts(&opts, &crypt)?;
5354
let aux_clients = Self::make_aux_clients(client, &opts)?;
@@ -68,7 +69,7 @@ impl ClientState {
6869
let exec = CryptExecutor::new_implicit(
6970
aux_clients.key_vault_client,
7071
opts.key_vault_namespace.clone(),
71-
opts.tls_options.take(),
72+
opts.kms_providers.tls_options().clone(),
7273
mongocryptd_opts,
7374
mongocryptd_client,
7475
aux_clients.metadata_client,
@@ -96,8 +97,7 @@ impl ClientState {
9697
}
9798

9899
fn make_crypt(opts: &AutoEncryptionOptions) -> Result<Crypt> {
99-
let mut builder =
100-
Crypt::builder().kms_providers(&bson::to_document(&opts.kms_providers)?)?;
100+
let mut builder = Crypt::builder().kms_providers(&opts.kms_providers.credentials()?)?;
101101
if let Some(m) = &opts.schema_map {
102102
builder = builder.schema_map(&bson::to_document(m)?)?;
103103
}

src/client/csfle/client_builder.rs

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
use crate::{bson::Document, error::Result, options::ClientOptions, Client, Namespace};
2+
3+
use super::options::{AutoEncryptionOptions, KmsProviders};
4+
5+
/// A builder for constructing a `Client` with auto-encryption enabled.
6+
///
7+
/// ```no_run
8+
/// # use bson::doc;
9+
/// # use mongocrypt::ctx::KmsProvider;
10+
/// # use mongodb::Client;
11+
/// # use mongodb::error::Result;
12+
/// # async fn func() -> Result<()> {
13+
/// # let client_options = todo!();
14+
/// # let key_vault_namespace = todo!();
15+
/// # let key_vault_client: Client = todo!();
16+
/// # let local_key: bson::Binary = todo!();
17+
/// let encrypted_client = Client::encrypted_builder(
18+
/// client_options,
19+
/// key_vault_namespace,
20+
/// [(KmsProvider::Local, doc! { "key": local_key }, None)],
21+
/// )?
22+
/// .key_vault_client(key_vault_client)
23+
/// .build()
24+
/// .await?;
25+
/// # Ok(())
26+
/// # }
27+
/// ```
28+
pub struct EncryptedClientBuilder {
29+
client_options: ClientOptions,
30+
enc_opts: AutoEncryptionOptions,
31+
}
32+
33+
impl EncryptedClientBuilder {
34+
pub(crate) fn new(
35+
client_options: ClientOptions,
36+
key_vault_namespace: Namespace,
37+
kms_providers: KmsProviders,
38+
) -> Self {
39+
EncryptedClientBuilder {
40+
client_options,
41+
enc_opts: AutoEncryptionOptions::new(key_vault_namespace, kms_providers),
42+
}
43+
}
44+
45+
/// Set the client used for data key queries. Will default to an internal client if not set.
46+
pub fn key_vault_client(mut self, client: impl Into<Option<Client>>) -> Self {
47+
self.enc_opts.key_vault_client = client.into();
48+
self
49+
}
50+
51+
/// Specify a JSONSchema locally.
52+
///
53+
/// Supplying a `schema_map` provides more security than relying on JSON Schemas obtained from
54+
/// the server. It protects against a malicious server advertising a false JSON Schema, which
55+
/// could trick the client into sending unencrypted data that should be encrypted.
56+
///
57+
/// Schemas supplied in the `schema_map` only apply to configuring automatic encryption for
58+
/// client side encryption. Other validation rules in the JSON schema will not be enforced by
59+
/// the driver and will result in an error.
60+
pub fn schema_map(mut self, map: impl IntoIterator<Item = (String, Document)>) -> Self {
61+
self.enc_opts.schema_map = Some(map.into_iter().collect());
62+
self
63+
}
64+
65+
/// Disable automatic encryption and do not spawn mongocryptd. Defaults to false.
66+
pub fn bypass_auto_encryption(mut self, bypass: impl Into<Option<bool>>) -> Self {
67+
self.enc_opts.bypass_auto_encryption = bypass.into();
68+
self
69+
}
70+
71+
/// Set options related to mongocryptd.
72+
pub fn extra_options(mut self, extra_opts: impl Into<Option<Document>>) -> Self {
73+
self.enc_opts.extra_options = extra_opts.into();
74+
self
75+
}
76+
77+
/// Maps namespace to encrypted fields.
78+
///
79+
/// Supplying an `encrypted_fields_map` provides more security than relying on an
80+
/// encryptedFields obtained from the server. It protects against a malicious server
81+
/// advertising a false encryptedFields.
82+
pub fn encrypted_fields_map(
83+
mut self,
84+
map: impl IntoIterator<Item = (String, Document)>,
85+
) -> Self {
86+
self.enc_opts.encrypted_fields_map = Some(map.into_iter().collect());
87+
self
88+
}
89+
90+
/// Disable serverside processing of encrypted indexed fields, allowing use of explicit
91+
/// encryption with queryable encryption.
92+
pub fn bypass_query_analysis(mut self, bypass: impl Into<Option<bool>>) -> Self {
93+
self.enc_opts.bypass_query_analysis = bypass.into();
94+
self
95+
}
96+
97+
/// Disable loading crypt_shared.
98+
#[cfg(test)]
99+
pub(crate) fn disable_crypt_shared(mut self, disable: bool) -> Self {
100+
self.enc_opts.disable_crypt_shared = Some(disable);
101+
self
102+
}
103+
104+
/// Constructs a new `Client` using automatic encryption. May perform DNS lookups as part of
105+
/// `Client` initialization.
106+
pub async fn build(self) -> Result<Client> {
107+
let client = Client::with_options(self.client_options)?;
108+
*client.inner.csfle.write().await =
109+
Some(super::ClientState::new(&client, self.enc_opts).await?);
110+
Ok(client)
111+
}
112+
}

0 commit comments

Comments
 (0)