-
Type: Bug
-
Resolution: Fixed
-
Priority: Minor - P4
-
Affects Version/s: 4.5.0
-
Component/s: Authentication
What problem are you facing?
When the MONGODB-AWS auth mechanism is selected, and credentials are not provided upfront, the auth mechanism will try loading credentials from the EC2 metadata service.
The problem is that the intended 10-second timeout is not programmed properly, so the auth mechanism will hang for more than a minute if attempted outside of EC2.
On my machine I'm seeing a delay of 75 seconds before the connection attempt fails.
Additionally, a timeout as low as 3 seconds may be more desirable to improve user experience.
This issue seems to also impact "mongosh".
What driver and relevant dependency versions are you using?
node v17.8.0
mongodb@4.5.0
mongosh 1.3.1
Steps to reproduce?
Within nodejs:
import { MongoClient } from "mongodb"; MongoClient.connect("mongodb+srv://some-stuff-here.mongodb.net", { authSource: "$external", authMechanism: "MONGODB-AWS", });
With mongosh:
$ mongosh "mongodb+srv://some-stuff-here.mongodb.net?authSource=%24external&authMechanism=MONGODB-AWS" --apiVersion 1Connecting to: mongodb+srv://......etc.......
Note that the issue only occurs when you do not have credentials in the environment and are not on EC2.
In both cases, this error is given after 75 seconds:
Error: connect ETIMEDOUT 169.254.169.254:80
Comparison with AWS SDK
I'd like to point out that the official AWS SDK JS only waits 3 seconds before giving up on a credential fetch. It issues up to 3 requests with a 1-second timeout on each request. Source: https://github.com/aws/aws-sdk-js/blob/8d6429f810abb24895a248b486746ffae92eedfb/lib/credentials/ec2_metadata_credentials.js#L12-L13
Logic fault details
This StackOverflow entry shows how HTTP timeouts work in NodeJS: https://stackoverflow.com/questions/6214902/how-to-set-a-timeout-on-a-http-request-in-node
Effectively, the timeout registered here does not have any effect on its own: https://github.com/mongodb/node-mongodb-native/blob/067fa077b6e3be266844b6f1c7ba1f34fd882917/src/cmap/auth/mongodb_aws.ts#L258
To enforce the timeout, this line of code can be added later in the function:
req.on('timeout', () => req.destroy());