@nestjs-aws/systems-manager
v1.0.4
Published
NestJS module for AWS Systems Manager (Parameter Store & Secrets Manager). Seamlessly integrate AWS SSM parameters and secrets into your NestJS applications with TypeScript support, automatic refresh, and hierarchical configuration management.
Downloads
33
Maintainers
Keywords
Readme
@nestjs-aws/systems-manager

A powerful NestJS module for seamless integration with AWS Systems Manager Parameter Store and AWS Secrets Manager.
Table of Contents
- Features
- Installation
- Quick Start
- Configuration
- API Reference
- Usage Examples
- IAM Permissions
- Best Practices
- Troubleshooting
- License
Features
- ✨ Dual Integration - Support for both AWS Parameter Store and Secrets Manager
- 🔄 Auto Refresh - Runtime parameter and secret refresh capability
- 🔐 Secure by Default - Automatic decryption of SecureString parameters
- 📦 Pagination Support - Handles large parameter sets automatically
- 🌲 Hierarchical Keys - Optional preservation of parameter path hierarchy
- ⚡ Fast Access - In-memory caching for lightning-fast runtime access
- 🛡️ Type Safe - Full TypeScript support with comprehensive type definitions
Installation
npm install @nestjs-aws/systems-managerPeer Dependencies
npm install @aws-sdk/client-ssm @aws-sdk/client-secrets-manager @nestjs/common @nestjs/configQuick Start
Basic Setup
import { Module } from '@nestjs/common';
import { SystemsManagerModule } from '@nestjs-aws/systems-manager';
@Module({
imports: [
SystemsManagerModule.register({
awsRegion: 'us-east-1',
awsParamStorePath: '/app/config',
awsParamStoreContinueOnError: false,
}),
],
})
export class AppModule {}Using the Service
import { Injectable } from '@nestjs/common';
import { SystemsManagerService } from '@nestjs-aws/systems-manager';
@Injectable()
export class AppService {
constructor(private readonly systemsManager: SystemsManagerService) {}
getConfig() {
const host = this.systemsManager.get('database-host');
const port = this.systemsManager.getAsNumber('database-port');
const password = this.systemsManager.getSecret('db-password');
return { host, port, password };
}
}Configuration
Static Registration
SystemsManagerModule.register({
awsRegion: 'us-east-1',
awsParamStorePath: '/production/app',
awsParamStoreContinueOnError: false,
preserveHierarchy: true,
pathSeparator: '.',
useSecretsManager: true,
secretsManagerSecretNames: ['prod/db/credentials', 'prod/api/keys'],
})Async Registration with ConfigService
import { ConfigModule } from '@nestjs/config';
@Module({
imports: [
ConfigModule.forRoot(),
SystemsManagerModule.registerAsync({
import: ConfigModule,
useClass: ConfigService,
}),
],
})
export class AppModule {}Environment variables:
param-store.awsRegion=us-east-1
param-store.awsParamStorePath=/app/config
param-store.awsParamStoreContinueOnError=false
param-store.preserveHierarchy=true
param-store.pathSeparator=.
param-store.useSecretsManager=true
param-store.secretsManagerSecretNames=prod/db/credentials,prod/api/keysConfiguration Properties
| Property | Type | Required | Default | Description |
|----------|------|----------|---------|-------------|
| awsRegion | string | Yes | - | AWS region where parameters are stored |
| awsParamStorePath | string | Yes | - | Parameter Store path (must start with /) |
| awsParamStoreContinueOnError | boolean | Yes | - | Continue startup if fetch fails |
| preserveHierarchy | boolean | No | false | Preserve parameter path structure |
| pathSeparator | string | No | . | Separator for hierarchical keys |
| enableParameterLogging | boolean | No | false | Enable debug logging (masks sensitive values) |
| useSecretsManager | boolean | No | false | Enable Secrets Manager integration |
| secretsManagerSecretNames | string[] | No | [] | Array of secret names to fetch |
API Reference
SystemsManagerService
Basic Methods
get(key: string): string // Get from either store
getParameter(key: string): string // Get from Parameter Store
getSecret(key: string): string // Get from Secrets Manager
getOrDefault(key: string, default: string): string // Get with fallbackType Conversion Methods
getAsNumber(key: string): number // Convert to number
getAsBoolean(key: string): boolean // Convert to boolean
getAsJSON<T>(key: string): T // Parse as JSONCheck Methods
has(key: string): boolean // Check either store
hasParameter(key: string): boolean // Check Parameter Store
hasSecret(key: string): boolean // Check Secrets ManagerBulk Methods
getAll(): Record<string, string> // Get all values
getAllParameters(): Record<string, string> // Get all parameters
getAllSecrets(): Record<string, string> // Get all secrets
getAllKeys(): string[] // Get all keysRefresh Methods
await refresh(): Promise<void> // Refresh both stores
await refreshParameters(): Promise<void> // Refresh parameters only
await refreshSecrets(): Promise<void> // Refresh secrets onlyUsage Examples
Basic Access
// Flat mode (default) - Parameter: /app/config/api-key
const apiKey = this.systemsManager.get('api-key');
// Hierarchical mode - Parameter: /app/config/database/host
const dbHost = this.systemsManager.get('database.host');Type Conversions
const port = this.systemsManager.getAsNumber('port');
const debugMode = this.systemsManager.getAsBoolean('debug-enabled');
interface Config {
timeout: number;
retries: number;
}
const config = this.systemsManager.getAsJSON<Config>('app-config');Working with Secrets
const dbPassword = this.systemsManager.getSecret('database-password');
if (this.systemsManager.hasSecret('api-key')) {
const key = this.systemsManager.getSecret('api-key');
}Runtime Refresh
import { Injectable } from '@nestjs/common';
import { Cron } from '@nestjs/schedule';
@Injectable()
export class ConfigRefreshService {
constructor(private readonly systemsManager: SystemsManagerService) {}
@Cron('0 */5 * * * *')
async refreshConfig() {
await this.systemsManager.refresh();
}
}Hierarchical Parameters
// AWS Parameter Store structure:
// /app/config/database/host
// /app/config/database/port
SystemsManagerModule.register({
awsRegion: 'us-east-1',
awsParamStorePath: '/app/config',
preserveHierarchy: true,
pathSeparator: '.',
})
// Access with dot notation
const dbHost = this.systemsManager.get('database.host');
const dbPort = this.systemsManager.get('database.port');IAM Permissions
Parameter Store
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssm:GetParametersByPath",
"ssm:GetParameter",
"ssm:GetParameters"
],
"Resource": "arn:aws:ssm:REGION:ACCOUNT_ID:parameter/app/config/*"
},
{
"Effect": "Allow",
"Action": ["kms:Decrypt"],
"Resource": "arn:aws:kms:REGION:ACCOUNT_ID:key/KEY_ID"
}
]
}Secrets Manager
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ["secretsmanager:GetSecretValue"],
"Resource": [
"arn:aws:secretsmanager:REGION:ACCOUNT_ID:secret:prod/db/credentials-*",
"arn:aws:secretsmanager:REGION:ACCOUNT_ID:secret:prod/api/keys-*"
]
}
]
}Best Practices
- Use Secrets Manager for Sensitive Data - Store passwords, API keys in Secrets Manager
- Organize Parameters Hierarchically - Use structured paths like
/production/app/database/host - Use Environment-Specific Paths - Separate configs per environment:
/dev/app,/prod/app - Enable Logging in Development Only - Set
enableParameterLogging: trueonly in dev - Fail Fast in Production - Set
awsParamStoreContinueOnError: falsefor production
Troubleshooting
Parameters Not Loading
- Check IAM permissions (
ssm:GetParametersByPath) - Verify AWS region matches where parameters are stored
- Ensure path starts with
/and exists in Parameter Store - Enable
enableParameterLogging: truefor debug logs
Secrets Not Loading
- Check IAM permissions (
secretsmanager:GetSecretValue) - Verify secret names exactly match those in Secrets Manager
- Ensure
useSecretsManager: trueis set - For ConfigService, use comma-separated values in .env
DecryptionFailure Error
Add KMS decrypt permissions:
{
"Effect": "Allow",
"Action": ["kms:Decrypt"],
"Resource": "arn:aws:kms:REGION:ACCOUNT_ID:key/KEY_ID"
}Requirements
- Node.js >= 20.0.0
- NPM >= 9.0.0
- NestJS >= 11.0.0
- AWS SDK >= 3.0.0
Contributing
Contributions are welcome! Please submit a Pull Request.
License
MIT License - see LICENSE.md for details.
Support
Author: Parik Maan
Made with ❤️ for the NestJS community
