From 34d7332499d0d2a7700fa8dfe60a8e622f8fce3a Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Wed, 22 Feb 2023 13:26:11 -0500 Subject: [PATCH 01/16] test(NODE-5069): move FLE prose test 14 to TS file --- ...cryption.prose.14.decrytion_events.test.ts | 221 +++++++++++++++++ .../client_side_encryption.prose.test.js | 222 ------------------ 2 files changed, 221 insertions(+), 222 deletions(-) create mode 100644 test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts new file mode 100644 index 00000000000..fd8ba30a9b3 --- /dev/null +++ b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts @@ -0,0 +1,221 @@ +context('14. Decryption Events', metadata, function () { + let setupClient; + let clientEncryption; + let keyId; + let cipherText; + let malformedCiphertext; + let encryptedClient; + let aggregateSucceeded; + let aggregateFailed; + + beforeEach(async function () { + const mongodbClientEncryption = this.configuration.mongodbClientEncryption; + // Create a MongoClient named ``setupClient``. + setupClient = this.configuration.newClient(); + // Drop and create the collection ``db.decryption_events``. + const db = setupClient.db('db'); + await dropCollection(db, 'decryption_events'); + await db.createCollection('decryption_events'); + // Create a ClientEncryption object named ``clientEncryption`` with these options: + // ClientEncryptionOpts { + // keyVaultClient: , + // keyVaultNamespace: "keyvault.datakeys", + // kmsProviders: { "local": { "key": } } + // } + clientEncryption = new mongodbClientEncryption.ClientEncryption(setupClient, { + keyVaultNamespace: 'keyvault.datakeys', + kmsProviders: getKmsProviders(LOCAL_KEY), + bson: BSON, + extraOptions: getEncryptExtraOptions() + }); + // Create a data key with the "local" KMS provider. + // Storing the result in a variable named ``keyID``. + keyId = await clientEncryption.createDataKey('local'); + // Use ``clientEncryption`` to encrypt the string "hello" with the following ``EncryptOpts``: + // EncryptOpts { + // keyId: , + // algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" + // } + // Store the result in a variable named ``ciphertext``. + cipherText = await clientEncryption.encrypt('hello', { + keyId: keyId, + algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' + }); + // Copy ``ciphertext`` into a variable named ``malformedCiphertext``. + // Change the last byte to 0. This will produce an invalid HMAC tag. + const buffer = Buffer.from(cipherText.buffer); + buffer.writeInt8(0, buffer.length - 1); + malformedCiphertext = new Binary(buffer, 6); + // Create a MongoClient named ``encryptedClient`` with these ``AutoEncryptionOpts``: + // AutoEncryptionOpts { + // keyVaultNamespace: "keyvault.datakeys"; + // kmsProviders: { "local": { "key": } } + // } + // Configure ``encryptedClient`` with "retryReads=false". + encryptedClient = this.configuration.newClient( + {}, + { + retryReads: false, + monitorCommands: true, + autoEncryption: { + keyVaultNamespace: 'keyvault.datakeys', + kmsProviders: getKmsProviders(LOCAL_KEY), + extraOptions: getEncryptExtraOptions() + } + } + ); + // Register a listener for CommandSucceeded events on ``encryptedClient``. + encryptedClient.on('commandSucceeded', event => { + if (event.commandName === 'aggregate') { + aggregateSucceeded = event; + } + }); + // The listener must store the most recent CommandFailedEvent error for the "aggregate" command. + encryptedClient.on('commandFailed', event => { + if (event.commandName === 'aggregate') { + aggregateFailed = event; + } + }); + }); + + afterEach(async function () { + aggregateSucceeded = undefined; + aggregateFailed = undefined; + await setupClient.close(); + await encryptedClient.close(); + }); + + context('Case 1: Command Error', metadata, function () { + beforeEach(async function () { + // Use ``setupClient`` to configure the following failpoint: + // { + // "configureFailPoint": "failCommand", + // "mode": { + // "times": 1 + // }, + // "data": { + // "errorCode": 123, + // "failCommands": [ + // "aggregate" + // ] + // } + // } + await setupClient + .db() + .admin() + .command({ + configureFailPoint: 'failCommand', + mode: { + times: 1 + }, + data: { + errorCode: 123, + failCommands: ['aggregate'] + } + }); + }); + + it('expects an error and a command failed event', async function () { + // Use ``encryptedClient`` to run an aggregate on ``db.decryption_events``. + // Expect an exception to be thrown from the command error. Expect a CommandFailedEvent. + const collection = encryptedClient.db('db').collection('decryption_events'); + try { + await collection.aggregate([]).toArray(); + expect.fail('aggregate must fail with error'); + } catch (error) { + expect(error.code).to.equal(123); + } + expect(aggregateFailed.failure.code).to.equal(123); + }); + }); + + context('Case 2: Network Error', metadata, function () { + beforeEach(async function () { + // Use ``setupClient`` to configure the following failpoint: + // { + // "configureFailPoint": "failCommand", + // "mode": { + // "times": 1 + // }, + // "data": { + // "errorCode": 123, + // "closeConnection": true, + // "failCommands": [ + // "aggregate" + // ] + // } + // } + await setupClient + .db() + .admin() + .command({ + configureFailPoint: 'failCommand', + mode: { + times: 1 + }, + data: { + errorCode: 123, + closeConnection: true, + failCommands: ['aggregate'] + } + }); + }); + + it('expects an error and a command failed event', async function () { + // Use ``encryptedClient`` to run an aggregate on ``db.decryption_events``. + // Expect an exception to be thrown from the network error. Expect a CommandFailedEvent. + const collection = encryptedClient.db('db').collection('decryption_events'); + try { + await collection.aggregate([]).toArray(); + expect.fail('aggregate must fail with error'); + } catch (error) { + expect(error).to.be.instanceOf(MongoNetworkError); + } + expect(aggregateFailed.failure.message).to.include('closed'); + }); + }); + + context('Case 3: Decrypt Error', metadata, function () { + it('errors on decryption but command succeeds', async function () { + // Use ``encryptedClient`` to insert the document ``{ "encrypted": }`` + // into ``db.decryption_events``. + // Use ``encryptedClient`` to run an aggregate on ``db.decryption_events``. + // Expect an exception to be thrown from the decryption error. + // Expect a CommandSucceededEvent. Expect the CommandSucceededEvent.reply + // to contain BSON binary for the field + // ``cursor.firstBatch.encrypted``. + const collection = encryptedClient.db('db').collection('decryption_events'); + await collection.insertOne({ encrypted: malformedCiphertext }); + try { + await collection.aggregate([]).toArray(); + expect.fail('aggregate must fail with error'); + } catch (error) { + expect(error.message).to.include('HMAC validation failure'); + } + const doc = aggregateSucceeded.reply.cursor.firstBatch[0]; + expect(doc.encrypted).to.be.instanceOf(Binary); + }); + }); + + context('Case 4: Decrypt Success', metadata, function () { + it('succeeds on decryption and command succeeds', async function () { + // Use ``encryptedClient`` to insert the document ``{ "encrypted": }`` + // into ``db.decryption_events``. + // Use ``encryptedClient`` to run an aggregate on ``db.decryption_events``. + // Expect no exception. + // Expect a CommandSucceededEvent. Expect the CommandSucceededEvent.reply + // to contain BSON binary for the field ``cursor.firstBatch.encrypted``. + const collection = encryptedClient.db('db').collection('decryption_events'); + await collection.insertOne({ encrypted: cipherText }); + let result; + try { + result = await collection.aggregate([]).toArray(); + } catch (error) { + expect.fail(`aggregate must not fail, got ${error.message}`); + } + expect(result[0].encrypted).to.equal('hello'); + const doc = aggregateSucceeded.reply.cursor.firstBatch[0]; + expect(doc.encrypted).to.be.instanceOf(Binary); + }); + }); +}); diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.test.js b/test/integration/client-side-encryption/client_side_encryption.prose.test.js index 3c14cd65ae7..edfbac4a1d3 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.test.js +++ b/test/integration/client-side-encryption/client_side_encryption.prose.test.js @@ -1850,228 +1850,6 @@ describe('Client Side Encryption Prose Tests', metadata, function () { }); }); - context('14. Decryption Events', metadata, function () { - let setupClient; - let clientEncryption; - let keyId; - let cipherText; - let malformedCiphertext; - let encryptedClient; - let aggregateSucceeded; - let aggregateFailed; - - beforeEach(async function () { - const mongodbClientEncryption = this.configuration.mongodbClientEncryption; - // Create a MongoClient named ``setupClient``. - setupClient = this.configuration.newClient(); - // Drop and create the collection ``db.decryption_events``. - const db = setupClient.db('db'); - await dropCollection(db, 'decryption_events'); - await db.createCollection('decryption_events'); - // Create a ClientEncryption object named ``clientEncryption`` with these options: - // ClientEncryptionOpts { - // keyVaultClient: , - // keyVaultNamespace: "keyvault.datakeys", - // kmsProviders: { "local": { "key": } } - // } - clientEncryption = new mongodbClientEncryption.ClientEncryption(setupClient, { - keyVaultNamespace: 'keyvault.datakeys', - kmsProviders: getKmsProviders(LOCAL_KEY), - bson: BSON, - extraOptions: getEncryptExtraOptions() - }); - // Create a data key with the "local" KMS provider. - // Storing the result in a variable named ``keyID``. - keyId = await clientEncryption.createDataKey('local'); - // Use ``clientEncryption`` to encrypt the string "hello" with the following ``EncryptOpts``: - // EncryptOpts { - // keyId: , - // algorithm: "AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic" - // } - // Store the result in a variable named ``ciphertext``. - cipherText = await clientEncryption.encrypt('hello', { - keyId: keyId, - algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' - }); - // Copy ``ciphertext`` into a variable named ``malformedCiphertext``. - // Change the last byte to 0. This will produce an invalid HMAC tag. - const buffer = Buffer.from(cipherText.buffer); - buffer.writeInt8(0, buffer.length - 1); - malformedCiphertext = new Binary(buffer, 6); - // Create a MongoClient named ``encryptedClient`` with these ``AutoEncryptionOpts``: - // AutoEncryptionOpts { - // keyVaultNamespace: "keyvault.datakeys"; - // kmsProviders: { "local": { "key": } } - // } - // Configure ``encryptedClient`` with "retryReads=false". - encryptedClient = this.configuration.newClient( - {}, - { - retryReads: false, - monitorCommands: true, - autoEncryption: { - keyVaultNamespace: 'keyvault.datakeys', - kmsProviders: getKmsProviders(LOCAL_KEY), - extraOptions: getEncryptExtraOptions() - } - } - ); - // Register a listener for CommandSucceeded events on ``encryptedClient``. - encryptedClient.on('commandSucceeded', event => { - if (event.commandName === 'aggregate') { - aggregateSucceeded = event; - } - }); - // The listener must store the most recent CommandFailedEvent error for the "aggregate" command. - encryptedClient.on('commandFailed', event => { - if (event.commandName === 'aggregate') { - aggregateFailed = event; - } - }); - }); - - afterEach(async function () { - aggregateSucceeded = undefined; - aggregateFailed = undefined; - await setupClient.close(); - await encryptedClient.close(); - }); - - context('Case 1: Command Error', metadata, function () { - beforeEach(async function () { - // Use ``setupClient`` to configure the following failpoint: - // { - // "configureFailPoint": "failCommand", - // "mode": { - // "times": 1 - // }, - // "data": { - // "errorCode": 123, - // "failCommands": [ - // "aggregate" - // ] - // } - // } - await setupClient - .db() - .admin() - .command({ - configureFailPoint: 'failCommand', - mode: { - times: 1 - }, - data: { - errorCode: 123, - failCommands: ['aggregate'] - } - }); - }); - - it('expects an error and a command failed event', async function () { - // Use ``encryptedClient`` to run an aggregate on ``db.decryption_events``. - // Expect an exception to be thrown from the command error. Expect a CommandFailedEvent. - const collection = encryptedClient.db('db').collection('decryption_events'); - try { - await collection.aggregate([]).toArray(); - expect.fail('aggregate must fail with error'); - } catch (error) { - expect(error.code).to.equal(123); - } - expect(aggregateFailed.failure.code).to.equal(123); - }); - }); - - context('Case 2: Network Error', metadata, function () { - beforeEach(async function () { - // Use ``setupClient`` to configure the following failpoint: - // { - // "configureFailPoint": "failCommand", - // "mode": { - // "times": 1 - // }, - // "data": { - // "errorCode": 123, - // "closeConnection": true, - // "failCommands": [ - // "aggregate" - // ] - // } - // } - await setupClient - .db() - .admin() - .command({ - configureFailPoint: 'failCommand', - mode: { - times: 1 - }, - data: { - errorCode: 123, - closeConnection: true, - failCommands: ['aggregate'] - } - }); - }); - - it('expects an error and a command failed event', async function () { - // Use ``encryptedClient`` to run an aggregate on ``db.decryption_events``. - // Expect an exception to be thrown from the network error. Expect a CommandFailedEvent. - const collection = encryptedClient.db('db').collection('decryption_events'); - try { - await collection.aggregate([]).toArray(); - expect.fail('aggregate must fail with error'); - } catch (error) { - expect(error).to.be.instanceOf(MongoNetworkError); - } - expect(aggregateFailed.failure.message).to.include('closed'); - }); - }); - - context('Case 3: Decrypt Error', metadata, function () { - it('errors on decryption but command succeeds', async function () { - // Use ``encryptedClient`` to insert the document ``{ "encrypted": }`` - // into ``db.decryption_events``. - // Use ``encryptedClient`` to run an aggregate on ``db.decryption_events``. - // Expect an exception to be thrown from the decryption error. - // Expect a CommandSucceededEvent. Expect the CommandSucceededEvent.reply - // to contain BSON binary for the field - // ``cursor.firstBatch.encrypted``. - const collection = encryptedClient.db('db').collection('decryption_events'); - await collection.insertOne({ encrypted: malformedCiphertext }); - try { - await collection.aggregate([]).toArray(); - expect.fail('aggregate must fail with error'); - } catch (error) { - expect(error.message).to.include('HMAC validation failure'); - } - const doc = aggregateSucceeded.reply.cursor.firstBatch[0]; - expect(doc.encrypted).to.be.instanceOf(Binary); - }); - }); - - context('Case 4: Decrypt Success', metadata, function () { - it('succeeds on decryption and command succeeds', async function () { - // Use ``encryptedClient`` to insert the document ``{ "encrypted": }`` - // into ``db.decryption_events``. - // Use ``encryptedClient`` to run an aggregate on ``db.decryption_events``. - // Expect no exception. - // Expect a CommandSucceededEvent. Expect the CommandSucceededEvent.reply - // to contain BSON binary for the field ``cursor.firstBatch.encrypted``. - const collection = encryptedClient.db('db').collection('decryption_events'); - await collection.insertOne({ encrypted: cipherText }); - let result; - try { - result = await collection.aggregate([]).toArray(); - } catch (error) { - expect.fail(`aggregate must not fail, got ${error.message}`); - } - expect(result[0].encrypted).to.equal('hello'); - const doc = aggregateSucceeded.reply.cursor.firstBatch[0]; - expect(doc.encrypted).to.be.instanceOf(Binary); - }); - }); - }); - context('16. Rewrap', function () { const masterKeys = { aws: { From 175a7965f23c162ea3cf5760502794e88dd04ef9 Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Wed, 22 Feb 2023 13:26:35 -0500 Subject: [PATCH 02/16] test: use describe --- .../client_side_encryption.prose.14.decrytion_events.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts index fd8ba30a9b3..2cace1c0528 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts @@ -1,4 +1,4 @@ -context('14. Decryption Events', metadata, function () { +describe('14. Decryption Events', metadata, function () { let setupClient; let clientEncryption; let keyId; From efb746b8169debdd1e42183f15c1bd307b4dc55f Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Wed, 22 Feb 2023 13:26:58 -0500 Subject: [PATCH 03/16] test: import chai --- .../client_side_encryption.prose.14.decrytion_events.test.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts index 2cace1c0528..5baa522462c 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts @@ -1,3 +1,5 @@ +import { expect } from 'chai'; + describe('14. Decryption Events', metadata, function () { let setupClient; let clientEncryption; From 86920b18f5deb0f92b4ffd4e6c562d47f8f46d78 Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Wed, 22 Feb 2023 13:27:21 -0500 Subject: [PATCH 04/16] test: add dns hooks --- .../client_side_encryption.prose.14.decrytion_events.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts index 5baa522462c..471ac13a65a 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts @@ -1,6 +1,10 @@ import { expect } from 'chai'; +import { installNodeDNSWorkaroundHooks } from '../../tools/runner/hooks/configuration'; + describe('14. Decryption Events', metadata, function () { + installNodeDNSWorkaroundHooks(); + let setupClient; let clientEncryption; let keyId; From 0c32bfa5c5d9ec9701f3797e1c1ed00347decba5 Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Wed, 22 Feb 2023 13:27:58 -0500 Subject: [PATCH 05/16] test: add metadata --- ...ient_side_encryption.prose.14.decrytion_events.test.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts index 471ac13a65a..beecc6a1002 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts @@ -2,6 +2,14 @@ import { expect } from 'chai'; import { installNodeDNSWorkaroundHooks } from '../../tools/runner/hooks/configuration'; +const metadata = { + requires: { + clientSideEncryption: true, + mongodb: '>=4.2.0', + topology: '!load-balanced' + } +}; + describe('14. Decryption Events', metadata, function () { installNodeDNSWorkaroundHooks(); From d8e5e0d84e0c72598e8e3f4d1cfeaeec445acf5e Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Wed, 22 Feb 2023 13:29:21 -0500 Subject: [PATCH 06/16] test: add local key --- ...lient_side_encryption.prose.14.decrytion_events.test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts index beecc6a1002..f21d98788eb 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts @@ -10,6 +10,11 @@ const metadata = { } }; +const LOCAL_KEY = Buffer.from( + 'Mng0NCt4ZHVUYUJCa1kxNkVyNUR1QURhZ2h2UzR2d2RrZzh0cFBwM3R6NmdWMDFBMUN3YkQ5aXRRMkhGRGdQV09wOGVNYUMxT2k3NjZKelhaQmRCZGJkTXVyZG9uSjFk', + 'base64' +); + describe('14. Decryption Events', metadata, function () { installNodeDNSWorkaroundHooks(); @@ -38,7 +43,7 @@ describe('14. Decryption Events', metadata, function () { // } clientEncryption = new mongodbClientEncryption.ClientEncryption(setupClient, { keyVaultNamespace: 'keyvault.datakeys', - kmsProviders: getKmsProviders(LOCAL_KEY), + kmsProviders: { local: { key: LOCAL_KEY } }, bson: BSON, extraOptions: getEncryptExtraOptions() }); From 5d0775f6709a9c8f6e07a8eb0f075d26c44a5524 Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Wed, 22 Feb 2023 13:29:41 -0500 Subject: [PATCH 07/16] test: import getEncryptExtraOptions --- .../client_side_encryption.prose.14.decrytion_events.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts index f21d98788eb..b23931ddbc4 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts @@ -1,6 +1,7 @@ import { expect } from 'chai'; import { installNodeDNSWorkaroundHooks } from '../../tools/runner/hooks/configuration'; +import { getEncryptExtraOptions } from '../../tools/utils'; const metadata = { requires: { From 9e009a5bca235fef6e710e92431217314e6e8ebe Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Wed, 22 Feb 2023 13:31:09 -0500 Subject: [PATCH 08/16] test: add driver imports, local key usage --- .../client_side_encryption.prose.14.decrytion_events.test.ts | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts index b23931ddbc4..e5c662ed3b9 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts @@ -1,9 +1,10 @@ import { expect } from 'chai'; +import { Binary, BSON, MongoNetworkError } from '../../mongodb'; import { installNodeDNSWorkaroundHooks } from '../../tools/runner/hooks/configuration'; import { getEncryptExtraOptions } from '../../tools/utils'; -const metadata = { +const metadata: MongoDBMetadataUI = { requires: { clientSideEncryption: true, mongodb: '>=4.2.0', @@ -79,7 +80,7 @@ describe('14. Decryption Events', metadata, function () { monitorCommands: true, autoEncryption: { keyVaultNamespace: 'keyvault.datakeys', - kmsProviders: getKmsProviders(LOCAL_KEY), + kmsProviders: { local: { key: LOCAL_KEY } }, extraOptions: getEncryptExtraOptions() } } From c5585924740ff984a44fc761d30eb6e675bfdbef Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Wed, 22 Feb 2023 13:31:55 -0500 Subject: [PATCH 09/16] test: drop collection --- .../client_side_encryption.prose.14.decrytion_events.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts index e5c662ed3b9..d40fb4afb2a 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts @@ -35,7 +35,7 @@ describe('14. Decryption Events', metadata, function () { setupClient = this.configuration.newClient(); // Drop and create the collection ``db.decryption_events``. const db = setupClient.db('db'); - await dropCollection(db, 'decryption_events'); + await db.dropCollection('decryption_events').catch(() => null); await db.createCollection('decryption_events'); // Create a ClientEncryption object named ``clientEncryption`` with these options: // ClientEncryptionOpts { From f4161423e37506633ab588cd0f156c84faa10eee Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Wed, 22 Feb 2023 13:34:21 -0500 Subject: [PATCH 10/16] test: change trycatch usage --- ...cryption.prose.14.decrytion_events.test.ts | 48 +++++++++---------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts index d40fb4afb2a..912ffe8cb80 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts @@ -140,12 +140,13 @@ describe('14. Decryption Events', metadata, function () { // Use ``encryptedClient`` to run an aggregate on ``db.decryption_events``. // Expect an exception to be thrown from the command error. Expect a CommandFailedEvent. const collection = encryptedClient.db('db').collection('decryption_events'); - try { - await collection.aggregate([]).toArray(); - expect.fail('aggregate must fail with error'); - } catch (error) { - expect(error.code).to.equal(123); - } + + const error = await collection + .aggregate([]) + .toArray() + .catch(error => error); + + expect(error.code).to.equal(123); expect(aggregateFailed.failure.code).to.equal(123); }); }); @@ -186,12 +187,13 @@ describe('14. Decryption Events', metadata, function () { // Use ``encryptedClient`` to run an aggregate on ``db.decryption_events``. // Expect an exception to be thrown from the network error. Expect a CommandFailedEvent. const collection = encryptedClient.db('db').collection('decryption_events'); - try { - await collection.aggregate([]).toArray(); - expect.fail('aggregate must fail with error'); - } catch (error) { - expect(error).to.be.instanceOf(MongoNetworkError); - } + + const error = await collection + .aggregate([]) + .toArray() + .catch(error => error); + + expect(error).to.be.instanceOf(MongoNetworkError); expect(aggregateFailed.failure.message).to.include('closed'); }); }); @@ -207,12 +209,13 @@ describe('14. Decryption Events', metadata, function () { // ``cursor.firstBatch.encrypted``. const collection = encryptedClient.db('db').collection('decryption_events'); await collection.insertOne({ encrypted: malformedCiphertext }); - try { - await collection.aggregate([]).toArray(); - expect.fail('aggregate must fail with error'); - } catch (error) { - expect(error.message).to.include('HMAC validation failure'); - } + + const error = await collection + .aggregate([]) + .toArray() + .catch(error => error); + + expect(error.message).to.include('HMAC validation failure'); const doc = aggregateSucceeded.reply.cursor.firstBatch[0]; expect(doc.encrypted).to.be.instanceOf(Binary); }); @@ -228,12 +231,9 @@ describe('14. Decryption Events', metadata, function () { // to contain BSON binary for the field ``cursor.firstBatch.encrypted``. const collection = encryptedClient.db('db').collection('decryption_events'); await collection.insertOne({ encrypted: cipherText }); - let result; - try { - result = await collection.aggregate([]).toArray(); - } catch (error) { - expect.fail(`aggregate must not fail, got ${error.message}`); - } + + const result = await collection.aggregate([]).toArray(); + expect(result[0].encrypted).to.equal('hello'); const doc = aggregateSucceeded.reply.cursor.firstBatch[0]; expect(doc.encrypted).to.be.instanceOf(Binary); From b03193cb06debecf0c3c182b4c342c61b5e8497c Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Wed, 22 Feb 2023 13:38:17 -0500 Subject: [PATCH 11/16] test: use property assertions --- ...cryption.prose.14.decrytion_events.test.ts | 20 ++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts index 912ffe8cb80..66561214b03 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts @@ -146,8 +146,8 @@ describe('14. Decryption Events', metadata, function () { .toArray() .catch(error => error); - expect(error.code).to.equal(123); - expect(aggregateFailed.failure.code).to.equal(123); + expect(error).property('code', 123); + expect(aggregateFailed).nested.property('failure.code', 123); }); }); @@ -194,7 +194,7 @@ describe('14. Decryption Events', metadata, function () { .catch(error => error); expect(error).to.be.instanceOf(MongoNetworkError); - expect(aggregateFailed.failure.message).to.include('closed'); + expect(aggregateFailed).nested.property('failure.message').to.include('closed'); }); }); @@ -215,9 +215,10 @@ describe('14. Decryption Events', metadata, function () { .toArray() .catch(error => error); - expect(error.message).to.include('HMAC validation failure'); - const doc = aggregateSucceeded.reply.cursor.firstBatch[0]; - expect(doc.encrypted).to.be.instanceOf(Binary); + expect(error).property('message').to.include('HMAC validation failure'); + expect(aggregateSucceeded) + .nested.property('reply.cursor.firstBatch[0]') + .to.be.instanceOf(Binary); }); }); @@ -234,9 +235,10 @@ describe('14. Decryption Events', metadata, function () { const result = await collection.aggregate([]).toArray(); - expect(result[0].encrypted).to.equal('hello'); - const doc = aggregateSucceeded.reply.cursor.firstBatch[0]; - expect(doc.encrypted).to.be.instanceOf(Binary); + expect(result).nested.property('[0].encrypted', 'hello'); + expect(aggregateSucceeded) + .nested.property('reply.cursor.firstBatch[0]') + .to.be.instanceOf(Binary); }); }); }); From 823a7266bcb949dbc6eb88040b403dbbc7b46c51 Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Wed, 22 Feb 2023 13:40:40 -0500 Subject: [PATCH 12/16] test: add type annotations --- ...cryption.prose.14.decrytion_events.test.ts | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts index 66561214b03..b93643e6fae 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts @@ -1,6 +1,13 @@ import { expect } from 'chai'; -import { Binary, BSON, MongoNetworkError } from '../../mongodb'; +import { + Binary, + BSON, + CommandFailedEvent, + CommandSucceededEvent, + MongoClient, + MongoNetworkError +} from '../../mongodb'; import { installNodeDNSWorkaroundHooks } from '../../tools/runner/hooks/configuration'; import { getEncryptExtraOptions } from '../../tools/utils'; @@ -20,14 +27,14 @@ const LOCAL_KEY = Buffer.from( describe('14. Decryption Events', metadata, function () { installNodeDNSWorkaroundHooks(); - let setupClient; + let setupClient: MongoClient; let clientEncryption; - let keyId; - let cipherText; - let malformedCiphertext; - let encryptedClient; - let aggregateSucceeded; - let aggregateFailed; + let keyId: Binary; + let cipherText: Binary; + let malformedCiphertext: Binary; + let encryptedClient: MongoClient; + let aggregateSucceeded: CommandSucceededEvent | undefined; + let aggregateFailed: CommandFailedEvent | undefined; beforeEach(async function () { const mongodbClientEncryption = this.configuration.mongodbClientEncryption; From 125f56f544c44e24eb9ee9c7328a60d803c26f0f Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Wed, 22 Feb 2023 13:43:58 -0500 Subject: [PATCH 13/16] test: add w majority to encryptedClient --- .../client_side_encryption.prose.14.decrytion_events.test.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts index b93643e6fae..f9a4030a7c4 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts @@ -83,6 +83,7 @@ describe('14. Decryption Events', metadata, function () { encryptedClient = this.configuration.newClient( {}, { + writeConcern: { w: 'majority' }, retryReads: false, monitorCommands: true, autoEncryption: { From 996d6f3591f287fc7de27ff19ee6de9a1c9a3ca6 Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Wed, 22 Feb 2023 14:04:30 -0500 Subject: [PATCH 14/16] test: fix nested assertions --- .../client_side_encryption.prose.14.decrytion_events.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts index f9a4030a7c4..9fa29814545 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts @@ -225,7 +225,7 @@ describe('14. Decryption Events', metadata, function () { expect(error).property('message').to.include('HMAC validation failure'); expect(aggregateSucceeded) - .nested.property('reply.cursor.firstBatch[0]') + .nested.property('reply.cursor.firstBatch[0].encrypted') .to.be.instanceOf(Binary); }); }); @@ -245,7 +245,7 @@ describe('14. Decryption Events', metadata, function () { expect(result).nested.property('[0].encrypted', 'hello'); expect(aggregateSucceeded) - .nested.property('reply.cursor.firstBatch[0]') + .nested.property('reply.cursor.firstBatch[0].encrypted') .to.be.instanceOf(Binary); }); }); From 01915114cabbcc61942c415e64cc8ad07ab6b294 Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Wed, 22 Feb 2023 14:55:07 -0500 Subject: [PATCH 15/16] lint: fix --- .../client_side_encryption.prose.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.test.js b/test/integration/client-side-encryption/client_side_encryption.prose.test.js index edfbac4a1d3..c026850f631 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.test.js +++ b/test/integration/client-side-encryption/client_side_encryption.prose.test.js @@ -7,9 +7,9 @@ const path = require('path'); const { deadlockTests } = require('./client_side_encryption.prose.deadlock'); const { dropCollection, APMEventCollector } = require('../shared'); -const { EJSON, Binary } = BSON; +const { EJSON } = BSON; const { LEGACY_HELLO_COMMAND } = require('../../mongodb'); -const { MongoNetworkError, MongoServerError } = require('../../mongodb'); +const { MongoServerError } = require('../../mongodb'); const { getEncryptExtraOptions } = require('../../tools/utils'); const { installNodeDNSWorkaroundHooks } = require('../../tools/runner/hooks/configuration'); const { coerce, gte } = require('semver'); From 7e4ec02b582568ba7c4f6689028c5a4beceef942 Mon Sep 17 00:00:00 2001 From: Neal Beeken Date: Mon, 27 Feb 2023 13:01:29 -0500 Subject: [PATCH 16/16] chore: rename & add connecting words --- ..._encryption.prose.14.decryption_events.test.ts} | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) rename test/integration/client-side-encryption/{client_side_encryption.prose.14.decrytion_events.test.ts => client_side_encryption.prose.14.decryption_events.test.ts} (94%) diff --git a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts b/test/integration/client-side-encryption/client_side_encryption.prose.14.decryption_events.test.ts similarity index 94% rename from test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts rename to test/integration/client-side-encryption/client_side_encryption.prose.14.decryption_events.test.ts index 9fa29814545..3b64df7e4a0 100644 --- a/test/integration/client-side-encryption/client_side_encryption.prose.14.decrytion_events.test.ts +++ b/test/integration/client-side-encryption/client_side_encryption.prose.14.decryption_events.test.ts @@ -154,8 +154,8 @@ describe('14. Decryption Events', metadata, function () { .toArray() .catch(error => error); - expect(error).property('code', 123); - expect(aggregateFailed).nested.property('failure.code', 123); + expect(error).to.have.property('code', 123); + expect(aggregateFailed).to.have.nested.property('failure.code', 123); }); }); @@ -202,7 +202,7 @@ describe('14. Decryption Events', metadata, function () { .catch(error => error); expect(error).to.be.instanceOf(MongoNetworkError); - expect(aggregateFailed).nested.property('failure.message').to.include('closed'); + expect(aggregateFailed).to.have.nested.property('failure.message').to.include('closed'); }); }); @@ -223,9 +223,9 @@ describe('14. Decryption Events', metadata, function () { .toArray() .catch(error => error); - expect(error).property('message').to.include('HMAC validation failure'); + expect(error).to.have.property('message').to.include('HMAC validation failure'); expect(aggregateSucceeded) - .nested.property('reply.cursor.firstBatch[0].encrypted') + .to.have.nested.property('reply.cursor.firstBatch[0].encrypted') .to.be.instanceOf(Binary); }); }); @@ -243,9 +243,9 @@ describe('14. Decryption Events', metadata, function () { const result = await collection.aggregate([]).toArray(); - expect(result).nested.property('[0].encrypted', 'hello'); + expect(result).to.have.nested.property('[0].encrypted', 'hello'); expect(aggregateSucceeded) - .nested.property('reply.cursor.firstBatch[0].encrypted') + .to.have.nested.property('reply.cursor.firstBatch[0].encrypted') .to.be.instanceOf(Binary); }); });