Skip to content

Commit

Permalink
feat(NODE-4986)!: remove callbacks from ClientEncryption encrypt, dec…
Browse files Browse the repository at this point in the history
…rypt, and createDataKey (#3797)
  • Loading branch information
nbbeeken authored Aug 8, 2023
1 parent 1044be1 commit 51a573f
Show file tree
Hide file tree
Showing 14 changed files with 129 additions and 239 deletions.
2 changes: 0 additions & 2 deletions .evergreen/run-azure-kms-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ source ".evergreen/init-node-and-npm-env.sh"

set -o xtrace

npm install mongodb-client-encryption@alpha

export MONGODB_URI="mongodb://localhost:27017"

export EXPECTED_AZUREKMS_OUTCOME=${EXPECTED_AZUREKMS_OUTCOME:-omitted}
Expand Down
2 changes: 0 additions & 2 deletions .evergreen/run-custom-csfle-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ bash ./etc/build-static.sh

npm run rebuild # just in case this is necessary?

ls
ls lib
BINDINGS_DIR=$(pwd)
popd # libmongocrypt/bindings/node
popd # ../csfle-deps-tmp
Expand Down
1 change: 0 additions & 1 deletion .evergreen/run-gcp-kms-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ source ".evergreen/init-node-and-npm-env.sh"

set -o xtrace

npm install mongodb-client-encryption@alpha
npm install gcp-metadata

export MONGODB_URI="mongodb://localhost:27017"
Expand Down
2 changes: 0 additions & 2 deletions .evergreen/run-serverless-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@ if [ -z ${MONGODB_URI+omitted} ]; then echo "MONGODB_URI is unset" && exit 1; fi
if [ -z ${SERVERLESS_ATLAS_USER+omitted} ]; then echo "SERVERLESS_ATLAS_USER is unset" && exit 1; fi
if [ -z ${SERVERLESS_ATLAS_PASSWORD+omitted} ]; then echo "SERVERLESS_ATLAS_PASSWORD is unset" && exit 1; fi

npm install mongodb-client-encryption@alpha

npx mocha \
--config test/mocha_mongodb.json \
test/integration/crud/crud.spec.test.js \
Expand Down
1 change: 0 additions & 1 deletion .evergreen/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ else
source "$DRIVERS_TOOLS"/.evergreen/csfle/set-temp-creds.sh
fi

npm install mongodb-client-encryption@alpha
npm install @mongodb-js/zstd
npm install snappy

Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@
"js-yaml": "^4.1.0",
"mocha": "^10.2.0",
"mocha-sinon": "^2.1.2",
"mongodb-client-encryption": "^6.0.0-alpha.1",
"mongodb-client-encryption": "6.0.0-alpha.1",
"mongodb-legacy": "^5.0.0",
"nyc": "^15.1.0",
"prettier": "^2.8.8",
Expand Down
3 changes: 2 additions & 1 deletion src/bson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ export {
MinKey,
ObjectId,
serialize,
Timestamp
Timestamp,
UUID
} from 'bson';

/**
Expand Down
126 changes: 29 additions & 97 deletions src/client-side-encryption/client_encryption.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type {
MongoCryptOptions
} from 'mongodb-client-encryption';

import { type Binary, type Document, type Long, serialize } from '../bson';
import { type Binary, type Document, type Long, serialize, type UUID } from '../bson';
import { type AnyBulkWriteOperation, type BulkWriteResult } from '../bulk/common';
import { type ProxyOptions } from '../cmap/connection';
import { type Collection } from '../collection';
Expand All @@ -16,8 +16,7 @@ import { type MongoClient } from '../mongo_client';
import { type Filter } from '../mongo_types';
import { type CreateCollectionOptions } from '../operations/create_collection';
import { type DeleteResult } from '../operations/delete';
import { type Callback, MongoDBCollectionNamespace } from '../utils';
import { maybeCallback, promiseOrCallback } from './common';
import { MongoDBCollectionNamespace } from '../utils';
import * as cryptoCallbacks from './crypto_callbacks';
import {
MongoCryptCreateDataKeyError,
Expand All @@ -36,7 +35,7 @@ import { type CSFLEKMSTlsOptions, StateMachine } from './state_machine';
* The schema for a DataKey in the key vault collection.
*/
export interface DataKey {
_id: Binary;
_id: UUID;
version?: number;
keyAltNames?: string[];
keyMaterial: Binary;
Expand Down Expand Up @@ -133,18 +132,6 @@ export class ClientEncryption {
*
* @example
* ```ts
* // Using callbacks to create a local key
* clientEncryption.createDataKey('local', (err, dataKey) => {
* if (err) {
* // This means creating the key failed.
* } else {
* // key creation succeeded
* }
* });
* ```
*
* @example
* ```ts
* // Using async/await to create a local key
* const dataKeyId = await clientEncryption.createDataKey('local');
* ```
Expand Down Expand Up @@ -172,21 +159,10 @@ export class ClientEncryption {
* });
* ```
*/
createDataKey(
async createDataKey(
provider: ClientEncryptionDataKeyProvider,
options?: ClientEncryptionCreateDataKeyProviderOptions,
callback?: Callback<DataKey>
) {
if (typeof options === 'function') {
callback = options;
options = {};
}
if (options == null) {
options = {};
}

const dataKey = Object.assign({ provider }, options.masterKey);

options: ClientEncryptionCreateDataKeyProviderOptions = {}
): Promise<UUID> {
if (options.keyAltNames && !Array.isArray(options.keyAltNames)) {
throw new MongoCryptInvalidArgumentError(
`Option "keyAltNames" must be an array of strings, but was of type ${typeof options.keyAltNames}.`
Expand All @@ -211,42 +187,33 @@ export class ClientEncryption {
keyMaterial = serialize({ keyMaterial: options.keyMaterial });
}

const dataKeyBson = serialize(dataKey);
const dataKeyBson = serialize({
provider,
...options.masterKey
});

const context = this._mongoCrypt.makeDataKeyContext(dataKeyBson, {
keyAltNames,
keyMaterial
});

const stateMachine = new StateMachine({
proxyOptions: this._proxyOptions,
tlsOptions: this._tlsOptions
});

// @ts-expect-error We did not convert promiseOrCallback to TS
return promiseOrCallback(callback, cb => {
stateMachine.execute<DataKey>(this, context, (err, dataKey) => {
if (err || !dataKey) {
cb(err, null);
return;
}
const dataKey = await stateMachine.executeAsync<DataKey>(this, context);

const { db: dbName, collection: collectionName } = MongoDBCollectionNamespace.fromString(
this._keyVaultNamespace
);
const { db: dbName, collection: collectionName } = MongoDBCollectionNamespace.fromString(
this._keyVaultNamespace
);

this._keyVaultClient
.db(dbName)
.collection<DataKey>(collectionName)
.insertOne(dataKey, { writeConcern: { w: 'majority' } })
.then(
result => {
return cb(null, result.insertedId);
},
err => {
cb(err, null);
}
);
});
});
const { insertedId } = await this._keyVaultClient
.db(dbName)
.collection<DataKey>(collectionName)
.insertOne(dataKey, { writeConcern: { w: 'majority' } });

return insertedId;
}

/**
Expand Down Expand Up @@ -601,21 +568,7 @@ export class ClientEncryption {
*
* @param value - The value that you wish to serialize. Must be of a type that can be serialized into BSON
* @param options -
* @param callback - Optional callback to invoke when value is encrypted
* @returns If no callback is provided, returns a Promise that either resolves with the encrypted value, or rejects with an error. If a callback is provided, returns nothing.
*
* @example
* ```ts
* // Encryption with callback API
* function encryptMyData(value, callback) {
* clientEncryption.createDataKey('local', (err, keyId) => {
* if (err) {
* return callback(err);
* }
* clientEncryption.encrypt(value, { keyId, algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic' }, callback);
* });
* }
* ```
* @returns a Promise that either resolves with the encrypted value, or rejects with an error.
*
* @example
* ```ts
Expand All @@ -635,12 +588,8 @@ export class ClientEncryption {
* }
* ```
*/
encrypt(
value: unknown,
options: ClientEncryptionEncryptOptions,
callback: Callback<Binary>
): Promise<Binary> | void {
return maybeCallback(() => this._encrypt(value, false, options), callback);
async encrypt(value: unknown, options: ClientEncryptionEncryptOptions): Promise<Binary> {
return this._encrypt(value, false, options);
}

/**
Expand Down Expand Up @@ -672,16 +621,7 @@ export class ClientEncryption {
* Explicitly decrypt a provided encrypted value
*
* @param value - An encrypted value
* @param callback - Optional callback to invoke when value is decrypted
* @returns If no callback is provided, returns a Promise that either resolves with the decrypted value, or rejects with an error. If a callback is provided, returns nothing.
*
* ```ts
* @example
* // Decrypting value with callback API
* function decryptMyValue(value, callback) {
* clientEncryption.decrypt(value, callback);
* }
* ```
* @returns a Promise that either resolves with the decrypted value, or rejects with an error
*
* @example
* ```ts
Expand All @@ -691,7 +631,7 @@ export class ClientEncryption {
* }
* ```
*/
decrypt<T = any>(value: Binary, callback?: Callback<T>): Promise<T> | void {
async decrypt<T = any>(value: Binary): Promise<T> {
const valueBuffer = serialize({ v: value });
const context = this._mongoCrypt.makeExplicitDecryptionContext(valueBuffer);

Expand All @@ -700,17 +640,9 @@ export class ClientEncryption {
tlsOptions: this._tlsOptions
});

// @ts-expect-error We did not convert promiseOrCallback to TS
return promiseOrCallback(callback, cb => {
stateMachine.execute<{ v: T }>(this, context, (err, result) => {
if (err || !result) {
cb(err, null);
return;
}
const { v } = await stateMachine.executeAsync<{ v: T }>(this, context);

cb(null, result.v);
});
});
return v;
}

/**
Expand Down
3 changes: 2 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ export {
MaxKey,
MinKey,
ObjectId,
Timestamp
Timestamp,
UUID
} from './bson';
export { AnyBulkWriteOperation, BulkWriteOptions, MongoBulkWriteError } from './bulk/common';
export { ClientEncryption } from './client-side-encryption/client_encryption';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import * as BSON from 'bson';
import { expect } from 'chai';
import { readFileSync } from 'fs';
import * as path from 'path';
import * as util from 'util';

// eslint-disable-next-line @typescript-eslint/no-restricted-imports
import { ClientEncryption } from '../../../src/client-side-encryption/client_encryption';
Expand Down Expand Up @@ -138,11 +137,8 @@ describe('Connection Pool Deadlock Prevention', function () {
keyVaultClient: this.keyVaultClient,
extraOptions: getEncryptExtraOptions()
});
this.clientEncryption.encryptPromisified = util.promisify(
this.clientEncryption.encrypt.bind(this.clientEncryption)
);

this.ciphertext = await this.clientEncryption.encryptPromisified('string0', {
this.ciphertext = await this.clientEncryption.encrypt('string0', {
algorithm: 'AEAD_AES_256_CBC_HMAC_SHA_512-Deterministic',
keyAltName: 'local'
});
Expand Down
Loading

0 comments on commit 51a573f

Please sign in to comment.