How to Read SSM Parameters in Lambda with AWS CDK and TS

AWS Systems Manager Parameter Store is a service that provides a handy centralized store to manage your configuration data, whether plain-text data like database strings or secrets like passwords.

In this article, we will look at how to add a new parameter, set permissions for our Lambda, and use the data in CDK with TypeScript.

OG image showcasing a calendar with marked dates, a minimalist representation of AWS Lambda functions, and cron expressions, set against a digital, cloud computing-themed background with cool blues, whites, and greys.

Before we start, make sure you have the following installed:

  • AWS CLI
  • AWS CDK
  • Node.js

Setting Up Your CDK Project

If you don't have a CDK project, create a new CDK project by running the following in your terminal and in your new projects folder:

cdk init app --language typescript

Setting a Parameter

The basic command to add (or update) a value in the Parameter Store is:

aws ssm put-parameter --name "YourParameterName" --value "YourParameterValue" --type String

Replace YourParameterName with the name you want to give the parameter and YourParameterValue with the actual value you want to store.

For my example, I'll use the following:

aws ssm put-parameter --name "/env/dev/greeting" --value "Hello World!" --type SecureString

I'm using a "secure string" here so you can see how to use encrypted values.

Create the Lambda Stack

In our stack, lets setup our Lambda. This is my example HelloLambda stack:

import * as cdk from "aws-cdk-lib";
import * as lambda from "aws-cdk-lib/aws-lambda";
import * as ssm from "aws-cdk-lib/aws-ssm";
import { NodejsFunction } from "aws-cdk-lib/aws-lambda-nodejs";
import type { Construct } from "constructs";
import * as path from "path";

export class HelloLambda extends cdk.Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    const lambdaFn = new NodejsFunction(this, "helloWorld", {
      timeout: cdk.Duration.seconds(120),
      runtime: lambda.Runtime.NODEJS_20_X,
      entry: path.join(__dirname, "/../lambdas/hello/index.js"),
      depsLockFilePath: path.join(
        __dirname,
        "/../lambdas/hello/package-lock.json",
      ),
      bundling: {
        nodeModules: ["@aws-sdk/client-ssm"],
      },
    });

    // Granting permission to read the SSM parameter
    const param = ssm.StringParameter.fromStringParameterName(
      this,
      "GreetingParam",
      "/env/dev/greeting",
    );
    param.grantRead(lambdaFn);
  }
}

You'll see here that I grant permission to a specific parameter rather than giving it access to all of my parameters for increased security.

Create the Lambda

Then, I made a folder for this lambda in lambdas/hello where I created an index.js to add the logic.

In this folder you'll need to install @aws-sdk/client-ssm.

If you haven't got it setup you can do it by running the following in the /hello folder:

npm init -y
npm i @aws-sdk/client-ssm

Then we can create the logic:

// hello/index.js
const { SSMClient, GetParameterCommand } = require("@aws-sdk/client-ssm");
const ssmClient = new SSMClient({ region: "eu-west-1" });

// Helper function to retrieve a secret from AWS SSM
async function getSecretValue(secretName) {
  const params = {
    Name: secretName,
    WithDecryption: true, // Required for secureString
  };

  try {
    const command = new GetParameterCommand(params);
    const response = await ssmClient.send(command);
    return response.Parameter.Value;
  } catch (error) {
    console.error(`Error retrieving secret: ${error}`);
    throw error;
  }
}

exports.handler = async function () {
  console.log("Lambda running");

  try {
    const result = await getSecretValue("/env/dev/greeting");
    console.log("Parameter Value:", result);
    return {
      statusCode: 200,
      headers: { "Content-Type": "text/json" },
      body: result,
    };
  } catch (error) {
    console.error("Error fetching parameter:", error);
    return {
      statusCode: 500,
      body: JSON.stringify({ message: "Error fetching parameter" }),
    };
  }
};

I've created a little helper function in this code that you can use in your own projects.

However, as you can see, it involves a two-step process: creating a new GetParameterCommand and then sending the command to the ssmClient.

Now deploy your stack:

Deploy and Destroy

To ensure it's all working, deploy your stack; as a little reminder, you can deploy your stack by running:

cdk deploy

And to make sure you clean when you are finished testing everything, delete the resources with:

cdk destroy

And that's it!

You've deployed a Lambda that can use your SSM Parameters, which opens up many options for what you can build next. 🎉

AwsCdk
Avatar for Niall Maher

Written by Niall Maher

Founder of Codú - The web developer community! I've worked in nearly every corner of technology businesses: Lead Developer, Software Architect, Product Manager, CTO, and now happily a Founder.

Loading

Fetching comments

Hey! 👋

Got something to say?

or to leave a comment.