Skip to content

Commit 523fdd3

Browse files
Comments
1 parent 25ee432 commit 523fdd3

File tree

4 files changed

+133
-111
lines changed

4 files changed

+133
-111
lines changed

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/model.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,8 +69,7 @@ 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-
const { ClientEncryption } = require('mongodb');
73-
72+
const driver = require('./driver');
7473
const modelCollectionSymbol = Symbol('mongoose#Model#collection');
7574
const modelDbSymbol = Symbol('mongoose#Model#db');
7675
const modelSymbol = require('./helpers/symbols').modelSymbol;
@@ -4882,7 +4881,11 @@ Model.compile = function compile(name, schema, collectionName, connection, base)
48824881
};
48834882

48844883
Model.clientEncryption = function clientEncryption() {
4885-
/** @type(import('mongodb').MongoClient) */
4884+
const ClientEncryption = driver.get().ClientEncryption;
4885+
if (!ClientEncryption) {
4886+
throw new Error('The mongodb driver must be used to obtain a ClientEncryption object.');
4887+
}
4888+
48864889
const client = this.collection?.conn?.client;
48874890

48884891
if (!client) return null;

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

test/encryption/encryption.test.js

Lines changed: 125 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,15 +1269,12 @@ describe('encryption integration tests', () => {
12691269
assert.equal(model.clientEncryption()._keyVaultClient, options.keyVaultClient, 'keyvault client not the same');
12701270
});
12711271
});
1272-
});
12731272

1273+
1274+
});
12741275
describe('auto index creation', function() {
12751276
let connection;
12761277

1277-
afterEach(async function() {
1278-
await connection?.close();
1279-
});
1280-
12811278
describe('CSFLE', function() {
12821279
it('automatically creates indexes for CSFLE models', async function() {
12831280
connection = mongoose.createConnection();
@@ -1313,141 +1310,130 @@ describe('encryption integration tests', () => {
13131310
const indexes = await model.listIndexes();
13141311
assert.ok(indexes.find(({ name }) => name === 'age_1'));
13151312
});
1316-
1317-
13181313
});
13191314
});
13201315

1321-
describe('auto collection creation', function() {
1322-
let connection;
13231316

1324-
afterEach(async function() {
1325-
await connection?.close();
1326-
});
1317+
describe('Queryable Encryption', function() {
1318+
let connection;
13271319

1328-
describe('CSFLE', function() {
1329-
it('automatically creates the model\'s collection', async function() {
1330-
connection = mongoose.createConnection();
1331-
const schema = new Schema({
1332-
name: { type: String, encrypt: { keyId: [keyId], algorithm } },
1333-
age: Number
1334-
}, { encryptionType: 'csfle', autoCreate: true });
1320+
it('automatically creates indexes for QE models', async function() {
1321+
connection = mongoose.createConnection();
1322+
const schema = new Schema({
1323+
name: { type: String, encrypt: { keyId } },
1324+
age: Number
1325+
}, { encryptionType: 'queryableEncryption' });
1326+
schema.index({ age: 1 });
1327+
const model = connection.model(new UUID().toHexString(), schema);
1328+
await connection.openUri(clusterUri, autoEncryptionOptions());
13351329

1336-
const model = connection.model(new UUID().toHexString(), schema);
1330+
await model.init();
13371331

1338-
await connection.openUri(clusterUri, autoEncryptionOptions());
1332+
const indexes = await model.listIndexes();
1333+
assert.ok(indexes.find(({ name }) => name === 'age_1'));
1334+
});
13391335

1340-
await model.init();
13411336

1342-
const collections = await connection.db.listCollections({}, { readPreference: 'primary' }).toArray();
1343-
assert.equal(collections.length, 1);
1344-
});
1345-
});
1337+
});
1338+
});
13461339

1347-
describe('Queryable Encryption', function() {
1348-
it('automatically creates the model\'s collection', async function() {
1349-
connection = mongoose.createConnection();
1350-
const schema = new Schema({
1351-
name: { type: String, encrypt: { keyId: keyId } }
1352-
}, { encryptionType: 'queryableEncryption', autoCreate: true });
1340+
describe('auto collection creation', function() {
1341+
let connection;
13531342

1354-
const model = connection.model(new UUID().toHexString(), schema);
1343+
afterEach(async function() {
1344+
await connection?.close();
1345+
});
13551346

1356-
await connection.openUri(clusterUri, autoEncryptionOptions());
1347+
describe('CSFLE', function() {
1348+
it('automatically creates the model\'s collection', async function() {
1349+
connection = mongoose.createConnection();
1350+
const schema = new Schema({
1351+
name: { type: String, encrypt: { keyId: [keyId], algorithm } },
1352+
age: Number
1353+
}, { encryptionType: 'csfle', autoCreate: true });
13571354

1355+
const model = connection.model(new UUID().toHexString(), schema);
13581356

1359-
await model.init();
1357+
await connection.openUri(clusterUri, autoEncryptionOptions());
1358+
await model.init();
13601359

1361-
const collections = await utilClient.db('db').listCollections().toArray();
1362-
assert.equal(collections.length, 3);
1363-
});
1360+
const collections = await connection.db.listCollections({}, { readPreference: 'primary' }).toArray();
1361+
assert.equal(collections.length, 1);
13641362
});
13651363
});
13661364

1367-
describe('read operations', function() {
1368-
let connection;
1365+
describe('Queryable Encryption', function() {
1366+
it('automatically creates the model\'s collection', async function() {
1367+
connection = mongoose.createConnection();
1368+
const schema = new Schema({
1369+
name: { type: String, encrypt: { keyId: keyId } }
1370+
}, { encryptionType: 'queryableEncryption', autoCreate: true });
13691371

1370-
afterEach(async function() {
1371-
await connection?.close();
1372-
});
1372+
const model = connection.model(new UUID().toHexString(), schema);
13731373

1374-
describe('CSFLE', function() {
1375-
it('encrypted documents can be read', async function() {
1376-
connection = mongoose.createConnection();
1377-
const schema = new Schema({
1378-
name: { type: String, encrypt: { keyId: [keyId], algorithm } },
1379-
age: Number
1380-
}, { encryptionType: 'csfle', autoCreate: true });
1374+
await connection.openUri(clusterUri, autoEncryptionOptions());
13811375

1382-
const model = connection.model(new UUID().toHexString(), schema);
13831376

1384-
await connection.openUri(clusterUri, autoEncryptionOptions());
1377+
await model.init();
13851378

1386-
await model.insertMany([
1387-
{ name: 'bailey', age: 1 },
1388-
{ name: 'john', age: 2 }
1389-
]);
1379+
const collections = await utilClient.db('db').listCollections().toArray();
1380+
assert.equal(collections.length, 3);
1381+
});
1382+
});
1383+
});
13901384

1391-
assert.equal((await model.find()).length, 2);
1392-
assert.deepEqual(await model.findOne({ age: 1 }, { _id: 0, name: 1 }, { lean: true }), { name: 'bailey' });
1393-
});
1385+
describe('read operations', function() {
1386+
let connection;
13941387

1395-
it('deterministically encrypted fields can be equality queried', async function() {
1396-
connection = mongoose.createConnection();
1397-
const schema = new Schema({
1398-
name: { type: String, encrypt: { keyId: [keyId], algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' } },
1399-
age: Number
1400-
}, { encryptionType: 'csfle', autoCreate: true });
1388+
afterEach(async function() {
1389+
await connection?.close();
1390+
});
14011391

1402-
const model = connection.model(new UUID().toHexString(), schema);
1392+
describe('CSFLE', function() {
1393+
it('encrypted documents can be read', async function() {
1394+
connection = mongoose.createConnection();
1395+
const schema = new Schema({
1396+
name: { type: String, encrypt: { keyId: [keyId], algorithm } },
1397+
age: Number
1398+
}, { encryptionType: 'csfle', autoCreate: true });
14031399

1404-
await connection.openUri(clusterUri, autoEncryptionOptions());
1400+
const model = connection.model(new UUID().toHexString(), schema);
14051401

1406-
await model.insertMany([
1407-
{ name: 'bailey', age: 1 },
1408-
{ name: 'john', age: 2 }
1409-
]);
1402+
await connection.openUri(clusterUri, autoEncryptionOptions());
14101403

1411-
assert.equal((await model.find()).length, 2);
1412-
assert.deepEqual(await model.findOne({ name: 'bailey' }, { _id: 0, name: 1 }, { lean: true }), { name: 'bailey' });
1413-
});
1414-
});
1404+
await model.insertMany([
1405+
{ name: 'bailey', age: 1 },
1406+
{ name: 'john', age: 2 }
1407+
]);
14151408

1416-
describe('QE encrypted queries', function() {
1417-
describe('when a field is configured for equality queries', function() {
1418-
it('can be queried with mongoose', async function() {
1419-
connection = mongoose.createConnection();
1420-
const schema = new Schema({
1421-
name: { type: String, encrypt: { keyId, queries: { queryType: 'equality' } } }
1422-
}, { encryptionType: 'queryableEncryption' });
1423-
const model = connection.model(new UUID().toHexString(), schema);
1424-
await connection.openUri(clusterUri, autoEncryptionOptions());
1409+
assert.equal((await model.find()).length, 2);
1410+
assert.deepEqual(await model.findOne({ age: 1 }, { _id: 0, name: 1 }, { lean: true }), { name: 'bailey' });
1411+
});
14251412

1426-
await model.insertMany([{ name: 'bailey' }, { name: 'john' }]);
1413+
it('deterministically encrypted fields can be equality queried', async function() {
1414+
connection = mongoose.createConnection();
1415+
const schema = new Schema({
1416+
name: { type: String, encrypt: { keyId: [keyId], algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' } },
1417+
age: Number
1418+
}, { encryptionType: 'csfle', autoCreate: true });
14271419

1428-
const doc = await model.findOne({ name: 'bailey' });
1429-
assert.ok(doc);
1430-
});
1431-
});
1420+
const model = connection.model(new UUID().toHexString(), schema);
14321421

1433-
describe('when a field is not configured for equality queries', function() {
1434-
it('cannot be queried directly', async function() {
1435-
connection = mongoose.createConnection();
1436-
const schema = new Schema({
1437-
name: { type: String, encrypt: { keyId } }
1438-
}, { encryptionType: 'queryableEncryption' });
1439-
const model = connection.model(new UUID().toHexString(), schema);
1440-
await connection.openUri(clusterUri, autoEncryptionOptions());
1422+
await connection.openUri(clusterUri, autoEncryptionOptions());
14411423

1442-
await model.insertMany([{ name: { toString: function() { 'asdf';} } }, { name: 'john' }]);
1424+
await model.insertMany([
1425+
{ name: 'bailey', age: 1 },
1426+
{ name: 'john', age: 2 }
1427+
]);
14431428

1444-
await assert.rejects(() => {
1445-
return model.findOne({ name: 'bailey' });
1446-
}, /Can only execute encrypted equality queries with an encrypted equality index/);
1447-
});
1448-
});
1429+
assert.equal((await model.find()).length, 2);
1430+
assert.deepEqual(await model.findOne({ name: 'bailey' }, { _id: 0, name: 1 }, { lean: true }), { name: 'bailey' });
1431+
});
1432+
});
14491433

1450-
it('queried documents can be modified and saved', async function() {
1434+
describe('QE encrypted queries', function() {
1435+
describe('when a field is configured for equality queries', function() {
1436+
it('can be queried with mongoose', async function() {
14511437
connection = mongoose.createConnection();
14521438
const schema = new Schema({
14531439
name: { type: String, encrypt: { keyId, queries: { queryType: 'equality' } } }
@@ -1458,12 +1444,44 @@ describe('encryption integration tests', () => {
14581444
await model.insertMany([{ name: 'bailey' }, { name: 'john' }]);
14591445

14601446
const doc = await model.findOne({ name: 'bailey' });
1461-
doc.name = 'new name!';
1462-
await doc.save();
1447+
assert.ok(doc);
1448+
});
1449+
});
1450+
1451+
describe('when a field is not configured for equality queries', function() {
1452+
it('cannot be queried directly', async function() {
1453+
connection = mongoose.createConnection();
1454+
const schema = new Schema({
1455+
name: { type: String, encrypt: { keyId } }
1456+
}, { encryptionType: 'queryableEncryption' });
1457+
const model = connection.model(new UUID().toHexString(), schema);
1458+
await connection.openUri(clusterUri, autoEncryptionOptions());
1459+
1460+
await model.insertMany([{ name: { toString: function() { 'asdf';} } }, { name: 'john' }]);
14631461

1464-
assert.ok(model.findOne({ name: 'new name!' }));
1462+
await assert.rejects(() => {
1463+
return model.findOne({ name: 'bailey' });
1464+
}, /Can only execute encrypted equality queries with an encrypted equality index/);
14651465
});
14661466
});
1467+
1468+
it('queried documents can be modified and saved', async function() {
1469+
connection = mongoose.createConnection();
1470+
const schema = new Schema({
1471+
name: { type: String, encrypt: { keyId, queries: { queryType: 'equality' } } }
1472+
}, { encryptionType: 'queryableEncryption' });
1473+
const model = connection.model(new UUID().toHexString(), schema);
1474+
await connection.openUri(clusterUri, autoEncryptionOptions());
1475+
await model.init();
1476+
await model.insertMany([{ name: 'bailey' }, { name: 'john' }]);
1477+
1478+
const doc = await model.findOne({ name: 'bailey' });
1479+
doc.name = 'new name!';
1480+
1481+
await doc.save();
1482+
1483+
assert.ok(await model.findOne({ name: 'new name!' }));
1484+
});
14671485
});
14681486
});
14691487
});

0 commit comments

Comments
 (0)