首页 > 解决方案 > 在从对 AWS Secrets Manager 的 API 调用返回后导出节点文件中的数据

问题描述

背景

我将 AWS 中 RDS 的数据库信息存储在 Secrets Manager 中。我正在使用 AWS-SDK 来检索密码和其他数据,以便可以secrets在运行时创建一个对象。当我尝试创建此对象然后将其导出时,导出的对象始终缺少我希望从 aws-sdk 返回的数据。

我试过的 -

我尝试过使用async await,但在正确填充所有数据之前它仍在导出对象。

例子

const AWS = require('aws-sdk');
const region = 'us-west-2';
const secretName = 'example/example/example';
let secrets = {
  username: '',
  password: '',
  host: '',
  port: '',
  database: '',
  email: 'example@example.com',
  emailPassword: 'SomePassword'
};

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

client.getSecretValue({ SecretId: secretName }, async (err, data) => {
  if (err) {
    throw err;
  } else {
    const res = await JSON.parse(data.SecretString);
    secrets.username = res.username;
    secrets.password = res.password;
    secrets.host = res.host;
    secrets.port = res.port;
    secrets.database = res.database;
  }
});

module.exports = secrets;

问题

这里明显的问题是没有正确创建承诺,但我不确定为什么我的尝试在文件导出后完成承诺。如果console.log(secrets)在某些情况下我在另一个文件中,它将输出对象丢失的数据,然后在我console.log(secrets)进入函数后几秒钟后显示由 promise 返回的数据。

secrets一旦数据从 AWS 返回并添加到对象中,构建此对象并导出它的正确方法是secrets什么?

标签: javascriptnode.js

解决方案


根据文档,第二个参数getSecretValue是回调函数,因此不需要使用 async/await,因为 async/await 是为了与 Promise 一起工作。

删除 async/await 应该可以工作。

client.getSecretValue({ SecretId: secretName }, (err, data) => {
  if (err) {
    throw err;
  } else {
    const res = JSON.parse(data.SecretString);
    secrets.username = res.username;
    secrets.password = res.password;
    secrets.host = res.host;
    secrets.port = res.port;
    secrets.database = res.database;
  }
}); 

但是,您正在secrets同步导出对象,并且它的属性正在异步设置。

相反,您可以返回一个承诺供您的其他模块使用。

const AWS = require('aws-sdk');
const region = 'us-west-2';
const secretName = 'example/example/example';
let secrets = {
  email: 'example@example.com',
  emailPassword: 'SomePassword'
};

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

const promise = new Promise((resolve, reject) => {
  client.getSecretValue({ SecretId: secretName }, async (err, data) => {
    if (err) {
      reject(err);
    } else {
      const res = await JSON.parse(data.SecretString);
      secrets.username = res.username;
      secrets.password = res.password;
      secrets.host = res.host;
      secrets.port = res.port;
      secrets.database = res.database;
      resolve(secrets);
    }
  });
})

module.exports = promise;

然后,在使用这个模块的其他模块中,您可以使用 async/await,因为我们现在有一个 Promise。

import {promise} from "./this-module";

(async () => {
  const secrets = await promise;
  console.log(secrets);
})();

更新

我不确定这是否可行,但值得一试。此处,module.exports仅设置后secrets设置。如果这不起作用,那么我会在 StackOverflow 上提出一个关于如何使用 CommonJS(这是您正在使用的模块格式)导出已解决承诺的新问题。

const AWS = require('aws-sdk');
const region = 'us-west-2';
const secretName = 'example/example/example';
let secrets = {
  email: 'example@example.com',
  emailPassword: 'SomePassword'
};

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

const promise = new Promise((resolve, reject) => {
  client.getSecretValue({ SecretId: secretName }, async (err, data) => {
    if (err) {
      reject(err);
    } else {
      const res = await JSON.parse(data.SecretString);
      secrets.username = res.username;
      secrets.password = res.password;
      secrets.host = res.host;
      secrets.port = res.port;
      secrets.database = res.database;
      resolve(secrets);
    }
  });
});

(async () => {
  module.exports = await promise;
})();

推荐阅读