@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/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
+ };