Установка секретов из менеджера AWS Secrets в Node.JS - PullRequest
2 голосов
/ 02 ноября 2019

До того как ожидание на высшем уровне станет чем-то особенным, загрузка секретов асинхронно из AWS Secrets Manager при запуске - это небольшая боль. Мне интересно, есть ли у кого-нибудь лучшее решение, чем у меня сейчас.

После запуска сервера Node.JS я загружаю все секреты из менеджера секретов AWS и устанавливаю их в конфигурационные файлы, где у меня естьсмесь жестко закодированных переменных и секретов. Вот пример:

В aws.js

import AWS from 'aws-sdk';
const region = "eu-north-1";

AWS.config.setPromisesDependency();

const client = new AWS.SecretsManager({
    region
});

export const getSecret = async(secretName) => {
    const data = await client.getSecretValue({SecretId: secretName}).promise();
    return data.SecretString;
}

Затем в sendgridConfig.js

import { getSecret } from "./aws";

export default async() => {
    const secret = JSON.parse(await getSecret("sendgridSecret"));
    return {
        APIKey: secret.sendgridKey,
        fromEmail: "some@email.com",
        toEmail: "some@email.com"
    }
}

Затем в каком-то файле, где используется конфигурация:

import { sendgridConfig } from "./sendgridConfig";

const myFunc = () => {
    const sendgridConf = await sendgridConfig();
    ... do stuff with config ...
}

Это работает нормально в асинхронных функциях, но что если я хотел бы использовать ту же настройку в неасинхронных функциях, где я использую свои жестко закодированные переменные? Тогда секреты еще не получены, и я не могу их использовать. Также я должен всегда ждать секретов. IMO хорошим решением в будущем может быть ожидание на высшем уровне, когда после загрузки сервера сервер будет ожидать секреты от AWS, прежде чем продолжить. Я думаю, я мог бы найти способ заблокировать основной поток и установить секреты, но это выглядит как хакерство.

У кого-нибудь есть лучшее решение?

Ответы [ 3 ]

0 голосов
/ 03 ноября 2019

Более общее решение для верхнего уровня, которое я склонен использовать:

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

main();

Чисто и просто.

0 голосов
/ 04 ноября 2019

Итак, я сделал следующее. Сначала я устанавливаю не-асинхронные переменные конфигурации в экспортированном литерале объекта. Затем я присваиваю значения литералу объекта в sendgridConfigAsync IIFE (не обязательно должен быть IFEE). Таким образом, мне не нужно ждать обещания конфигурации. Пока приложение ожидает IIFE при запуске, ключи будут назначены перед доступом.

В sendgridConfig.js

import { getSecret } from "./aws";

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

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

Затем в основном файле конфигурации _index.js, где яИмпортируйте все файлы конфигурации.

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

export const setAsyncConfig = async() => {
    await Promise.all([
        appConfigAsync,
        sendgridConfigAsync,
        twilioConfigAsync
    ]);
}

Затем в основном файле index.js сначала я жду функцию setAsyncConfig. Я также несколько перестроил приложение, чтобы контролировать все вызовы функций и обещать разрешение в нужном порядке.

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';

async function startServer() {
    await setAsyncConfig();
    await servicesConnect();
    await initJobs();
    app.use(middleware);

    app.server = http.createServer(app);

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

asyncHandler(startServer());
0 голосов
/ 03 ноября 2019

Да, у меня та же проблема. Как только вы начинаете с обещания, все зависимости на линии требуют ожидания.

Одним из решений является выполнение ваших ожиданий, и только после этого запуск всего вашего нижестоящего кода. Требуется немного другая архитектура программного обеспечения.

Например

export const getSecretAndThenDoStuff = async(secretName) => {
    const data = await client.getSecretValue({SecretId: secretName}).promise();
    // instead of return data.SecretString;
    runYourCodeThatNeedsSecret(data);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...