Search code examples
node.jsstringaws-lambdaaws-secrets-manager

String gets serialised twice when returned from Lambda (NodeJs)


I'm working on some Lambda functions. One Lambda is used to retrieve an API key from AWS Secrets Manager. I have a 2nd Lambda where I call the 1st one to get that API key.

It might not be the best approach but here's how I'm doing it :

1st lambda (that gets the API key from Secrets Manager)

const AWS = require("aws-sdk");
const sm = new AWS.SecretsManager({ region: "us-east-1" });

const getSecrets = async(SecretId) => {
  return await new Promise((resolve, reject) => {
    sm.getSecretValue({ SecretId }, (err, results) => {
      if (err) reject(err);
      else resolve(JSON.parse(results.SecretString));
    });
  });
};

const main = async(event) => {
  const { stripe_secret_key } = await getSecrets(
    process.env.prod ? "stripe_production" : "stripe_test"
  );
  return stripe_secret_key;
};

exports.handler = main;

That works a treat and if I test that one I get the following output:

"sk_test_XXXXXXXXXXXXXXXXXXX"

at that point, I assume the api key is well formatted just as you would expect

Now comes the 2nd Lambda

2nd Lambda (that calls the 1st one to use the API key)

const AWS = require("aws-sdk");
const lambda = new AWS.Lambda({ region: "us-east-1" });

const getStripeSecret = async () => {
  return await new Promise((resolve, reject) => {
    const params = {
      FunctionName: "getStripeSecret",
    };

    lambda.invoke(params, (err, results) => {
      if (err) reject(err);
      else resolve(results.Payload);
    });
  });
};

const main = async (event, context) => {
  const stripeSecret = getStripeSecret();
  const stripe = require("stripe")(stripeSecret);
  const { name, email, description, phone } = event;

  const customer = await stripe.customers.create({
    name,
    email,
    description,
    phone,
  });

  console.info(`${message}`);

  return customer.id;
};

exports.handler = main;

The problem is that the string that is results.Payload is actually "\"sk_test_XXXXXXXXXXXXXXXXXXX\"" rather than "sk_test_XXXXXXXXXXXXXXXXXXX" so I can't obviously use that to make my API request.

  1. How can I make sure that the string doesn't get serialised twice (I assume that's what's happening here).

  2. At some point I was able to get "sk_test_XXXXXXXXXXXXXXXXXXX" as an output in the 2nd Lambda by using eval() on the string ( I know, that's bad) but even then, I could not use the API key since it was still being passed with its double quotes if that makes sense.

Any hint on how to approach this would be greatly appreciated.


Solution

  • I believe that the problem is that the output from the first function is a JSON string.

    Try to change the return of the first function to some like:

    return {"response": stripe_secret_key}
    

    And in the second function:

    JSON.parse(results.Payload).response
    

    This way your return is already a JSON and you can use the value response in your second function.