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.
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. 🎉