156 lines
5.2 KiB
JavaScript
156 lines
5.2 KiB
JavaScript
/**
|
|
* Tests basic CRUD operations with queryable encrypted fields.
|
|
*
|
|
* @tags: [
|
|
* no_selinux,
|
|
* tenant_migration_incompatible,
|
|
* does_not_support_transactions,
|
|
* does_not_support_stepdowns,
|
|
* # Test requires an internal connection for the keyvault that can't be overriden by the
|
|
* # `simulate_atlas_proxy` override.
|
|
* simulate_atlas_proxy_incompatible,
|
|
* ]
|
|
*/
|
|
import {
|
|
assertIsIndexedEncryptedField,
|
|
EncryptedClient,
|
|
kSafeContentField
|
|
} from "jstests/fle2/libs/encrypted_client_util.js";
|
|
|
|
if (!(buildInfo().modules.includes("enterprise"))) {
|
|
jsTestLog("Skipping test as it requires the enterprise module");
|
|
quit();
|
|
}
|
|
|
|
const dbName = "qetestdb";
|
|
const collName = "qetestcoll";
|
|
const initialConn = db.getMongo();
|
|
const localKMS = {
|
|
key: BinData(
|
|
0,
|
|
"/tu9jUCBqZdwCelwE/EAm/4WqdxrSMi04B8e9uAV+m30rI1J2nhKZZtQjdvsSCwuI4erR6IEcEK+5eGUAODv43NDNIR9QheT2edWFewUfHKsl9cnzTc86meIzOmYl6dr")
|
|
};
|
|
|
|
// Some tests silently change the DB name to prefix it with a tenant ID, but we
|
|
// need to pass the real DB name for the keyvault when setting up the auto encryption,
|
|
// so that the internal connection for the key vault will target the right DB name.
|
|
const kvDbName = (typeof (initialConn.getDbNameWithTenantPrefix) === "function")
|
|
? initialConn.getDbNameWithTenantPrefix(dbName)
|
|
: dbName;
|
|
jsTestLog("Using key vault db " + kvDbName);
|
|
|
|
const clientSideFLEOptions = {
|
|
kmsProviders: {local: localKMS},
|
|
keyVaultNamespace: kvDbName + ".keystore",
|
|
schemaMap: {},
|
|
};
|
|
|
|
db.getSiblingDB(dbName).dropDatabase();
|
|
|
|
assert(initialConn.setAutoEncryption(clientSideFLEOptions));
|
|
initialConn.toggleAutoEncryption(true);
|
|
|
|
let encryptedClient = new EncryptedClient(initialConn, dbName);
|
|
assert.commandWorked(encryptedClient.createEncryptionCollection(collName, {
|
|
encryptedFields: {
|
|
"fields": [
|
|
{"path": "first", "bsonType": "string", "queries": {"queryType": "equality"}},
|
|
]
|
|
}
|
|
}));
|
|
|
|
function runIndexedEqualityEncryptedCRUDTest(client, iterations) {
|
|
let conn = client.getDB().getMongo();
|
|
let ecoll = client.getDB()[collName];
|
|
let values =
|
|
[["frodo", "baggins"], ["sam", "gamgee"], ["pippin", "took"], ["merry", "brandybuck"]];
|
|
let count = 0;
|
|
let escCount = 0;
|
|
let ecocCount = 0;
|
|
|
|
// Do encrypted inserts
|
|
for (let it = 0; it < iterations; it++) {
|
|
for (let val of values) {
|
|
assert.commandWorked(ecoll.insert({_id: count, first: val[0], last: val[1]}));
|
|
count++;
|
|
client.assertEncryptedCollectionCounts(collName, count, count, count);
|
|
}
|
|
}
|
|
escCount = count;
|
|
ecocCount = count;
|
|
|
|
// Do finds using unencrypted connection
|
|
{
|
|
conn.toggleAutoEncryption(false);
|
|
|
|
let rawDocs = ecoll.find().toArray();
|
|
assert.eq(rawDocs.length, count);
|
|
for (let rawDoc of rawDocs) {
|
|
assertIsIndexedEncryptedField(rawDoc.first);
|
|
assert(rawDoc[kSafeContentField] !== undefined);
|
|
}
|
|
conn.toggleAutoEncryption(true);
|
|
}
|
|
|
|
// Do encrypted queries using encrypted connection
|
|
for (let mod = 0; mod < values.length; mod++) {
|
|
let docs = ecoll.find({last: values[mod][1]}).toArray();
|
|
|
|
for (let doc of docs) {
|
|
assert.eq(doc._id % values.length, mod);
|
|
assert.eq(doc.first, values[mod][0]);
|
|
assert(doc[kSafeContentField] !== undefined);
|
|
}
|
|
}
|
|
|
|
// Do updates on encrypted fields
|
|
for (let it = 0; it < iterations; it++) {
|
|
let res = assert.commandWorked(ecoll.updateOne(
|
|
{$and: [{last: "baggins"}, {first: "frodo"}]}, {$set: {first: "bilbo"}}));
|
|
assert.eq(res.matchedCount, 1);
|
|
assert.eq(res.modifiedCount, 1);
|
|
escCount++;
|
|
ecocCount++;
|
|
client.assertEncryptedCollectionCounts(collName, count, escCount, ecocCount);
|
|
|
|
res = assert.commandWorked(
|
|
ecoll.replaceOne({last: "took"}, {first: "paladin", last: "took"}));
|
|
assert.eq(res.matchedCount, 1);
|
|
assert.eq(res.modifiedCount, 1);
|
|
escCount++;
|
|
ecocCount++;
|
|
client.assertEncryptedCollectionCounts(collName, count, escCount, ecocCount);
|
|
}
|
|
|
|
// Do findAndModifies
|
|
for (let it = 0; it < iterations; it++) {
|
|
let res = assert.commandWorked(ecoll.runCommand({
|
|
findAndModify: ecoll.getName(),
|
|
query: {$and: [{last: "gamgee"}, {first: "sam"}]},
|
|
update: {$set: {first: "rosie"}},
|
|
}));
|
|
print(tojson(res));
|
|
assert.eq(res.value.first, "sam");
|
|
assert(res.value[kSafeContentField] !== undefined);
|
|
escCount++;
|
|
ecocCount++;
|
|
client.assertEncryptedCollectionCounts(collName, count, escCount, ecocCount);
|
|
}
|
|
|
|
// Do deletes
|
|
for (let it = 0; it < iterations; it++) {
|
|
let res = assert.commandWorked(
|
|
ecoll.deleteOne({last: "brandybuck"}, {writeConcern: {w: "majority"}}));
|
|
assert.eq(res.deletedCount, 1);
|
|
count--;
|
|
client.assertEncryptedCollectionCounts(collName, count, escCount, ecocCount);
|
|
}
|
|
assert.eq(ecoll.find({last: "brandybuck"}).count(), 0);
|
|
}
|
|
|
|
// Test CRUD on indexed equality encrypted fields
|
|
runIndexedEqualityEncryptedCRUDTest(encryptedClient, 10);
|
|
|
|
encryptedClient = undefined;
|
|
initialConn.unsetAutoEncryption();
|