how do I use aws secret manager with nodejs lambda

red888 picture red888 · Aug 23, 2019 · Viewed 14.1k times · Source

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.

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

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

Answer

iwaduarte picture iwaduarte · Aug 23, 2019

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 ...
    }