Skip to content

Commit 1307757

Browse files
chore(shell-api): simplify key-mangement helpers by using driver helpers MONGOSH-1205 (#1404)
This PR updates the below mentioned methods to start using helpers provided by [libmongocrypt](https://github.com/mongodb/libmongocrypt/blob/f38c549/bindings/node/lib/clientEncryption.js) - KeyVault.getKeys - KeyVault.deleteKey - KeyVault.addKeyAlternateName - KeyVault.removeKeyAlternateName
1 parent 0725693 commit 1307757

File tree

2 files changed

+44
-86
lines changed

2 files changed

+44
-86
lines changed

packages/shell-api/src/field-level-encryption.spec.ts

Lines changed: 34 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import { signatures, toShellResult } from './decorators';
1111
import { ALL_PLATFORMS, ALL_SERVER_VERSIONS, ALL_TOPOLOGIES, ALL_API_VERSIONS } from './enums';
1212
import { ClientEncryption, ClientSideFieldLevelEncryptionOptions, ClientSideFieldLevelEncryptionKmsProvider as KMSProvider, KeyVault } from './field-level-encryption';
1313
import Mongo from './mongo';
14-
import { DeleteResult } from './result';
1514
import ShellInstanceState from './shell-instance-state';
1615
import { CliServiceProvider } from '../../service-provider-server';
1716
import { startTestServer } from '../../../testing/integration-testing-hooks';
@@ -340,6 +339,18 @@ describe('Field Level Encryption', () => {
340339
}
341340
expect.fail('Expected error');
342341
});
342+
it('reads keyAltNames and keyMaterial from DataKeyEncryptionKeyOptions', async() => {
343+
const rawResult = { result: 1 };
344+
const keyVault = await mongo.getKeyVault();
345+
const options = {
346+
keyAltNames: ['b'],
347+
keyMaterial: new bson.Binary(Buffer.from('12345678123498761234123456789012', 'hex'), 4)
348+
};
349+
350+
libmongoc.createDataKey.resolves(rawResult);
351+
await keyVault.createKey('local', options);
352+
expect(libmongoc.createDataKey).calledOnceWithExactly('local', options);
353+
});
343354
});
344355
describe('getKey', () => {
345356
it('calls find on key coll', async() => {
@@ -401,87 +412,45 @@ describe('Field Level Encryption', () => {
401412
});
402413
});
403414
describe('getKeys', () => {
404-
it('calls find on key coll', async() => {
405-
const c = { cursor: 1 } as any;
406-
sp.find.returns(c);
415+
it('calls getKeys on libmongocrypt', async() => {
416+
const c = { count: 1 } as any;
417+
libmongoc.getKeys.returns(c);
407418
const result = await keyVault.getKeys();
408-
expect(sp.find).to.have.been.calledOnceWithExactly(DB, COLL, {}, {});
419+
expect(libmongoc.getKeys).to.have.been.called;
409420
expect(result._cursor).to.deep.equal(c);
410421
});
411422
});
412423
describe('deleteKey', () => {
413-
it('calls deleteOne on key coll', async() => {
414-
const r = { acknowledged: 1, deletedCount: 1 } as any;
415-
sp.deleteOne.resolves(r);
424+
it('calls deleteKey on libmongocrypt', async() => {
425+
const r = { acknowledged: true, deletedCount: 1 } as any;
426+
libmongoc.deleteKey.resolves(r);
416427
const result = await keyVault.deleteKey(KEY_ID);
417-
expect(sp.deleteOne).to.have.been.calledOnceWithExactly(DB, COLL, { _id: KEY_ID }, {});
418-
expect(result).to.deep.equal(new DeleteResult(true, 1));
428+
expect(libmongoc.deleteKey).to.have.been.calledOnceWithExactly(KEY_ID);
429+
expect(result).to.deep.eq(r);
419430
});
420431
});
421432
describe('addKeyAlternateName', () => {
422-
it('calls findOneAndUpdate on key coll', async() => {
433+
it('calls addKeyAltName on libmongocrypt', async() => {
423434
const r = { value: { ok: 1 } } as any;
424-
sp.findOneAndUpdate.resolves(r);
435+
libmongoc.addKeyAltName.resolves(r.value);
425436
const result = await keyVault.addKeyAlternateName(KEY_ID, 'altname');
426-
expect(sp.findOneAndUpdate).to.have.been.calledOnceWithExactly(
427-
DB,
428-
COLL,
429-
{ _id: KEY_ID },
430-
{ $addToSet: { 'keyAltNames': 'altname' }, $currentDate: { 'updateDate': true } },
431-
{ returnDocument: 'before' }
437+
expect(libmongoc.addKeyAltName).to.have.been.calledOnceWithExactly(
438+
KEY_ID,
439+
'altname'
432440
);
433-
expect(result).to.deep.equal({ ok: 1 });
441+
expect(result).to.deep.equal(r.value);
434442
});
435443
});
436444
describe('removeKeyAlternateName', () => {
437-
it('calls findOneAndUpdate on key coll without empty result', async() => {
438-
const r = { value: { ok: 1, keyAltNames: ['other'] } } as any;
439-
sp.findOneAndUpdate.resolves(r);
445+
it('calls removeKeyAltName on libmongocrypt', async() => {
446+
const r = { value: { ok: 1 } } as any;
447+
libmongoc.removeKeyAltName.resolves(r.value);
440448
const result = await keyVault.removeKeyAlternateName(KEY_ID, 'altname');
441-
expect(sp.findOneAndUpdate).to.have.been.calledOnceWithExactly(
442-
DB,
443-
COLL,
444-
{ _id: KEY_ID },
445-
{ $pull: { 'keyAltNames': 'altname' }, $currentDate: { 'updateDate': true } },
446-
{ returnDocument: 'before' }
449+
expect(libmongoc.removeKeyAltName).to.have.been.calledOnceWithExactly(
450+
KEY_ID,
451+
'altname'
447452
);
448-
expect(result).to.deep.equal({ ok: 1, keyAltNames: ['other'] });
449-
});
450-
it('calls findOneAndUpdate on key coll with empty result', async() => {
451-
const r = { value: { ok: 1, keyAltNames: ['altname'] } } as any;
452-
const r2 = { value: { ok: 2 } } as any;
453-
sp.findOneAndUpdate.onFirstCall().resolves(r);
454-
sp.findOneAndUpdate.onSecondCall().resolves(r2);
455-
const result = await keyVault.removeKeyAlternateName(KEY_ID, 'altname');
456-
const calls = sp.findOneAndUpdate.getCalls();
457-
expect(calls.length).to.equal(2);
458-
expect(calls[0].args).to.deep.equal([
459-
DB,
460-
COLL,
461-
{ _id: KEY_ID },
462-
{ $pull: { 'keyAltNames': 'altname' }, $currentDate: { 'updateDate': true } },
463-
{ returnDocument: 'before' }
464-
]);
465-
expect(calls[1].args).to.deep.equal([
466-
DB,
467-
COLL,
468-
{ _id: KEY_ID, keyAltNames: { $size: 0 } },
469-
{ $unset: { 'keyAltNames': '' }, $currentDate: { 'updateDate': true } },
470-
{ returnDocument: 'before' }
471-
]);
472-
expect(result).to.deep.equal(r2.value);
473-
});
474-
it('reads keyAltNames and keyMaterial from DataKeyEncryptionKeyOptions', async() => {
475-
const rawResult = { result: 1 };
476-
const keyVault = await mongo.getKeyVault();
477-
const options = {
478-
keyAltNames: ['b'],
479-
keyMaterial: new bson.Binary(Buffer.from('12345678123498761234123456789012', 'hex'), 4)
480-
};
481-
482-
libmongoc.createDataKey.resolves(rawResult);
483-
await keyVault.createKey('local', options);
484-
expect(libmongoc.createDataKey).calledOnceWithExactly('local', options);
453+
expect(result).to.deep.equal(r.value);
485454
});
486455
});
487456
describe('rewrapManyDataKey', () => {

packages/shell-api/src/field-level-encryption.ts

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -364,47 +364,36 @@ export class KeyVault extends ShellApiWithMongoClass {
364364
return await makeSingleDocReturnValue(() => this._keyColl.find({ 'keyAltNames': keyAltName }), 'KeyVault.getKeyByAltName', this._instanceState);
365365
}
366366

367+
// eslint-disable-next-line @typescript-eslint/require-await
367368
@returnType('Cursor')
368369
@apiVersions([1])
369370
@returnsPromise
370371
async getKeys(): Promise<Cursor> {
371-
return this._keyColl.find({});
372+
return new Cursor(
373+
this._mongo,
374+
this._clientEncryption._libmongocrypt.getKeys()
375+
);
372376
}
373377

374378
@returnsPromise
375379
@apiVersions([1])
376380
async deleteKey(keyId: BinaryType): Promise<DeleteResult | Document> {
377381
assertArgsDefinedType([keyId], [true], 'KeyVault.deleteKey');
378-
return this._keyColl.deleteOne({ '_id': keyId });
382+
return this._clientEncryption._libmongocrypt.deleteKey(keyId);
379383
}
380384

381385
@returnsPromise
382386
@apiVersions([1])
383-
async addKeyAlternateName(keyId: BinaryType, keyAltName: string): Promise<Document> {
387+
async addKeyAlternateName(keyId: BinaryType, keyAltName: string): Promise<Document | null> {
384388
assertArgsDefinedType([keyId, keyAltName], [true, 'string'], 'KeyVault.addKeyAlternateName');
385-
return this._keyColl.findAndModify({
386-
query: { '_id': keyId },
387-
update: { $addToSet: { 'keyAltNames': keyAltName }, $currentDate: { 'updateDate': true } },
388-
});
389+
return this._clientEncryption._libmongocrypt.addKeyAltName(keyId, keyAltName);
389390
}
390391

391392
@returnsPromise
392393
@apiVersions([1])
393-
async removeKeyAlternateName(keyId: BinaryType, keyAltName: string): Promise<Document> {
394+
async removeKeyAlternateName(keyId: BinaryType, keyAltName: string): Promise<Document | null> {
394395
assertArgsDefinedType([keyId, keyAltName], [true, 'string'], 'KeyVault.removeKeyAlternateName');
395-
const ret = await this._keyColl.findAndModify({
396-
query: { '_id': keyId },
397-
update: { $pull: { 'keyAltNames': keyAltName }, $currentDate: { 'updateDate': true } }
398-
});
399-
400-
if (ret !== null && ret.keyAltNames !== undefined && ret.keyAltNames.length === 1 && ret.keyAltNames[0] === keyAltName) {
401-
// Remove the empty array to prevent duplicate key violations
402-
return this._keyColl.findAndModify({
403-
query: { '_id': keyId, 'keyAltNames': { $size: 0 } },
404-
update: { $unset: { 'keyAltNames': '' }, $currentDate: { 'updateDate': true } }
405-
});
406-
}
407-
return ret;
396+
return this._clientEncryption._libmongocrypt.removeKeyAltName(keyId, keyAltName);
408397
}
409398

410399
@returnsPromise

0 commit comments

Comments
 (0)