Insights, News & Events

AWS Secrets Caching

How to get up and running with the new Lambda Secrets extension using the Serverless Framework and NodeJS.

On the 18th of October, AWS released a new Lambda extension to simplify and cache secrets and parameters: https://aws.amazon.com/about-aws/whats-new/2022/10/aws-parameters-secrets-lambda-extension/

This extension helps reduce the number of API calls a function needs to make to Secrets Manager and allows values to be cached locally for concurrent executions. Not only does this get around API rate limiting issues, but it can also drive down costs per lambda execution.

It works by hosting a local HTTP server within a Lambda Layer where your functions can make GET requests to retrieve secrets rather than relying on the AWS SDK.

lambda fucntion

We’re going to run through how to get up and running with this new extension using the Serverless Framework and NodeJS.

First, we will start by creating a new serverless project using the basic starter template:

[MacBook-Pro-3:serverless-extensions paulflowers$ serverless

Creating a new serverless project

? What do you want to make? AWS - Node.is - Starter 
[? What do you want to call this project? secrets-extension

~ Project successfully created in secrets-extension folder

[? Do you want to login/register to Serverless Dashboard? No

[? Do you want to deploy now? No

What next?
Run these commands in the project directory:
yamlhhhhhhh
serverless deploy    Deploy changes 
serverless info      View deployed endpoints and resources             
serverless invoke    Invoke deployed functions 
serverless --help    Discover more commands

When we open this in VScode we will have a directory structure like this:

directorystructure

We will start by adding the AWS Secrets extension as a new layer in ‘serverless.yml’

service: secrets-extension

frameworkVersion: '3'

provider:
  name: aws 
  region: eu-west-1 
  runtime: nodeis14eX

functions:
  hello:
    handler: handler.hello 
    layers:
      -arn:aws:lambda:eu-west-1:015030872274:layer:AWS-Parameters-and-Secrets-Lambda-Extension:2

I am deploying to eu-west-1 so I have used the ARN that corresponds to this region, you can find the relevant ARN for your deployment here https://docs.aws.amazon.com/secretsmanager/latest/userguide/retrieving-secrets_lambda.html#retrieving-secrets_lambda_ARNs

We also need to configure the Lambda IAM role to allow access to secrets manager, I am going to set this quite loose, but you should be more selective in a production environment and scope the role accordingly.

Modify the ‘providers’ section like so:

provider:
  name: aws 
  region: eu-west-1 
  runtime: nodeistAx 
  iam:
    role:
      statements:
        # Allow functions to access all secrets - not for production use
        - Effect: Allow
        Action: 'seccetsmanager:Get*
        Resource: I * I
        - Effect: Allow
        Action: 'secretsmanager :List*'
        Resource:
        - Effect: Allow
        Action: 'secretsmanager :DescribeSecret
        Resource: I * I

We now have a Lambda function defined with Serverless, have attached the Secrets Manager extension and configured the required IAM permissions to fulfill its duties.

Next, we will create a Secret which we will use to test the extension using the AWS CLI:

aws secretsmanager create-secret --name my-secret --secret-string "Thor Love & Thunder wasn't actually that bad"

And now we will configure our Lambda function to grab the secret using the extensions web service and output it to the console.

Update handler.js as follows:

'use strict'

exports.hello = function (event, context, callback) {
  const https = require('http')
    const options = {
      hostname: 'localhost' 
      port: 2773, 
      path: '/secretsmanager/get?secretId-my-secret" 
      method: 'GET'
      headers: {
        'X-Aws-Parameters-Secrets-Token': process. env.AWS_SESSION_TOKEN
      },
  }
  const req = https. request (options, res =› {
    res.on ('data', d => {
      const mySecret = JSON.parse (d) . SecretString;
      console.log (mySecret)
      return d;
    })
  })
  reg.on('error', error => {
      console.error (error)
  })
  reg.end ( )
};

The header:

'X-Aws-Parameters-Secrets-Token': process.env.AWS_ SESSION_ TOKEN

is used to pass the session token from the Lambda functions execution role into the extension so it can authenticate with Secrets Manager.

Now deploy the function with:

[MacBook-Pro-3:secrets-extension paulflowers$ serverless deploy

Deploying secrets-extension to stage dev (eu-west-1)

Service deployed to stack secrets-extension-dev (36s)

functions:
  hello: secrets-extension-dev-hello (1.7 kB)

Finally, we can invoke the function and see the output of the cached secret:

aws lambda invoke  - -function-name "secrets-extension-dev-hello"   --log-type Tail out - -query
"LogResult" - -output text | base64 - - decode

START RequestId: Oaa674ba-9d21-47c8-932d-720a6506ab Version: $LATEST
[AWS Parameters and Secrets Lambda Extension] 2022/10/19 15:55:43 INFO ready to serve traffic
2022-10-19T15:55:43.9727 0aa674ba-9d21-47c8-932d-7e20fa6506ab
INFO  Thor Love & Thunder wasn't actually that bad
END RequestId: Oaa674ba-9d21-47c8-932d-7e20a6506ab
REPORT RequestId: 0aa674ba-9d21-47c8-932d-7e20fa6506ab
Duration: 9.05 ms Billed Duration: 10 ms
Memory Size: 1024 MB
Max Memory Used: 77 MB

And there you have it.

Written By Paul Flowers 25 Jun 2022
Share