@faizahmed/secret-keystore 1.1.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.
- package/LICENSE +21 -0
- package/README.md +1203 -0
- package/SECURITY.md +505 -0
- package/bin/cli.js +969 -0
- package/package.json +77 -0
- package/src/attestation/attestation-client.js +146 -0
- package/src/attestation/attestation-manager.js +339 -0
- package/src/attestation/cms-unwrap.js +166 -0
- package/src/attestation/index.js +66 -0
- package/src/attestation/key-pair.js +129 -0
- package/src/config.js +130 -0
- package/src/content-operations.js +494 -0
- package/src/errors.js +372 -0
- package/src/index.d.ts +641 -0
- package/src/index.js +438 -0
- package/src/keystore.js +678 -0
- package/src/kms.js +858 -0
- package/src/object-operations.js +232 -0
- package/src/options.js +541 -0
- package/src/path-matcher.js +319 -0
- package/src/rotate.js +92 -0
- package/src/yaml-utils.js +265 -0
package/src/index.js
ADDED
|
@@ -0,0 +1,438 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @faizahmed/secret-keystore
|
|
3
|
+
*
|
|
4
|
+
* Secure secrets management library with AWS KMS encryption.
|
|
5
|
+
*
|
|
6
|
+
* Features:
|
|
7
|
+
* - Build-time encryption of configuration values
|
|
8
|
+
* - Runtime decryption with secure in-memory storage
|
|
9
|
+
* - Attestation support for AWS Nitro Enclaves
|
|
10
|
+
* - Support for ENV, JSON, and YAML formats
|
|
11
|
+
*
|
|
12
|
+
* SECURITY NOTES:
|
|
13
|
+
* - Decrypted values are ONLY stored in KeyStore memory (never in process.env)
|
|
14
|
+
* - kmsKeyId is REQUIRED for all operations (no auto-detection)
|
|
15
|
+
* - Uses IAM roles by default; explicit credentials are opt-in
|
|
16
|
+
* - No third-party libraries for crypto operations
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
20
|
+
// CORE KMS OPERATIONS
|
|
21
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
22
|
+
|
|
23
|
+
const {
|
|
24
|
+
encryptKMSValue,
|
|
25
|
+
decryptKMSValue,
|
|
26
|
+
encryptKMSValues,
|
|
27
|
+
decryptKMSValues,
|
|
28
|
+
isEncryptedFormat,
|
|
29
|
+
isKmsCiphertext,
|
|
30
|
+
isAlreadyEncrypted,
|
|
31
|
+
isEnvelopeFormat,
|
|
32
|
+
wrapCiphertext,
|
|
33
|
+
unwrapCiphertext,
|
|
34
|
+
maskKmsKeyId,
|
|
35
|
+
clearAttestationCache,
|
|
36
|
+
getAttestationStatus,
|
|
37
|
+
ENCRYPTED_PREFIX,
|
|
38
|
+
ENCRYPTED_SUFFIX
|
|
39
|
+
} = require('./kms');
|
|
40
|
+
|
|
41
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
42
|
+
// ATTESTATION MODULE
|
|
43
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
44
|
+
|
|
45
|
+
const {
|
|
46
|
+
// Key pair utilities
|
|
47
|
+
generateEphemeralKeyPair,
|
|
48
|
+
prepareAttestationParams,
|
|
49
|
+
toBase64Url,
|
|
50
|
+
toBase64,
|
|
51
|
+
|
|
52
|
+
// CMS unwrapping
|
|
53
|
+
unwrapCms,
|
|
54
|
+
validatePrivateKeyFormat,
|
|
55
|
+
|
|
56
|
+
// Attestation client
|
|
57
|
+
fetchAttestationDocument,
|
|
58
|
+
isNitroEnclave,
|
|
59
|
+
isAttestationAvailable,
|
|
60
|
+
DEFAULT_ATTESTATION_ENDPOINT,
|
|
61
|
+
|
|
62
|
+
// Attestation manager
|
|
63
|
+
AttestationManager,
|
|
64
|
+
createAttestationManager
|
|
65
|
+
} = require('./attestation');
|
|
66
|
+
|
|
67
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
68
|
+
// OPTIONS ARCHITECTURE
|
|
69
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
70
|
+
|
|
71
|
+
const {
|
|
72
|
+
DEFAULT_AWS_OPTIONS,
|
|
73
|
+
DEFAULT_ATTESTATION_OPTIONS,
|
|
74
|
+
DEFAULT_COMMON_OPTIONS,
|
|
75
|
+
DEFAULT_ENCRYPT_OPTIONS,
|
|
76
|
+
DEFAULT_DECRYPT_OPTIONS,
|
|
77
|
+
DEFAULT_PATH_SELECTION_OPTIONS,
|
|
78
|
+
DEFAULT_CONTENT_OPTIONS,
|
|
79
|
+
DEFAULT_KEYSTORE_OPTIONS,
|
|
80
|
+
RESERVED_KEYS,
|
|
81
|
+
validateKmsKeyId,
|
|
82
|
+
validateAwsOptions,
|
|
83
|
+
validateAttestationOptions,
|
|
84
|
+
validatePathSelectionOptions,
|
|
85
|
+
validateCommonOptions,
|
|
86
|
+
buildCommonOptions,
|
|
87
|
+
buildEncryptOptions,
|
|
88
|
+
buildDecryptOptions,
|
|
89
|
+
buildPathSelectionOptions,
|
|
90
|
+
buildContentOptions,
|
|
91
|
+
buildKeystoreOptions,
|
|
92
|
+
buildAwsSdkOptions,
|
|
93
|
+
deepMerge,
|
|
94
|
+
createLogger
|
|
95
|
+
} = require('./options');
|
|
96
|
+
|
|
97
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
98
|
+
// ERROR CLASSES
|
|
99
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
100
|
+
|
|
101
|
+
const {
|
|
102
|
+
SecretKeyStoreError,
|
|
103
|
+
KmsError,
|
|
104
|
+
AttestationError,
|
|
105
|
+
ContentError,
|
|
106
|
+
PathError,
|
|
107
|
+
EncryptionError,
|
|
108
|
+
DecryptionError,
|
|
109
|
+
KeystoreError,
|
|
110
|
+
ValidationError,
|
|
111
|
+
KMS_ERROR_CODES,
|
|
112
|
+
ATTESTATION_ERROR_CODES,
|
|
113
|
+
CONTENT_ERROR_CODES,
|
|
114
|
+
PATH_ERROR_CODES,
|
|
115
|
+
ENCRYPTION_ERROR_CODES,
|
|
116
|
+
DECRYPTION_ERROR_CODES,
|
|
117
|
+
KEYSTORE_ERROR_CODES,
|
|
118
|
+
VALIDATION_ERROR_CODES,
|
|
119
|
+
isRecoverableError,
|
|
120
|
+
createKmsErrorFromAws
|
|
121
|
+
} = require('./errors');
|
|
122
|
+
|
|
123
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
124
|
+
// PATH MATCHING
|
|
125
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
126
|
+
|
|
127
|
+
const {
|
|
128
|
+
getByPath,
|
|
129
|
+
setByPath,
|
|
130
|
+
getAllPaths,
|
|
131
|
+
matchesPattern,
|
|
132
|
+
filterPaths,
|
|
133
|
+
transformAtPaths
|
|
134
|
+
} = require('./path-matcher');
|
|
135
|
+
|
|
136
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
137
|
+
// OBJECT-BASED OPERATIONS
|
|
138
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
139
|
+
|
|
140
|
+
const { encryptKMSObject, decryptKMSObject } = require('./object-operations');
|
|
141
|
+
|
|
142
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
143
|
+
// CONTENT-BASED OPERATIONS
|
|
144
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
145
|
+
|
|
146
|
+
const {
|
|
147
|
+
encryptKMSEnvContent,
|
|
148
|
+
decryptKMSEnvContent,
|
|
149
|
+
parseEnvContent,
|
|
150
|
+
reconstructEnvContent,
|
|
151
|
+
encryptKMSJsonContent,
|
|
152
|
+
decryptKMSJsonContent,
|
|
153
|
+
encryptKMSYamlContent,
|
|
154
|
+
decryptKMSYamlContent
|
|
155
|
+
} = require('./content-operations');
|
|
156
|
+
|
|
157
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
158
|
+
// YAML UTILITIES
|
|
159
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
160
|
+
|
|
161
|
+
const { isJsYamlAvailable, parseYaml, serializeYaml } = require('./yaml-utils');
|
|
162
|
+
|
|
163
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
164
|
+
// RUNTIME KEYSTORE
|
|
165
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
166
|
+
|
|
167
|
+
const { SecretKeyStore, createSecretKeyStore } = require('./keystore');
|
|
168
|
+
|
|
169
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
170
|
+
// RUNTIME CONFIG LOADER
|
|
171
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
172
|
+
|
|
173
|
+
const { config, resolveEnvFiles, mergeEnvFiles } = require('./config');
|
|
174
|
+
const { rotateKMSContent } = require('./rotate');
|
|
175
|
+
|
|
176
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
177
|
+
// EXPORTS
|
|
178
|
+
// ═══════════════════════════════════════════════════════════════════════════
|
|
179
|
+
|
|
180
|
+
module.exports = {
|
|
181
|
+
// =========================================================================
|
|
182
|
+
// CORE KMS OPERATIONS
|
|
183
|
+
// =========================================================================
|
|
184
|
+
|
|
185
|
+
/** Encrypt a single value using KMS */
|
|
186
|
+
encryptKMSValue,
|
|
187
|
+
|
|
188
|
+
/** Decrypt a single value using KMS */
|
|
189
|
+
decryptKMSValue,
|
|
190
|
+
|
|
191
|
+
/** Encrypt multiple key-value pairs using KMS */
|
|
192
|
+
encryptKMSValues,
|
|
193
|
+
|
|
194
|
+
/** Decrypt multiple key-value pairs using KMS */
|
|
195
|
+
decryptKMSValues,
|
|
196
|
+
|
|
197
|
+
// =========================================================================
|
|
198
|
+
// FORMAT HELPERS
|
|
199
|
+
// =========================================================================
|
|
200
|
+
|
|
201
|
+
/** Check if value is in ENC[...] format */
|
|
202
|
+
isEncryptedFormat,
|
|
203
|
+
|
|
204
|
+
/** Check if value looks like raw KMS ciphertext */
|
|
205
|
+
isKmsCiphertext,
|
|
206
|
+
|
|
207
|
+
/** Check if value is already encrypted (any format) */
|
|
208
|
+
isAlreadyEncrypted,
|
|
209
|
+
|
|
210
|
+
/** Check if decoded ciphertext buffer is envelope format (RSA envelope encryption) */
|
|
211
|
+
isEnvelopeFormat,
|
|
212
|
+
|
|
213
|
+
/** Wrap base64 ciphertext in ENC[...] format */
|
|
214
|
+
wrapCiphertext,
|
|
215
|
+
|
|
216
|
+
/** Unwrap ciphertext from ENC[...] format */
|
|
217
|
+
unwrapCiphertext,
|
|
218
|
+
|
|
219
|
+
/** Mask KMS key ID for logging */
|
|
220
|
+
maskKmsKeyId,
|
|
221
|
+
|
|
222
|
+
/** Encrypted value prefix */
|
|
223
|
+
ENCRYPTED_PREFIX,
|
|
224
|
+
|
|
225
|
+
/** Encrypted value suffix */
|
|
226
|
+
ENCRYPTED_SUFFIX,
|
|
227
|
+
|
|
228
|
+
// =========================================================================
|
|
229
|
+
// PATH MATCHING
|
|
230
|
+
// =========================================================================
|
|
231
|
+
|
|
232
|
+
/** Get value from object by dot-notation path */
|
|
233
|
+
getByPath,
|
|
234
|
+
|
|
235
|
+
/** Set value in object by dot-notation path */
|
|
236
|
+
setByPath,
|
|
237
|
+
|
|
238
|
+
/** Get all leaf paths in an object */
|
|
239
|
+
getAllPaths,
|
|
240
|
+
|
|
241
|
+
/** Check if path matches a ** pattern */
|
|
242
|
+
matchesPattern,
|
|
243
|
+
|
|
244
|
+
/** Filter paths using patterns and explicit paths */
|
|
245
|
+
filterPaths,
|
|
246
|
+
|
|
247
|
+
/** Transform values at selected paths */
|
|
248
|
+
transformAtPaths,
|
|
249
|
+
|
|
250
|
+
// =========================================================================
|
|
251
|
+
// OBJECT-BASED OPERATIONS
|
|
252
|
+
// =========================================================================
|
|
253
|
+
|
|
254
|
+
/** Encrypt values at selected paths in a nested object using KMS */
|
|
255
|
+
encryptKMSObject,
|
|
256
|
+
|
|
257
|
+
/** Decrypt values at selected paths in a nested object using KMS */
|
|
258
|
+
decryptKMSObject,
|
|
259
|
+
|
|
260
|
+
// =========================================================================
|
|
261
|
+
// CONTENT-BASED OPERATIONS
|
|
262
|
+
// =========================================================================
|
|
263
|
+
|
|
264
|
+
/** Encrypt .env content string using KMS */
|
|
265
|
+
encryptKMSEnvContent,
|
|
266
|
+
|
|
267
|
+
/** Decrypt .env content string using KMS */
|
|
268
|
+
decryptKMSEnvContent,
|
|
269
|
+
|
|
270
|
+
/** Parse .env content into structured entries */
|
|
271
|
+
parseEnvContent,
|
|
272
|
+
|
|
273
|
+
/** Reconstruct .env content from structured entries */
|
|
274
|
+
reconstructEnvContent,
|
|
275
|
+
|
|
276
|
+
/** Encrypt JSON content string using KMS */
|
|
277
|
+
encryptKMSJsonContent,
|
|
278
|
+
|
|
279
|
+
/** Decrypt JSON content string using KMS */
|
|
280
|
+
decryptKMSJsonContent,
|
|
281
|
+
|
|
282
|
+
/** Encrypt YAML content string using KMS */
|
|
283
|
+
encryptKMSYamlContent,
|
|
284
|
+
|
|
285
|
+
/** Decrypt YAML content string using KMS */
|
|
286
|
+
decryptKMSYamlContent,
|
|
287
|
+
|
|
288
|
+
// =========================================================================
|
|
289
|
+
// YAML UTILITIES
|
|
290
|
+
// =========================================================================
|
|
291
|
+
|
|
292
|
+
/** Check if js-yaml is installed (for complex YAML support) */
|
|
293
|
+
isJsYamlAvailable,
|
|
294
|
+
|
|
295
|
+
/** Parse YAML content to object (uses js-yaml if available, falls back to simple parser) */
|
|
296
|
+
parseYaml,
|
|
297
|
+
|
|
298
|
+
/** Serialize object to YAML string (uses js-yaml if available) */
|
|
299
|
+
serializeYaml,
|
|
300
|
+
|
|
301
|
+
// =========================================================================
|
|
302
|
+
// OPTIONS & DEFAULTS
|
|
303
|
+
// =========================================================================
|
|
304
|
+
|
|
305
|
+
DEFAULT_AWS_OPTIONS,
|
|
306
|
+
DEFAULT_ATTESTATION_OPTIONS,
|
|
307
|
+
DEFAULT_COMMON_OPTIONS,
|
|
308
|
+
DEFAULT_ENCRYPT_OPTIONS,
|
|
309
|
+
DEFAULT_DECRYPT_OPTIONS,
|
|
310
|
+
DEFAULT_PATH_SELECTION_OPTIONS,
|
|
311
|
+
DEFAULT_CONTENT_OPTIONS,
|
|
312
|
+
DEFAULT_KEYSTORE_OPTIONS,
|
|
313
|
+
RESERVED_KEYS,
|
|
314
|
+
|
|
315
|
+
// Validation
|
|
316
|
+
validateKmsKeyId,
|
|
317
|
+
validateAwsOptions,
|
|
318
|
+
validateAttestationOptions,
|
|
319
|
+
validatePathSelectionOptions,
|
|
320
|
+
validateCommonOptions,
|
|
321
|
+
|
|
322
|
+
// Builders
|
|
323
|
+
buildCommonOptions,
|
|
324
|
+
buildEncryptOptions,
|
|
325
|
+
buildDecryptOptions,
|
|
326
|
+
buildPathSelectionOptions,
|
|
327
|
+
buildContentOptions,
|
|
328
|
+
buildKeystoreOptions,
|
|
329
|
+
buildAwsSdkOptions,
|
|
330
|
+
|
|
331
|
+
// Helpers
|
|
332
|
+
deepMerge,
|
|
333
|
+
createLogger,
|
|
334
|
+
|
|
335
|
+
// =========================================================================
|
|
336
|
+
// ERRORS
|
|
337
|
+
// =========================================================================
|
|
338
|
+
|
|
339
|
+
SecretKeyStoreError,
|
|
340
|
+
KmsError,
|
|
341
|
+
AttestationError,
|
|
342
|
+
ContentError,
|
|
343
|
+
PathError,
|
|
344
|
+
EncryptionError,
|
|
345
|
+
DecryptionError,
|
|
346
|
+
KeystoreError,
|
|
347
|
+
ValidationError,
|
|
348
|
+
|
|
349
|
+
// Error codes
|
|
350
|
+
KMS_ERROR_CODES,
|
|
351
|
+
ATTESTATION_ERROR_CODES,
|
|
352
|
+
CONTENT_ERROR_CODES,
|
|
353
|
+
PATH_ERROR_CODES,
|
|
354
|
+
ENCRYPTION_ERROR_CODES,
|
|
355
|
+
DECRYPTION_ERROR_CODES,
|
|
356
|
+
KEYSTORE_ERROR_CODES,
|
|
357
|
+
VALIDATION_ERROR_CODES,
|
|
358
|
+
|
|
359
|
+
// Error helpers
|
|
360
|
+
isRecoverableError,
|
|
361
|
+
createKmsErrorFromAws,
|
|
362
|
+
|
|
363
|
+
// =========================================================================
|
|
364
|
+
// RUNTIME KEYSTORE
|
|
365
|
+
// =========================================================================
|
|
366
|
+
|
|
367
|
+
/** SecretKeyStore class with TTL, autoRefresh, source types */
|
|
368
|
+
SecretKeyStore,
|
|
369
|
+
|
|
370
|
+
/** Create and initialize a keystore */
|
|
371
|
+
createSecretKeyStore,
|
|
372
|
+
|
|
373
|
+
// =========================================================================
|
|
374
|
+
// RUNTIME CONFIG LOADER
|
|
375
|
+
// =========================================================================
|
|
376
|
+
|
|
377
|
+
/** Discover + cascade .env files, decrypt, and load into an in-memory store */
|
|
378
|
+
config,
|
|
379
|
+
|
|
380
|
+
/** Resolve the ordered list of .env files for the cascade */
|
|
381
|
+
resolveEnvFiles,
|
|
382
|
+
|
|
383
|
+
/** Merge parsed .env files into one key→value map (later wins) */
|
|
384
|
+
mergeEnvFiles,
|
|
385
|
+
|
|
386
|
+
/** Re-encrypt a file's encrypted values under a new KMS Key ID */
|
|
387
|
+
rotateKMSContent,
|
|
388
|
+
|
|
389
|
+
// =========================================================================
|
|
390
|
+
// ATTESTATION
|
|
391
|
+
// =========================================================================
|
|
392
|
+
|
|
393
|
+
// Key pair utilities
|
|
394
|
+
/** Generate ephemeral RSA-4096 key pair for attestation */
|
|
395
|
+
generateEphemeralKeyPair,
|
|
396
|
+
|
|
397
|
+
/** Prepare attestation request parameters */
|
|
398
|
+
prepareAttestationParams,
|
|
399
|
+
|
|
400
|
+
/** Convert buffer to base64url */
|
|
401
|
+
toBase64Url,
|
|
402
|
+
|
|
403
|
+
/** Convert buffer to base64 */
|
|
404
|
+
toBase64,
|
|
405
|
+
|
|
406
|
+
// CMS utilities
|
|
407
|
+
/** Unwrap CMS EnvelopedData using PKIjs */
|
|
408
|
+
unwrapCms,
|
|
409
|
+
|
|
410
|
+
/** Validate PKCS#8 PEM private key format */
|
|
411
|
+
validatePrivateKeyFormat,
|
|
412
|
+
|
|
413
|
+
// Attestation client
|
|
414
|
+
/** Fetch attestation document from Nitro/Anjuna endpoint */
|
|
415
|
+
fetchAttestationDocument,
|
|
416
|
+
|
|
417
|
+
/** Check if running inside Nitro Enclave */
|
|
418
|
+
isNitroEnclave,
|
|
419
|
+
|
|
420
|
+
/** Check if attestation endpoint is reachable */
|
|
421
|
+
isAttestationAvailable,
|
|
422
|
+
|
|
423
|
+
/** Default attestation endpoint URL */
|
|
424
|
+
DEFAULT_ATTESTATION_ENDPOINT,
|
|
425
|
+
|
|
426
|
+
// Attestation manager
|
|
427
|
+
/** AttestationManager class for full attestation lifecycle */
|
|
428
|
+
AttestationManager,
|
|
429
|
+
|
|
430
|
+
/** Create and initialize an AttestationManager */
|
|
431
|
+
createAttestationManager,
|
|
432
|
+
|
|
433
|
+
/** Clear all cached attestation managers */
|
|
434
|
+
clearAttestationCache,
|
|
435
|
+
|
|
436
|
+
/** Get attestation status for an endpoint */
|
|
437
|
+
getAttestationStatus
|
|
438
|
+
};
|