I've got a number of encrypted environmental variables I need to decrypt in an AWS Lambda function. They give an example bit of code, but I'd rather not run a huge chunk for each value I need to decrypt:
const AWS = require('aws-sdk');
const encrypted = process.env['my_password'];
let decrypted;
function processEvent(event, context, callback) {
// TODO handle the event here
}
exports.handler = (event, context, callback) => {
if (decrypted) {
processEvent(event, context, callback);
} else {
// Decrypt code should run once and variables stored outside of the function
// handler so that these are decrypted once per container
const kms = new AWS.KMS();
kms.decrypt({ CiphertextBlob: new Buffer(encrypted, 'base64') }, (err, data) => {
if (err) {
console.log('Decrypt error:', err);
return callback(err);
}
decrypted = data.Plaintext.toString('ascii');
processEvent(event, context, callback);
});
}
};
I'm wondering if the AWS SDK includes a function that lets me decrypt multiple values at once. Failing that, is there a way to elegantly chain these calls together so they don't take up ~75 lines of my otherwise simple function?
You can use promises to achieve this. See the example below for decrypting both a username and password via KMS. You can add as many additional decryption promises to the decryptPromises
array as you'd like:
const AWS = require('aws-sdk'); const encrypted = { username: process.env.username, password: process.env.password }; let decrypted = {}; function processEvent(event, context, callback) { //do work } exports.handler = (event, context, callback) => { if ( decrypted.username && decrypted.password ) { processEvent(event, context, callback); } else { const kms = new AWS.KMS(); const decryptPromises = [ kms.decrypt( { CiphertextBlob: new Buffer(encrypted.username, 'base64') } ).promise(), kms.decrypt( { CiphertextBlob: new Buffer(encrypted.password, 'base64') } ).promise() ]; Promise.all( decryptPromises ).then( data => { decrypted.username = data[0].Plaintext.toString('ascii'); decrypted.password = data[1].Plaintext.toString('ascii'); processEvent(event, context, callback); }).catch( err => { console.log('Decrypt error:', err); return callback(err); }); } };
You can find more information on how promises have been implimented for the AWS SDK in the Support for Promises in the SDK documentation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With