@memberjunction/encryption 0.0.1 → 2.130.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 (46) hide show
  1. package/README.md +391 -28
  2. package/dist/EncryptionEngine.d.ts +351 -0
  3. package/dist/EncryptionEngine.d.ts.map +1 -0
  4. package/dist/EncryptionEngine.js +683 -0
  5. package/dist/EncryptionEngine.js.map +1 -0
  6. package/dist/EncryptionKeySourceBase.d.ts +203 -0
  7. package/dist/EncryptionKeySourceBase.d.ts.map +1 -0
  8. package/dist/EncryptionKeySourceBase.js +133 -0
  9. package/dist/EncryptionKeySourceBase.js.map +1 -0
  10. package/dist/actions/EnableFieldEncryptionAction.d.ts +87 -0
  11. package/dist/actions/EnableFieldEncryptionAction.d.ts.map +1 -0
  12. package/dist/actions/EnableFieldEncryptionAction.js +308 -0
  13. package/dist/actions/EnableFieldEncryptionAction.js.map +1 -0
  14. package/dist/actions/RotateEncryptionKeyAction.d.ts +79 -0
  15. package/dist/actions/RotateEncryptionKeyAction.d.ts.map +1 -0
  16. package/dist/actions/RotateEncryptionKeyAction.js +343 -0
  17. package/dist/actions/RotateEncryptionKeyAction.js.map +1 -0
  18. package/dist/actions/index.d.ts +12 -0
  19. package/dist/actions/index.d.ts.map +1 -0
  20. package/dist/actions/index.js +17 -0
  21. package/dist/actions/index.js.map +1 -0
  22. package/dist/index.d.ts +66 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +81 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/interfaces.d.ts +216 -0
  27. package/dist/interfaces.d.ts.map +1 -0
  28. package/dist/interfaces.js +15 -0
  29. package/dist/interfaces.js.map +1 -0
  30. package/dist/providers/AWSKMSKeySource.d.ts +110 -0
  31. package/dist/providers/AWSKMSKeySource.d.ts.map +1 -0
  32. package/dist/providers/AWSKMSKeySource.js +245 -0
  33. package/dist/providers/AWSKMSKeySource.js.map +1 -0
  34. package/dist/providers/AzureKeyVaultKeySource.d.ts +109 -0
  35. package/dist/providers/AzureKeyVaultKeySource.d.ts.map +1 -0
  36. package/dist/providers/AzureKeyVaultKeySource.js +268 -0
  37. package/dist/providers/AzureKeyVaultKeySource.js.map +1 -0
  38. package/dist/providers/ConfigFileKeySource.d.ts +173 -0
  39. package/dist/providers/ConfigFileKeySource.d.ts.map +1 -0
  40. package/dist/providers/ConfigFileKeySource.js +310 -0
  41. package/dist/providers/ConfigFileKeySource.js.map +1 -0
  42. package/dist/providers/EnvVarKeySource.d.ts +152 -0
  43. package/dist/providers/EnvVarKeySource.d.ts.map +1 -0
  44. package/dist/providers/EnvVarKeySource.js +251 -0
  45. package/dist/providers/EnvVarKeySource.js.map +1 -0
  46. package/package.json +65 -6
@@ -0,0 +1,310 @@
1
+ "use strict";
2
+ /**
3
+ * @fileoverview Configuration file key source provider.
4
+ *
5
+ * This provider retrieves encryption keys from MemberJunction's
6
+ * configuration file (mj.config.cjs or other cosmiconfig-compatible formats).
7
+ *
8
+ * ## Usage
9
+ *
10
+ * 1. Add keys to your mj.config.cjs:
11
+ * ```javascript
12
+ * module.exports = {
13
+ * encryptionKeys: {
14
+ * pii_master: 'K7gNU3sdo+OL0wNhqoVWhr3g6s1xYv72ol/pe/Unols=',
15
+ * api_secrets: 'aW5kZXhfbmV3X2tleV9mb3JfdjJfcm90YXRpb24='
16
+ * }
17
+ * };
18
+ * ```
19
+ *
20
+ * 2. Configure in database with:
21
+ * - EncryptionKeySourceID pointing to 'Configuration File' source
22
+ * - KeyLookupValue = 'pii_master' (the key name in the config)
23
+ *
24
+ * ## Key Format
25
+ *
26
+ * Keys must be base64-encoded strings. Generate with:
27
+ * ```bash
28
+ * openssl rand -base64 32 # For AES-256
29
+ * openssl rand -base64 16 # For AES-128
30
+ * ```
31
+ *
32
+ * ## Security Considerations
33
+ *
34
+ * - Config files should have restricted file permissions (600 or 640)
35
+ * - Don't commit config files with keys to source control
36
+ * - Consider using .gitignore for mj.config.cjs
37
+ * - For production, prefer environment variables or secrets managers
38
+ *
39
+ * ## Key Rotation
40
+ *
41
+ * Add the new key with a versioned name:
42
+ * ```javascript
43
+ * encryptionKeys: {
44
+ * pii_master: '<current-key>',
45
+ * pii_master_v2: '<new-key>'
46
+ * }
47
+ * ```
48
+ *
49
+ * @module @memberjunction/encryption
50
+ */
51
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
52
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
53
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
54
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
55
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
56
+ };
57
+ Object.defineProperty(exports, "__esModule", { value: true });
58
+ exports.ConfigFileKeySource = void 0;
59
+ const global_1 = require("@memberjunction/global");
60
+ const EncryptionKeySourceBase_1 = require("../EncryptionKeySourceBase");
61
+ /**
62
+ * Encryption key source that retrieves keys from configuration files.
63
+ *
64
+ * Uses cosmiconfig to locate configuration in standard locations:
65
+ * - mj.config.cjs (recommended)
66
+ * - mj.config.js
67
+ * - .mjrc.json
68
+ * - .mjrc.yaml
69
+ *
70
+ * Keys are read from the `encryptionKeys` section of the configuration.
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * // Configuration file (mj.config.cjs):
75
+ * module.exports = {
76
+ * encryptionKeys: {
77
+ * pii_master: 'base64-encoded-key-here',
78
+ * financial_data: 'another-base64-key'
79
+ * }
80
+ * };
81
+ *
82
+ * // Usage (typically automatic via ClassFactory):
83
+ * const source = new ConfigFileKeySource();
84
+ * await source.Initialize(); // Load the config file
85
+ *
86
+ * const key = await source.GetKey('pii_master');
87
+ * ```
88
+ */
89
+ let ConfigFileKeySource = class ConfigFileKeySource extends EncryptionKeySourceBase_1.EncryptionKeySourceBase {
90
+ /**
91
+ * Loaded configuration from the config file.
92
+ * Set during Initialize(), null if not yet loaded.
93
+ *
94
+ * @private
95
+ */
96
+ _loadedConfig = null;
97
+ /**
98
+ * Path to the loaded config file (for error messages).
99
+ *
100
+ * @private
101
+ */
102
+ _configFilePath = null;
103
+ /**
104
+ * Human-readable name for this source.
105
+ */
106
+ get SourceName() {
107
+ return 'Configuration File';
108
+ }
109
+ /**
110
+ * Initializes the key source by loading the configuration file.
111
+ *
112
+ * Uses cosmiconfig to search for configuration in standard locations.
113
+ * Must be called before any key operations.
114
+ *
115
+ * @throws Error if cosmiconfig module cannot be loaded
116
+ */
117
+ async Initialize() {
118
+ try {
119
+ // Dynamic import to avoid bundling cosmiconfig if not used
120
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
121
+ const { cosmiconfigSync } = require('cosmiconfig');
122
+ const explorer = cosmiconfigSync('mj', {
123
+ searchStrategy: 'global'
124
+ });
125
+ const result = explorer.search();
126
+ if (result?.config?.encryptionKeys) {
127
+ const keys = result.config.encryptionKeys;
128
+ // Validate that encryptionKeys is an object with string values
129
+ if (typeof keys !== 'object' || keys === null) {
130
+ throw new Error('Invalid encryptionKeys configuration: expected an object with string values');
131
+ }
132
+ // Type check all values
133
+ for (const [keyName, keyValue] of Object.entries(keys)) {
134
+ if (typeof keyValue !== 'string') {
135
+ throw new Error(`Invalid key "${keyName}" in encryptionKeys: ` +
136
+ `expected base64 string, got ${typeof keyValue}`);
137
+ }
138
+ }
139
+ this._loadedConfig = keys;
140
+ this._configFilePath = result.filepath;
141
+ }
142
+ }
143
+ catch (err) {
144
+ // If cosmiconfig is not available or fails, log but don't crash
145
+ // The ValidateConfiguration check will fail appropriately
146
+ const message = err instanceof Error ? err.message : String(err);
147
+ console.warn(`ConfigFileKeySource: Failed to load configuration: ${message}`);
148
+ }
149
+ }
150
+ /**
151
+ * Validates that the configuration file was loaded successfully.
152
+ *
153
+ * @returns `true` if the config file was loaded and contains encryptionKeys
154
+ */
155
+ ValidateConfiguration() {
156
+ return this._loadedConfig !== null;
157
+ }
158
+ /**
159
+ * Checks if a key exists in the configuration file.
160
+ *
161
+ * @param lookupValue - The key name to check
162
+ * @returns Promise resolving to `true` if the key exists
163
+ */
164
+ async KeyExists(lookupValue) {
165
+ if (!this._loadedConfig) {
166
+ return false;
167
+ }
168
+ if (!lookupValue || typeof lookupValue !== 'string') {
169
+ return false;
170
+ }
171
+ // Validate key name format
172
+ if (!this.isValidKeyName(lookupValue)) {
173
+ return false;
174
+ }
175
+ return this._loadedConfig[lookupValue] !== undefined;
176
+ }
177
+ /**
178
+ * Retrieves key material from the configuration file.
179
+ *
180
+ * Keys should be stored as base64-encoded strings in the encryptionKeys
181
+ * section of the configuration file.
182
+ *
183
+ * For versioned keys, the version is appended with an underscore:
184
+ * - `key_name` for version 1 (default)
185
+ * - `key_name_v2` for version 2
186
+ *
187
+ * @param lookupValue - The key name in the configuration
188
+ * @param keyVersion - Optional version number (defaults to '1')
189
+ * @returns Promise resolving to the decoded key bytes
190
+ *
191
+ * @throws Error if Initialize() was not called
192
+ * @throws Error if the key is not found
193
+ * @throws Error if the value is not valid base64
194
+ *
195
+ * @example
196
+ * ```typescript
197
+ * // Config file has: encryptionKeys: { pii_master: '...' }
198
+ * const key = await source.GetKey('pii_master');
199
+ *
200
+ * // For versioned keys during rotation:
201
+ * // Config has: pii_master, pii_master_v2
202
+ * const newKey = await source.GetKey('pii_master', '2');
203
+ * ```
204
+ */
205
+ async GetKey(lookupValue, keyVersion) {
206
+ // Check if initialized
207
+ if (!this._loadedConfig) {
208
+ const configPath = this._configFilePath || 'mj.config.cjs';
209
+ throw new Error(`Configuration file not loaded. Ensure Initialize() was called and ` +
210
+ `the configuration file (${configPath}) exists with an "encryptionKeys" section. ` +
211
+ `Example:\n` +
212
+ `module.exports = {\n` +
213
+ ` encryptionKeys: {\n` +
214
+ ` your_key_name: 'base64-encoded-key'\n` +
215
+ ` }\n` +
216
+ `};`);
217
+ }
218
+ // Validate lookup value
219
+ if (!lookupValue || typeof lookupValue !== 'string') {
220
+ throw new Error('Invalid lookup value: key name is required. ' +
221
+ 'Provide the name of the key as defined in the encryptionKeys section.');
222
+ }
223
+ // Validate key name format
224
+ if (!this.isValidKeyName(lookupValue)) {
225
+ throw new Error(`Invalid key name: "${lookupValue}". ` +
226
+ 'Key names must start with a letter or underscore and contain only ' +
227
+ 'letters, numbers, and underscores.');
228
+ }
229
+ // Build the full key name with version
230
+ const keyName = this.buildKeyName(lookupValue, keyVersion);
231
+ // Retrieve the value
232
+ const keyValue = this._loadedConfig[keyName];
233
+ if (keyValue === undefined || keyValue === null) {
234
+ throw new Error(`Encryption key "${keyName}" not found in configuration file. ` +
235
+ `Add it to the "encryptionKeys" section of ${this._configFilePath || 'mj.config.cjs'}. ` +
236
+ `Example:\n` +
237
+ `encryptionKeys: {\n` +
238
+ ` "${keyName}": "base64-encoded-key"\n` +
239
+ `}\n\n` +
240
+ `Generate a key with: openssl rand -base64 32`);
241
+ }
242
+ if (keyValue.trim() === '') {
243
+ throw new Error(`Encryption key "${keyName}" in configuration file is empty. ` +
244
+ 'The value must be a non-empty base64-encoded key.');
245
+ }
246
+ // Decode from base64
247
+ try {
248
+ const keyBytes = Buffer.from(keyValue, 'base64');
249
+ if (keyBytes.length === 0) {
250
+ throw new Error('Decoded key is empty');
251
+ }
252
+ return keyBytes;
253
+ }
254
+ catch (err) {
255
+ const message = err instanceof Error ? err.message : String(err);
256
+ throw new Error(`Invalid base64 encoding for key "${keyName}" in configuration file. ` +
257
+ `The value must be a valid base64-encoded string. Error: ${message}. ` +
258
+ 'Generate a valid key with: openssl rand -base64 32');
259
+ }
260
+ }
261
+ /**
262
+ * Cleans up resources (no-op for config file source).
263
+ */
264
+ async Dispose() {
265
+ this._loadedConfig = null;
266
+ this._configFilePath = null;
267
+ }
268
+ /**
269
+ * Builds the full key name with optional version suffix.
270
+ *
271
+ * @param baseName - The base key name
272
+ * @param keyVersion - Optional version number
273
+ * @returns The full key name
274
+ *
275
+ * @private
276
+ */
277
+ buildKeyName(baseName, keyVersion) {
278
+ // No version or version '1' = use base name
279
+ if (!keyVersion || keyVersion === '1') {
280
+ return baseName;
281
+ }
282
+ // For other versions, append _v{version} (lowercase for config files)
283
+ return `${baseName}_v${keyVersion}`;
284
+ }
285
+ /**
286
+ * Validates that a string is a valid configuration key name.
287
+ *
288
+ * @param name - The name to validate
289
+ * @returns `true` if the name is valid
290
+ *
291
+ * @private
292
+ */
293
+ isValidKeyName(name) {
294
+ if (!name || name.length === 0) {
295
+ return false;
296
+ }
297
+ if (name.length > 256) {
298
+ return false;
299
+ }
300
+ // Allow alphanumeric, underscores, and hyphens
301
+ // Must start with letter or underscore
302
+ const keyNamePattern = /^[A-Za-z_][A-Za-z0-9_-]*$/;
303
+ return keyNamePattern.test(name);
304
+ }
305
+ };
306
+ exports.ConfigFileKeySource = ConfigFileKeySource;
307
+ exports.ConfigFileKeySource = ConfigFileKeySource = __decorate([
308
+ (0, global_1.RegisterClass)(EncryptionKeySourceBase_1.EncryptionKeySourceBase, 'ConfigFileKeySource')
309
+ ], ConfigFileKeySource);
310
+ //# sourceMappingURL=ConfigFileKeySource.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ConfigFileKeySource.js","sourceRoot":"","sources":["../../src/providers/ConfigFileKeySource.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,152 @@
1
+ /**
2
+ * @fileoverview Environment variable key source provider.
3
+ *
4
+ * This provider retrieves encryption keys from environment variables.
5
+ * It's the simplest and most commonly used key source for development
6
+ * and containerized deployments.
7
+ *
8
+ * ## Usage
9
+ *
10
+ * 1. Generate a key: `openssl rand -base64 32`
11
+ * 2. Set environment variable: `export MJ_ENCRYPTION_KEY_PII="<base64-key>"`
12
+ * 3. Configure in database with KeyLookupValue = 'MJ_ENCRYPTION_KEY_PII'
13
+ *
14
+ * ## Key Format
15
+ *
16
+ * Keys must be base64-encoded. For AES-256, generate with:
17
+ * ```bash
18
+ * openssl rand -base64 32
19
+ * ```
20
+ *
21
+ * For AES-128:
22
+ * ```bash
23
+ * openssl rand -base64 16
24
+ * ```
25
+ *
26
+ * ## Key Rotation
27
+ *
28
+ * During rotation, store the new key in a separate variable:
29
+ * ```bash
30
+ * export MJ_ENCRYPTION_KEY_PII="<current-key>"
31
+ * export MJ_ENCRYPTION_KEY_PII_NEW="<new-key>"
32
+ * ```
33
+ *
34
+ * After rotation completes, remove the old key and optionally
35
+ * rename the new key to the original variable name.
36
+ *
37
+ * ## Security Considerations
38
+ *
39
+ * - Environment variables may be logged or visible to child processes
40
+ * - Consider using secrets managers for production deployments
41
+ * - Ensure proper access controls on the runtime environment
42
+ * - Never commit keys to source control
43
+ *
44
+ * @module @memberjunction/encryption
45
+ */
46
+ /// <reference types="node" />
47
+ import { EncryptionKeySourceBase } from '../EncryptionKeySourceBase';
48
+ /**
49
+ * Encryption key source that retrieves keys from environment variables.
50
+ *
51
+ * This is the default and recommended key source for:
52
+ * - Development environments
53
+ * - Docker/Kubernetes deployments with secret injection
54
+ * - Serverless functions with environment configuration
55
+ *
56
+ * Keys are expected to be base64-encoded strings in the environment.
57
+ * The provider decodes them to raw bytes for crypto operations.
58
+ *
59
+ * @example
60
+ * ```typescript
61
+ * // The provider is automatically instantiated by ClassFactory
62
+ * // based on database configuration. For manual usage:
63
+ *
64
+ * import { EnvVarKeySource } from '@memberjunction/encryption';
65
+ *
66
+ * const source = new EnvVarKeySource();
67
+ *
68
+ * // Check if key exists
69
+ * if (await source.KeyExists('MJ_ENCRYPTION_KEY_PII')) {
70
+ * const keyBytes = await source.GetKey('MJ_ENCRYPTION_KEY_PII');
71
+ * console.log(`Key length: ${keyBytes.length} bytes`);
72
+ * }
73
+ * ```
74
+ */
75
+ export declare class EnvVarKeySource extends EncryptionKeySourceBase {
76
+ /**
77
+ * Human-readable name for this source.
78
+ */
79
+ get SourceName(): string;
80
+ /**
81
+ * Validates the source configuration.
82
+ *
83
+ * For environment variables, configuration is always valid as
84
+ * keys are validated at lookup time. This allows the source
85
+ * to be used dynamically for any environment variable.
86
+ *
87
+ * @returns Always returns `true`
88
+ */
89
+ ValidateConfiguration(): boolean;
90
+ /**
91
+ * Checks if an environment variable containing a key exists.
92
+ *
93
+ * @param lookupValue - The environment variable name to check
94
+ * @returns Promise resolving to `true` if the variable is defined
95
+ */
96
+ KeyExists(lookupValue: string): Promise<boolean>;
97
+ /**
98
+ * Retrieves key material from an environment variable.
99
+ *
100
+ * The environment variable should contain a base64-encoded key.
101
+ * For versioned keys, the version is appended with an underscore:
102
+ * - `KEY_NAME` for version 1 (default)
103
+ * - `KEY_NAME_V2` for version 2
104
+ * - etc.
105
+ *
106
+ * @param lookupValue - The environment variable name
107
+ * @param keyVersion - Optional version number (defaults to '1')
108
+ * @returns Promise resolving to the decoded key bytes
109
+ *
110
+ * @throws Error if the environment variable is not set
111
+ * @throws Error if the value is not valid base64
112
+ *
113
+ * @example
114
+ * ```typescript
115
+ * // Get current key
116
+ * const key = await source.GetKey('MJ_ENCRYPTION_KEY_PII');
117
+ *
118
+ * // Get specific version during rotation
119
+ * const oldKey = await source.GetKey('MJ_ENCRYPTION_KEY_PII', '1');
120
+ * const newKey = await source.GetKey('MJ_ENCRYPTION_KEY_PII', '2');
121
+ * // The above looks for MJ_ENCRYPTION_KEY_PII_V2
122
+ * ```
123
+ */
124
+ GetKey(lookupValue: string, keyVersion?: string): Promise<Buffer>;
125
+ /**
126
+ * Builds the full environment variable name with optional version suffix.
127
+ *
128
+ * @param baseName - The base environment variable name
129
+ * @param keyVersion - Optional version number
130
+ * @returns The full environment variable name
131
+ *
132
+ * @private
133
+ */
134
+ private buildEnvVarName;
135
+ /**
136
+ * Validates that a string is a valid environment variable name.
137
+ *
138
+ * Valid names:
139
+ * - Start with a letter (A-Z, a-z) or underscore (_)
140
+ * - Contain only letters, numbers, and underscores
141
+ *
142
+ * This prevents injection attacks where malicious lookupValues
143
+ * could be crafted to access unintended variables.
144
+ *
145
+ * @param name - The name to validate
146
+ * @returns `true` if the name is valid
147
+ *
148
+ * @private
149
+ */
150
+ private isValidEnvVarName;
151
+ }
152
+ //# sourceMappingURL=EnvVarKeySource.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EnvVarKeySource.d.ts","sourceRoot":"","sources":["../../src/providers/EnvVarKeySource.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;;AAGH,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AAErE;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,qBACa,eAAgB,SAAQ,uBAAuB;IACxD;;OAEG;IACH,IAAI,UAAU,IAAI,MAAM,CAEvB;IAED;;;;;;;;OAQG;IACH,qBAAqB,IAAI,OAAO;IAMhC;;;;;OAKG;IACG,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAatD;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACG,MAAM,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAsEvE;;;;;;;;OAQG;IACH,OAAO,CAAC,eAAe;IAUvB;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,iBAAiB;CAiB5B"}