Skip to content

Commit 3d047ed

Browse files
authoredMar 14, 2025··
feat(NODE-6141): allow custom aws sdk config (#4373)
1 parent 6895b25 commit 3d047ed

12 files changed

+323
-47
lines changed
 

‎src/client-side-encryption/auto_encrypter.ts

+17-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,12 @@ import { autoSelectSocketOptions } from './client_encryption';
1717
import * as cryptoCallbacks from './crypto_callbacks';
1818
import { MongoCryptInvalidArgumentError } from './errors';
1919
import { MongocryptdManager } from './mongocryptd_manager';
20-
import { type KMSProviders, refreshKMSCredentials } from './providers';
20+
import {
21+
type CredentialProviders,
22+
isEmptyCredentials,
23+
type KMSProviders,
24+
refreshKMSCredentials
25+
} from './providers';
2126
import { type CSFLEKMSTlsOptions, StateMachine } from './state_machine';
2227

2328
/** @public */
@@ -30,6 +35,8 @@ export interface AutoEncryptionOptions {
3035
keyVaultNamespace?: string;
3136
/** Configuration options that are used by specific KMS providers during key generation, encryption, and decryption. */
3237
kmsProviders?: KMSProviders;
38+
/** Configuration options for custom credential providers. */
39+
credentialProviders?: CredentialProviders;
3340
/**
3441
* A map of namespaces to a local JSON schema for encryption
3542
*
@@ -153,6 +160,7 @@ export class AutoEncrypter {
153160
_kmsProviders: KMSProviders;
154161
_bypassMongocryptdAndCryptShared: boolean;
155162
_contextCounter: number;
163+
_credentialProviders?: CredentialProviders;
156164

157165
_mongocryptdManager?: MongocryptdManager;
158166
_mongocryptdClient?: MongoClient;
@@ -237,6 +245,13 @@ export class AutoEncrypter {
237245
this._proxyOptions = options.proxyOptions || {};
238246
this._tlsOptions = options.tlsOptions || {};
239247
this._kmsProviders = options.kmsProviders || {};
248+
this._credentialProviders = options.credentialProviders;
249+
250+
if (options.credentialProviders?.aws && !isEmptyCredentials('aws', this._kmsProviders)) {
251+
throw new MongoCryptInvalidArgumentError(
252+
'Can only provide a custom AWS credential provider when the state machine is configured for automatic AWS credential fetching'
253+
);
254+
}
240255

241256
const mongoCryptOptions: MongoCryptOptions = {
242257
enableMultipleCollinfo: true,
@@ -439,7 +454,7 @@ export class AutoEncrypter {
439454
* the original ones.
440455
*/
441456
async askForKMSCredentials(): Promise<KMSProviders> {
442-
return await refreshKMSCredentials(this._kmsProviders);
457+
return await refreshKMSCredentials(this._kmsProviders, this._credentialProviders);
443458
}
444459

445460
/**

‎src/client-side-encryption/client_encryption.ts

+18-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ import {
3434
} from './errors';
3535
import {
3636
type ClientEncryptionDataKeyProvider,
37+
type CredentialProviders,
38+
isEmptyCredentials,
3739
type KMSProviders,
3840
refreshKMSCredentials
3941
} from './providers/index';
@@ -81,6 +83,9 @@ export class ClientEncryption {
8183
/** @internal */
8284
_mongoCrypt: MongoCrypt;
8385

86+
/** @internal */
87+
_credentialProviders?: CredentialProviders;
88+
8489
/** @internal */
8590
static getMongoCrypt(): MongoCryptConstructor {
8691
const encryption = getMongoDBClientEncryption();
@@ -125,6 +130,13 @@ export class ClientEncryption {
125130
this._kmsProviders = options.kmsProviders || {};
126131
const { timeoutMS } = resolveTimeoutOptions(client, options);
127132
this._timeoutMS = timeoutMS;
133+
this._credentialProviders = options.credentialProviders;
134+
135+
if (options.credentialProviders?.aws && !isEmptyCredentials('aws', this._kmsProviders)) {
136+
throw new MongoCryptInvalidArgumentError(
137+
'Can only provide a custom AWS credential provider when the state machine is configured for automatic AWS credential fetching'
138+
);
139+
}
128140

129141
if (options.keyVaultNamespace == null) {
130142
throw new MongoCryptInvalidArgumentError('Missing required option `keyVaultNamespace`');
@@ -712,7 +724,7 @@ export class ClientEncryption {
712724
* the original ones.
713725
*/
714726
async askForKMSCredentials(): Promise<KMSProviders> {
715-
return await refreshKMSCredentials(this._kmsProviders);
727+
return await refreshKMSCredentials(this._kmsProviders, this._credentialProviders);
716728
}
717729

718730
static get libmongocryptVersion() {
@@ -858,6 +870,11 @@ export interface ClientEncryptionOptions {
858870
*/
859871
kmsProviders?: KMSProviders;
860872

873+
/**
874+
* Options for user provided custom credential providers.
875+
*/
876+
credentialProviders?: CredentialProviders;
877+
861878
/**
862879
* Options for specifying a Socks5 proxy to use for connecting to the KMS.
863880
*/

‎src/client-side-encryption/providers/aws.ts

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
import { AWSSDKCredentialProvider } from '../../cmap/auth/aws_temporary_credentials';
1+
import {
2+
type AWSCredentialProvider,
3+
AWSSDKCredentialProvider
4+
} from '../../cmap/auth/aws_temporary_credentials';
25
import { type KMSProviders } from '.';
36

47
/**
58
* @internal
69
*/
7-
export async function loadAWSCredentials(kmsProviders: KMSProviders): Promise<KMSProviders> {
8-
const credentialProvider = new AWSSDKCredentialProvider();
10+
export async function loadAWSCredentials(
11+
kmsProviders: KMSProviders,
12+
provider?: AWSCredentialProvider
13+
): Promise<KMSProviders> {
14+
const credentialProvider = new AWSSDKCredentialProvider(provider);
915

1016
// We shouldn't ever receive a response from the AWS SDK that doesn't have a `SecretAccessKey`
1117
// or `AccessKeyId`. However, TS says these fields are optional. We provide empty strings

‎src/client-side-encryption/providers/index.ts

+15-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import type { Binary } from '../../bson';
2+
import { type AWSCredentialProvider } from '../../cmap/auth/aws_temporary_credentials';
23
import { loadAWSCredentials } from './aws';
34
import { loadAzureCredentials } from './azure';
45
import { loadGCPCredentials } from './gcp';
@@ -112,6 +113,15 @@ export type GCPKMSProviderConfiguration =
112113
accessToken: string;
113114
};
114115

116+
/**
117+
* @public
118+
* Configuration options for custom credential providers for KMS requests.
119+
*/
120+
export interface CredentialProviders {
121+
/* A custom AWS credential provider */
122+
aws?: AWSCredentialProvider;
123+
}
124+
115125
/**
116126
* @public
117127
* Configuration options that are used by specific KMS providers during key generation, encryption, and decryption.
@@ -176,11 +186,14 @@ export function isEmptyCredentials(
176186
*
177187
* @internal
178188
*/
179-
export async function refreshKMSCredentials(kmsProviders: KMSProviders): Promise<KMSProviders> {
189+
export async function refreshKMSCredentials(
190+
kmsProviders: KMSProviders,
191+
credentialProviders?: CredentialProviders
192+
): Promise<KMSProviders> {
180193
let finalKMSProviders = kmsProviders;
181194

182195
if (isEmptyCredentials('aws', kmsProviders)) {
183-
finalKMSProviders = await loadAWSCredentials(finalKMSProviders);
196+
finalKMSProviders = await loadAWSCredentials(finalKMSProviders, credentialProviders?.aws);
184197
}
185198

186199
if (isEmptyCredentials('gcp', kmsProviders)) {

‎src/cmap/auth/aws_temporary_credentials.ts

+17-1
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ export interface AWSTempCredentials {
2121
Expiration?: Date;
2222
}
2323

24+
/** @public **/
25+
export type AWSCredentialProvider = () => Promise<AWSCredentials>;
26+
2427
/**
2528
* @internal
2629
*
@@ -41,7 +44,20 @@ export abstract class AWSTemporaryCredentialProvider {
4144

4245
/** @internal */
4346
export class AWSSDKCredentialProvider extends AWSTemporaryCredentialProvider {
44-
private _provider?: () => Promise<AWSCredentials>;
47+
private _provider?: AWSCredentialProvider;
48+
49+
/**
50+
* Create the SDK credentials provider.
51+
* @param credentialsProvider - The credentials provider.
52+
*/
53+
constructor(credentialsProvider?: AWSCredentialProvider) {
54+
super();
55+
56+
if (credentialsProvider) {
57+
this._provider = credentialsProvider;
58+
}
59+
}
60+
4561
/**
4662
* The AWS SDK caches credentials automatically and handles refresh when the credentials have expired.
4763
* To ensure this occurs, we need to cache the `provider` returned by the AWS sdk and re-use it when fetching credentials.

‎src/cmap/auth/mongo_credentials.ts

+28
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
MongoInvalidArgumentError,
77
MongoMissingCredentialsError
88
} from '../../error';
9+
import type { AWSCredentialProvider } from './aws_temporary_credentials';
910
import { GSSAPICanonicalizationValue } from './gssapi';
1011
import type { OIDCCallbackFunction } from './mongodb_oidc';
1112
import { AUTH_MECHS_AUTH_SRC_EXTERNAL, AuthMechanism } from './providers';
@@ -68,6 +69,33 @@ export interface AuthMechanismProperties extends Document {
6869
ALLOWED_HOSTS?: string[];
6970
/** The resource token for OIDC auth in Azure and GCP. */
7071
TOKEN_RESOURCE?: string;
72+
/**
73+
* A custom AWS credential provider to use. An example using the AWS SDK default provider chain:
74+
*
75+
* ```ts
76+
* const client = new MongoClient(process.env.MONGODB_URI, {
77+
* authMechanismProperties: {
78+
* AWS_CREDENTIAL_PROVIDER: fromNodeProviderChain()
79+
* }
80+
* });
81+
* ```
82+
*
83+
* Using a custom function that returns AWS credentials:
84+
*
85+
* ```ts
86+
* const client = new MongoClient(process.env.MONGODB_URI, {
87+
* authMechanismProperties: {
88+
* AWS_CREDENTIAL_PROVIDER: async () => {
89+
* return {
90+
* accessKeyId: process.env.ACCESS_KEY_ID,
91+
* secretAccessKey: process.env.SECRET_ACCESS_KEY
92+
* }
93+
* }
94+
* }
95+
* });
96+
* ```
97+
*/
98+
AWS_CREDENTIAL_PROVIDER?: AWSCredentialProvider;
7199
}
72100

73101
/** @public */

‎src/cmap/auth/mongodb_aws.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
import { ByteUtils, maxWireVersion, ns, randomBytes } from '../../utils';
1010
import { type AuthContext, AuthProvider } from './auth_provider';
1111
import {
12+
type AWSCredentialProvider,
1213
AWSSDKCredentialProvider,
1314
type AWSTempCredentials,
1415
AWSTemporaryCredentialProvider,
@@ -34,11 +35,14 @@ interface AWSSaslContinuePayload {
3435

3536
export class MongoDBAWS extends AuthProvider {
3637
private credentialFetcher: AWSTemporaryCredentialProvider;
37-
constructor() {
38+
private credentialProvider?: AWSCredentialProvider;
39+
40+
constructor(credentialProvider?: AWSCredentialProvider) {
3841
super();
3942

43+
this.credentialProvider = credentialProvider;
4044
this.credentialFetcher = AWSTemporaryCredentialProvider.isAWSSDKInstalled
41-
? new AWSSDKCredentialProvider()
45+
? new AWSSDKCredentialProvider(credentialProvider)
4246
: new LegacyAWSTemporaryCredentialProvider();
4347
}
4448

‎src/deps.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,14 @@ export function getZstdLibrary(): ZStandardLib | { kModuleError: MongoMissingDep
7878
}
7979

8080
/**
81-
* @internal
81+
* @public
8282
* Copy of the AwsCredentialIdentityProvider interface from [`smithy/types`](https://socket.dev/npm/package/\@smithy/types/files/1.1.1/dist-types/identity/awsCredentialIdentity.d.ts),
8383
* the return type of the aws-sdk's `fromNodeProviderChain().provider()`.
8484
*/
8585
export interface AWSCredentials {
8686
accessKeyId: string;
8787
secretAccessKey: string;
88-
sessionToken: string;
88+
sessionToken?: string;
8989
expiration?: Date;
9090
}
9191

‎src/index.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,11 @@ export { ReadPreferenceMode } from './read_preference';
128128
export { ServerType, TopologyType } from './sdam/common';
129129

130130
// Helper classes
131+
export type { AWSCredentialProvider } from './cmap/auth/aws_temporary_credentials';
132+
export type { AWSCredentials } from './deps';
131133
export { ReadConcern } from './read_concern';
132134
export { ReadPreference } from './read_preference';
133135
export { WriteConcern } from './write_concern';
134-
135136
// events
136137
export {
137138
CommandFailedEvent,
@@ -255,6 +256,7 @@ export type {
255256
AWSKMSProviderConfiguration,
256257
AzureKMSProviderConfiguration,
257258
ClientEncryptionDataKeyProvider,
259+
CredentialProviders,
258260
GCPKMSProviderConfiguration,
259261
KMIPKMSProviderConfiguration,
260262
KMSProviders,

‎src/mongo_client_auth_providers.ts

+26-29
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,14 @@ import { X509 } from './cmap/auth/x509';
1313
import { MongoInvalidArgumentError } from './error';
1414

1515
/** @internal */
16-
const AUTH_PROVIDERS = new Map<AuthMechanism | string, (workflow?: Workflow) => AuthProvider>([
17-
[AuthMechanism.MONGODB_AWS, () => new MongoDBAWS()],
16+
const AUTH_PROVIDERS = new Map<
17+
AuthMechanism | string,
18+
(authMechanismProperties: AuthMechanismProperties) => AuthProvider
19+
>([
20+
[
21+
AuthMechanism.MONGODB_AWS,
22+
({ AWS_CREDENTIAL_PROVIDER }) => new MongoDBAWS(AWS_CREDENTIAL_PROVIDER)
23+
],
1824
[
1925
AuthMechanism.MONGODB_CR,
2026
() => {
@@ -24,7 +30,7 @@ const AUTH_PROVIDERS = new Map<AuthMechanism | string, (workflow?: Workflow) =>
2430
}
2531
],
2632
[AuthMechanism.MONGODB_GSSAPI, () => new GSSAPI()],
27-
[AuthMechanism.MONGODB_OIDC, (workflow?: Workflow) => new MongoDBOIDC(workflow)],
33+
[AuthMechanism.MONGODB_OIDC, properties => new MongoDBOIDC(getWorkflow(properties))],
2834
[AuthMechanism.MONGODB_PLAIN, () => new Plain()],
2935
[AuthMechanism.MONGODB_SCRAM_SHA1, () => new ScramSHA1()],
3036
[AuthMechanism.MONGODB_SCRAM_SHA256, () => new ScramSHA256()],
@@ -62,37 +68,28 @@ export class MongoClientAuthProviders {
6268
throw new MongoInvalidArgumentError(`authMechanism ${name} not supported`);
6369
}
6470

65-
let provider;
66-
if (name === AuthMechanism.MONGODB_OIDC) {
67-
provider = providerFunction(this.getWorkflow(authMechanismProperties));
68-
} else {
69-
provider = providerFunction();
70-
}
71-
71+
const provider = providerFunction(authMechanismProperties);
7272
this.existingProviders.set(name, provider);
7373
return provider;
7474
}
75+
}
7576

76-
/**
77-
* Gets either a device workflow or callback workflow.
78-
*/
79-
getWorkflow(authMechanismProperties: AuthMechanismProperties): Workflow {
80-
if (authMechanismProperties.OIDC_HUMAN_CALLBACK) {
81-
return new HumanCallbackWorkflow(
82-
new TokenCache(),
83-
authMechanismProperties.OIDC_HUMAN_CALLBACK
77+
/**
78+
* Gets either a device workflow or callback workflow.
79+
*/
80+
function getWorkflow(authMechanismProperties: AuthMechanismProperties): Workflow {
81+
if (authMechanismProperties.OIDC_HUMAN_CALLBACK) {
82+
return new HumanCallbackWorkflow(new TokenCache(), authMechanismProperties.OIDC_HUMAN_CALLBACK);
83+
} else if (authMechanismProperties.OIDC_CALLBACK) {
84+
return new AutomatedCallbackWorkflow(new TokenCache(), authMechanismProperties.OIDC_CALLBACK);
85+
} else {
86+
const environment = authMechanismProperties.ENVIRONMENT;
87+
const workflow = OIDC_WORKFLOWS.get(environment)?.();
88+
if (!workflow) {
89+
throw new MongoInvalidArgumentError(
90+
`Could not load workflow for environment ${authMechanismProperties.ENVIRONMENT}`
8491
);
85-
} else if (authMechanismProperties.OIDC_CALLBACK) {
86-
return new AutomatedCallbackWorkflow(new TokenCache(), authMechanismProperties.OIDC_CALLBACK);
87-
} else {
88-
const environment = authMechanismProperties.ENVIRONMENT;
89-
const workflow = OIDC_WORKFLOWS.get(environment)?.();
90-
if (!workflow) {
91-
throw new MongoInvalidArgumentError(
92-
`Could not load workflow for environment ${authMechanismProperties.ENVIRONMENT}`
93-
);
94-
}
95-
return workflow;
9692
}
93+
return workflow;
9794
}
9895
}

‎test/integration/auth/mongodb_aws.test.ts

+70-4
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,47 @@ describe('MONGODB-AWS', function () {
136136
});
137137
});
138138

139+
context('when user supplies a credentials provider', function () {
140+
let providerCount = 0;
141+
142+
beforeEach(function () {
143+
if (!awsSdkPresent) {
144+
this.skipReason = 'only relevant to AssumeRoleWithWebIdentity with SDK installed';
145+
return this.skip();
146+
}
147+
// If we have a username the credentials have been set from the URI, options, or environment
148+
// variables per the auth spec stated order.
149+
if (client.options.credentials.username) {
150+
this.skipReason = 'Credentials in the URI on env variables will not use custom provider.';
151+
return this.skip();
152+
}
153+
});
154+
155+
it('authenticates with a user provided credentials provider', async function () {
156+
// @ts-expect-error We intentionally access a protected variable.
157+
const credentialProvider = AWSTemporaryCredentialProvider.awsSDK;
158+
const provider = async () => {
159+
providerCount++;
160+
return await credentialProvider.fromNodeProviderChain().apply();
161+
};
162+
client = this.configuration.newClient(process.env.MONGODB_URI, {
163+
authMechanismProperties: {
164+
AWS_CREDENTIAL_PROVIDER: provider
165+
}
166+
});
167+
168+
const result = await client
169+
.db('aws')
170+
.collection('aws_test')
171+
.estimatedDocumentCount()
172+
.catch(error => error);
173+
174+
expect(result).to.not.be.instanceOf(MongoServerError);
175+
expect(result).to.be.a('number');
176+
expect(providerCount).to.be.greaterThan(0);
177+
});
178+
});
179+
139180
it('should allow empty string in authMechanismProperties.AWS_SESSION_TOKEN to override AWS_SESSION_TOKEN environment variable', function () {
140181
client = this.configuration.newClient(this.configuration.url(), {
141182
authMechanismProperties: { AWS_SESSION_TOKEN: '' }
@@ -426,11 +467,36 @@ describe('AWS KMS Credential Fetching', function () {
426467
: undefined;
427468
this.currentTest?.skipReason && this.skip();
428469
});
429-
it('KMS credentials are successfully fetched.', async function () {
430-
const { aws } = await refreshKMSCredentials({ aws: {} });
431470

432-
expect(aws).to.have.property('accessKeyId');
433-
expect(aws).to.have.property('secretAccessKey');
471+
context('when a credential provider is not provided', function () {
472+
it('KMS credentials are successfully fetched.', async function () {
473+
const { aws } = await refreshKMSCredentials({ aws: {} });
474+
475+
expect(aws).to.have.property('accessKeyId');
476+
expect(aws).to.have.property('secretAccessKey');
477+
});
478+
});
479+
480+
context('when a credential provider is provided', function () {
481+
let credentialProvider;
482+
let providerCount = 0;
483+
484+
beforeEach(function () {
485+
// @ts-expect-error We intentionally access a protected variable.
486+
const provider = AWSTemporaryCredentialProvider.awsSDK;
487+
credentialProvider = async () => {
488+
providerCount++;
489+
return await provider.fromNodeProviderChain().apply();
490+
};
491+
});
492+
493+
it('KMS credentials are successfully fetched.', async function () {
494+
const { aws } = await refreshKMSCredentials({ aws: {} }, { aws: credentialProvider });
495+
496+
expect(aws).to.have.property('accessKeyId');
497+
expect(aws).to.have.property('secretAccessKey');
498+
expect(providerCount).to.be.greaterThan(0);
499+
});
434500
});
435501

436502
it('does not return any extra keys for the `aws` credential provider', async function () {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
import { expect } from 'chai';
2+
3+
/* eslint-disable @typescript-eslint/no-restricted-imports */
4+
import { ClientEncryption } from '../../../src/client-side-encryption/client_encryption';
5+
import { AWSTemporaryCredentialProvider, Binary, MongoClient } from '../../mongodb';
6+
import { getEncryptExtraOptions } from '../../tools/utils';
7+
8+
const metadata: MongoDBMetadataUI = {
9+
requires: {
10+
clientSideEncryption: true,
11+
mongodb: '>=4.2.0',
12+
topology: '!load-balanced'
13+
}
14+
} as const;
15+
16+
const masterKey = {
17+
region: 'us-east-1',
18+
key: 'arn:aws:kms:us-east-1:579766882180:key/89fcc2c4-08b0-4bd9-9f25-e30687b580d0'
19+
};
20+
21+
describe('26. Custom AWS Credential Providers', metadata, () => {
22+
let keyVaultClient;
23+
let credentialProvider;
24+
25+
beforeEach(async function () {
26+
this.currentTest.skipReason = !AWSTemporaryCredentialProvider.isAWSSDKInstalled
27+
? 'This test must run in an environment where the AWS SDK is installed.'
28+
: undefined;
29+
this.currentTest?.skipReason && this.skip();
30+
31+
keyVaultClient = this.configuration.newClient(process.env.MONGODB_UR);
32+
// @ts-expect-error We intentionally access a protected variable.
33+
credentialProvider = AWSTemporaryCredentialProvider.awsSDK;
34+
});
35+
36+
afterEach(async () => {
37+
await keyVaultClient?.close();
38+
});
39+
40+
context(
41+
'Case 1: ClientEncryption with credentialProviders and incorrect kmsProviders',
42+
metadata,
43+
function () {
44+
it('throws an error', metadata, function () {
45+
expect(() => {
46+
new ClientEncryption(keyVaultClient, {
47+
keyVaultNamespace: 'keyvault.datakeys',
48+
kmsProviders: {
49+
aws: {
50+
accessKeyId: process.env.FLE_AWS_KEY,
51+
secretAccessKey: process.env.FLE_AWS_SECRET
52+
}
53+
},
54+
credentialProviders: { aws: credentialProvider.fromNodeProviderChain() }
55+
});
56+
}).to.throw(/Can only provide a custom AWS credential provider/);
57+
});
58+
}
59+
);
60+
61+
context('Case 2: ClientEncryption with credentialProviders works', metadata, function () {
62+
let clientEncryption;
63+
let providerCount = 0;
64+
65+
beforeEach(function () {
66+
const options = {
67+
keyVaultNamespace: 'keyvault.datakeys',
68+
kmsProviders: { aws: {} },
69+
credentialProviders: {
70+
aws: async () => {
71+
providerCount++;
72+
return {
73+
accessKeyId: process.env.FLE_AWS_KEY,
74+
secretAccessKey: process.env.FLE_AWS_SECRET
75+
};
76+
}
77+
},
78+
extraOptions: getEncryptExtraOptions()
79+
};
80+
clientEncryption = new ClientEncryption(keyVaultClient, options);
81+
});
82+
83+
it('is successful', metadata, async function () {
84+
const dk = await clientEncryption.createDataKey('aws', { masterKey });
85+
expect(dk).to.be.instanceOf(Binary);
86+
expect(providerCount).to.be.greaterThan(0);
87+
});
88+
});
89+
90+
context(
91+
'Case 3: AutoEncryptionOpts with credentialProviders and incorrect kmsProviders',
92+
metadata,
93+
function () {
94+
it('throws an error', metadata, function () {
95+
expect(() => {
96+
new MongoClient('mongodb://127.0.0.1:27017', {
97+
autoEncryption: {
98+
keyVaultNamespace: 'keyvault.datakeys',
99+
kmsProviders: {
100+
aws: {
101+
accessKeyId: process.env.FLE_AWS_KEY,
102+
secretAccessKey: process.env.FLE_AWS_SECRET
103+
}
104+
},
105+
credentialProviders: { aws: credentialProvider.fromNodeProviderChain() }
106+
}
107+
});
108+
}).to.throw(/Can only provide a custom AWS credential provider/);
109+
});
110+
}
111+
);
112+
});

0 commit comments

Comments
 (0)
Please sign in to comment.