简体   繁体   English

我如何在 nodejs lambda 中使用 aws 秘密管理器

[英]how do I use aws secret manager with nodejs lambda

I tried to wrap the example code snippet to get secrets in a function and then call it but it does not appear to be working.我试图包装示例代码片段以获取函数中的秘密,然后调用它,但它似乎不起作用。 I suspect I am calling it asynchronously and I need to call it synchronously?我怀疑我是异步调用它,我需要同步调用它? I just want a function I can call to get a secret value and put it in a var.我只想要一个可以调用的函数来获取一个秘密值并将其放入一个 var 中。

this is the function:这是功能:

//outside exports.handler = (event, context, callback) => {
function getSecret(secretName) {
  // Load the AWS SDK
  var AWS = require('aws-sdk'),
      region = process.env.AWS_REGION,
      secretName = secretName,
      secret,
      decodedBinarySecret;

  // Create a Secrets Manager client
  var client = new AWS.SecretsManager({
      region: region
  });

  // In this sample we only handle the specific exceptions for the 'GetSecretValue' API.
  // See https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
  // We rethrow the exception by default.

  client.getSecretValue({SecretId: secretName}, function(err, data) {
      if (err) {
          if (err.code === 'DecryptionFailureException')
              // Secrets Manager can't decrypt the protected secret text using the provided KMS key.
              // Deal with the exception here, and/or rethrow at your discretion.
              throw err;
          else if (err.code === 'InternalServiceErrorException')
              // An error occurred on the server side.
              // Deal with the exception here, and/or rethrow at your discretion.
              throw err;
          else if (err.code === 'InvalidParameterException')
              // You provided an invalid value for a parameter.
              // Deal with the exception here, and/or rethrow at your discretion.
              throw err;
          else if (err.code === 'InvalidRequestException')
              // You provided a parameter value that is not valid for the current state of the resource.
              // Deal with the exception here, and/or rethrow at your discretion.
              throw err;
          else if (err.code === 'ResourceNotFoundException')
              // We can't find the resource that you asked for.
              // Deal with the exception here, and/or rethrow at your discretion.
              throw err;
      }
      else {
          // Decrypts secret using the associated KMS CMK.
          // Depending on whether the secret is a string or binary, one of these fields will be populated.
          if ('SecretString' in data) {
              return data.SecretString;
          } else {
              let buff = new Buffer(data.SecretBinary, 'base64');
              return buff.toString('ascii');
          }
    }
  });
}

Then I call it然后我叫它

// inside exports.handler = (event, context, callback) => {
var secret = getSecret('mySecret')
console.log('mysecret: ' + secret )

The secret var is always undefined秘密变量总是undefined

EDIT: Async only works with promises so I had to make my function async and return a promise:编辑:异步只适用于承诺,所以我必须使我的函数异步并返回一个承诺:

async function mySecrets(secretName) {
    // Load the AWS SDK
    var AWS = require('aws-sdk'),
        region = process.env.AWS_REGION,
        secretName = secretName,
        secret,
        decodedBinarySecret;

    // Create a Secrets Manager client
    var client = new AWS.SecretsManager({
        region: region
    });

    return new Promise((resolve,reject)=>{
        client.getSecretValue({SecretId: secretName}, function(err, data) {

            // In this sample we only handle the specific exceptions for the 'GetSecretValue' API.
            // See https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html
            // We rethrow the exception by default.
            if (err) {
                reject(err);
            }
            else {
                // Decrypts secret using the associated KMS CMK.
                // Depending on whether the secret is a string or binary, one of these fields will be populated.
                if ('SecretString' in data) {
                    resolve(data.SecretString);
                } else {
                    let buff = new Buffer(data.SecretBinary, 'base64');
                    resolve(buff.toString('ascii'));
                }
            }
        });
    });
}

.....
// inside handler
exports.handler = async (event) => {
....
var value = await mySecrets('mysecret')

You need wait for the async call to finish.您需要等待异步调用完成。

Inside your main handler you will have something like:在您的主处理程序中,您将拥有如下内容:

// inside your main handler
exports.handler =  async function(event, context) {
    var secret = await getSecret('mySecret')
    console.log('mysecret: ' + secret )

    return ...
    }

Here is a more simple example if someone will need to resolve this issue:如果有人需要解决这个问题,这里有一个更简单的例子:

const result = await client
  .getSecretValue({
    SecretId: AWSConfig.secretName,
  })
  .promise();

const parsedResult = JSON.parse(result.SecretString);

The aws-sdk provides two means of getting values back from APIs. aws-sdk提供了两种从 API 取回值的方法。 You can use the native callback mechanism, as shown above, or you can, instead, use .promise() on the end of the call chain, to convert the API call to its promise equivalent.您可以使用本机回调机制,如上所示,或者您可以改为在调用链的末尾使用.promise()将 API 调用转换为其等效的 promise。

Eg例如

const data = await (secretManager.getSecret({ SecretId }).promise();

If you're using await then your function needs to be async as do all the functions calling it, unless they choose to use Promise's then / catch etc.如果您正在使用await那么您的函数需要与调用它的所有函数一样async ,除非他们选择使用 Promise 的then / catch等。

I've created a Synchronous solution which you can find here: https://github.com/jwerre/secrets我创建了一个同步解决方案,您可以在这里找到: https : //github.com/jwerre/secrets

With this package you can load all your secrets inside of a particular namespace like so:使用此包,您可以将所有机密加载到特定命名空间中,如下所示:

const config = require('@jwerre/secrets').configSync({
    region: 'us-east-1',
    env: 'production',
    namespace: 'my-namespace',
});

This will retrieve all your secrets which may not be exactly what you want.这将检索您所有可能不完全是您想要的秘密。 If you want a single secret you can do it like this:如果你想要一个秘密,你可以这样做:

const config = require('@jwerre/secrets').secretSync({
    region: 'us-west-2'
    id: '/my-co/apis/'
});

A much better way is to do this inside your async lambda function更好的方法是在异步 lambda 函数中执行此操作

Example key:val => password:rootPassword示例key:val => password:rootPassword

const secret = await secretClient.getSecretValue({SecretId: 'SecretKeyName'}).promise().then((data) => {
        return JSON.parse(data.SecretString);
})

and then access it as secret.password .然后以secret.password访问它。

Note : wrap around try/catch block to handle errors automatically.注意:环绕try/catch块以自动处理错误。

There is a one more easier way to read from secret manager it.有一种更简单的方法可以从秘密管理器中读取它。

let secretManager = new SecretsManager({ region: 'region-name' });
const data = await secretManager.getSecretValue({ SecretId: 'secretid' }).promise();
console.log(`data is: ${JSON.stringify(data)}`);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM