Today, lambda powertools has released version 1.7.0. Although it is a beta developer preview, it is already very close to the GA version. This version includes a feature that I have been waiting for a long time, so I can't wait to use it and introduce it to you. This feature is called Parameters utility. This new utility allows you to retrieve one or more parameter values from a range of AWS services, while also helping you reduce the amount of custom code needed to handle caching, transformations, and error handling.
The Parameters utility provides high-level functions to retrieve one or multiple parameter values from AWS Systems Manager Parameter Store, AWS Secrets Manager, AWS AppConfig, Amazon DynamoDB, or your own parameter store.
Key features
- Retrieve one or multiple parameters from the underlying provider
- Cache parameter values for a given amount of time (defaults to 5 seconds)
- Transform parameter values from JSON or base64 encoded strings
- Bring Your Own Parameter Store Provider
Getting started
To start testing the utility, install it from npm using the @aws-lambda-powertools/parameters@1.7.0-beta
alias.
In addition, you will need to add the AWS SDK client for the parameter store you are planning to use. The Parameters utility supports AWS SDK v3 for JavaScript only which allows the utility to be modular, and you to install only the SDK packages you need and keep your bundle size small:
- SSM Parameters Store ->
@aws-sdk/client-ssm
- Secrets Manager ->
@aws-sdk/client-secrets-manager
- AppConfig ->
@aws-sdk/client-appconfigdata
- DynamoDB ->
@aws-sdk/client-dynamodb @aws-sdk/util-dynamodb
Next, assign appropriate AWS Identity and Access Management (IAM) permissions to the Lambda function execution role of your Lambda function that allow retrieving parameters from the parameter store. You can see which permissions are needed for each action and store in the IAM Permissions section of the utility's docs.
In the section below we will use Secrets Manager as store to showcase different features of the Parameters utility. The same features are available for all other providers, as well as some others unique to each store. If you are interested in another store, skip to the utility docs.
Retrieving a single secret
To retrieve an individual parameter, the Parameters utility provides the getSecret
function:
import { getSecret } from '@aws-lambda-powertools/parameters/secrets';
export const handler = async (): Promise<void> => {
// Retrieve a single secret
const secret = await getSecret('my-secret');
console.log(secret);
}
Adjusting cache TTL
By default, the retrieved value will be cached in-memory for 5 seconds. This cached value is used for subsequent invocations of the Lambda function until it expires. If you want to keep the value around longer, the Parameters utility allows you to adjust the time-to-live (TTL) via the maxAge
argument:
import { getSecret } from '@aws-lambda-powertools/parameters/secrets';
export const handler = async (): Promise<void> => {
// Retrieve a single secret with a 60 seconds cache TTL
const secret = await getSecret('my-secret', { maxAge: 60 });
console.log(secret);
}
If instead you want to make sure that the latest value is always retrieved and cache is skipped, you can use the forceFetch
option:
import { getSecret } from '@aws-lambda-powertools/parameters/secrets';
export const handler = async (): Promise<void> => {
// Retrieve a single secret skipping cache
const secret = await getSecret('my-secret', { forceFetch: true });
console.log(secret);
}
Decoding secrets stored in JSON or base64 format
If some of your secrets are stored in base64 or JSON, you can deserialize them via the Parameters utility’s transform
argument:
import { SecretsProvider } from '@aws-lambda-powertools/parameters/secrets';
const secretsProvider = new SecretsProvider();
export const handler = async (): Promise<void> => {
// Retrieve a secret and deserialize it as JSON
const json = await secretsProvider.get('my-secret-json', { transform: 'json' });
console.log(json);
// Transform a base64 encoded string
const binary = await secretsProvider.getMultiple('my-secret-binary', { transform: 'binary' });
console.log(binary);
}
Customizing the AWS SDK
In some cases, you might want to use your own custom AWS SDK to retrieve values. This is useful in those instances in which you want to configure specific parameters or if you want to apply tracing. To do so, you can use the provider class directly:
import { Tracer } from "@aws-lambda-powertools/tracer";
import { SecretsProvider } from "@aws-lambda-powertools/parameters/secrets";
import { SecretsManagerClient } from "@aws-sdk/client-secrets-manager";
// initialize the tracer
const tracer = new Tracer();
// construct your client and instrument it to emit tracing data
const secretsManagerClient = tracer.captureAWSv3Client(new SecretsManagerClient({}));
// pass the client to the SecretProvider
const secretProvider = new SecretsProvider({ awsSdkV3Client: secretsManagerClient });
export const handler = async (): Promise<void> => {
// this operation will now appear in your X-Ray traces and service map
const secret = await secretProvider.get('my-secret');
console.log(secret);
}
To learn more about all the features available for each provider, check the Parameters docs.
Other provider
The examples above are all secrets, and you can use the same approach to access configurations stored in AppConfig, SSM, or DynamoDB.
import { AppConfigProvider } from "@aws-lambda-powertools/parameters/appconfig";
import { SSMProvider } from "@aws-lambda-powertools/parameters/ssm";
import { DynamoDBProvider } from "@aws-lambda-powertools/parameters/dynamodb";
SSM Provider
For example, using SSM, you can retrieve multiple parameters at once and apply specific transformations or TTLs.
import { getParametersByName } from '@aws-lambda-powertools/parameters/ssm';
import type { SSMGetParametersByNameOptionsInterface } from "@aws-lambda-powertools/parameters/types";
const props: Record<string, SSMGetParametersByNameOptionsInterface> = {
'/develop/service/commons/telemetry/config': { maxAge: 300, transform: 'json' },
'/no_cache_param': { maxAge: 0 },
'/develop/service/payment/api/capture/url': {}, // When empty or undefined, it uses default values
'/this/param/does/not/exist': {}, // <- Example of non-existent parameter
};
export const handler = async (): Promise<void> => {
// This returns an object with the parameter name as key
const {
_errors: errors,
...parameters
} = await getParametersByName(props, { maxAge: 60 });
// Handle gracefully, since `/this/param/does/not/exist` will only be available in `_errors`
if (errors && errors.length) {
console.error(`Unable to retrieve parameters: ${errors.join(',')}`);
}
for (const [key, value] of Object.entries(parameters)) {
console.log(`${key}: ${value}`);
}
};