@webda/core 4.0.0-beta.6 → 4.0.0-beta.7
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/README.md +6 -5
- package/lib/application/application.d.ts.map +1 -1
- package/lib/application/application.js +6 -5
- package/lib/application/application.js.map +1 -1
- package/lib/application/iconfiguration.d.ts +31 -0
- package/lib/application/iconfiguration.d.ts.map +1 -1
- package/lib/application/iconfiguration.js.map +1 -1
- package/lib/application/unpackedapplication.d.ts.map +1 -1
- package/lib/application/unpackedapplication.js +2 -1
- package/lib/application/unpackedapplication.js.map +1 -1
- package/lib/bin/cli-phase.d.ts +18 -2
- package/lib/bin/cli-phase.d.ts.map +1 -1
- package/lib/bin/cli-phase.js +25 -0
- package/lib/bin/cli-phase.js.map +1 -1
- package/lib/bin/cli.d.ts +8 -0
- package/lib/bin/cli.d.ts.map +1 -1
- package/lib/bin/cli.js +94 -35
- package/lib/bin/cli.js.map +1 -1
- package/lib/configurations/configuration.service.d.ts +7 -0
- package/lib/configurations/configuration.service.d.ts.map +1 -1
- package/lib/configurations/configuration.service.js +18 -5
- package/lib/configurations/configuration.service.js.map +1 -1
- package/lib/configurations/kubernetesconfiguration.service.d.ts.map +1 -1
- package/lib/configurations/kubernetesconfiguration.service.js +1 -4
- package/lib/configurations/kubernetesconfiguration.service.js.map +1 -1
- package/lib/contexts/httpcontext.d.ts +15 -1
- package/lib/contexts/httpcontext.d.ts.map +1 -1
- package/lib/contexts/httpcontext.js +61 -19
- package/lib/contexts/httpcontext.js.map +1 -1
- package/lib/contexts/operationcontext.d.ts +6 -0
- package/lib/contexts/operationcontext.d.ts.map +1 -1
- package/lib/contexts/operationcontext.js +16 -2
- package/lib/contexts/operationcontext.js.map +1 -1
- package/lib/contexts/restcontext.d.ts +110 -0
- package/lib/contexts/restcontext.d.ts.map +1 -0
- package/lib/contexts/restcontext.js +247 -0
- package/lib/contexts/restcontext.js.map +1 -0
- package/lib/contexts/streamingcontext.d.ts +71 -0
- package/lib/contexts/streamingcontext.d.ts.map +1 -0
- package/lib/contexts/streamingcontext.js +93 -0
- package/lib/contexts/streamingcontext.js.map +1 -0
- package/lib/contexts/webcontext.d.ts +20 -0
- package/lib/contexts/webcontext.d.ts.map +1 -1
- package/lib/contexts/webcontext.js +43 -10
- package/lib/contexts/webcontext.js.map +1 -1
- package/lib/contexts/websocketcontext.d.ts +39 -0
- package/lib/contexts/websocketcontext.d.ts.map +1 -0
- package/lib/contexts/websocketcontext.js +67 -0
- package/lib/contexts/websocketcontext.js.map +1 -0
- package/lib/core/asyncqueue.d.ts +50 -0
- package/lib/core/asyncqueue.d.ts.map +1 -0
- package/lib/core/asyncqueue.js +96 -0
- package/lib/core/asyncqueue.js.map +1 -0
- package/lib/core/core.d.ts +18 -0
- package/lib/core/core.d.ts.map +1 -1
- package/lib/core/core.js +72 -7
- package/lib/core/core.js.map +1 -1
- package/lib/core/icore.d.ts +14 -1
- package/lib/core/icore.d.ts.map +1 -1
- package/lib/core/icore.js.map +1 -1
- package/lib/core/instancestorage.d.ts +1 -0
- package/lib/core/instancestorage.d.ts.map +1 -1
- package/lib/core/instancestorage.js +1 -0
- package/lib/core/instancestorage.js.map +1 -1
- package/lib/core/operations.d.ts +49 -6
- package/lib/core/operations.d.ts.map +1 -1
- package/lib/core/operations.js +187 -24
- package/lib/core/operations.js.map +1 -1
- package/lib/deployers/git.d.ts +4 -2
- package/lib/deployers/git.d.ts.map +1 -1
- package/lib/deployers/git.js +44 -5
- package/lib/deployers/git.js.map +1 -1
- package/lib/errors/errors.d.ts +15 -0
- package/lib/errors/errors.d.ts.map +1 -1
- package/lib/errors/errors.js +20 -0
- package/lib/errors/errors.js.map +1 -1
- package/lib/index.d.ts +5 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +5 -0
- package/lib/index.js.map +1 -1
- package/lib/rest/restoperationstransport.service.d.ts +108 -0
- package/lib/rest/restoperationstransport.service.d.ts.map +1 -1
- package/lib/rest/restoperationstransport.service.js +348 -9
- package/lib/rest/restoperationstransport.service.js.map +1 -1
- package/lib/rest/router.service.d.ts +1 -1
- package/lib/rest/router.service.d.ts.map +1 -1
- package/lib/rest/router.service.js.map +1 -1
- package/lib/services/authenticatedencryption.d.ts +25 -0
- package/lib/services/authenticatedencryption.d.ts.map +1 -0
- package/lib/services/authenticatedencryption.js +56 -0
- package/lib/services/authenticatedencryption.js.map +1 -0
- package/lib/services/cloudbinary.d.ts.map +1 -1
- package/lib/services/cloudbinary.js +3 -2
- package/lib/services/cloudbinary.js.map +1 -1
- package/lib/services/command.d.ts +7 -1
- package/lib/services/command.d.ts.map +1 -1
- package/lib/services/command.js +4 -0
- package/lib/services/command.js.map +1 -1
- package/lib/services/cryptoservice.service.d.ts +405 -25
- package/lib/services/cryptoservice.service.d.ts.map +1 -1
- package/lib/services/cryptoservice.service.js +779 -72
- package/lib/services/cryptoservice.service.js.map +1 -1
- package/lib/services/httpserver.service.d.ts.map +1 -1
- package/lib/services/httpserver.service.js +15 -9
- package/lib/services/httpserver.service.js.map +1 -1
- package/lib/services/icryptoservice.d.ts +11 -0
- package/lib/services/icryptoservice.d.ts.map +1 -1
- package/lib/services/icryptoservice.js +2 -0
- package/lib/services/icryptoservice.js.map +1 -1
- package/lib/services/mailer.service.d.ts +4 -0
- package/lib/services/mailer.service.d.ts.map +1 -1
- package/lib/services/mailer.service.js +7 -1
- package/lib/services/mailer.service.js.map +1 -1
- package/lib/services/operationstransport.d.ts +13 -0
- package/lib/services/operationstransport.d.ts.map +1 -1
- package/lib/services/operationstransport.js +28 -6
- package/lib/services/operationstransport.js.map +1 -1
- package/lib/services/pki.encrypter.d.ts +214 -0
- package/lib/services/pki.encrypter.d.ts.map +1 -0
- package/lib/services/pki.encrypter.js +350 -0
- package/lib/services/pki.encrypter.js.map +1 -0
- package/lib/services/secretscheck.d.ts +120 -0
- package/lib/services/secretscheck.d.ts.map +1 -0
- package/lib/services/secretscheck.js +322 -0
- package/lib/services/secretscheck.js.map +1 -0
- package/lib/services/servicecommands.d.ts +8 -4
- package/lib/services/servicecommands.d.ts.map +1 -1
- package/lib/services/servicecommands.js +14 -5
- package/lib/services/servicecommands.js.map +1 -1
- package/lib/session/manager.model.d.ts +3 -1
- package/lib/session/manager.model.d.ts.map +1 -1
- package/lib/session/manager.model.js +6 -3
- package/lib/session/manager.model.js.map +1 -1
- package/lib/test/objects.d.ts.map +1 -1
- package/lib/test/objects.js +3 -1
- package/lib/test/objects.js.map +1 -1
- package/package.json +12 -11
- package/webda.module.json +135 -41
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
import { KeyObject } from "crypto";
|
|
2
|
+
import type { EncrypterContext, StringEncrypter } from "./cryptoservice.service.js";
|
|
3
|
+
/**
|
|
4
|
+
* Options of the `pki` encrypter, in `parameters.configurationEncryption.encrypters.pki`
|
|
5
|
+
*/
|
|
6
|
+
export interface PkiEncrypterOptions {
|
|
7
|
+
/**
|
|
8
|
+
* Key id used to encrypt new values
|
|
9
|
+
*
|
|
10
|
+
* Its public key must be available: `<publicKeys>/<activeKey>.pub.pem`
|
|
11
|
+
*/
|
|
12
|
+
activeKey?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Directory of the public keys, relative to the application: `<kid>.pub.pem`
|
|
15
|
+
*
|
|
16
|
+
* Commit it with the application, any developer or CI job can then encrypt a value.
|
|
17
|
+
*
|
|
18
|
+
* @default ".webda/keys"
|
|
19
|
+
*/
|
|
20
|
+
publicKeys?: string;
|
|
21
|
+
/**
|
|
22
|
+
* Directory of the private keys at runtime, a Kubernetes Secret mount for example: `<kid>.pem` or `<kid>`
|
|
23
|
+
*
|
|
24
|
+
* @default env WEBDA_PKI_PRIVATE_KEYS_DIR, then "/etc/webda/pki"
|
|
25
|
+
*/
|
|
26
|
+
privateKeys?: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Version of the `pki` encrypted format
|
|
30
|
+
*/
|
|
31
|
+
export declare const PKI_FORMAT_V1 = "v1";
|
|
32
|
+
/**
|
|
33
|
+
* Default directory of the public keys, relative to the application
|
|
34
|
+
*/
|
|
35
|
+
export declare const PKI_DEFAULT_PUBLIC_KEYS = ".webda/keys";
|
|
36
|
+
/**
|
|
37
|
+
* Default directory of the private keys
|
|
38
|
+
*/
|
|
39
|
+
export declare const PKI_DEFAULT_PRIVATE_KEYS = "/etc/webda/pki";
|
|
40
|
+
/**
|
|
41
|
+
* Environment variable overriding the private keys directory
|
|
42
|
+
*/
|
|
43
|
+
export declare const PKI_PRIVATE_KEYS_DIR_ENV = "WEBDA_PKI_PRIVATE_KEYS_DIR";
|
|
44
|
+
/**
|
|
45
|
+
* Environment variable prefix holding one private key PEM: `WEBDA_PKI_PRIVATE_KEY_<KID>`
|
|
46
|
+
*/
|
|
47
|
+
export declare const PKI_PRIVATE_KEY_ENV_PREFIX = "WEBDA_PKI_PRIVATE_KEY_";
|
|
48
|
+
/**
|
|
49
|
+
* Environment variable holding the passphrase of the private keys
|
|
50
|
+
*/
|
|
51
|
+
export declare const PKI_PASSPHRASE_ENV = "WEBDA_PKI_PASSPHRASE";
|
|
52
|
+
/**
|
|
53
|
+
* Minimum RSA modulus length
|
|
54
|
+
*/
|
|
55
|
+
export declare const PKI_MIN_BITS = 3072;
|
|
56
|
+
/**
|
|
57
|
+
* Check a key id
|
|
58
|
+
* @param kid - the key id
|
|
59
|
+
* @returns the key id
|
|
60
|
+
*/
|
|
61
|
+
export declare function checkKid(kid: string): string;
|
|
62
|
+
/**
|
|
63
|
+
* Name of the environment variable holding the private key of a kid
|
|
64
|
+
* @param kid - the key id
|
|
65
|
+
* @returns the variable name
|
|
66
|
+
*/
|
|
67
|
+
export declare function getPrivateKeyEnv(kid: string): string;
|
|
68
|
+
/**
|
|
69
|
+
* Parsed `pki` encrypted value
|
|
70
|
+
*/
|
|
71
|
+
export interface PkiValue {
|
|
72
|
+
kid: string;
|
|
73
|
+
wrappedKey: string;
|
|
74
|
+
ciphertext: string;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Parse a `v1:<kid>:<wrappedKey>:<ciphertext>` value
|
|
78
|
+
* @param data - the encrypted value, without `crypt:pki:`
|
|
79
|
+
* @returns the parts
|
|
80
|
+
*/
|
|
81
|
+
export declare function parsePkiValue(data: string): PkiValue;
|
|
82
|
+
/**
|
|
83
|
+
* Public and private keys of the `pki` encrypter
|
|
84
|
+
*
|
|
85
|
+
* The keys are loaded lazily and cached by kid.
|
|
86
|
+
*/
|
|
87
|
+
export declare class PkiKeyring {
|
|
88
|
+
/**
|
|
89
|
+
* Key id used to encrypt
|
|
90
|
+
*/
|
|
91
|
+
readonly activeKey?: string;
|
|
92
|
+
/**
|
|
93
|
+
* Absolute directory of the public keys
|
|
94
|
+
*/
|
|
95
|
+
readonly publicKeysDir: string;
|
|
96
|
+
/**
|
|
97
|
+
* Absolute directory of the private keys
|
|
98
|
+
*/
|
|
99
|
+
readonly privateKeysDir: string;
|
|
100
|
+
protected publicKeys: Map<string, KeyObject>;
|
|
101
|
+
protected privateKeys: Map<string, KeyObject>;
|
|
102
|
+
/**
|
|
103
|
+
* @param options - the encrypter options
|
|
104
|
+
* @param appPath - the application path, relative directories resolve against it
|
|
105
|
+
*/
|
|
106
|
+
constructor(options?: PkiEncrypterOptions, appPath?: string);
|
|
107
|
+
/**
|
|
108
|
+
* List the kids of a directory
|
|
109
|
+
* @param dir - the directory
|
|
110
|
+
* @param suffix - the file suffix
|
|
111
|
+
* @param optionalSuffix - also accept files without the suffix
|
|
112
|
+
* @returns the sorted kids
|
|
113
|
+
*/
|
|
114
|
+
protected static listDir(dir: string, suffix: string, optionalSuffix: boolean): string[];
|
|
115
|
+
/**
|
|
116
|
+
* List the kids having a public key
|
|
117
|
+
* @returns the kids
|
|
118
|
+
*/
|
|
119
|
+
listKids(): string[];
|
|
120
|
+
/**
|
|
121
|
+
* List the kids having a private key file
|
|
122
|
+
* @returns the kids
|
|
123
|
+
*/
|
|
124
|
+
listPrivateKids(): string[];
|
|
125
|
+
/**
|
|
126
|
+
* Get the public key of a kid
|
|
127
|
+
*
|
|
128
|
+
* From `<publicKeys>/<kid>.pub.pem`, or derived from its private key when it is available
|
|
129
|
+
*
|
|
130
|
+
* @param kid - the key id
|
|
131
|
+
* @returns the public key
|
|
132
|
+
*/
|
|
133
|
+
getPublicKey(kid: string): KeyObject;
|
|
134
|
+
/**
|
|
135
|
+
* Find the source of a private key
|
|
136
|
+
* @param kid - the key id
|
|
137
|
+
* @returns the environment variable or file name, undefined if not found
|
|
138
|
+
*/
|
|
139
|
+
protected findPrivateKey(kid: string): {
|
|
140
|
+
env?: string;
|
|
141
|
+
file?: string;
|
|
142
|
+
} | undefined;
|
|
143
|
+
/**
|
|
144
|
+
* Check if the private key of a kid is available
|
|
145
|
+
* @param kid - the key id
|
|
146
|
+
* @returns true if available
|
|
147
|
+
*/
|
|
148
|
+
hasPrivateKey(kid: string): boolean;
|
|
149
|
+
/**
|
|
150
|
+
* Get the private key of a kid
|
|
151
|
+
*
|
|
152
|
+
* From `WEBDA_PKI_PRIVATE_KEY_<KID>`, then `<privateKeys>/<kid>.pem` or `<privateKeys>/<kid>`.
|
|
153
|
+
* The passphrase, if any, is read from `WEBDA_PKI_PASSPHRASE`.
|
|
154
|
+
*
|
|
155
|
+
* @param kid - the key id
|
|
156
|
+
* @returns the private key
|
|
157
|
+
*/
|
|
158
|
+
getPrivateKey(kid: string): KeyObject;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Asymmetric encrypter: hybrid RSA-OAEP-256 + AES-256-GCM
|
|
162
|
+
*
|
|
163
|
+
* The public keys are committed with the application, so anyone can encrypt a value. The private keys only live
|
|
164
|
+
* in the runtime (a Kubernetes Secret mount or environment variables), so only the application can decrypt.
|
|
165
|
+
*
|
|
166
|
+
* Format: `v1:<kid>:<base64(wrappedKey)>:<base64(iv | tag | ciphertext)>`, the kid is authenticated.
|
|
167
|
+
*/
|
|
168
|
+
export declare class PkiEncrypter implements StringEncrypter {
|
|
169
|
+
protected keyring: PkiKeyring;
|
|
170
|
+
/**
|
|
171
|
+
* Serialized configuration of the keyring, to keep its cache when unchanged
|
|
172
|
+
*/
|
|
173
|
+
protected configuration: string;
|
|
174
|
+
/**
|
|
175
|
+
* Configure the keyring
|
|
176
|
+
* @param options - the encrypter options
|
|
177
|
+
* @param context - the encryption context
|
|
178
|
+
*/
|
|
179
|
+
configure(options?: PkiEncrypterOptions, context?: EncrypterContext): void;
|
|
180
|
+
/**
|
|
181
|
+
* Get the keyring, with the default options when not configured
|
|
182
|
+
* @returns the keyring
|
|
183
|
+
*/
|
|
184
|
+
getKeyring(): PkiKeyring;
|
|
185
|
+
/**
|
|
186
|
+
* Additional authenticated data binding the format and the kid
|
|
187
|
+
* @param kid - the key id
|
|
188
|
+
* @returns the AAD
|
|
189
|
+
*/
|
|
190
|
+
protected static aad(kid: string): Uint8Array;
|
|
191
|
+
/**
|
|
192
|
+
* Encrypt with the public key of the active key
|
|
193
|
+
* @param data - the plain value
|
|
194
|
+
* @returns the encrypted value
|
|
195
|
+
*/
|
|
196
|
+
encrypt(data: string): Promise<string>;
|
|
197
|
+
/**
|
|
198
|
+
* Decrypt with the private key of the value kid
|
|
199
|
+
* @param data - the encrypted value
|
|
200
|
+
* @returns the plain value
|
|
201
|
+
*/
|
|
202
|
+
decrypt(data: string): Promise<string>;
|
|
203
|
+
/**
|
|
204
|
+
* A value needs an upgrade when it was not encrypted with the active key
|
|
205
|
+
* @param data - the encrypted value
|
|
206
|
+
* @returns true to re-encrypt it
|
|
207
|
+
*/
|
|
208
|
+
needsUpgrade(data: string): boolean;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* The `pki` encrypter instance, registered by CryptoService
|
|
212
|
+
*/
|
|
213
|
+
export declare const pkiEncrypter: PkiEncrypter;
|
|
214
|
+
//# sourceMappingURL=pki.encrypter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pki.encrypter.d.ts","sourceRoot":"","sources":["../../src/services/pki.encrypter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
import { constants, createPrivateKey, createPublicKey, privateDecrypt, publicEncrypt, randomBytes } from "crypto";
|
|
2
|
+
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
3
|
+
import { join, resolve } from "node:path";
|
|
4
|
+
import { AuthenticatedEncryption } from "./authenticatedencryption.js";
|
|
5
|
+
/**
|
|
6
|
+
* Version of the `pki` encrypted format
|
|
7
|
+
*/
|
|
8
|
+
export const PKI_FORMAT_V1 = "v1";
|
|
9
|
+
/**
|
|
10
|
+
* Default directory of the public keys, relative to the application
|
|
11
|
+
*/
|
|
12
|
+
export const PKI_DEFAULT_PUBLIC_KEYS = ".webda/keys";
|
|
13
|
+
/**
|
|
14
|
+
* Default directory of the private keys
|
|
15
|
+
*/
|
|
16
|
+
export const PKI_DEFAULT_PRIVATE_KEYS = "/etc/webda/pki";
|
|
17
|
+
/**
|
|
18
|
+
* Environment variable overriding the private keys directory
|
|
19
|
+
*/
|
|
20
|
+
export const PKI_PRIVATE_KEYS_DIR_ENV = "WEBDA_PKI_PRIVATE_KEYS_DIR";
|
|
21
|
+
/**
|
|
22
|
+
* Environment variable prefix holding one private key PEM: `WEBDA_PKI_PRIVATE_KEY_<KID>`
|
|
23
|
+
*/
|
|
24
|
+
export const PKI_PRIVATE_KEY_ENV_PREFIX = "WEBDA_PKI_PRIVATE_KEY_";
|
|
25
|
+
/**
|
|
26
|
+
* Environment variable holding the passphrase of the private keys
|
|
27
|
+
*/
|
|
28
|
+
export const PKI_PASSPHRASE_ENV = "WEBDA_PKI_PASSPHRASE";
|
|
29
|
+
/**
|
|
30
|
+
* Minimum RSA modulus length
|
|
31
|
+
*/
|
|
32
|
+
export const PKI_MIN_BITS = 3072;
|
|
33
|
+
/**
|
|
34
|
+
* Valid key id
|
|
35
|
+
*/
|
|
36
|
+
const KID = /^[A-Za-z0-9_.-]+$/;
|
|
37
|
+
/**
|
|
38
|
+
* Check a key id
|
|
39
|
+
* @param kid - the key id
|
|
40
|
+
* @returns the key id
|
|
41
|
+
*/
|
|
42
|
+
export function checkKid(kid) {
|
|
43
|
+
if (typeof kid !== "string" || !KID.test(kid)) {
|
|
44
|
+
throw new Error(`Invalid key id '${kid}', use letters, digits, '_', '-' and '.' only`);
|
|
45
|
+
}
|
|
46
|
+
return kid;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Name of the environment variable holding the private key of a kid
|
|
50
|
+
* @param kid - the key id
|
|
51
|
+
* @returns the variable name
|
|
52
|
+
*/
|
|
53
|
+
export function getPrivateKeyEnv(kid) {
|
|
54
|
+
return PKI_PRIVATE_KEY_ENV_PREFIX + kid.toUpperCase().replace(/[-.]/g, "_");
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Check that a key can be used by the `pki` encrypter
|
|
58
|
+
* @param key - the key
|
|
59
|
+
* @param kid - the key id, for the message
|
|
60
|
+
* @returns the key
|
|
61
|
+
*/
|
|
62
|
+
function checkKey(key, kid) {
|
|
63
|
+
if (key.asymmetricKeyType !== "rsa") {
|
|
64
|
+
throw new Error(`Key '${kid}' is not an RSA key (${key.asymmetricKeyType})`);
|
|
65
|
+
}
|
|
66
|
+
if ((key.asymmetricKeyDetails?.modulusLength ?? 0) < PKI_MIN_BITS) {
|
|
67
|
+
throw new Error(`Key '${kid}' is too small, RSA ${PKI_MIN_BITS} bits at least is required`);
|
|
68
|
+
}
|
|
69
|
+
return key;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Parse a `v1:<kid>:<wrappedKey>:<ciphertext>` value
|
|
73
|
+
* @param data - the encrypted value, without `crypt:pki:`
|
|
74
|
+
* @returns the parts
|
|
75
|
+
*/
|
|
76
|
+
export function parsePkiValue(data) {
|
|
77
|
+
const parts = typeof data === "string" ? data.split(":") : [];
|
|
78
|
+
if (parts.length !== 4 || parts[0] !== PKI_FORMAT_V1 || !KID.test(parts[1])) {
|
|
79
|
+
throw new Error("Invalid pki encrypted data");
|
|
80
|
+
}
|
|
81
|
+
return { kid: parts[1], wrappedKey: parts[2], ciphertext: parts[3] };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Public and private keys of the `pki` encrypter
|
|
85
|
+
*
|
|
86
|
+
* The keys are loaded lazily and cached by kid.
|
|
87
|
+
*/
|
|
88
|
+
export class PkiKeyring {
|
|
89
|
+
/**
|
|
90
|
+
* Key id used to encrypt
|
|
91
|
+
*/
|
|
92
|
+
activeKey;
|
|
93
|
+
/**
|
|
94
|
+
* Absolute directory of the public keys
|
|
95
|
+
*/
|
|
96
|
+
publicKeysDir;
|
|
97
|
+
/**
|
|
98
|
+
* Absolute directory of the private keys
|
|
99
|
+
*/
|
|
100
|
+
privateKeysDir;
|
|
101
|
+
publicKeys = new Map();
|
|
102
|
+
privateKeys = new Map();
|
|
103
|
+
/**
|
|
104
|
+
* @param options - the encrypter options
|
|
105
|
+
* @param appPath - the application path, relative directories resolve against it
|
|
106
|
+
*/
|
|
107
|
+
constructor(options = {}, appPath = process.cwd()) {
|
|
108
|
+
if (options.activeKey !== undefined) {
|
|
109
|
+
this.activeKey = checkKid(options.activeKey);
|
|
110
|
+
}
|
|
111
|
+
this.publicKeysDir = resolve(appPath, options.publicKeys ?? PKI_DEFAULT_PUBLIC_KEYS);
|
|
112
|
+
this.privateKeysDir = resolve(appPath, options.privateKeys ?? process.env[PKI_PRIVATE_KEYS_DIR_ENV] ?? PKI_DEFAULT_PRIVATE_KEYS);
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* List the kids of a directory
|
|
116
|
+
* @param dir - the directory
|
|
117
|
+
* @param suffix - the file suffix
|
|
118
|
+
* @param optionalSuffix - also accept files without the suffix
|
|
119
|
+
* @returns the sorted kids
|
|
120
|
+
*/
|
|
121
|
+
static listDir(dir, suffix, optionalSuffix) {
|
|
122
|
+
if (!existsSync(dir)) {
|
|
123
|
+
return [];
|
|
124
|
+
}
|
|
125
|
+
const kids = new Set();
|
|
126
|
+
for (const file of readdirSync(dir)) {
|
|
127
|
+
// Kubernetes Secret mounts hold `..data` and `..<timestamp>` entries
|
|
128
|
+
if (file.startsWith(".") || !statSync(join(dir, file)).isFile()) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
let kid;
|
|
132
|
+
if (file.endsWith(suffix)) {
|
|
133
|
+
kid = file.substring(0, file.length - suffix.length);
|
|
134
|
+
}
|
|
135
|
+
else if (optionalSuffix && !file.includes(".pem")) {
|
|
136
|
+
kid = file;
|
|
137
|
+
}
|
|
138
|
+
if (kid && KID.test(kid)) {
|
|
139
|
+
kids.add(kid);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
return [...kids].sort();
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* List the kids having a public key
|
|
146
|
+
* @returns the kids
|
|
147
|
+
*/
|
|
148
|
+
listKids() {
|
|
149
|
+
return PkiKeyring.listDir(this.publicKeysDir, ".pub.pem", false);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* List the kids having a private key file
|
|
153
|
+
* @returns the kids
|
|
154
|
+
*/
|
|
155
|
+
listPrivateKids() {
|
|
156
|
+
return PkiKeyring.listDir(this.privateKeysDir, ".pem", true);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Get the public key of a kid
|
|
160
|
+
*
|
|
161
|
+
* From `<publicKeys>/<kid>.pub.pem`, or derived from its private key when it is available
|
|
162
|
+
*
|
|
163
|
+
* @param kid - the key id
|
|
164
|
+
* @returns the public key
|
|
165
|
+
*/
|
|
166
|
+
getPublicKey(kid) {
|
|
167
|
+
checkKid(kid);
|
|
168
|
+
if (!this.publicKeys.has(kid)) {
|
|
169
|
+
const file = join(this.publicKeysDir, `${kid}.pub.pem`);
|
|
170
|
+
let key;
|
|
171
|
+
if (existsSync(file)) {
|
|
172
|
+
try {
|
|
173
|
+
key = createPublicKey(readFileSync(file));
|
|
174
|
+
}
|
|
175
|
+
catch (err) {
|
|
176
|
+
throw new Error(`Cannot load public key '${kid}' from ${file}: ${err.message}`);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
else if (this.hasPrivateKey(kid)) {
|
|
180
|
+
key = createPublicKey(this.getPrivateKey(kid));
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
throw new Error(`No public key for active key '${kid}' in ${this.publicKeysDir}`);
|
|
184
|
+
}
|
|
185
|
+
this.publicKeys.set(kid, checkKey(key, kid));
|
|
186
|
+
}
|
|
187
|
+
return this.publicKeys.get(kid);
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Find the source of a private key
|
|
191
|
+
* @param kid - the key id
|
|
192
|
+
* @returns the environment variable or file name, undefined if not found
|
|
193
|
+
*/
|
|
194
|
+
findPrivateKey(kid) {
|
|
195
|
+
const env = getPrivateKeyEnv(kid);
|
|
196
|
+
if (process.env[env]) {
|
|
197
|
+
return { env };
|
|
198
|
+
}
|
|
199
|
+
for (const file of [join(this.privateKeysDir, `${kid}.pem`), join(this.privateKeysDir, kid)]) {
|
|
200
|
+
if (existsSync(file) && statSync(file).isFile()) {
|
|
201
|
+
return { file };
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
return undefined;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Check if the private key of a kid is available
|
|
208
|
+
* @param kid - the key id
|
|
209
|
+
* @returns true if available
|
|
210
|
+
*/
|
|
211
|
+
hasPrivateKey(kid) {
|
|
212
|
+
return this.privateKeys.has(kid) || this.findPrivateKey(kid) !== undefined;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Get the private key of a kid
|
|
216
|
+
*
|
|
217
|
+
* From `WEBDA_PKI_PRIVATE_KEY_<KID>`, then `<privateKeys>/<kid>.pem` or `<privateKeys>/<kid>`.
|
|
218
|
+
* The passphrase, if any, is read from `WEBDA_PKI_PASSPHRASE`.
|
|
219
|
+
*
|
|
220
|
+
* @param kid - the key id
|
|
221
|
+
* @returns the private key
|
|
222
|
+
*/
|
|
223
|
+
getPrivateKey(kid) {
|
|
224
|
+
checkKid(kid);
|
|
225
|
+
if (!this.privateKeys.has(kid)) {
|
|
226
|
+
const source = this.findPrivateKey(kid);
|
|
227
|
+
if (!source) {
|
|
228
|
+
const available = this.listPrivateKids();
|
|
229
|
+
throw new Error(`No private key for kid '${kid}' (available: ${available.length ? available.join(", ") : "none"} in ${this.privateKeysDir})`);
|
|
230
|
+
}
|
|
231
|
+
const origin = source.env ?? source.file;
|
|
232
|
+
let key;
|
|
233
|
+
try {
|
|
234
|
+
key = createPrivateKey({
|
|
235
|
+
key: source.env ? process.env[source.env] : readFileSync(source.file),
|
|
236
|
+
passphrase: process.env[PKI_PASSPHRASE_ENV]
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
catch (err) {
|
|
240
|
+
// The error never contains the key material
|
|
241
|
+
throw new Error(`Cannot load private key '${kid}' from ${origin}: ${err.message}`);
|
|
242
|
+
}
|
|
243
|
+
this.privateKeys.set(kid, checkKey(key, kid));
|
|
244
|
+
}
|
|
245
|
+
return this.privateKeys.get(kid);
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Asymmetric encrypter: hybrid RSA-OAEP-256 + AES-256-GCM
|
|
250
|
+
*
|
|
251
|
+
* The public keys are committed with the application, so anyone can encrypt a value. The private keys only live
|
|
252
|
+
* in the runtime (a Kubernetes Secret mount or environment variables), so only the application can decrypt.
|
|
253
|
+
*
|
|
254
|
+
* Format: `v1:<kid>:<base64(wrappedKey)>:<base64(iv | tag | ciphertext)>`, the kid is authenticated.
|
|
255
|
+
*/
|
|
256
|
+
export class PkiEncrypter {
|
|
257
|
+
keyring;
|
|
258
|
+
/**
|
|
259
|
+
* Serialized configuration of the keyring, to keep its cache when unchanged
|
|
260
|
+
*/
|
|
261
|
+
configuration;
|
|
262
|
+
/**
|
|
263
|
+
* Configure the keyring
|
|
264
|
+
* @param options - the encrypter options
|
|
265
|
+
* @param context - the encryption context
|
|
266
|
+
*/
|
|
267
|
+
configure(options = {}, context) {
|
|
268
|
+
const appPath = context?.appPath ?? process.cwd();
|
|
269
|
+
const configuration = JSON.stringify([options, appPath, process.env[PKI_PRIVATE_KEYS_DIR_ENV]]);
|
|
270
|
+
if (this.keyring && configuration === this.configuration) {
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
this.keyring = new PkiKeyring(options, appPath);
|
|
274
|
+
this.configuration = configuration;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Get the keyring, with the default options when not configured
|
|
278
|
+
* @returns the keyring
|
|
279
|
+
*/
|
|
280
|
+
getKeyring() {
|
|
281
|
+
if (!this.keyring) {
|
|
282
|
+
this.configure();
|
|
283
|
+
}
|
|
284
|
+
return this.keyring;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Additional authenticated data binding the format and the kid
|
|
288
|
+
* @param kid - the key id
|
|
289
|
+
* @returns the AAD
|
|
290
|
+
*/
|
|
291
|
+
static aad(kid) {
|
|
292
|
+
return new Uint8Array(Buffer.from(`${PKI_FORMAT_V1}:${kid}`));
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Encrypt with the public key of the active key
|
|
296
|
+
* @param data - the plain value
|
|
297
|
+
* @returns the encrypted value
|
|
298
|
+
*/
|
|
299
|
+
async encrypt(data) {
|
|
300
|
+
const keyring = this.getKeyring();
|
|
301
|
+
const kid = keyring.activeKey;
|
|
302
|
+
if (!kid) {
|
|
303
|
+
throw new Error("No active key, set parameters.configurationEncryption.encrypters.pki.activeKey");
|
|
304
|
+
}
|
|
305
|
+
const publicKey = keyring.getPublicKey(kid);
|
|
306
|
+
const dataKey = new Uint8Array(randomBytes(32));
|
|
307
|
+
const ciphertext = AuthenticatedEncryption.encrypt(dataKey, data, PkiEncrypter.aad(kid));
|
|
308
|
+
const wrappedKey = publicEncrypt({ key: publicKey, padding: constants.RSA_PKCS1_OAEP_PADDING, oaepHash: "sha256" }, dataKey).toString("base64");
|
|
309
|
+
return `${PKI_FORMAT_V1}:${kid}:${wrappedKey}:${ciphertext}`;
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Decrypt with the private key of the value kid
|
|
313
|
+
* @param data - the encrypted value
|
|
314
|
+
* @returns the plain value
|
|
315
|
+
*/
|
|
316
|
+
async decrypt(data) {
|
|
317
|
+
const { kid, wrappedKey, ciphertext } = parsePkiValue(data);
|
|
318
|
+
const privateKey = this.getKeyring().getPrivateKey(kid);
|
|
319
|
+
let dataKey;
|
|
320
|
+
try {
|
|
321
|
+
dataKey = new Uint8Array(privateDecrypt({ key: privateKey, padding: constants.RSA_PKCS1_OAEP_PADDING, oaepHash: "sha256" }, new Uint8Array(Buffer.from(wrappedKey, "base64"))));
|
|
322
|
+
}
|
|
323
|
+
catch {
|
|
324
|
+
throw new Error("Wrong key or altered data");
|
|
325
|
+
}
|
|
326
|
+
if (dataKey.length !== 32) {
|
|
327
|
+
throw new Error("Wrong key or altered data");
|
|
328
|
+
}
|
|
329
|
+
return AuthenticatedEncryption.decrypt(dataKey, ciphertext, PkiEncrypter.aad(kid));
|
|
330
|
+
}
|
|
331
|
+
/**
|
|
332
|
+
* A value needs an upgrade when it was not encrypted with the active key
|
|
333
|
+
* @param data - the encrypted value
|
|
334
|
+
* @returns true to re-encrypt it
|
|
335
|
+
*/
|
|
336
|
+
needsUpgrade(data) {
|
|
337
|
+
const activeKey = this.getKeyring().activeKey;
|
|
338
|
+
try {
|
|
339
|
+
return activeKey !== undefined && parsePkiValue(data).kid !== activeKey;
|
|
340
|
+
}
|
|
341
|
+
catch {
|
|
342
|
+
return true;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* The `pki` encrypter instance, registered by CryptoService
|
|
348
|
+
*/
|
|
349
|
+
export const pkiEncrypter = new PkiEncrypter();
|
|
350
|
+
//# sourceMappingURL=pki.encrypter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pki.encrypter.js","sourceRoot":"","sources":["../../src/services/pki.encrypter.ts"],"names":[],"mappings":"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"}
|