Skip to content

Commit 91bb63b

Browse files
feat(NODE-5076): add support for Azure KMS credential auto refresh (#583)
Co-authored-by: Neal Beeken <[email protected]>
1 parent 102d510 commit 91bb63b

16 files changed

+925
-340
lines changed

index.d.ts

+12-1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,16 @@ export class MongoCryptCreateDataKeyError extends MongoCryptError {
6262
cause: Error;
6363
}
6464

65+
/**
66+
* An error indicating that mongodb-client-encryption failed to auto-refresh Azure KMS credentials.
67+
*/
68+
export class MongoCryptAzureKMSRequestError extends MongoCryptError {
69+
/* The body of the IMDS request that produced the error, if present. */
70+
body?: Document ;
71+
}
72+
73+
export class MongoCryptKMSRequestNetworkTimeoutError extends MongoCryptError {}
74+
6575
/**
6676
* A set of options for specifying a Socks5 proxy.
6777
*/
@@ -179,7 +189,8 @@ export interface KMSProviders {
179189
* If present, an access token to authenticate with Azure.
180190
*/
181191
accessToken: string;
182-
};
192+
}
193+
| Record<string, never>;
183194

184195
/**
185196
* Configuration options for using 'gcp' as your KMS provider

lib/autoEncrypter.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ module.exports = function (modules) {
99
const MongoClient = modules.mongodb.MongoClient;
1010
const MongoError = modules.mongodb.MongoError;
1111
const BSON = modules.mongodb.BSON;
12-
const { loadCredentials } = require('./credentialsProvider');
12+
const { loadCredentials } = require('./providers/index');
1313
const cryptoCallbacks = require('./cryptoCallbacks');
1414

1515
/**

lib/clientEncryption.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ module.exports = function (modules) {
1313
MongoCryptCreateEncryptedCollectionError,
1414
MongoCryptCreateDataKeyError
1515
} = require('./errors');
16-
const { loadCredentials } = require('./credentialsProvider');
16+
const { loadCredentials } = require('./providers/index');
1717
const cryptoCallbacks = require('./cryptoCallbacks');
1818
const { promisify } = require('util');
1919

lib/credentialsProvider.js

-90
This file was deleted.

lib/errors.js

+19
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,27 @@ class MongoCryptCreateEncryptedCollectionError extends MongoCryptError {
4949
}
5050
}
5151

52+
/**
53+
* @class
54+
* An error indicating that mongodb-client-encryption failed to auto-refresh Azure KMS credentials.
55+
*/
56+
class MongoCryptAzureKMSRequestError extends MongoCryptError {
57+
/**
58+
* @param {string} message
59+
* @param {object | undefined} body
60+
*/
61+
constructor(message, body) {
62+
super(message);
63+
this.body = body;
64+
}
65+
}
66+
67+
class MongoCryptKMSRequestNetworkTimeoutError extends MongoCryptError {}
68+
5269
module.exports = {
5370
MongoCryptError,
71+
MongoCryptKMSRequestNetworkTimeoutError,
72+
MongoCryptAzureKMSRequestError,
5473
MongoCryptCreateDataKeyError,
5574
MongoCryptCreateEncryptedCollectionError
5675
};

lib/index.js

+25-3
Original file line numberDiff line numberDiff line change
@@ -12,30 +12,46 @@ function loadDefaultModule() {
1212
const {
1313
MongoCryptError,
1414
MongoCryptCreateEncryptedCollectionError,
15-
MongoCryptCreateDataKeyError
15+
MongoCryptCreateDataKeyError,
16+
MongoCryptAzureKMSRequestError,
17+
MongoCryptKMSRequestNetworkTimeoutError
1618
} = require('./errors');
1719

20+
const { fetchAzureKMSToken } = require('./providers/index');
21+
1822
function extension(mongodb) {
1923
const modules = { mongodb };
2024

2125
modules.stateMachine = require('./stateMachine')(modules);
2226
modules.autoEncrypter = require('./autoEncrypter')(modules);
2327
modules.clientEncryption = require('./clientEncryption')(modules);
2428

25-
return {
29+
const exports = {
2630
AutoEncrypter: modules.autoEncrypter.AutoEncrypter,
2731
ClientEncryption: modules.clientEncryption.ClientEncryption,
2832
MongoCryptError,
2933
MongoCryptCreateEncryptedCollectionError,
30-
MongoCryptCreateDataKeyError
34+
MongoCryptCreateDataKeyError,
35+
MongoCryptAzureKMSRequestError,
36+
MongoCryptKMSRequestNetworkTimeoutError
3137
};
38+
39+
Object.defineProperty(exports, '___azureKMSProseTestExports', {
40+
enumerable: false,
41+
configurable: false,
42+
value: fetchAzureKMSToken
43+
});
44+
45+
return exports;
3246
}
3347

3448
module.exports = {
3549
extension,
3650
MongoCryptError,
3751
MongoCryptCreateEncryptedCollectionError,
3852
MongoCryptCreateDataKeyError,
53+
MongoCryptAzureKMSRequestError,
54+
MongoCryptKMSRequestNetworkTimeoutError,
3955
get AutoEncrypter() {
4056
const m = loadDefaultModule();
4157
delete module.exports.AutoEncrypter;
@@ -49,3 +65,9 @@ module.exports = {
4965
return m.ClientEncryption;
5066
}
5167
};
68+
69+
Object.defineProperty(module.exports, '___azureKMSProseTestExports', {
70+
enumerable: false,
71+
configurable: false,
72+
value: fetchAzureKMSToken
73+
});

lib/providers/aws.js

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
'use strict';
2+
3+
let awsCredentialProviders = null;
4+
/** @ignore */
5+
async function loadAWSCredentials(kmsProviders) {
6+
if (awsCredentialProviders == null) {
7+
try {
8+
// Ensure you always wrap an optional require in the try block NODE-3199
9+
awsCredentialProviders = require('@aws-sdk/credential-providers');
10+
// eslint-disable-next-line no-empty
11+
} catch {}
12+
}
13+
14+
if (awsCredentialProviders != null) {
15+
const { fromNodeProviderChain } = awsCredentialProviders;
16+
const provider = fromNodeProviderChain();
17+
// The state machine is the only place calling this so it will
18+
// catch if there is a rejection here.
19+
const aws = await provider();
20+
return { ...kmsProviders, aws };
21+
}
22+
23+
return kmsProviders;
24+
}
25+
26+
module.exports = { loadAWSCredentials };

0 commit comments

Comments
 (0)