Skip to content

Commit 8271c1f

Browse files
committed
feat(NODE-7047): use custom credential provider first
1 parent 0e89311 commit 8271c1f

File tree

2 files changed

+138
-10
lines changed

2 files changed

+138
-10
lines changed

test/integration/auth/mongodb_aws.test.ts

Lines changed: 93 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import * as sinon from 'sinon';
88
// eslint-disable-next-line @typescript-eslint/no-restricted-imports
99
import { refreshKMSCredentials } from '../../../src/client-side-encryption/providers';
1010
import {
11+
type AWSCredentials,
1112
AWSTemporaryCredentialProvider,
1213
type CommandOptions,
1314
Connection,
@@ -136,29 +137,27 @@ describe('MONGODB-AWS', function () {
136137
});
137138
});
138139

139-
context('when user supplies a credentials provider', function () {
140+
context('1. Custom Credential Provider Authenticates', function () {
140141
let providerCount = 0;
142+
let provider;
141143

142144
beforeEach(function () {
143145
if (!awsSdkPresent) {
144146
this.skipReason = 'only relevant to AssumeRoleWithWebIdentity with SDK installed';
145147
return this.skip();
146148
}
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.';
149+
if (client?.options.credentials.username) {
150+
this.skipReason = 'only relevant when no credentials are in the URI';
151151
return this.skip();
152152
}
153-
});
154-
155-
it('authenticates with a user provided credentials provider', async function () {
156-
// @ts-expect-error We intentionally access a protected variable.
157153
const credentialProvider = AWSTemporaryCredentialProvider.awsSDK;
158-
const provider = async () => {
154+
provider = async () => {
159155
providerCount++;
160156
return await credentialProvider.fromNodeProviderChain().apply();
161157
};
158+
});
159+
160+
it('authenticates with a user provided credentials provider', async function () {
162161
client = this.configuration.newClient(process.env.MONGODB_URI, {
163162
authMechanismProperties: {
164163
AWS_CREDENTIAL_PROVIDER: provider
@@ -177,6 +176,90 @@ describe('MONGODB-AWS', function () {
177176
});
178177
});
179178

179+
context('2. Custom Credential Provider Authentication Precedence', function () {
180+
context('Case 1: Credentials in URI Take Precedence', function () {
181+
let providerCount = 0;
182+
let provider;
183+
184+
beforeEach(function () {
185+
if (!awsSdkPresent) {
186+
this.skipReason = 'only relevant to AssumeRoleWithWebIdentity with SDK installed';
187+
return this.skip();
188+
}
189+
console.log(client?.options);
190+
if (!client?.options.credentials.username) {
191+
this.skipReason = 'Test only runs when credentials are present in the URI';
192+
return this.skip();
193+
}
194+
// @ts-expect-error We intentionally access a protected variable.
195+
const credentialProvider = AWSTemporaryCredentialProvider.awsSDK;
196+
provider = async () => {
197+
providerCount++;
198+
return await credentialProvider.fromNodeProviderChain().apply();
199+
};
200+
});
201+
202+
it('authenticates with a user provided credentials provider', async function () {
203+
console.log(process.env);
204+
client = this.configuration.newClient(process.env.MONGODB_URI, {
205+
authMechanismProperties: {
206+
AWS_CREDENTIAL_PROVIDER: provider
207+
}
208+
});
209+
210+
const result = await client
211+
.db('aws')
212+
.collection('aws_test')
213+
.estimatedDocumentCount()
214+
.catch(error => error);
215+
216+
expect(result).to.not.be.instanceOf(MongoServerError);
217+
expect(result).to.be.a('number');
218+
expect(providerCount).to.equal(0);
219+
});
220+
});
221+
222+
context('Case 2: Custom Provider Takes Precedence Over Environment Variables', function () {
223+
let providerCount = 0;
224+
let provider;
225+
226+
beforeEach(function () {
227+
if (!awsSdkPresent) {
228+
this.skipReason = 'only relevant to AssumeRoleWithWebIdentity with SDK installed';
229+
return this.skip();
230+
}
231+
if (client?.options.credentials.username || !process.env.AWS_ACCESS_KEY_ID) {
232+
this.skipReason = 'Test only runs when credentials are present in the environment';
233+
return this.skip();
234+
}
235+
// @ts-expect-error We intentionally access a protected variable.
236+
const credentialProvider = AWSTemporaryCredentialProvider.awsSDK;
237+
provider = async () => {
238+
providerCount++;
239+
return await credentialProvider.fromNodeProviderChain().apply();
240+
};
241+
});
242+
243+
it('authenticates with a user provided credentials provider', async function () {
244+
client = this.configuration.newClient(process.env.MONGODB_URI, {
245+
authMechanismProperties: {
246+
AWS_CREDENTIAL_PROVIDER: provider
247+
}
248+
});
249+
250+
const result = await client
251+
.db('aws')
252+
.collection('aws_test')
253+
.estimatedDocumentCount()
254+
.catch(error => error);
255+
256+
expect(result).to.not.be.instanceOf(MongoServerError);
257+
expect(result).to.be.a('number');
258+
expect(providerCount).to.be.greaterThan(0);
259+
});
260+
});
261+
});
262+
180263
it('should allow empty string in authMechanismProperties.AWS_SESSION_TOKEN to override AWS_SESSION_TOKEN environment variable', function () {
181264
client = this.configuration.newClient(this.configuration.url(), {
182265
authMechanismProperties: { AWS_SESSION_TOKEN: '' }

test/integration/client-side-encryption/client_side_encryption.prose.26.custom_aws_credential_providers.test.ts

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,49 @@ describe('26. Custom AWS Credential Providers', metadata, () => {
108108
});
109109
}
110110
);
111+
112+
context(
113+
'ClientEncryption with credentialProviders and valid environment variables',
114+
metadata,
115+
function () {
116+
let clientEncryption;
117+
let providerCount = 0;
118+
let previousAccessKey;
119+
let previousSecretKey;
120+
121+
beforeEach(function () {
122+
previousAccessKey = process.env.AWS_ACCESS_KEY_ID;
123+
previousSecretKey = process.env.AWS_SECRET_ACCESS_KEY;
124+
process.env.AWS_ACCESS_KEY_ID = process.env.FLE_AWS_KEY;
125+
process.env.AWS_SECRET_ACCESS_KEY = process.env.FLE_AWS_SECRET;
126+
127+
const options = {
128+
keyVaultNamespace: 'keyvault.datakeys',
129+
kmsProviders: { aws: {} },
130+
credentialProviders: {
131+
aws: async () => {
132+
providerCount++;
133+
return {
134+
accessKeyId: process.env.FLE_AWS_KEY,
135+
secretAccessKey: process.env.FLE_AWS_SECRET
136+
};
137+
}
138+
},
139+
extraOptions: getEncryptExtraOptions()
140+
};
141+
clientEncryption = new ClientEncryption(keyVaultClient, options);
142+
});
143+
144+
afterEach(function () {
145+
process.env.AWS_ACCESS_KEY_ID = previousAccessKey;
146+
process.env.AWS_SECRET_ACCESS_KEY = previousSecretKey;
147+
});
148+
149+
it('is successful', metadata, async function () {
150+
const dk = await clientEncryption.createDataKey('aws', { masterKey });
151+
expect(dk).to.be.instanceOf(Binary);
152+
expect(providerCount).to.be.greaterThan(0);
153+
});
154+
}
155+
);
111156
});

0 commit comments

Comments
 (0)