@duabalabs/secure-keys
v1.0.0
Published
Production-grade cryptographic secret generation, rotation, and policy enforcement for fintech, KYC, Parse Server, CI/CD, and automation systems
Maintainers
Readme
@duabalabs/secure-keys
Production-grade cryptographic secret generation, rotation, and policy enforcement for fintech, KYC, Parse Server, CI/CD, and automation systems.
Features
- 🔐 Cryptographically Secure - Uses Node.js
crypto.randomBytes()for all secret generation - 🎯 Opinionated Presets - Ready-to-use generators for Parse Server, JWT, webhooks, and more
- 🔄 Zero-Downtime Rotation - Dual-key rotation support for seamless secret updates
- ✅ Policy Enforcement - Blocks weak secrets, UUIDs-as-secrets, and insufficient entropy
- 📝 Environment Writers - Writes
.envfiles with timestamps and metadata - ☁️ Cloud Exporters - Export to AWS Secrets Manager, HashiCorp Vault, Doppler, Kubernetes
- 🖥️ CLI Tool - Full-featured command-line interface
- 🤖 n8n Integration - Custom node for automation workflows
- 🚀 CI/CD Ready - GitHub Actions workflow included
Installation
npm install @duabalabs/secure-keysOr install globally for CLI access:
npm install -g @duabalabs/secure-keysQuick Start
Generate Parse Server Keys
import { generateParseKeys, writeParseEnv } from '@duabalabs/secure-keys';
const keys = generateParseKeys({
includeEncryptionKey: true,
environment: 'production',
});
// Write to .env file
writeParseEnv(keys, '.env.parse');
console.log('App ID:', keys.appId);
// Master key and other secrets are NOT logged for securityGenerate JWT Secrets
import { generateJwtSecrets } from '@duabalabs/secure-keys';
const secrets = generateJwtSecrets({
includeIdTokenSecret: true,
});
console.log('Access Token Secret:', secrets.accessTokenSecret);
console.log('Refresh Token Secret:', secrets.refreshTokenSecret);Generate Webhook Secret
import { generateWebhookSecret } from '@duabalabs/secure-keys';
const webhook = generateWebhookSecret();
console.log('Webhook Secret:', webhook.fullSecret);
// Output: whsec_a1b2c3d4e5f6...CLI Usage
Generate Parse Keys
# Generate and write to .env.parse
secure-keys parse
# Output as JSON
secure-keys parse --json
# With additional options
secure-keys parse --read-only-master --encryption-key -o .env.productionGenerate JWT Secrets
secure-keys jwt --id-token --output .env.jwtGenerate Webhook Secret
secure-keys webhook --prefix "myapp_"Rotate a Secret
secure-keys rotate "old-secret-here" --grace-period 7 --jsonLint Environment Files
# Lint and fail on weak secrets
secure-keys lint .env.production
# Output GitHub Actions annotations
secure-keys lint .env.production --github
# Strict mode (fail on warnings)
secure-keys lint .env.production --strictBootstrap Parse Server
secure-keys parse-bootstrap \
--server-url https://api.example.com/parse \
--database-uri mongodb://localhost:27017/parse \
--dockerExport to Cloud Providers
# Export to AWS Secrets Manager format
secure-keys export -i .env.parse -t aws -n "myapp/production"
# Export to HashiCorp Vault format
secure-keys export -i .env.parse -t vault -n "secret/data/myapp"
# Export to Doppler format
secure-keys export -i .env.parse -t doppler -n "myproject"Secret Rotation
Zero-downtime rotation is achieved by maintaining both primary (new) and secondary (old) secrets:
import { rotateSecret, verifyWithRotation, signWithRotation } from '@duabalabs/secure-keys';
// Rotate an existing secret
const rotated = rotateSecret('current-secret', {
gracePeriodMs: 7 * 24 * 60 * 60 * 1000, // 7 days
reason: 'scheduled',
});
// Sign with the new primary secret
const signature = signWithRotation(payload, rotated);
// Verify accepts both old and new secrets
const result = verifyWithRotation(payload, signature, rotated);
if (result.valid) {
console.log(`Verified with ${result.matchedKey} key`);
}Rotate Parse Keys
import { rotateParseKeys } from '@duabalabs/secure-keys';
const rotatedKeys = rotateParseKeys(currentKeys, {
gracePeriodMs: 14 * 24 * 60 * 60 * 1000, // 14 days
reason: 'compliance',
});Policy Enforcement
Prevent weak secrets from reaching production:
import { enforcePolicy, validateSecret, SecretPolicyError } from '@duabalabs/secure-keys';
// Validate a secret
const result = validateSecret(mySecret, { secretType: 'parse-master-key' });
if (!result.valid) {
console.error('Violations:', result.violations);
}
// Enforce policy (throws on failure)
try {
enforcePolicy(process.env.MASTER_KEY, { secretType: 'parse-master-key' });
} catch (error) {
if (error instanceof SecretPolicyError) {
console.error('Security policy violation:', error.violations);
process.exit(1);
}
}Lint Environment at Startup
import { requireSecrets } from '@duabalabs/secure-keys';
// Fail fast if secrets are missing or weak
requireSecrets(process.env, [
'PARSE_MASTER_KEY',
'JWT_ACCESS_TOKEN_SECRET',
{ key: 'WEBHOOK_SECRET', type: 'webhook-secret' },
]);Cloud Exporters
Export secrets to cloud providers without making API calls:
import { exportToAwsSecretsManager, exportToVault, exportToKubernetes } from '@duabalabs/secure-keys';
// AWS Secrets Manager
const awsExport = exportToAwsSecretsManager(secrets, {
name: 'myapp/production',
description: 'Production secrets',
environment: 'production',
});
// Use with: aws secretsmanager create-secret --cli-input-json '...'
// HashiCorp Vault
const vaultExport = exportToVault(secrets, {
name: 'secret/data/myapp',
});
// Use with: vault kv put myapp @data.json
// Kubernetes Secret
const k8sExport = exportToKubernetes(secrets, {
name: 'myapp-secrets',
namespace: 'production',
});
// Convert to YAML and apply with kubectln8n Integration
The package includes an n8n custom node for automation workflows:
import { executeSecureKeysNode } from '@duabalabs/secure-keys/n8n';
const result = executeSecureKeysNode({
operation: 'generateParse',
includeEncryptionKey: true,
environment: 'production',
});
console.log(result.secrets);GitHub Actions
See .github/workflows/secrets-management.yml for a complete CI/CD workflow that:
- Validates secrets in PRs
- Generates new secrets on demand
- Rotates secrets on schedule
- Exports to AWS/Vault/Doppler
Security Requirements
All secrets must meet these minimum requirements:
| Secret Type | Minimum Entropy | Minimum Bytes | |-------------|-----------------|---------------| | Master Key | 256 bits | 32 bytes | | API Keys | 256 bits | 32 bytes | | JWT Secrets | 256 bits | 32 bytes | | Webhook Secrets | 256 bits | 32 bytes | | Identifiers (App ID) | 128 bits | 16 bytes |
Policy Violations
The following will cause policy failures:
- ❌ UUIDs used as secrets
- ❌ Secrets shorter than minimum entropy
- ❌ Weak patterns (sequential, repeated characters)
- ❌ Common weak values (password, secret, test)
- ❌ Empty or undefined secrets
API Reference
Generators
| Function | Description |
|----------|-------------|
| generateSecret(bytes?) | Generates hex secret |
| generateBase64Secret(bytes?) | Generates Base64 secret |
| generateBase64UrlSecret(bytes?) | Generates URL-safe Base64 secret |
| generateUUID() | Generates UUID v4 (identifiers only!) |
| generateIdentifier(bytes?) | Generates identifier (128+ bits) |
| generatePrefixedSecret(prefix, bytes?) | Generates prefixed secret |
Presets
| Function | Description |
|----------|-------------|
| generateParseKeys(options?) | Complete Parse Server keys |
| generateJwtSecrets(options?) | JWT signing secrets |
| generateWebhookSecret(options?) | Webhook signing secret |
| generateApiKeyPair(environment?) | API key pair (pk/sk) |
| generateEncryptionKey() | AES-256 encryption key |
| generateSessionSecrets() | Session secrets with rotation |
| generateOAuthCredentials() | OAuth client credentials |
| generateDatabaseKeys() | Database encryption keys |
| generateHmacKey(algorithm?) | HMAC signing key |
Rotation
| Function | Description |
|----------|-------------|
| rotateSecret(oldSecret, options?) | Rotate to new primary |
| verifyWithRotation(payload, sig, rotated) | Verify with either key |
| signWithRotation(payload, rotated) | Sign with primary |
| isSecondaryExpired(rotated) | Check if secondary expired |
| rotateParseKeys(currentKeys, options?) | Rotate all Parse keys |
| rotateJwtSecrets(currentSecrets, options?) | Rotate all JWT secrets |
Policy
| Function | Description |
|----------|-------------|
| validateSecret(secret, options?) | Validate against policy |
| validateSecrets(secrets, mapping?) | Validate multiple secrets |
| enforcePolicy(secret, options?) | Throw on policy violation |
| enforcePolicies(secrets, mapping?) | Enforce on multiple |
| isUUID(value) | Check if value is UUID |
| isWeakSecret(value) | Check if secret is weak |
Linter
| Function | Description |
|----------|-------------|
| lintEnvFile(path, options?) | Lint .env file |
| lintEnvObject(envVars, options?) | Lint env object |
| requireSecrets(env, required) | Require valid secrets |
| formatLintResult(result) | Format for console |
| createGitHubAnnotations(result) | GitHub Actions format |
Exporters
| Function | Description |
|----------|-------------|
| exportToAwsSecretsManager(secrets, options) | AWS format |
| exportToVault(secrets, options) | Vault KV v2 format |
| exportToDoppler(secrets, options) | Doppler format |
| exportToGitHubActions(secrets, options) | GitHub Actions format |
| exportToKubernetes(secrets, options) | K8s Secret manifest |
| exportToDockerCompose(secrets) | Docker Compose env |
License
MIT © Duaba Labs
