Access Secrets-Manager values in Serverless Framework script.

Mohd Afzal
VectoScalar
Published in
3 min readSep 7, 2021

While deploying the application using the Serverless script, we want to access some confidential values like- AWS & encryption/decryption keys, Database details, etc which we don’t want to expose or commit into the codebase.

To achieve this, we will use the AWS JavaScript SDK to access the Secrets-Manager service.

Install the aws-sdk using npm.

Let’s get started. First, create a secrets.js file in the root of your project. [Or at any other place you want to create]. Add the below code in this file.

const AWS = require("aws-sdk");// Create a Secrets Manager client
const client = new AWS.SecretsManager({
region: 'your_aws_region'
});
const getAllSecret = () => {
return new Promise((resolve, reject) => {
let secrets = {};
const secretName = '<your_aws_secret_manager_name>';
client.getSecretValue({ SecretId: secretName }, function (err, data) {
if (err) {
console.error('getAllSecret - error: ', err);
reject(err);
}
else {
// Depending on whether the secret is a string or binary, one of these fields will be populated.
if ('SecretString' in data) {
secrets = data.SecretString;
}
else {
let buff = new Buffer(data.SecretBinary, 'base64');
secrets = buff.toString('ascii');
}
secrets = JSON.parse(secrets);
resolve(secrets);
}
});
});
};
module.exports.getSecrets = async () => {
const keys = await getAllSecret();
return {
DB_HOSTNAME: keys.DB_HOSTNAME,
DB_USERNAME: keys.DB_USERNAME,
DB_PASSWORD: keys.DB_PASSWORD,
DB_PORT: keys.DB_PORT
}
}

In above code:

  1. Firstly, we have imported the AWS SDK.
  2. Created an object of Secrets-Manager service.
  3. Define a getAllSecret() function that will use the Secrets-Manager’s getSecretValue() function to get the secrets and it takes the secret name [which you have created in AWS Console] as parameter.
  4. Once the secrets are received, parse them and resolve the promise.
  5. We put this function inside Promise, so that we can invoke it using the async/await pattern.
  6. At end, we have exported a function called getSecrets. It will invoke the getAllSecret() and map the result in key-value pairs.

Now, create a serverless.yml file in the root of the project.

app: my-app
service: my-service
custom:
SECRETS: ${file(./secrets.js):getSecrets}
provider:
name: aws
runtime: nodejs14.x
functions:
my-function:
name: my-lambda-function
handler: index.handler
description: Test lambda
memorySize: 128
timeout: 30
environment:
DB_HOSTNAME: ${self:custom.SECRETS.DB_HOSTNAME}
DB_USERNAME: ${self:custom.SECRETS.DB_USERNAME}
DB_PASSWORD: ${self:custom.SECRETS.DB_PASSWORD}
DB_PORT: ${self:custom.SECRETS.DB_PORT}

Note: The indentation should be proper of the yml file otherwise Serverless gives error while start deployment.

It is a simple serverless.yml script that deploy a lambda function. [we made it simple for example purpose]

But, few things, need to be note there are:

  1. Inside the custom section of the above script, we have defined a custom variable called SECRETS and we have passed the path of our secrets.js to Serverless ${file()} function. Please make sure file path should be correct.
  2. Using it, Serverless will include the JavaScript file and we can invoke the exported getSecrets() function on the same [this function is accessible because we have exported it] using : symbol in Serverless script.
  3. No need to worry about async getSecrets() function invocation, Serverless will take care of it before starting the deployment and the coming result will assign to SECRETS custom variable.
  4. Now, we can use those received secrets from Secrets-Manager and assign their values to the lambda’s environment variables.
  5. The syntax/way of using the custom variables in script is:
${self:custom.SECRETS.DB_HOSTNAME}

self: Refers to the current script.

custom: Refers to the custom section of the script.

SECRETS: Refers to the SECRETS variable in the custom section.

DB_HOSTNAME: Refers to the key name that we have mapped with the coming value from the AWS Secrets-Manager.

Note: Your IAM user that you will use to deploy the script should have atleast the following permissions to access the AWS Secrets-Manager.

secretsmanager:GetSecretValue

secretsmanager:DescribeSecret

secretsmanager:ListSecrets

That’s it, we have done here, now just go ahead and deploy your Serverless script and you should see the AWS Secrets-Manager values are assigned to your lambda’s environment variables.

To create the secret in Secrets-Manager, please refer to the official AWS documentation: https://docs.aws.amazon.com/secretsmanager/latest/userguide/tutorials_basic.html#tutorial-basic-step1

--

--

Mohd Afzal
VectoScalar

I'm a writer who writes ✍programming poetries & stories. 😎