New Research: Supply Chain Attack on Axios Pulls Malicious Dependency from npm.Details →
Socket
Book a DemoSign in
Socket

@abstraks-dev/aws-helpers

Package Overview
Dependencies
Maintainers
1
Versions
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@abstraks-dev/aws-helpers

AWS SDK helpers with caching and retry logic for Secrets Manager and SSM Parameter Store

latest
npmnpm
Version
1.0.0
Version published
Maintainers
1
Created
Source

@abstraks-dev/aws-helpers

AWS SDK helpers with caching and retry logic for Secrets Manager and SSM Parameter Store.

Features

  • 🔐 Secrets Manager: Retrieve secrets with automatic JSON parsing
  • 📦 SSM Parameter Store: Get single or multiple parameters
  • Caching: 5-minute cache reduces AWS API calls and costs
  • 🔄 Retry Logic: Exponential backoff for transient errors
  • 🎯 Lazy Loading: AWS SDK loaded only when needed
  • 🛡️ Error Handling: Smart retry vs. immediate failure
  • 📊 Cache Management: Clear cache and get statistics
  • 🔌 Drop-in Replacement: Compatible with existing getSecret() patterns

Installation

npm install @abstraks-dev/aws-helpers

Optional Peer Dependencies

Install only what you need:

# For Secrets Manager
npm install @aws-sdk/client-secrets-manager

# For SSM Parameter Store
npm install @aws-sdk/client-ssm

Usage

Secrets Manager - Simple

import { getSecret } from '@abstraks-dev/aws-helpers';

// Get entire JSON secret
const config = await getSecret('app-config');
console.log(config.API_KEY, config.DB_URL);

// Extract specific key from JSON secret
const apiKey = await getSecret('app-config', 'API_KEY');

// Get plain text secret
const token = await getSecret('github-token');

Secrets Manager - With Caching

import { createSecretsManagerHelper } from '@abstraks-dev/aws-helpers';

const secrets = createSecretsManagerHelper({
	region: 'us-west-2',
	cacheTTL: 5 * 60 * 1000, // 5 minutes (default)
	maxRetries: 3, // Default
});

// First call fetches from AWS
const key1 = await secrets.getSecret('app-config', 'API_KEY');

// Second call uses cache (no AWS API call)
const key2 = await secrets.getSecret('app-config', 'API_KEY');

// Clear cache when secrets rotate
secrets.clearCache('app-config');

// Get cache statistics
const stats = secrets.getCacheStats();
console.log(stats); // { size: 2, entries: [...] }

SSM Parameter Store - Single Parameter

import { getParameter } from '@abstraks-dev/aws-helpers';

// Get decrypted parameter
const dbUrl = await getParameter('/app/database-url');

// Get without decryption
const value = await getParameter('/app/config', { withDecryption: false });

SSM Parameter Store - Multiple Parameters

import { createSSMHelper } from '@abstraks-dev/aws-helpers';

const ssm = createSSMHelper({ region: 'us-west-2' });

// Get multiple parameters efficiently
const params = await ssm.getParameters([
	'/app/database-url',
	'/app/api-key',
	'/app/redis-url',
]);

console.log(params['/app/database-url']);
console.log(params['/app/api-key']);

Integration with Existing Code

Drop-in replacement for existing patterns:

// Before: Custom getSecret helper
import { getSecret } from './helpers/secrets.js';

// After: @abstraks-dev/aws-helpers
import { getSecret } from '@abstraks-dev/aws-helpers';

// Same API!
const secret = await getSecret('app-config', 'JWT_SECRET');

API Documentation

createSecretsManagerHelper(options)

Creates a Secrets Manager helper with caching and retry logic.

Parameters:

  • options.region (string, optional): AWS region (default: AWS_REGION env var or 'us-west-2')
  • options.cacheTTL (number, optional): Cache TTL in milliseconds (default: 300000 = 5 minutes)
  • options.maxRetries (number, optional): Maximum retry attempts (default: 3)
  • options.retryDelay (number, optional): Initial retry delay in ms (default: 100)

Returns: Object with methods: getSecret, clearCache, getCacheStats

Example:

const secrets = createSecretsManagerHelper({
	region: 'us-west-2',
	cacheTTL: 10 * 60 * 1000, // 10 minutes
	maxRetries: 5,
	retryDelay: 200,
});

helper.getSecret(secretName, key)

Retrieves a secret from AWS Secrets Manager with caching.

Parameters:

  • secretName (string, required): Name or ARN of the secret
  • key (string, optional): Key to extract from JSON secret

Returns: Promise<string | object>

Behavior:

  • Returns full object if secret is JSON and no key provided
  • Returns specific value if key provided
  • Returns raw string for non-JSON secrets
  • Throws if trying to extract key from non-JSON secret

Example:

// JSON secret: {"API_KEY": "abc123", "DB": "mongodb://..."}
const fullConfig = await helper.getSecret('app-config');
// Returns: { API_KEY: 'abc123', DB: 'mongodb://...' }

const apiKey = await helper.getSecret('app-config', 'API_KEY');
// Returns: 'abc123'

// Plain text secret
const token = await helper.getSecret('github-token');
// Returns: 'ghp_abc123...'

helper.clearCache(secretName)

Clears cached secrets.

Parameters:

  • secretName (string, optional): Secret name to clear (clears all if omitted)

Example:

// Clear specific secret (including all keys)
helper.clearCache('app-config');

// Clear all cached secrets
helper.clearCache();

helper.getCacheStats()

Returns cache statistics.

Returns: Object with size (number) and entries (array of strings)

Example:

const stats = helper.getCacheStats();
console.log(stats.size); // 3
console.log(stats.entries); // ['secret1:KEY1', 'secret2', 'secret3:KEY2']

createSSMHelper(options)

Creates an SSM Parameter Store helper with caching and retry logic.

Parameters:

  • options.region (string, optional): AWS region (default: AWS_REGION env var or 'us-west-2')
  • options.cacheTTL (number, optional): Cache TTL in milliseconds (default: 300000 = 5 minutes)
  • options.maxRetries (number, optional): Maximum retry attempts (default: 3)
  • options.retryDelay (number, optional): Initial retry delay in ms (default: 100)

Returns: Object with methods: getParameter, getParameters, clearCache, getCacheStats

helper.getParameter(name, options)

Retrieves a parameter from SSM Parameter Store with caching.

Parameters:

  • name (string, required): Parameter name or path
  • options.withDecryption (boolean, optional): Decrypt SecureString (default: true)

Returns: Promise

Example:

const dbUrl = await helper.getParameter('/app/database-url');

const publicConfig = await helper.getParameter('/app/version', {
	withDecryption: false,
});

helper.getParameters(names, options)

Retrieves multiple parameters efficiently with caching.

Parameters:

  • names (string[], required): Array of parameter names
  • options.withDecryption (boolean, optional): Decrypt SecureString (default: true)

Returns: Promise - Map of parameter names to values

Behavior:

  • Uses cache for already-fetched parameters
  • Fetches uncached parameters in single AWS API call
  • Caches all fetched parameters

Example:

const params = await helper.getParameters([
	'/app/db-url',
	'/app/api-key',
	'/app/redis-url',
]);

console.log(params['/app/db-url']);

Simple Wrapper Functions

getSecret(secretName, key, options)

Simple wrapper for one-off secret retrieval (no persistent cache).

Example:

import { getSecret } from '@abstraks-dev/aws-helpers';

const secret = await getSecret('app-config', 'API_KEY', {
	region: 'us-west-2',
});

getParameter(name, options)

Simple wrapper for one-off parameter retrieval (no persistent cache).

Example:

import { getParameter } from '@abstraks-dev/aws-helpers';

const value = await getParameter('/app/config');

Caching Strategy

How Caching Works

  • First Request: Fetches from AWS, stores in memory with timestamp
  • Subsequent Requests: Returns cached value if within TTL
  • After TTL: Fetches fresh value from AWS, updates cache
  • Per-Container: Each Lambda container has independent cache

Cache Benefits

const secrets = createSecretsManagerHelper({ cacheTTL: 5 * 60 * 1000 });

await secrets.getSecret('config', 'KEY'); // AWS API call
await secrets.getSecret('config', 'KEY'); // Cache (0ms)
await secrets.getSecret('config', 'KEY'); // Cache (0ms)

// After 5 minutes...
await secrets.getSecret('config', 'KEY'); // Fresh fetch from AWS

Performance Impact:

  • ✅ Reduces AWS API calls by ~90%+
  • ✅ Saves $0.05 per 10,000 requests (Secrets Manager pricing)
  • ✅ Improves Lambda response time (cache: <1ms vs AWS: 50-100ms)
  • ✅ Reduces throttling risk

Considerations:

  • ⚠️ Secret rotation takes up to TTL to propagate
  • ⚠️ Cache is per-container (not shared across containers)
  • ⚠️ Cold starts always fetch fresh secrets
  • ⚠️ Call clearCache() after manual secret updates

Retry Logic

Automatic Retries

The package automatically retries transient errors with exponential backoff:

const helper = createSecretsManagerHelper({
	maxRetries: 3,
	retryDelay: 100, // Initial delay
});

// Retry delays: 100ms, 200ms, 400ms
// Total max wait: 700ms before giving up

Errors That Are Retried

  • ServiceUnavailableException
  • ThrottlingException
  • InternalServiceErrorException
  • Network timeouts and connection errors

Errors That Are NOT Retried

  • AccessDeniedException (permission issue)
  • ResourceNotFoundException (secret/parameter doesn't exist)
  • ValidationException (bad request)

Why? These errors won't be fixed by retrying.

Migration Guide

From Social/Media Service Pattern

Before:

// helpers/secrets.js
import {
	SecretsManagerClient,
	GetSecretValueCommand,
} from '@aws-sdk/client-secrets-manager';

const client = new SecretsManagerClient({ region: 'us-west-2' });

export async function getSecret(secretName, key) {
	try {
		const command = new GetSecretValueCommand({
			SecretId: secretName,
			VersionStage: 'AWSCURRENT',
		});
		const response = await client.send(command);
		const secretString = response.SecretString;

		try {
			const secretObj = JSON.parse(secretString);
			return key ? secretObj[key] : secretObj;
		} catch (e) {
			return secretString;
		}
	} catch (error) {
		console.error(`Error retrieving secret ${secretName}:`, error);
		throw error;
	}
}

After:

import { createSecretsManagerHelper } from '@abstraks-dev/aws-helpers';

export const secrets = createSecretsManagerHelper({ region: 'us-west-2' });
export const getSecret = secrets.getSecret.bind(secrets);

Or just replace imports:

// Before
import { getSecret } from './helpers/secrets.js';

// After
import { getSecret } from '@abstraks-dev/aws-helpers';

Benefits:

  • ✅ 5-minute caching (80-90% fewer AWS calls)
  • ✅ Automatic retry with exponential backoff
  • ✅ Lazy AWS SDK loading (faster cold starts)
  • ✅ Cache management and statistics
  • ✅ Same API, drop-in compatible

Best Practices

1. Reuse Helper Instances

// Good: Single instance with shared cache
const secrets = createSecretsManagerHelper();
export const getSecret = secrets.getSecret.bind(secrets);

// Avoid: New instance every time (no cache benefit)
function getSecret(name, key) {
	const helper = createSecretsManagerHelper();
	return helper.getSecret(name, key);
}

2. Use Appropriate Cache TTL

// Production secrets (rotate monthly)
const secrets = createSecretsManagerHelper({
	cacheTTL: 10 * 60 * 1000, // 10 minutes
});

// Development secrets (rotate frequently)
const secrets = createSecretsManagerHelper({
	cacheTTL: 60 * 1000, // 1 minute
});

// High-security (no caching)
const secrets = createSecretsManagerHelper({
	cacheTTL: 0, // Always fetch fresh
});

3. Handle Secret Rotation

// After rotating secret in AWS console
secrets.clearCache('app-config'); // Force fresh fetch

4. Batch Parameter Fetches

// Good: Single API call
const params = await ssm.getParameters(['/app/db', '/app/key', '/app/url']);

// Avoid: Multiple API calls
const db = await ssm.getParameter('/app/db');
const key = await ssm.getParameter('/app/key');
const url = await ssm.getParameter('/app/url');

5. Monitor Cache Effectiveness

const stats = secrets.getCacheStats();
console.log(`Cache size: ${stats.size}`);
console.log(`Cached entries: ${stats.entries.join(', ')}`);

// Log in CloudWatch for monitoring

Troubleshooting

"AWS Secrets Manager SDK not installed"

Cause: Missing peer dependency.

Solution:

npm install @aws-sdk/client-secrets-manager

"Access denied" / "AccessDeniedException"

Cause: Lambda execution role lacks permissions.

Solution: Add IAM policy:

{
	"Effect": "Allow",
	"Action": ["secretsmanager:GetSecretValue"],
	"Resource": "arn:aws:secretsmanager:REGION:ACCOUNT:secret:SECRET_NAME-*"
}

"Secret not found" / "ResourceNotFoundException"

Cause: Secret doesn't exist or wrong name/region.

Solution:

  • Verify secret name (case-sensitive)
  • Check region matches
  • Confirm secret exists: aws secretsmanager list-secrets

"Throttling" Errors

Cause: Too many AWS API calls.

Solution: Increase cache TTL:

const secrets = createSecretsManagerHelper({
	cacheTTL: 10 * 60 * 1000, // Increase from 5 to 10 minutes
});

Secrets Not Updating After Rotation

Cause: Cache still has old value.

Solution:

// Clear cache after rotation
secrets.clearCache('app-config');

// Or reduce cache TTL for frequently-rotated secrets
const secrets = createSecretsManagerHelper({
	cacheTTL: 60 * 1000, // 1 minute
});

Performance Characteristics

OperationWithout CacheWith CacheImprovement
getSecret (first call)50-100ms50-100ms-
getSecret (cached)50-100ms<1ms50-100x faster
API calls (100 requests)100~2-520-50x fewer
Cost (1M requests)$400$8-2020-50x cheaper

Note: Actual performance depends on AWS region, network latency, and secret size.

License

MIT

Keywords

aws

FAQs

Package last updated on 20 Nov 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts