Skip to content

Commit 7634218

Browse files
authored
Merge pull request #15356 from mongodb-js/NODE-6894
feat: expose a ClientEncryption object on encrypted Models
2 parents 92bb79b + 1e342ff commit 7634218

File tree

6 files changed

+388
-186
lines changed

6 files changed

+388
-186
lines changed

docs/field-level-encryption.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,30 @@ const ModelWithBirthday = model.discriminator('ModelWithBirthday', new Schema({
216216
```
217217

218218
When generating encryption schemas, Mongoose merges all discriminators together for the all discriminators declared on the same namespace. As a result, discriminators that declare the same key with different types are not supported. Furthermore, all discriminators must share the same encryption type - it is not possible to configure discriminators on the same model for both CSFLE and QE.
219+
220+
## Managing Data Keys
221+
222+
Mongoose provides a convenient API to obtain a [ClientEncryption](https://mongodb.github.io/node-mongodb-native/Next/classes/ClientEncryption.html)
223+
object configured to manage data keys in the key vault. A client encryption can be obtained with the `Model.clientEncryption()` helper:
224+
225+
```javascript
226+
const connection = createConnection();
227+
228+
const schema = new Schema({
229+
name: {
230+
type: String, encrypt: { keyId }
231+
}
232+
}, {
233+
encryptionType: 'queryableEncryption'
234+
});
235+
236+
const Model = connection.model('BaseUserModel', schema);
237+
await connection.openUri(`mongodb://localhost:27017`, {
238+
autoEncryption: {
239+
keyVaultNamespace: 'datakeys.datakeys',
240+
kmsProviders: { local: '....' }
241+
}
242+
});
243+
244+
const clientEncryption = Model.clientEncryption();
245+
```

lib/drivers/node-mongodb-native/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@
77
exports.BulkWriteResult = require('./bulkWriteResult');
88
exports.Collection = require('./collection');
99
exports.Connection = require('./connection');
10+
exports.ClientEncryption = require('mongodb').ClientEncryption;

lib/helpers/model/discriminator.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,8 @@ function validateDiscriminatorSchemasForEncryption(parentSchema, childSchema) {
4444
}
4545
}
4646

47-
function* allNestedPaths(schema) {
48-
const { paths, singleNestedPaths } = schema;
49-
yield* Object.keys(paths);
50-
yield* Object.keys(singleNestedPaths);
47+
function allNestedPaths(schema) {
48+
return [...Object.keys(schema.paths), ...Object.keys(schema.singleNestedPaths)];
5149
}
5250

5351
/**

lib/model.js

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ const minimize = require('./helpers/minimize');
6969
const MongooseBulkSaveIncompleteError = require('./error/bulkSaveIncompleteError');
7070
const ObjectExpectedError = require('./error/objectExpected');
7171
const decorateBulkWriteResult = require('./helpers/model/decorateBulkWriteResult');
72-
7372
const modelCollectionSymbol = Symbol('mongoose#Model#collection');
7473
const modelDbSymbol = Symbol('mongoose#Model#db');
7574
const modelSymbol = require('./helpers/symbols').modelSymbol;
@@ -4880,6 +4879,33 @@ Model.compile = function compile(name, schema, collectionName, connection, base)
48804879
return model;
48814880
};
48824881

4882+
Model.clientEncryption = function clientEncryption() {
4883+
const ClientEncryption = this.base.driver.get().ClientEncryption;
4884+
if (!ClientEncryption) {
4885+
throw new Error('The mongodb driver must be used to obtain a ClientEncryption object.');
4886+
}
4887+
4888+
const client = this.collection?.conn?.client;
4889+
4890+
if (!client) return null;
4891+
4892+
const autoEncryptionOptions = client.options.autoEncryption;
4893+
4894+
if (!autoEncryptionOptions) return null;
4895+
4896+
const {
4897+
keyVaultNamespace,
4898+
keyVaultClient,
4899+
kmsProviders,
4900+
credentialProviders,
4901+
proxyOptions,
4902+
tlsOptions
4903+
} = autoEncryptionOptions;
4904+
return new ClientEncryption(keyVaultClient ?? client,
4905+
{ keyVaultNamespace, kmsProviders, credentialProviders, proxyOptions, tlsOptions }
4906+
);
4907+
};
4908+
48834909
/**
48844910
* Update this model to use the new connection, including updating all internal
48854911
* references and creating a new `Collection` instance using the new connection.

scripts/configure-cluster-with-encryption.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ if [ ! -d "data" ]; then
4949
echo 'Configuring Cluster...'
5050

5151
# start cluster
52-
(bash $DRIVERS_TOOLS/.evergreen/run-orchestration.sh) 1>/dev/null 2>/dev/null
52+
(bash $DRIVERS_TOOLS/.evergreen/run-orchestration.sh)
5353

5454
echo 'Cluster Configuration Finished!'
5555

0 commit comments

Comments
 (0)