1

I'm having difficulty decrypting multiple environment variables in nodejs for an AWS lambda. I've looked at the code sample supplied in the console and the following two related questions:

Question 1, Question 2

I have been able to successfully decrypt a single environment variable through their code sample, however, when I try to apply a cleaner approach through the use of promises (methods outlined in the questions above), I get this error when testing the lambda function in the console:

TypeError: First argument must be a string, Buffer, ArrayBuffer, Array, or array-like object.

I was wondering if anyone has had this issue before and how I could go about resolving it?

Edit: I've added some samples from my code below

const AWS = require('aws-sdk');
const mysql = require('mysql');
let connection;

const encrypted = {
    username: process.env.username,
    password: process.env.password,
    database: process.env.database,
    host: process.env.host
};

let decrypted = {};

const encryptedEnvVars = [process.env.username, process.env.password, process.env.database, process.env.host ];


exports.handler = (event, context, callback) => {
    if (isEnvVarsDecrypted()) {
        processEvent(event, context);
    } else {  
        Promise.all(encryptedEnvVars.map(decryptKMS))
        .then(decryptEnvVars)
        .catch(console.log);
    }
};

function decryptKMS(key) {
    return new Promise((resolve, reject) => {
      const kms = new AWS.KMS()

      kms.decrypt({ CiphertextBlob: new Buffer(key, 'base64') }, (err, data) => {
        if(err) { reject(err); }
        else { resolve(data.Plaintext.toString('ascii')); }
      });
    });
  }

var decryptEnvVars = data =>  {
    return new Promise((resolve, reject) => {
        console.log(data);
        decrypted.username = data[0].Plaintext.toString('ascii');
        decrypted.password = data[1].Plaintext.toString('ascii');
        decrypted.database = data[2].Plaintext.toString('ascii');
        decrypted.host = data[3].Plaintext.toString('ascii');
        resolve();
    });
};

var isEnvVarsDecrypted = () => {
    return decrypted.username && decrypted.password && decrypted.database && decrypted.host;
}
  • Please post a sample of your breaking code. Can you inspect the type of the "first argument" and confirm that it is in fact one of the requested types (string, Buffer, etc...)? – Nicholas Sizer Apr 05 '18 at 04:55
  • I've added some of my sample code.. The argument passed in is "... new Buffer(..." – Gabriel Tiongco Apr 06 '18 at 01:41

1 Answers1

0

If key is null, then new Buffer(key, 'base64') will fail with the error you describe.

When I ran your code myself:

  • If any environment variable was missing, the error occurred
  • When all environment variables were declared, the error ceased

So, you should confirm that the environment variables you reference are actually defined.

A couple of other pointers:

  • Make sure you are always calling the lambda callback, regardless of success/failure; this is how you signal to the lambda environment that execution has ended.
  • After calling decryptEnvVars, you should call your processEvent function
Nicholas Sizer
  • 3,490
  • 3
  • 26
  • 29