The documentation here recommends:
- Instantiating the Mongo client once in global scope
- Assuming an IAM role to authenticate with atlas.
This can create a problem in higher traffic lambdas where the global scope lives longer than 60 minutes. When using role chaining to assume an AWS role, there is a time limit of one hour, so requests send after this one hour time limit will always fail with a MongoServerError: Authentication failed.
error message.
It would be helpful to add this caveat to the documentation.
For reference, this is the workaround we have been using:
const fetchClient = async () => {
const { Credentials } = await sts.assumeRole({
arn: 'arn:aws:iam::000000000000:role/MyMongoRole',
roleSessionName: 'MyMongoSession',
});
const auth = `${Credentials?.AccessKeyId!}:${encodeURIComponent(Credentials?.SecretAccessKey!)}`;
const params = new URLSearchParams({
// ...etc
authMechanismProperties: `AWS_SESSION_TOKEN:${Credentials?.SessionToken!}`,
});
const uri = `mongodb+srv://${auth}@my-cluster-name.mongodb.net/?${params.toString()}`;
return { client: new MongoClient(uri), expiry: Credentials?.Expiration! };
};
let globalConnection = await fetchClient();
const handler = async () => {
if (globalConnection.expiry) {
globalConnection = await fetchClient();
}
await globalConnection.client.db('MyMongoDb').command({ listDatabases: 1 });
};
It would be good to know if this is the recommended approach for this problem, or if I’ve missed some neater way to reconnect to the client on token expiry.