BinaryPhinary
BinaryPhinary

Reputation: 21

Express/AwsServerlessExpress/lambda/Secrets Manager - Exporting a Variable from a function -

Outline: Im attempting to port an express application to lambda using AWS Serverless Express, and I need to access Secrets Manager which stores credentials for MongoDB Atlas.

Problem: I have successfully retrieved my secret, however I cannot 'export' the secret for the remainder of the AWS Serverless Express application to use.

What I have tried: parsing and updating environment variables modules.export.variableName (trying to export just the variable with the secret) modules.export.functionName (trying to export the entire function) return to an array (returning the results of the function to an array and calling from the array)

Application Structure: lambda.js server.js /db/db.js controllers: there are 6 controllers in tota

lambda.js

'use strict'
const awsServerlessExpress = require('aws-serverless-express');
const app = require('./server');
const AWS = require('aws-sdk');
require('dotenv').config();
const secretsManager = new AWS.SecretsManager({
region: 'us-east-1' });
const AWS_SECRET = process.env.AWS_SECRET;

let server;
let uri
var password
module.exports.uri3;
let uri2;

const createServer = async (callback) => {
const secret = await secretsManager.getSecretValue({SecretId: AWS_SECRET}).promise();

const secretBackup = JSON.parse(secret.SecretString)
   
Object.assign(process.env, JSON.parse(secret.SecretString));

module.exports.exporteduserName = secretBackup.username;
console.log('undernasdnfkasdf ' + this.exporteduserName) //This returns the correct value
password = secretBackup.password;
//console.log('this is what is stored in userName ' + userName)
console.log('this is what is stored in password ' + password) //This returns the correct value

uri2 = `mongodb+srv://${process.env.username}:${process.env.password}@cluster0.3jrug.mongodb.net/lamb?retryWrites=true&w=majority`; //This returns the correct value

module.exports.uri3 = uri2

console.log(uri2) 

server = awsServerlessExpress.createServer(app, null, binaryMimeTypes)
return server 

}

console.log('this is uri3 ' + this.uri3) //undefined

console.log('outside function ' + this.exporteduserName) //undefined
const binaryMimeTypes = [
  'application/javascript',
  'application/json',
  'application/octet-stream',
  'application/xml',
  'font/eot',
  'font/opentype',
  'font/otf',
  'image/jpeg',
  'image/png',
  'image/svg+xml',
  'text/comma-separated-values',
  'text/css',
  'text/html',
  'text/javascript',
  'text/plain',
  'text/text',
  'text/xml'
]

I suspect my problem is here (below)- however I dont know fully what this code does. It seems to resolve the promise function and then set server to the createServer function with the SecretId. why it is using this variable I'm not sure.

exports.handler = (event, context) => {
    Promise.resolve(server || createServer({SecretId: AWS_SECRET}, )).then((server) => {
    awsServerlessExpress.proxy(server, event, context);
    //console.log('this is what i have stored ' + process.env.AWS_SECRET);
    });
};

Upvotes: 0

Views: 251

Answers (1)

BinaryPhinary
BinaryPhinary

Reputation: 21

Ok so I managed to solve this issue and wanted to update it in the event that someone else may have this question.

The following documents Lambda 'best practices'. In the link - they largely provide the format that should be used with using exports.handler https://docs.aws.amazon.com/lambda/latest/dg/best-practices.html

There is a caveat however - because Im using AWS Serverless Express - it requires the creation of Promise.resolve create server event. Due to this - you CANNOT use a promise function from inside the AWS Serverless Express exports.handler function. This is because it already contains a Promise.resolve - so it just causes confusion if there are two promises.

exports.handler = (event, context, callback) => {
    Promise.resolve(server || createServer({SecretId: AWS_SECRET})).then((server) => {
        awsServerlessExpress.proxy(server, event, context);
        context.callbackWaitsForEmptyEventLoop = false;
        var uri2 = `mongodb+srv://${process.env.username}:${process.env.password}@clusterX.XYYYYY.mongodb.net/lamb?retryWrites=true&w=majority`;
        var serverjstest = app.abetatestfunc (uri2);
        var dbfiletest = dbfile.dbfiletest (uri2);
      
    });


};

In my case - since Im using Express, I have many different *.js files. In order to execute the functions - I have to module.exports the JS files as you can see above (dbfile.debfiletest(uri2)). After that - I need to put my new pseudo function over top of the existing code, also with the uri2 input/variable. ie:

function abetatestfunc(uri2) {
    console.log('this is a test call from within server.js to see if we can get uri2 here ' + uri2)
    uri = uri2
    console.log('server.js value of uri ' + uri)

//your code goes here

}

In this manner - the function will be invoked with exports.handler gets called by the api gateway.

Hope that helps. Im sure there are 100 different ways to make it nicer/better/run better - but Im not there yet. Im just at the 'lets make it functional' stage.

Upvotes: 0

Related Questions