env-secrets 0.1.10 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/.devcontainer/devcontainer.json +33 -0
  2. package/.dockerignore +9 -0
  3. package/.eslintignore +4 -2
  4. package/.github/dependabot.yml +4 -0
  5. package/.github/workflows/build-main.yml +6 -2
  6. package/.github/workflows/deploy-docs.yml +50 -0
  7. package/.github/workflows/e2e-tests.yaml +54 -0
  8. package/.github/workflows/lint.yaml +6 -2
  9. package/.github/workflows/release.yml +13 -3
  10. package/.github/workflows/snyk.yaml +5 -1
  11. package/.github/workflows/unittests.yaml +18 -6
  12. package/.lintstagedrc +2 -7
  13. package/.prettierignore +6 -0
  14. package/AGENTS.md +149 -0
  15. package/Dockerfile +14 -0
  16. package/README.md +507 -36
  17. package/__e2e__/README.md +160 -0
  18. package/__e2e__/index.test.ts +339 -0
  19. package/__e2e__/setup.ts +58 -0
  20. package/__e2e__/utils/debug-logger.ts +45 -0
  21. package/__e2e__/utils/test-utils.ts +645 -0
  22. package/__tests__/index.test.ts +573 -31
  23. package/__tests__/vaults/secretsmanager.test.ts +460 -0
  24. package/__tests__/vaults/utils.test.ts +183 -0
  25. package/__tests__/version.test.ts +8 -0
  26. package/dist/index.js +36 -10
  27. package/dist/vaults/secretsmanager.js +44 -43
  28. package/dist/vaults/utils.js +2 -2
  29. package/docker-compose.yaml +29 -0
  30. package/docs/AWS.md +257 -0
  31. package/jest.config.js +4 -1
  32. package/jest.e2e.config.js +8 -0
  33. package/package.json +18 -10
  34. package/src/index.ts +44 -10
  35. package/src/vaults/secretsmanager.ts +48 -48
  36. package/src/vaults/utils.ts +6 -4
  37. package/website/docs/advanced-usage.mdx +399 -0
  38. package/website/docs/best-practices.mdx +416 -0
  39. package/website/docs/cli-reference.mdx +204 -0
  40. package/website/docs/examples.mdx +960 -0
  41. package/website/docs/faq.mdx +302 -0
  42. package/website/docs/index.mdx +56 -0
  43. package/website/docs/installation.mdx +30 -0
  44. package/website/docs/overview.mdx +17 -0
  45. package/website/docs/production-deployment.mdx +622 -0
  46. package/website/docs/providers/aws-secrets-manager.mdx +28 -0
  47. package/website/docs/security.mdx +122 -0
  48. package/website/docs/troubleshooting.mdx +236 -0
  49. package/website/docs/tutorials/local-dev/devcontainer-localstack.mdx +31 -0
  50. package/website/docs/tutorials/local-dev/docker-compose.mdx +22 -0
  51. package/website/docs/tutorials/local-dev/nextjs.mdx +18 -0
  52. package/website/docs/tutorials/local-dev/node-python-go.mdx +39 -0
  53. package/website/docs/tutorials/local-dev/quickstart.mdx +23 -0
  54. package/website/docusaurus.config.ts +89 -0
  55. package/website/package.json +21 -0
  56. package/website/sidebars.ts +33 -0
  57. package/website/src/css/custom.css +1 -0
  58. package/website/static/img/env-secrets.png +0 -0
  59. package/website/static/img/favicon.ico +0 -0
  60. package/website/static/img/logo.svg +4 -0
  61. package/website/yarn.lock +8764 -0
@@ -0,0 +1,622 @@
1
+ ---
2
+ title: Production Deployment
3
+ ---
4
+
5
+ # Production Deployment
6
+
7
+ This guide covers best practices for deploying applications with `env-secrets` in production environments.
8
+
9
+ ## Pre-Deployment Checklist
10
+
11
+ Before deploying to production, ensure you have:
12
+
13
+ - [ ] **IAM Roles Configured**: Use IAM roles instead of access keys
14
+ - [ ] **Secrets Created**: All required secrets exist in AWS Secrets Manager
15
+ - [ ] **Permissions Verified**: Applications can access their required secrets
16
+ - [ ] **Monitoring Setup**: CloudTrail and CloudWatch logging enabled
17
+ - [ ] **Backup Strategy**: Secrets are backed up and recoverable
18
+ - [ ] **Rotation Plan**: Secret rotation procedures documented
19
+
20
+ ## AWS Infrastructure Setup
21
+
22
+ ### IAM Roles and Policies
23
+
24
+ Create dedicated IAM roles for your applications:
25
+
26
+ ```json
27
+ {
28
+ "Version": "2012-10-17",
29
+ "Statement": [
30
+ {
31
+ "Effect": "Allow",
32
+ "Action": "secretsmanager:GetSecretValue",
33
+ "Resource": [
34
+ "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/myapp/*",
35
+ "arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/myapp-api/*"
36
+ ]
37
+ }
38
+ ]
39
+ }
40
+ ```
41
+
42
+ ### VPC Endpoints (Optional)
43
+
44
+ For enhanced security, use VPC endpoints for AWS Secrets Manager:
45
+
46
+ ```bash
47
+ # Create VPC endpoint
48
+ aws ec2 create-vpc-endpoint \
49
+ --vpc-id vpc-12345678 \
50
+ --service-name com.amazonaws.us-east-1.secretsmanager \
51
+ --subnet-ids subnet-12345678 subnet-87654321 \
52
+ --security-group-ids sg-12345678
53
+ ```
54
+
55
+ ## Container Deployment
56
+
57
+ ### Docker
58
+
59
+ #### Single Container
60
+
61
+ ```dockerfile
62
+ # Dockerfile
63
+ FROM node:18-alpine
64
+
65
+ WORKDIR /app
66
+ COPY package*.json ./
67
+ RUN npm ci --only=production
68
+
69
+ COPY . .
70
+
71
+ # Use env-secrets as entrypoint
72
+ ENTRYPOINT ["env-secrets", "aws", "-s", "prod/myapp", "-r", "us-east-1", "--"]
73
+ CMD ["node", "app.js"]
74
+ ```
75
+
76
+ #### Multi-Container with Docker Compose
77
+
78
+ ```yaml
79
+ # docker-compose.prod.yml
80
+ version: '3.8'
81
+ services:
82
+ app:
83
+ build: .
84
+ environment:
85
+ - AWS_REGION=us-east-1
86
+ command:
87
+ [
88
+ 'env-secrets',
89
+ 'aws',
90
+ '-s',
91
+ 'prod/myapp',
92
+ '-r',
93
+ 'us-east-1',
94
+ '--',
95
+ 'node',
96
+ 'app.js'
97
+ ]
98
+ restart: unless-stopped
99
+ healthcheck:
100
+ test:
101
+ [
102
+ 'CMD',
103
+ 'env-secrets',
104
+ 'aws',
105
+ '-s',
106
+ 'health/check',
107
+ '-r',
108
+ 'us-east-1',
109
+ '--',
110
+ 'echo',
111
+ 'healthy'
112
+ ]
113
+ interval: 30s
114
+ timeout: 10s
115
+ retries: 3
116
+ ```
117
+
118
+ ### Kubernetes
119
+
120
+ #### Deployment with env-secrets
121
+
122
+ ```yaml
123
+ # deployment.yaml
124
+ apiVersion: apps/v1
125
+ kind: Deployment
126
+ metadata:
127
+ name: myapp
128
+ labels:
129
+ app: myapp
130
+ spec:
131
+ replicas: 3
132
+ selector:
133
+ matchLabels:
134
+ app: myapp
135
+ template:
136
+ metadata:
137
+ labels:
138
+ app: myapp
139
+ spec:
140
+ serviceAccountName: myapp-sa
141
+ containers:
142
+ - name: app
143
+ image: myapp:latest
144
+ command: ['env-secrets']
145
+ args:
146
+ [
147
+ 'aws',
148
+ '-s',
149
+ 'prod/myapp',
150
+ '-r',
151
+ 'us-east-1',
152
+ '--',
153
+ 'node',
154
+ 'app.js'
155
+ ]
156
+ env:
157
+ - name: AWS_REGION
158
+ value: 'us-east-1'
159
+ ports:
160
+ - containerPort: 3000
161
+ livenessProbe:
162
+ exec:
163
+ command:
164
+ - env-secrets
165
+ - aws
166
+ - -s
167
+ - health/check
168
+ - -r
169
+ - us-east-1
170
+ - --
171
+ - echo
172
+ - 'healthy'
173
+ initialDelaySeconds: 30
174
+ periodSeconds: 10
175
+ readinessProbe:
176
+ httpGet:
177
+ path: /health
178
+ port: 3000
179
+ initialDelaySeconds: 5
180
+ periodSeconds: 5
181
+ ```
182
+
183
+ #### Service Account
184
+
185
+ ```yaml
186
+ # service-account.yaml
187
+ apiVersion: v1
188
+ kind: ServiceAccount
189
+ metadata:
190
+ name: myapp-sa
191
+ annotations:
192
+ eks.amazonaws.com/role-arn: arn:aws:iam::123456789012:role/myapp-role
193
+ ```
194
+
195
+ #### ConfigMap for Configuration
196
+
197
+ ```yaml
198
+ # configmap.yaml
199
+ apiVersion: v1
200
+ kind: ConfigMap
201
+ metadata:
202
+ name: myapp-config
203
+ data:
204
+ AWS_REGION: 'us-east-1'
205
+ SECRET_NAME: 'prod/myapp'
206
+ NODE_ENV: 'production'
207
+ ```
208
+
209
+ ## Serverless Deployment
210
+
211
+ ### AWS Lambda
212
+
213
+ ```yaml
214
+ # serverless.yml
215
+ service: myapp
216
+
217
+ provider:
218
+ name: aws
219
+ runtime: nodejs18.x
220
+ region: us-east-1
221
+ iam:
222
+ role:
223
+ statements:
224
+ - Effect: Allow
225
+ Action:
226
+ - secretsmanager:GetSecretValue
227
+ Resource:
228
+ - arn:aws:secretsmanager:us-east-1:123456789012:secret:prod/myapp/*
229
+
230
+ functions:
231
+ api:
232
+ handler: handler.api
233
+ events:
234
+ - http:
235
+ path: /{proxy+}
236
+ method: ANY
237
+ environment:
238
+ SECRET_NAME: prod/myapp
239
+ ```
240
+
241
+ ```javascript
242
+ // handler.js
243
+ const { spawn } = require('child_process');
244
+
245
+ exports.api = async (event, context) => {
246
+ return new Promise((resolve, reject) => {
247
+ const child = spawn(
248
+ 'env-secrets',
249
+ [
250
+ 'aws',
251
+ '-s',
252
+ process.env.SECRET_NAME,
253
+ '-r',
254
+ 'us-east-1',
255
+ '--',
256
+ 'node',
257
+ 'app.js'
258
+ ],
259
+ {
260
+ stdio: ['pipe', 'pipe', 'pipe']
261
+ }
262
+ );
263
+
264
+ // Handle Lambda event
265
+ child.stdin.write(JSON.stringify(event));
266
+ child.stdin.end();
267
+
268
+ let output = '';
269
+ child.stdout.on('data', (data) => {
270
+ output += data.toString();
271
+ });
272
+
273
+ child.on('close', (code) => {
274
+ if (code === 0) {
275
+ resolve(JSON.parse(output));
276
+ } else {
277
+ reject(new Error(`Process exited with code ${code}`));
278
+ }
279
+ });
280
+ });
281
+ };
282
+ ```
283
+
284
+ ### AWS ECS
285
+
286
+ ```json
287
+ {
288
+ "family": "myapp",
289
+ "networkMode": "awsvpc",
290
+ "requiresCompatibilities": ["FARGATE"],
291
+ "cpu": "256",
292
+ "memory": "512",
293
+ "executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
294
+ "taskRoleArn": "arn:aws:iam::123456789012:role/myapp-task-role",
295
+ "containerDefinitions": [
296
+ {
297
+ "name": "app",
298
+ "image": "myapp:latest",
299
+ "command": [
300
+ "env-secrets",
301
+ "aws",
302
+ "-s",
303
+ "prod/myapp",
304
+ "-r",
305
+ "us-east-1",
306
+ "--",
307
+ "node",
308
+ "app.js"
309
+ ],
310
+ "environment": [
311
+ {
312
+ "name": "AWS_REGION",
313
+ "value": "us-east-1"
314
+ }
315
+ ],
316
+ "portMappings": [
317
+ {
318
+ "containerPort": 3000,
319
+ "protocol": "tcp"
320
+ }
321
+ ],
322
+ "healthCheck": {
323
+ "command": [
324
+ "env-secrets",
325
+ "aws",
326
+ "-s",
327
+ "health/check",
328
+ "-r",
329
+ "us-east-1",
330
+ "--",
331
+ "echo",
332
+ "healthy"
333
+ ],
334
+ "interval": 30,
335
+ "timeout": 5,
336
+ "retries": 3,
337
+ "startPeriod": 60
338
+ }
339
+ }
340
+ ]
341
+ }
342
+ ```
343
+
344
+ ## CI/CD Integration
345
+
346
+ ### GitHub Actions
347
+
348
+ ```yaml
349
+ # .github/workflows/deploy.yml
350
+ name: Deploy to Production
351
+
352
+ on:
353
+ push:
354
+ branches: [main]
355
+
356
+ jobs:
357
+ deploy:
358
+ runs-on: ubuntu-latest
359
+ steps:
360
+ - uses: actions/checkout@v3
361
+
362
+ - name: Setup Node.js
363
+ uses: actions/setup-node@v3
364
+ with:
365
+ node-version: '18'
366
+
367
+ - name: Configure AWS credentials
368
+ uses: aws-actions/configure-aws-credentials@v2
369
+ with:
370
+ aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
371
+ aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
372
+ aws-region: us-east-1
373
+
374
+ - name: Install env-secrets
375
+ run: npm install -g env-secrets
376
+
377
+ - name: Build Docker image
378
+ run: docker build -t myapp:${{ github.sha }} .
379
+
380
+ - name: Deploy to ECS
381
+ run: |
382
+ aws ecs update-service \
383
+ --cluster production \
384
+ --service myapp \
385
+ --force-new-deployment
386
+
387
+ - name: Verify deployment
388
+ run: |
389
+ env-secrets aws -s prod/myapp -r us-east-1 -- curl -f http://localhost:3000/health
390
+ ```
391
+
392
+ ### GitLab CI
393
+
394
+ ```yaml
395
+ # .gitlab-ci.yml
396
+ stages:
397
+ - test
398
+ - deploy
399
+
400
+ test:
401
+ stage: test
402
+ image: node:18
403
+ script:
404
+ - npm install -g env-secrets
405
+ - env-secrets aws -s test/myapp -r us-east-1 -- npm test
406
+
407
+ deploy:
408
+ stage: deploy
409
+ image: node:18
410
+ before_script:
411
+ - npm install -g env-secrets
412
+ script:
413
+ - env-secrets aws -s prod/myapp -r us-east-1 -- npm run deploy
414
+ environment:
415
+ name: production
416
+ only:
417
+ - main
418
+ ```
419
+
420
+ ## Monitoring and Alerting
421
+
422
+ ### CloudWatch Alarms
423
+
424
+ ```bash
425
+ # Create alarm for secret access failures
426
+ aws cloudwatch put-metric-alarm \
427
+ --alarm-name "SecretAccessFailures" \
428
+ --alarm-description "Alarm when secret access fails" \
429
+ --metric-name "Errors" \
430
+ --namespace "AWS/SecretsManager" \
431
+ --statistic "Sum" \
432
+ --period 300 \
433
+ --threshold 1 \
434
+ --comparison-operator "GreaterThanThreshold" \
435
+ --evaluation-periods 1
436
+ ```
437
+
438
+ ### Health Checks
439
+
440
+ ```bash
441
+ #!/bin/bash
442
+ # health-check.sh
443
+
444
+ # Check if secrets are accessible
445
+ if env-secrets aws -s health/check -r us-east-1 -- echo "OK" 2>/dev/null; then
446
+ echo "Secrets accessible"
447
+ exit 0
448
+ else
449
+ echo "Secrets not accessible"
450
+ exit 1
451
+ fi
452
+ ```
453
+
454
+ ### Application Health Endpoint
455
+
456
+ ```javascript
457
+ // health.js
458
+ app.get('/health', (req, res) => {
459
+ const requiredVars = ['DATABASE_URL', 'API_KEY'];
460
+ const missing = requiredVars.filter(var => !process.env[var]);
461
+
462
+ if (missing.length > 0) {
463
+ res.status(503).json({
464
+ status: 'unhealthy',
465
+ missing: missing
466
+ });
467
+ } else {
468
+ res.json({
469
+ status: 'healthy',
470
+ timestamp: new Date().toISOString()
471
+ });
472
+ }
473
+ });
474
+ ```
475
+
476
+ ## Disaster Recovery
477
+
478
+ ### Secret Backup Strategy
479
+
480
+ ```bash
481
+ #!/bin/bash
482
+ # backup-secrets.sh
483
+
484
+ SECRETS=("prod/myapp" "prod/myapp-api" "prod/myapp-db")
485
+
486
+ for secret in "${SECRETS[@]}"; do
487
+ echo "Backing up $secret..."
488
+ aws secretsmanager get-secret-value \
489
+ --secret-id "$secret" \
490
+ --query SecretString \
491
+ --output text > "backup/$secret.json"
492
+ done
493
+ ```
494
+
495
+ ### Recovery Procedures
496
+
497
+ ```bash
498
+ #!/bin/bash
499
+ # restore-secrets.sh
500
+
501
+ SECRET_NAME="prod/myapp"
502
+ BACKUP_FILE="backup/$SECRET_NAME.json"
503
+
504
+ if [ -f "$BACKUP_FILE" ]; then
505
+ echo "Restoring $SECRET_NAME..."
506
+ aws secretsmanager create-secret \
507
+ --name "$SECRET_NAME" \
508
+ --secret-string "$(cat $BACKUP_FILE)"
509
+ else
510
+ echo "Backup file not found: $BACKUP_FILE"
511
+ exit 1
512
+ fi
513
+ ```
514
+
515
+ ## Security Hardening
516
+
517
+ ### Network Security
518
+
519
+ ```bash
520
+ # Restrict access to specific IP ranges
521
+ aws secretsmanager update-secret \
522
+ --secret-id prod/myapp \
523
+ --policy '{
524
+ "Version": "2012-10-17",
525
+ "Statement": [
526
+ {
527
+ "Effect": "Deny",
528
+ "Principal": "*",
529
+ "Action": "secretsmanager:*",
530
+ "Resource": "*",
531
+ "Condition": {
532
+ "NotIpAddress": {
533
+ "aws:SourceIp": ["192.168.1.0/24", "10.0.0.0/8"]
534
+ }
535
+ }
536
+ }
537
+ ]
538
+ }'
539
+ ```
540
+
541
+ ### Encryption
542
+
543
+ ```bash
544
+ # Use customer-managed KMS keys
545
+ aws secretsmanager create-secret \
546
+ --name prod/myapp \
547
+ --secret-string '{"DATABASE_URL":"postgres://..."}' \
548
+ --kms-key-id arn:aws:kms:us-east-1:123456789012:key/myapp-key
549
+ ```
550
+
551
+ ## Performance Optimization
552
+
553
+ ### Connection Pooling
554
+
555
+ ```javascript
556
+ // Use connection pooling with secrets
557
+ const pool = new Pool({
558
+ connectionString: process.env.DATABASE_URL,
559
+ max: 20,
560
+ idleTimeoutMillis: 30000,
561
+ connectionTimeoutMillis: 2000
562
+ });
563
+ ```
564
+
565
+ ### Caching Strategy
566
+
567
+ While `env-secrets` doesn't cache secrets, implement application-level caching:
568
+
569
+ ```javascript
570
+ // Cache frequently accessed data
571
+ const cache = new Map();
572
+
573
+ function getCachedData(key) {
574
+ if (cache.has(key)) {
575
+ return cache.get(key);
576
+ }
577
+
578
+ const data = fetchData(key);
579
+ cache.set(key, data);
580
+ return data;
581
+ }
582
+ ```
583
+
584
+ ## Rollback Procedures
585
+
586
+ ### Application Rollback
587
+
588
+ ```bash
589
+ #!/bin/bash
590
+ # rollback.sh
591
+
592
+ VERSION=$1
593
+
594
+ echo "Rolling back to version $VERSION..."
595
+
596
+ # Update deployment to previous version
597
+ kubectl set image deployment/myapp app=myapp:$VERSION
598
+
599
+ # Verify rollback
600
+ kubectl rollout status deployment/myapp
601
+
602
+ echo "Rollback completed"
603
+ ```
604
+
605
+ ### Secret Rollback
606
+
607
+ ```bash
608
+ #!/bin/bash
609
+ # rollback-secret.sh
610
+
611
+ SECRET_NAME="prod/myapp"
612
+ VERSION=$1
613
+
614
+ echo "Rolling back secret $SECRET_NAME to version $VERSION..."
615
+
616
+ # Restore previous secret version
617
+ aws secretsmanager restore-secret \
618
+ --secret-id "$SECRET_NAME" \
619
+ --secret-version-id "$VERSION"
620
+
621
+ echo "Secret rollback completed"
622
+ ```
@@ -0,0 +1,28 @@
1
+ ---
2
+ title: AWS Secrets Manager
3
+ ---
4
+
5
+ `env-secrets` supports pulling a single JSON secret from AWS Secrets Manager, mapping each top-level key to an environment variable.
6
+
7
+ ### Create a secret (JSON)
8
+
9
+ ```bash
10
+ aws secretsmanager create-secret --region us-east-1 --name local/sample --secret-string '{"user":"marka","password":"mypassword"}'
11
+ ```
12
+
13
+ ### Run a command with injected vars
14
+
15
+ ```bash
16
+ env-secrets aws -s local/sample -r us-east-1 -- echo $user/$password
17
+ ```
18
+
19
+ ### Parameters
20
+
21
+ - `-s, --secret` — **required** secret name/id
22
+ - `-r, --region` — AWS region (or `AWS_DEFAULT_REGION`)
23
+ - `-p, --profile` — AWS profile to use
24
+
25
+ ### Tips
26
+
27
+ - Use `DEBUG=env-secrets,env-secrets:secretsmanager` for verbose logs.
28
+ - Prefer least-privilege IAM (`secretsmanager:GetSecretValue`).