Skip to content Skip to sidebar Skip to footer

Setting Secrets From Aws Secrets Manager In Node.js

Before top-level await becomes a thing, loading secrets asynchronously from AWS Secrets Manager upon startup is a bit of a pain. I'm wondering if anyone has a better solution than

Solution 1:

So I ended up doing the following. First I'm setting the non-async config variables in an exported object literal. Then I'm assigning values to the object literal in the sendgridConfigAsync IIFE (doesn't have to be an IFEE). That way I don't have to await the config promise. As long as the app awaits the IIFE on startup, the keys will be assigned before being accessed.

In sendgridConfig.js

import { getSecret } from"./aws";

exportconst sendgridConfig = {
    emailFrom: process.env.sendgridFromEmail,
    emailTo: process.env.sendgridToEmail
}

exportconst sendgridConfigAsync = (async() => {
    const secret = JSON.parse(awaitgetSecret("Sendgrid-dev"));
    sendgridConfig.sendgridKey = secret.key;
})()

Then in the main config file _index.js where I import all the config files.

import { sendgridConfigAsync } from"./sendgrid";
import { twilioConfigAsync } from"./twilio";
import { appConfigAsync } from"./app";

exportconst setAsyncConfig = async() => {
    awaitPromise.all([
        appConfigAsync,
        sendgridConfigAsync,
        twilioConfigAsync
    ]);
}

Then in the main index.js file I'm awaiting the setAsyncConfig function first. I did also rebuild the app somewhat in order to control all function invocations and promise resolving in the desired order.

import { servicesConnect } from"../src/service/_index.js";
import { setAsyncConfig } from'$config';
import { asyncHandler } from"./middleware/async";
import { middleware } from"./middleware/_index";
import { initJobs } from"./jobs/_index"import http from'http';

asyncfunctionstartServer() {
    awaitsetAsyncConfig();
    awaitservicesConnect();
    awaitinitJobs();
    app.use(middleware);

    app.server = http.createServer(app);

    app.server.listen(appConfig.port);
    console.log(`Started on port ${app.server.address().port}`);
}

asyncHandler(startServer());

Solution 2:

Yup I have the same problem. Once you start with a promise, all dependencies down the line require await.

One solution is to do your awaits and only after that have all your downstream code run. Requires a slightly different software architecture.

E.g.

export const getSecretAndThenDoStuff = async(secretName) => {
    const data = await client.getSecretValue({SecretId: secretName}).promise();
    // instead of return data.SecretString;
    runYourCodeThatNeedsSecret(data);
}

Solution 3:

A more generic solution to the top-level await that I tend to use:

async function main() {
  // Do whatever you want with await here
}

main();

Clean and simple.

Post a Comment for "Setting Secrets From Aws Secrets Manager In Node.js"