Skip to content

Commit d14ac3f

Browse files
authored
feat(NODE-7046)!: remove AWS uri/options support (#4689)
1 parent 1702987 commit d14ac3f

File tree

12 files changed

+158
-157
lines changed

12 files changed

+158
-157
lines changed

.evergreen/setup-mongodb-aws-auth-tests.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ cd $DRIVERS_TOOLS/.evergreen/auth_aws
1818
# Create a python virtual environment.
1919
. ./activate-authawsvenv.sh
2020
# Source the environment variables. Configure the environment and the server.
21-
. aws_setup.sh $AWS_CREDENTIAL_TYPE
21+
. aws_setup.sh --nouri $AWS_CREDENTIAL_TYPE
2222

2323
cd $BEFORE
2424

.gitmodules

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
[submodule "drivers-evergreen-tools"]
22
path = drivers-evergreen-tools
3-
url = https://github.com/mongodb-labs/drivers-evergreen-tools.git
3+
url = https://github.com/mongodb-labs/drivers-evergreen-tools.git

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@
144144
"check:ts": "node ./node_modules/typescript/bin/tsc -v && node ./node_modules/typescript/bin/tsc --noEmit",
145145
"check:atlas": "nyc mocha --config test/manual/mocharc.js test/manual/atlas_connectivity.test.ts",
146146
"check:drivers-atlas-testing": "nyc mocha --config test/mocha_mongodb.js test/atlas/drivers_atlas_testing.test.ts",
147-
"check:aws": "nyc mocha --config test/mocha_mongodb.js test/integration/auth/mongodb_aws.test.ts",
147+
"check:aws": "nyc mocha --config test/mocha_mongodb.js test/integration/auth/mongodb_aws.test.ts test/integration/auth/mongodb_aws.prose.test.ts",
148148
"check:oidc-auth": "nyc mocha --config test/mocha_mongodb.js test/integration/auth/auth.spec.test.ts",
149149
"check:oidc-test": "nyc mocha --config test/mocha_mongodb.js test/integration/auth/mongodb_oidc.prose.test.ts",
150150
"check:oidc-azure": "nyc mocha --config test/mocha_mongodb.js test/integration/auth/mongodb_oidc_azure.prose.05.test.ts",

src/cmap/auth/mongo_credentials.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ export interface AuthMechanismProperties extends Document {
5858
SERVICE_NAME?: string;
5959
SERVICE_REALM?: string;
6060
CANONICALIZE_HOST_NAME?: GSSAPICanonicalizationValue;
61+
/** @internal */
6162
AWS_SESSION_TOKEN?: string;
6263
/** A user provided OIDC machine callback function. */
6364
OIDC_CALLBACK?: OIDCCallbackFunction;

src/cmap/auth/mongodb_aws.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,12 +56,10 @@ export class MongoDBAWS extends AuthProvider {
5656
);
5757
}
5858

59-
if (!authContext.credentials.username) {
60-
authContext.credentials = await makeTempCredentials(
61-
authContext.credentials,
62-
this.credentialFetcher
63-
);
64-
}
59+
authContext.credentials = await makeTempCredentials(
60+
authContext.credentials,
61+
this.credentialFetcher
62+
);
6563

6664
const { credentials } = authContext;
6765

src/connection_string.ts

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,7 @@ import { MongoCredentials } from './cmap/auth/mongo_credentials';
77
import { AUTH_MECHS_AUTH_SRC_EXTERNAL, AuthMechanism } from './cmap/auth/providers';
88
import { Compressor, type CompressorName } from './cmap/wire_protocol/compression';
99
import { Encrypter } from './encrypter';
10-
import {
11-
MongoAPIError,
12-
MongoInvalidArgumentError,
13-
MongoMissingCredentialsError,
14-
MongoParseError
15-
} from './error';
10+
import { MongoAPIError, MongoInvalidArgumentError, MongoParseError } from './error';
1611
import {
1712
MongoClient,
1813
type MongoClientOptions,
@@ -417,10 +412,18 @@ export function parseOptions(
417412
});
418413
}
419414

420-
if (isAws && mongoOptions.credentials.username && !mongoOptions.credentials.password) {
421-
throw new MongoMissingCredentialsError(
422-
`When using ${mongoOptions.credentials.mechanism} password must be set when a username is specified`
423-
);
415+
if (isAws) {
416+
const { username, password } = mongoOptions.credentials;
417+
if (username || password) {
418+
throw new MongoAPIError(
419+
'username and password cannot be provided when using MONGODB-AWS. Credentials must be provided in a manner that can be read by the AWS SDK.'
420+
);
421+
}
422+
if (mongoOptions.credentials.mechanismProperties.AWS_SESSION_TOKEN) {
423+
throw new MongoAPIError(
424+
'AWS_SESSION_TOKEN cannot be provided when using MONGODB-AWS. Credentials must be provided in a manner that can be read by the AWS SDK.'
425+
);
426+
}
424427
}
425428

426429
mongoOptions.credentials.validate();
Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import * as process from 'node:process';
2+
3+
import { expect } from 'chai';
4+
5+
import { AWSSDKCredentialProvider, type MongoClient, MongoServerError } from '../../mongodb';
6+
7+
const isMongoDBAWSAuthEnvironment = (process.env.MONGODB_URI ?? '').includes('MONGODB-AWS');
8+
9+
describe('MONGODB-AWS Prose Tests', function () {
10+
let client: MongoClient;
11+
12+
beforeEach(function () {
13+
if (!isMongoDBAWSAuthEnvironment) {
14+
this.currentTest.skipReason = 'requires MONGODB_URI to contain MONGODB-AWS auth mechanism';
15+
return this.skip();
16+
}
17+
});
18+
19+
afterEach(async () => {
20+
await client?.close();
21+
});
22+
23+
// NOTE: Logic for scenarios 1-6 is handled via the evergreen variant configs.
24+
// Scenarios 1-6 from the previous section with a user provided AWS_CREDENTIAL_PROVIDER auth mechanism
25+
// property. This credentials MAY be obtained from the default credential provider from the AWS SDK.
26+
// If the default provider does not cover all scenarios above, those not covered MAY be skipped.
27+
// In these tests the driver MUST also assert that the user provided credential provider was called
28+
// in each test. This may be via a custom function or object that wraps the calls to the custom provider
29+
// and asserts that it was called at least once. For test scenarios where the drivers tools scripts put
30+
// the credentials in the MONGODB_URI, drivers MAY extract the credentials from the URI and return the AWS
31+
// credentials directly from the custom provider instead of using the AWS SDK default provider.
32+
context('1. Custom Credential Provider Authenticates', function () {
33+
let providerCount = 0;
34+
35+
it('authenticates with a user provided credentials provider', async function () {
36+
const credentialProvider = AWSSDKCredentialProvider.awsSDK;
37+
const provider = async () => {
38+
providerCount++;
39+
return await credentialProvider.fromNodeProviderChain().apply();
40+
};
41+
client = this.configuration.newClient(process.env.MONGODB_URI, {
42+
authMechanismProperties: {
43+
AWS_CREDENTIAL_PROVIDER: provider
44+
}
45+
});
46+
47+
const result = await client
48+
.db('aws')
49+
.collection('aws_test')
50+
.estimatedDocumentCount()
51+
.catch(error => error);
52+
53+
expect(result).to.not.be.instanceOf(MongoServerError);
54+
expect(result).to.be.a('number');
55+
expect(providerCount).to.be.greaterThan(0);
56+
});
57+
});
58+
59+
context('2. Custom Credential Provider Authentication Precedence', function () {
60+
// Run this test in an environment with AWS credentials configured as environment variables
61+
// (e.g. AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN)
62+
// Create a MongoClient configured to use AWS auth. Example: mongodb://localhost:27017/?authMechanism=MONGODB-AWS.
63+
// Configure a custom credential provider to pass valid AWS credentials. The provider must track if it was called.
64+
// Expect authentication to succeed and the custom credential provider was called.
65+
context('Case 2: Custom Provider Takes Precedence Over Environment Variables', function () {
66+
let providerCount = 0;
67+
let provider;
68+
69+
beforeEach(function () {
70+
if (client?.options.credentials.username || !process.env.AWS_ACCESS_KEY_ID) {
71+
this.skipReason = 'Test only runs when credentials are present in the environment';
72+
return this.skip();
73+
}
74+
const credentialProvider = AWSSDKCredentialProvider.awsSDK;
75+
provider = async () => {
76+
providerCount++;
77+
return await credentialProvider.fromNodeProviderChain().apply();
78+
};
79+
});
80+
81+
it('authenticates with a user provided credentials provider', async function () {
82+
client = this.configuration.newClient(process.env.MONGODB_URI, {
83+
authMechanismProperties: {
84+
AWS_CREDENTIAL_PROVIDER: provider
85+
}
86+
});
87+
88+
const result = await client
89+
.db('aws')
90+
.collection('aws_test')
91+
.estimatedDocumentCount()
92+
.catch(error => error);
93+
94+
expect(result).to.not.be.instanceOf(MongoServerError);
95+
expect(result).to.be.a('number');
96+
expect(providerCount).to.be.greaterThan(0);
97+
});
98+
});
99+
});
100+
});

test/integration/auth/mongodb_aws.test.ts

Lines changed: 0 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -162,135 +162,6 @@ describe('MONGODB-AWS', function () {
162162
});
163163
});
164164

165-
context('when using a custom credential provider', function () {
166-
// NOTE: Logic for scenarios 1-6 is handled via the evergreen variant configs.
167-
// Scenarios 1-6 from the previous section with a user provided AWS_CREDENTIAL_PROVIDER auth mechanism
168-
// property. This credentials MAY be obtained from the default credential provider from the AWS SDK.
169-
// If the default provider does not cover all scenarios above, those not covered MAY be skipped.
170-
// In these tests the driver MUST also assert that the user provided credential provider was called
171-
// in each test. This may be via a custom function or object that wraps the calls to the custom provider
172-
// and asserts that it was called at least once. For test scenarios where the drivers tools scripts put
173-
// the credentials in the MONGODB_URI, drivers MAY extract the credentials from the URI and return the AWS
174-
// credentials directly from the custom provider instead of using the AWS SDK default provider.
175-
context('1. Custom Credential Provider Authenticates', function () {
176-
let providerCount = 0;
177-
178-
beforeEach(function () {
179-
// If we have a username the credentials have been set from the URI, options, or environment
180-
// variables per the auth spec stated order.
181-
if (client.options.credentials.username) {
182-
this.skipReason = 'Credentials in the URI will not use custom provider.';
183-
return this.skip();
184-
}
185-
});
186-
187-
it('authenticates with a user provided credentials provider', async function () {
188-
const credentialProvider = AWSSDKCredentialProvider.awsSDK;
189-
const provider = async () => {
190-
providerCount++;
191-
return await credentialProvider.fromNodeProviderChain().apply();
192-
};
193-
client = this.configuration.newClient(process.env.MONGODB_URI, {
194-
authMechanismProperties: {
195-
AWS_CREDENTIAL_PROVIDER: provider
196-
}
197-
});
198-
199-
const result = await client
200-
.db('aws')
201-
.collection('aws_test')
202-
.estimatedDocumentCount()
203-
.catch(error => error);
204-
205-
expect(result).to.not.be.instanceOf(MongoServerError);
206-
expect(result).to.be.a('number');
207-
expect(providerCount).to.be.greaterThan(0);
208-
});
209-
});
210-
211-
context('2. Custom Credential Provider Authentication Precedence', function () {
212-
// Create a MongoClient configured with AWS auth and credentials in the URI.
213-
// Example: mongodb://<AccessKeyId>:<SecretAccessKey>@localhost:27017/?authMechanism=MONGODB-AWS
214-
// Configure a custom credential provider to pass valid AWS credentials. The provider must
215-
// track if it was called.
216-
// Expect authentication to succeed and the custom credential provider was not called.
217-
context('Case 1: Credentials in URI Take Precedence', function () {
218-
let providerCount = 0;
219-
let provider;
220-
221-
beforeEach(function () {
222-
if (!client?.options.credentials.username) {
223-
this.skipReason = 'Test only runs when credentials are present in the URI';
224-
return this.skip();
225-
}
226-
const credentialProvider = AWSSDKCredentialProvider.awsSDK;
227-
provider = async () => {
228-
providerCount++;
229-
return await credentialProvider.fromNodeProviderChain().apply();
230-
};
231-
});
232-
233-
it('authenticates with a user provided credentials provider', async function () {
234-
client = this.configuration.newClient(process.env.MONGODB_URI, {
235-
authMechanismProperties: {
236-
AWS_CREDENTIAL_PROVIDER: provider
237-
}
238-
});
239-
240-
const result = await client
241-
.db('aws')
242-
.collection('aws_test')
243-
.estimatedDocumentCount()
244-
.catch(error => error);
245-
246-
expect(result).to.not.be.instanceOf(MongoServerError);
247-
expect(result).to.be.a('number');
248-
expect(providerCount).to.equal(0);
249-
});
250-
});
251-
252-
// Run this test in an environment with AWS credentials configured as environment variables
253-
// (e.g. AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN)
254-
// Create a MongoClient configured to use AWS auth. Example: mongodb://localhost:27017/?authMechanism=MONGODB-AWS.
255-
// Configure a custom credential provider to pass valid AWS credentials. The provider must track if it was called.
256-
// Expect authentication to succeed and the custom credential provider was called.
257-
context('Case 2: Custom Provider Takes Precedence Over Environment Variables', function () {
258-
let providerCount = 0;
259-
let provider;
260-
261-
beforeEach(function () {
262-
if (client?.options.credentials.username || !process.env.AWS_ACCESS_KEY_ID) {
263-
this.skipReason = 'Test only runs when credentials are present in the environment';
264-
return this.skip();
265-
}
266-
const credentialProvider = AWSSDKCredentialProvider.awsSDK;
267-
provider = async () => {
268-
providerCount++;
269-
return await credentialProvider.fromNodeProviderChain().apply();
270-
};
271-
});
272-
273-
it('authenticates with a user provided credentials provider', async function () {
274-
client = this.configuration.newClient(process.env.MONGODB_URI, {
275-
authMechanismProperties: {
276-
AWS_CREDENTIAL_PROVIDER: provider
277-
}
278-
});
279-
280-
const result = await client
281-
.db('aws')
282-
.collection('aws_test')
283-
.estimatedDocumentCount()
284-
.catch(error => error);
285-
286-
expect(result).to.not.be.instanceOf(MongoServerError);
287-
expect(result).to.be.a('number');
288-
expect(providerCount).to.be.greaterThan(0);
289-
});
290-
});
291-
});
292-
});
293-
294165
it('should allow empty string in authMechanismProperties.AWS_SESSION_TOKEN to override AWS_SESSION_TOKEN environment variable', function () {
295166
client = this.configuration.newClient(this.configuration.url(), {
296167
authMechanismProperties: { AWS_SESSION_TOKEN: '' }

test/integration/node-specific/examples/aws_handler.js

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,10 @@
11
// begin lambda connection
22
const { MongoClient } = require('mongodb');
33

4-
// Get the URI for the cluster then set AWS_ACCESS_KEY_ID as the username in the
5-
// URI and AWS_SECRET_ACCESS_KEY as the password, then set the appropriate auth
6-
// options. Note that MongoClient now auto-connects so no need to store the connect()
7-
// promise anywhere and reference it.
4+
// Get the URI for the cluster and use AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
5+
// from the environment, then set the appropriate auth options. Note that MongoClient
6+
// now auto-connects so no need to store the connect() promise anywhere and reference it.
87
const client = new MongoClient(process.env.MONGODB_URI, {
9-
auth: {
10-
username: process.env.AWS_ACCESS_KEY_ID,
11-
password: process.env.AWS_SECRET_ACCESS_KEY
12-
},
138
authSource: '$external',
149
authMechanism: 'MONGODB-AWS'
1510
});

test/spec/auth/legacy/connection-string.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -440,6 +440,21 @@
440440
}
441441
}
442442
},
443+
{
444+
"description": "should throw an exception if username provided (MONGODB-AWS)",
445+
"uri": "mongodb://[email protected]/?authMechanism=MONGODB-AWS",
446+
"valid": false
447+
},
448+
{
449+
"description": "should throw an exception if username and password provided (MONGODB-AWS)",
450+
"uri": "mongodb://user:[email protected]/?authMechanism=MONGODB-AWS",
451+
"valid": false
452+
},
453+
{
454+
"description": "should throw an exception if AWS_SESSION_TOKEN provided (MONGODB-AWS)",
455+
"uri": "mongodb://localhost/?authMechanism=MONGODB-AWS&authMechanismProperties=AWS_SESSION_TOKEN:token",
456+
"valid": false
457+
},
443458
{
444459
"description": "should recognise the mechanism with test environment (MONGODB-OIDC)",
445460
"uri": "mongodb://localhost/?authMechanism=MONGODB-OIDC&authMechanismProperties=ENVIRONMENT:test",

0 commit comments

Comments
 (0)