@webda/core 4.0.0-beta.5 → 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 +18 -6
- 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 +19 -0
- package/lib/bin/cli.d.ts.map +1 -1
- package/lib/bin/cli.js +120 -41
- 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 +21 -2
- package/lib/core/core.d.ts.map +1 -1
- package/lib/core/core.js +87 -24
- 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/deployers/packager.d.ts +38 -0
- package/lib/deployers/packager.d.ts.map +1 -1
- package/lib/deployers/packager.js +70 -18
- package/lib/deployers/packager.js.map +1 -1
- package/lib/deployers/packager.service.d.ts +33 -0
- package/lib/deployers/packager.service.d.ts.map +1 -0
- package/lib/deployers/packager.service.js +112 -0
- package/lib/deployers/packager.service.js.map +1 -0
- 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 +7 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +6 -0
- package/lib/index.js.map +1 -1
- package/lib/models/permissions.d.ts +12 -1
- package/lib/models/permissions.d.ts.map +1 -1
- package/lib/models/permissions.js +29 -2
- package/lib/models/permissions.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/audit.model.d.ts.map +1 -1
- package/lib/services/audit.model.js +7 -3
- package/lib/services/audit.model.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 +8 -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/stores/store.d.ts +20 -1
- package/lib/stores/store.d.ts.map +1 -1
- package/lib/stores/store.js +29 -1
- package/lib/stores/store.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 +15 -15
- package/webda.module.json +224 -50
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { JSONSchema7 } from "json-schema";
|
|
2
|
+
import { type DeploymentUnit } from "../application/deployment.js";
|
|
3
|
+
/**
|
|
4
|
+
* JSON Schema keyword marking a configuration value that must be encrypted
|
|
5
|
+
*
|
|
6
|
+
* Written by the compiler for a property typed with `SecretString` or tagged `@secret`:
|
|
7
|
+
* - `true`: the whole value, every string below it
|
|
8
|
+
* - a list of names: only these children of the object, a name can be a dotted path
|
|
9
|
+
* and the arrays on the way are traversed (`users.token`)
|
|
10
|
+
*/
|
|
11
|
+
export declare const SECRET_KEYWORD = "x-webda-secret";
|
|
12
|
+
/**
|
|
13
|
+
* Encrypter of the values kept in clear text on purpose: `crypt:none:<value>`
|
|
14
|
+
*/
|
|
15
|
+
export declare const OPT_OUT_ENCRYPTER = "none";
|
|
16
|
+
/**
|
|
17
|
+
* A secret configuration value that is not encrypted
|
|
18
|
+
*
|
|
19
|
+
* It never holds the value itself.
|
|
20
|
+
*/
|
|
21
|
+
export interface SecretFinding {
|
|
22
|
+
/**
|
|
23
|
+
* Configuration path of the value, like `services.db.postgresqlServer.password`
|
|
24
|
+
*/
|
|
25
|
+
path: string;
|
|
26
|
+
/**
|
|
27
|
+
* Location of the value in the checked configuration object, like `["units", 0, "apiKey"]`
|
|
28
|
+
*/
|
|
29
|
+
location?: (string | number)[];
|
|
30
|
+
/**
|
|
31
|
+
* Service or deployment unit name
|
|
32
|
+
*/
|
|
33
|
+
service?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Service type
|
|
36
|
+
*/
|
|
37
|
+
type?: string;
|
|
38
|
+
/**
|
|
39
|
+
* - `plain`: written in clear text
|
|
40
|
+
* - `marked`: still `encrypt:` or `sencrypt:`, run `webda config encrypt`
|
|
41
|
+
* - `opted-out`: kept in clear text on purpose with `crypt:none:` or `scrypt:none:`
|
|
42
|
+
*/
|
|
43
|
+
reason: "plain" | "marked" | "opted-out";
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Format a configuration path: `services.db.keys[0]`
|
|
47
|
+
* @param path - the path segments
|
|
48
|
+
* @returns the formatted path
|
|
49
|
+
*/
|
|
50
|
+
export declare function formatSecretPath(path: (string | number)[]): string;
|
|
51
|
+
/**
|
|
52
|
+
* Find the secrets of a value that are not encrypted
|
|
53
|
+
*
|
|
54
|
+
* A schema node marked {@link SECRET_KEYWORD} must hold a `crypt:` or `scrypt:` string, or nothing.
|
|
55
|
+
* The findings never contain the values.
|
|
56
|
+
*
|
|
57
|
+
* @param value - the value, a service configuration for example
|
|
58
|
+
* @param schema - its schema
|
|
59
|
+
* @param root - the document holding the definitions, for `$ref`
|
|
60
|
+
* @param path - path of the value, prefixed to the findings
|
|
61
|
+
* @returns the findings
|
|
62
|
+
*/
|
|
63
|
+
export declare function findUnencryptedSecrets(value: any, schema: JSONSchema7, root?: JSONSchema7, path?: (string | number)[]): SecretFinding[];
|
|
64
|
+
/**
|
|
65
|
+
* Parse the patterns of the secret paths to exclude
|
|
66
|
+
*
|
|
67
|
+
* A pattern uses the path syntax of the findings, `$.` prefix optional: `*` matches one name or index
|
|
68
|
+
* (`units[*].auth.pass`), `**` matches anything, and a pattern also excludes the values below it
|
|
69
|
+
* (`services.demo`).
|
|
70
|
+
*
|
|
71
|
+
* @param patterns - the patterns, a comma-separated string or a list
|
|
72
|
+
* @returns a function telling whether a finding path is excluded
|
|
73
|
+
*/
|
|
74
|
+
export declare function secretPathExcluder(patterns?: string | string[]): (path: string) => boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Configuration to check: an application configuration, a deployment, or both merged
|
|
77
|
+
*/
|
|
78
|
+
export interface SecretsCheckConfiguration {
|
|
79
|
+
/**
|
|
80
|
+
* Services configuration
|
|
81
|
+
*/
|
|
82
|
+
services?: Record<string, any>;
|
|
83
|
+
/**
|
|
84
|
+
* Global parameters, merged into every service
|
|
85
|
+
*/
|
|
86
|
+
parameters?: Record<string, any>;
|
|
87
|
+
/**
|
|
88
|
+
* Parameters shared by the deployment units
|
|
89
|
+
*/
|
|
90
|
+
resources?: Record<string, any>;
|
|
91
|
+
/**
|
|
92
|
+
* Deployment units
|
|
93
|
+
*/
|
|
94
|
+
units?: DeploymentUnit[];
|
|
95
|
+
}
|
|
96
|
+
/**
|
|
97
|
+
* Find the unencrypted secrets of a configuration
|
|
98
|
+
*
|
|
99
|
+
* Each service is checked against the schema of its type, with the global parameters it inherits:
|
|
100
|
+
* a secret written in `parameters` is reported once, under `parameters`. The deployment units are
|
|
101
|
+
* checked with the `resources` they inherit, reported under `resources`.
|
|
102
|
+
*
|
|
103
|
+
* @param configuration - the configuration to check
|
|
104
|
+
* @param options - how to find the schemas
|
|
105
|
+
* @param options.getSchema - the schema of a service type
|
|
106
|
+
* @param options.completeNamespace - add the namespace to a service type
|
|
107
|
+
* @param options.getType - the type of a service without one, from the application configuration
|
|
108
|
+
* @param options.inheritingServices - other services inheriting `parameters`, defined in another file
|
|
109
|
+
* @returns the findings, and the service types without schema
|
|
110
|
+
*/
|
|
111
|
+
export declare function findConfigurationSecrets(configuration: SecretsCheckConfiguration, options: {
|
|
112
|
+
getSchema: (type: string) => JSONSchema7 | undefined;
|
|
113
|
+
completeNamespace?: (type: string) => string;
|
|
114
|
+
getType?: (service: string) => string | undefined;
|
|
115
|
+
inheritingServices?: Record<string, any>;
|
|
116
|
+
}): {
|
|
117
|
+
findings: SecretFinding[];
|
|
118
|
+
unknownTypes: string[];
|
|
119
|
+
};
|
|
120
|
+
//# sourceMappingURL=secretscheck.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secretscheck.d.ts","sourceRoot":"","sources":["../../src/services/secretscheck.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAA6B,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAE9F;;;;;;;GAOG;AACH,eAAO,MAAM,cAAc,mBAAmB,CAAC;AAE/C;;GAEG;AACH,eAAO,MAAM,iBAAiB,SAAS,CAAC;AAExC;;;;GAIG;AACH,MAAM,WAAW,aAAa;IAC5B;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;OAEG;IACH,QAAQ,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAC/B;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;OAIG;IACH,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,WAAW,CAAC;CAC1C;AA4BD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,MAAM,CAOlE;AAqKD;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CACpC,KAAK,EAAE,GAAG,EACV,MAAM,EAAE,WAAW,EACnB,IAAI,GAAE,WAAoB,EAC1B,IAAI,GAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAO,GAC7B,aAAa,EAAE,CAEjB;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,GAAE,MAAM,GAAG,MAAM,EAAO,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAmB9F;AAmBD;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC/B;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACjC;;OAEG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAChC;;OAEG;IACH,KAAK,CAAC,EAAE,cAAc,EAAE,CAAC;CAC1B;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,wBAAwB,CACtC,aAAa,EAAE,yBAAyB,EACxC,OAAO,EAAE;IACP,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,WAAW,GAAG,SAAS,CAAC;IACrD,iBAAiB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;IAC7C,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;IAClD,kBAAkB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC1C,GACA;IAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;IAAC,YAAY,EAAE,MAAM,EAAE,CAAA;CAAE,CA6DvD"}
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
import { getDeploymentUnitServices } from "../application/deployment.js";
|
|
2
|
+
/**
|
|
3
|
+
* JSON Schema keyword marking a configuration value that must be encrypted
|
|
4
|
+
*
|
|
5
|
+
* Written by the compiler for a property typed with `SecretString` or tagged `@secret`:
|
|
6
|
+
* - `true`: the whole value, every string below it
|
|
7
|
+
* - a list of names: only these children of the object, a name can be a dotted path
|
|
8
|
+
* and the arrays on the way are traversed (`users.token`)
|
|
9
|
+
*/
|
|
10
|
+
export const SECRET_KEYWORD = "x-webda-secret";
|
|
11
|
+
/**
|
|
12
|
+
* Encrypter of the values kept in clear text on purpose: `crypt:none:<value>`
|
|
13
|
+
*/
|
|
14
|
+
export const OPT_OUT_ENCRYPTER = "none";
|
|
15
|
+
/**
|
|
16
|
+
* Limit of `$ref` followed without going down the value, protects from a reference cycle
|
|
17
|
+
*/
|
|
18
|
+
const MAX_REF_DEPTH = 32;
|
|
19
|
+
/**
|
|
20
|
+
* Check if a value is a plain object, class instances are not
|
|
21
|
+
* @param value - the value to test
|
|
22
|
+
* @returns true for a plain object
|
|
23
|
+
*/
|
|
24
|
+
function isPlainObject(value) {
|
|
25
|
+
if (value === null || typeof value !== "object") {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
const proto = Object.getPrototypeOf(value);
|
|
29
|
+
return proto === Object.prototype || proto === null;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Format a configuration path: `services.db.keys[0]`
|
|
33
|
+
* @param path - the path segments
|
|
34
|
+
* @returns the formatted path
|
|
35
|
+
*/
|
|
36
|
+
export function formatSecretPath(path) {
|
|
37
|
+
return path.reduce((res, segment) => {
|
|
38
|
+
if (typeof segment === "number") {
|
|
39
|
+
return `${res}[${segment}]`;
|
|
40
|
+
}
|
|
41
|
+
return res ? `${res}.${segment}` : segment;
|
|
42
|
+
}, "");
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Classify a secret value
|
|
46
|
+
*
|
|
47
|
+
* `crypt:` and `scrypt:` values are encrypted, except the opted-out `crypt:none:` ones. Unset values (`""`,
|
|
48
|
+
* `null`, `undefined`) are allowed: the service then falls back to its environment.
|
|
49
|
+
*
|
|
50
|
+
* @param value - the secret value
|
|
51
|
+
* @returns the reason it fails, or undefined when it is fine
|
|
52
|
+
*/
|
|
53
|
+
function classify(value) {
|
|
54
|
+
if (typeof value !== "string" || value === "") {
|
|
55
|
+
return undefined;
|
|
56
|
+
}
|
|
57
|
+
if (value.startsWith(`crypt:${OPT_OUT_ENCRYPTER}:`) || value.startsWith(`scrypt:${OPT_OUT_ENCRYPTER}:`)) {
|
|
58
|
+
return "opted-out";
|
|
59
|
+
}
|
|
60
|
+
if (/^s?crypt:/.test(value)) {
|
|
61
|
+
return undefined;
|
|
62
|
+
}
|
|
63
|
+
return /^s?encrypt:/.test(value) ? "marked" : "plain";
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Check a secret value: a string, or every string below an object or an array
|
|
67
|
+
* @param value - the secret value
|
|
68
|
+
* @param path - its path
|
|
69
|
+
* @param findings - collected findings
|
|
70
|
+
*/
|
|
71
|
+
function checkLeaves(value, path, findings) {
|
|
72
|
+
if (Array.isArray(value)) {
|
|
73
|
+
value.forEach((item, index) => checkLeaves(item, [...path, index], findings));
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (isPlainObject(value)) {
|
|
77
|
+
for (const [key, item] of Object.entries(value)) {
|
|
78
|
+
checkLeaves(item, [...path, key], findings);
|
|
79
|
+
}
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const reason = classify(value);
|
|
83
|
+
if (reason) {
|
|
84
|
+
findings.push({ path, reason });
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check the children of a value listed by a scoped secret marker
|
|
89
|
+
* @param value - the value holding the children
|
|
90
|
+
* @param segments - the remaining segments of the child name
|
|
91
|
+
* @param path - path of the value
|
|
92
|
+
* @param findings - collected findings
|
|
93
|
+
*/
|
|
94
|
+
function checkScoped(value, segments, path, findings) {
|
|
95
|
+
if (Array.isArray(value)) {
|
|
96
|
+
value.forEach((item, index) => checkScoped(item, segments, [...path, index], findings));
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
if (segments.length === 0) {
|
|
100
|
+
checkLeaves(value, path, findings);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
// A string where an object is expected (a file path for example) holds no listed child
|
|
104
|
+
if (isPlainObject(value) && value[segments[0]] !== undefined) {
|
|
105
|
+
checkScoped(value[segments[0]], segments.slice(1), [...path, segments[0]], findings);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Resolve a `#/definitions/...` reference
|
|
110
|
+
* @param ref - the reference
|
|
111
|
+
* @param root - the document holding the definitions
|
|
112
|
+
* @returns the referenced schema
|
|
113
|
+
*/
|
|
114
|
+
function resolveRef(ref, root) {
|
|
115
|
+
if (!ref.startsWith("#/")) {
|
|
116
|
+
return undefined;
|
|
117
|
+
}
|
|
118
|
+
let target = root;
|
|
119
|
+
for (const segment of ref.substring(2).split("/")) {
|
|
120
|
+
target = target?.[decodeURIComponent(segment).replace(/~1/g, "/").replace(/~0/g, "~")];
|
|
121
|
+
}
|
|
122
|
+
return typeof target === "object" ? target : undefined;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Walk a value with its schema and collect the secrets that are not encrypted
|
|
126
|
+
* @param value - the value
|
|
127
|
+
* @param schema - its schema
|
|
128
|
+
* @param root - the document, for `$ref`
|
|
129
|
+
* @param path - path of the value
|
|
130
|
+
* @param findings - collected findings
|
|
131
|
+
* @param refDepth - `$ref` followed since the value last changed
|
|
132
|
+
*/
|
|
133
|
+
function walk(value, schema, root, path, findings, refDepth = 0) {
|
|
134
|
+
if (value === undefined || value === null || !schema || typeof schema !== "object") {
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const marker = schema[SECRET_KEYWORD];
|
|
138
|
+
if (marker === true) {
|
|
139
|
+
checkLeaves(value, path, findings);
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
if (Array.isArray(marker)) {
|
|
143
|
+
for (const name of marker) {
|
|
144
|
+
checkScoped(value, String(name).split("."), path, findings);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
if (schema.$ref && refDepth < MAX_REF_DEPTH) {
|
|
148
|
+
walk(value, resolveRef(schema.$ref, root), root, path, findings, refDepth + 1);
|
|
149
|
+
}
|
|
150
|
+
for (const branch of [...(schema.anyOf ?? []), ...(schema.oneOf ?? []), ...(schema.allOf ?? [])]) {
|
|
151
|
+
walk(value, branch, root, path, findings, refDepth + 1);
|
|
152
|
+
}
|
|
153
|
+
if (Array.isArray(value)) {
|
|
154
|
+
value.forEach((item, index) => {
|
|
155
|
+
const items = Array.isArray(schema.items) ? schema.items[index] : schema.items;
|
|
156
|
+
walk(item, items, root, [...path, index], findings);
|
|
157
|
+
});
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
if (isPlainObject(value)) {
|
|
161
|
+
for (const [key, item] of Object.entries(value)) {
|
|
162
|
+
const child = schema.properties?.[key] ?? schema.additionalProperties;
|
|
163
|
+
walk(item, child, root, [...path, key], findings);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Collect the secrets of a value that are not encrypted, with their path in segments
|
|
169
|
+
* @param value - the value
|
|
170
|
+
* @param schema - its schema
|
|
171
|
+
* @param root - the document, for `$ref`
|
|
172
|
+
* @param path - path of the value
|
|
173
|
+
* @returns the findings, each path once
|
|
174
|
+
*/
|
|
175
|
+
function collect(value, schema, root = schema, path = []) {
|
|
176
|
+
const findings = [];
|
|
177
|
+
walk(value, schema, root, path, findings);
|
|
178
|
+
// A value can be reached through several branches or markers
|
|
179
|
+
const seen = new Set();
|
|
180
|
+
return findings.filter(finding => {
|
|
181
|
+
const key = JSON.stringify(finding.path);
|
|
182
|
+
if (seen.has(key)) {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
seen.add(key);
|
|
186
|
+
return true;
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Find the secrets of a value that are not encrypted
|
|
191
|
+
*
|
|
192
|
+
* A schema node marked {@link SECRET_KEYWORD} must hold a `crypt:` or `scrypt:` string, or nothing.
|
|
193
|
+
* The findings never contain the values.
|
|
194
|
+
*
|
|
195
|
+
* @param value - the value, a service configuration for example
|
|
196
|
+
* @param schema - its schema
|
|
197
|
+
* @param root - the document holding the definitions, for `$ref`
|
|
198
|
+
* @param path - path of the value, prefixed to the findings
|
|
199
|
+
* @returns the findings
|
|
200
|
+
*/
|
|
201
|
+
export function findUnencryptedSecrets(value, schema, root = schema, path = []) {
|
|
202
|
+
return collect(value, schema, root, path).map(({ path, reason }) => ({ path: formatSecretPath(path), reason }));
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Parse the patterns of the secret paths to exclude
|
|
206
|
+
*
|
|
207
|
+
* A pattern uses the path syntax of the findings, `$.` prefix optional: `*` matches one name or index
|
|
208
|
+
* (`units[*].auth.pass`), `**` matches anything, and a pattern also excludes the values below it
|
|
209
|
+
* (`services.demo`).
|
|
210
|
+
*
|
|
211
|
+
* @param patterns - the patterns, a comma-separated string or a list
|
|
212
|
+
* @returns a function telling whether a finding path is excluded
|
|
213
|
+
*/
|
|
214
|
+
export function secretPathExcluder(patterns = []) {
|
|
215
|
+
const list = (typeof patterns === "string" ? patterns.split(",") : patterns)
|
|
216
|
+
.map(pattern => pattern.trim().replace(/^\$\.?/, ""))
|
|
217
|
+
.filter(pattern => pattern !== "");
|
|
218
|
+
const expressions = list.map(pattern => {
|
|
219
|
+
let source = "";
|
|
220
|
+
for (let i = 0; i < pattern.length; i++) {
|
|
221
|
+
if (pattern.startsWith("**", i)) {
|
|
222
|
+
source += ".*";
|
|
223
|
+
i++;
|
|
224
|
+
}
|
|
225
|
+
else if (pattern[i] === "*") {
|
|
226
|
+
source += "[^.\\[\\]]+";
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
source += pattern[i].replace(/[.+?^${}()|[\]\\]/g, "\\$&");
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return new RegExp(`^${source}(?:[.[].*)?$`);
|
|
233
|
+
});
|
|
234
|
+
return path => expressions.some(expression => expression.test(path));
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Check if a structure holds a value at a path
|
|
238
|
+
* @param data - the structure
|
|
239
|
+
* @param path - the path
|
|
240
|
+
* @returns true when the value is defined
|
|
241
|
+
*/
|
|
242
|
+
function hasPath(data, path) {
|
|
243
|
+
let target = data;
|
|
244
|
+
for (const segment of path) {
|
|
245
|
+
if (target === null || typeof target !== "object" || target[segment] === undefined) {
|
|
246
|
+
return false;
|
|
247
|
+
}
|
|
248
|
+
target = target[segment];
|
|
249
|
+
}
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
/**
|
|
253
|
+
* Find the unencrypted secrets of a configuration
|
|
254
|
+
*
|
|
255
|
+
* Each service is checked against the schema of its type, with the global parameters it inherits:
|
|
256
|
+
* a secret written in `parameters` is reported once, under `parameters`. The deployment units are
|
|
257
|
+
* checked with the `resources` they inherit, reported under `resources`.
|
|
258
|
+
*
|
|
259
|
+
* @param configuration - the configuration to check
|
|
260
|
+
* @param options - how to find the schemas
|
|
261
|
+
* @param options.getSchema - the schema of a service type
|
|
262
|
+
* @param options.completeNamespace - add the namespace to a service type
|
|
263
|
+
* @param options.getType - the type of a service without one, from the application configuration
|
|
264
|
+
* @param options.inheritingServices - other services inheriting `parameters`, defined in another file
|
|
265
|
+
* @returns the findings, and the service types without schema
|
|
266
|
+
*/
|
|
267
|
+
export function findConfigurationSecrets(configuration, options) {
|
|
268
|
+
const completeNamespace = options.completeNamespace ?? (type => type);
|
|
269
|
+
const findings = [];
|
|
270
|
+
const unknownTypes = new Set();
|
|
271
|
+
const reported = new Set();
|
|
272
|
+
const report = (finding) => {
|
|
273
|
+
if (reported.has(finding.path))
|
|
274
|
+
return;
|
|
275
|
+
reported.add(finding.path);
|
|
276
|
+
findings.push(finding);
|
|
277
|
+
};
|
|
278
|
+
const check = (name, type, own, merged, ownLocation, ownPrefix, inheritedPrefix) => {
|
|
279
|
+
const schema = options.getSchema(type);
|
|
280
|
+
if (!schema) {
|
|
281
|
+
unknownTypes.add(type);
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
for (const { path, reason } of collect(merged, schema)) {
|
|
285
|
+
const inherited = !hasPath(own, path);
|
|
286
|
+
report({
|
|
287
|
+
path: formatSecretPath([...(inherited ? [inheritedPrefix] : ownPrefix), ...path]),
|
|
288
|
+
location: [...(inherited ? [inheritedPrefix] : ownLocation), ...path],
|
|
289
|
+
service: name,
|
|
290
|
+
type,
|
|
291
|
+
reason
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
};
|
|
295
|
+
const parameters = configuration.parameters ?? {};
|
|
296
|
+
const services = configuration.services ?? {};
|
|
297
|
+
for (const [name, service] of Object.entries(services)) {
|
|
298
|
+
if (!isPlainObject(service))
|
|
299
|
+
continue;
|
|
300
|
+
const type = completeNamespace(service.type ?? options.getType?.(name) ?? name);
|
|
301
|
+
check(name, type, service, { ...parameters, ...service }, ["services", name], ["services", name], "parameters");
|
|
302
|
+
}
|
|
303
|
+
// The parameters also reach the services of the other files, unless they set the same key
|
|
304
|
+
for (const [name, service] of Object.entries(options.inheritingServices ?? {})) {
|
|
305
|
+
if (!isPlainObject(service) || services[name] !== undefined)
|
|
306
|
+
continue;
|
|
307
|
+
const type = completeNamespace(service.type ?? name);
|
|
308
|
+
const inherited = Object.fromEntries(Object.entries(parameters).filter(([key]) => service[key] === undefined));
|
|
309
|
+
check(name, type, {}, inherited, ["services", name], ["services", name], "parameters");
|
|
310
|
+
}
|
|
311
|
+
const units = configuration.units ?? [];
|
|
312
|
+
if (units.length) {
|
|
313
|
+
const merged = getDeploymentUnitServices({ units, resources: configuration.resources }, completeNamespace);
|
|
314
|
+
units.forEach((unit, index) => {
|
|
315
|
+
const { name, type: _type, ...own } = unit;
|
|
316
|
+
const { type, ...service } = merged[name];
|
|
317
|
+
check(name, type, own, service, ["units", index], [`units[${name}]`], "resources");
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
return { findings, unknownTypes: [...unknownTypes] };
|
|
321
|
+
}
|
|
322
|
+
//# sourceMappingURL=secretscheck.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"secretscheck.js","sourceRoot":"","sources":["../../src/services/secretscheck.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,yBAAyB,EAAuB,MAAM,8BAA8B,CAAC;AAE9F;;;;;;;GAOG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,gBAAgB,CAAC;AAE/C;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,MAAM,CAAC;AAwCxC;;GAEG;AACH,MAAM,aAAa,GAAG,EAAE,CAAC;AAEzB;;;;GAIG;AACH,SAAS,aAAa,CAAC,KAAU;IAC/B,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAC3C,OAAO,KAAK,KAAK,MAAM,CAAC,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC;AACtD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAyB;IACxD,OAAO,IAAI,CAAC,MAAM,CAAS,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE;QAC1C,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;YAChC,OAAO,GAAG,GAAG,IAAI,OAAO,GAAG,CAAC;QAC9B,CAAC;QACD,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,OAAO,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;IAC7C,CAAC,EAAE,EAAE,CAAC,CAAC;AACT,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,QAAQ,CAAC,KAAU;IAC1B,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,EAAE,EAAE,CAAC;QAC9C,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,KAAK,CAAC,UAAU,CAAC,SAAS,iBAAiB,GAAG,CAAC,IAAI,KAAK,CAAC,UAAU,CAAC,UAAU,iBAAiB,GAAG,CAAC,EAAE,CAAC;QACxG,OAAO,WAAW,CAAC;IACrB,CAAC;IACD,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5B,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,OAAO,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;AACxD,CAAC;AAED;;;;;GAKG;AACH,SAAS,WAAW,CAAC,KAAU,EAAE,IAAyB,EAAE,QAAsB;IAChF,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;QAC9E,OAAO;IACT,CAAC;IACD,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAChD,WAAW,CAAC,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;QAC9C,CAAC;QACD,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC/B,IAAI,MAAM,EAAE,CAAC;QACX,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,SAAS,WAAW,CAAC,KAAU,EAAE,QAAkB,EAAE,IAAyB,EAAE,QAAsB;IACpG,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC;QACxF,OAAO;IACT,CAAC;IACD,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACnC,OAAO;IACT,CAAC;IACD,uFAAuF;IACvF,IAAI,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,SAAS,EAAE,CAAC;QAC7D,WAAW,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;IACvF,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAS,UAAU,CAAC,GAAW,EAAE,IAAiB;IAChD,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QAC1B,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,IAAI,MAAM,GAAQ,IAAI,CAAC;IACvB,KAAK,MAAM,OAAO,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QAClD,MAAM,GAAG,MAAM,EAAE,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IACzF,CAAC;IACD,OAAO,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;AACzD,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,IAAI,CACX,KAAU,EACV,MAAyC,EACzC,IAAiB,EACjB,IAAyB,EACzB,QAAsB,EACtB,QAAQ,GAAW,CAAC;IAEpB,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QACnF,OAAO;IACT,CAAC;IACD,MAAM,MAAM,GAAG,MAAM,CAAC,cAAc,CAAC,CAAC;IACtC,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACpB,WAAW,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QACnC,OAAO;IACT,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;YAC1B,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;IACD,IAAI,MAAM,CAAC,IAAI,IAAI,QAAQ,GAAG,aAAa,EAAE,CAAC;QAC5C,IAAI,CAAC,KAAK,EAAE,UAAU,CAAC,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC;IACjF,CAAC;IACD,KAAK,MAAM,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;QACjG,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC;IAC1D,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YAC5B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YAC/E,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,EAAE,QAAQ,CAAC,CAAC;QACtD,CAAC,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IACD,IAAI,aAAa,CAAC,KAAK,CAAC,EAAE,CAAC;QACzB,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YAChD,MAAM,KAAK,GAAG,MAAM,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,oBAAoB,CAAC;YACtE,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;QACpD,CAAC;IACH,CAAC;AACH,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,OAAO,CACd,KAAU,EACV,MAAmB,EACnB,IAAI,GAAgB,MAAM,EAC1B,IAAI,GAAwB,EAAE;IAE9B,MAAM,QAAQ,GAAiB,EAAE,CAAC;IAClC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC1C,6DAA6D;IAC7D,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,OAAO,QAAQ,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE;QAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAClB,OAAO,KAAK,CAAC;QACf,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,OAAO,IAAI,CAAC;IACd,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,sBAAsB,CACpC,KAAU,EACV,MAAmB,EACnB,IAAI,GAAgB,MAAM,EAC1B,IAAI,GAAwB,EAAE;IAE9B,OAAO,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;AAClH,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAAC,QAAQ,GAAsB,EAAE;IACjE,MAAM,IAAI,GAAG,CAAC,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;SACzE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;SACpD,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC;IACrC,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC,EAAE;QACrC,IAAI,MAAM,GAAG,EAAE,CAAC;QAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,IAAI,OAAO,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC;gBAChC,MAAM,IAAI,IAAI,CAAC;gBACf,CAAC,EAAE,CAAC;YACN,CAAC;iBAAM,IAAI,OAAO,CAAC,CAAC,CAAC,KAAK,GAAG,EAAE,CAAC;gBAC9B,MAAM,IAAI,aAAa,CAAC;YAC1B,CAAC;iBAAM,CAAC;gBACN,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,oBAAoB,EAAE,MAAM,CAAC,CAAC;YAC7D,CAAC;QACH,CAAC;QACD,OAAO,IAAI,MAAM,CAAC,IAAI,MAAM,cAAc,CAAC,CAAC;IAC9C,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC,EAAE,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;AACvE,CAAC;AAED;;;;;GAKG;AACH,SAAS,OAAO,CAAC,IAAS,EAAE,IAAyB;IACnD,IAAI,MAAM,GAAG,IAAI,CAAC;IAClB,KAAK,MAAM,OAAO,IAAI,IAAI,EAAE,CAAC;QAC3B,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,SAAS,EAAE,CAAC;YACnF,OAAO,KAAK,CAAC;QACf,CAAC;QACD,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAwBD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,wBAAwB,CACtC,aAAwC,EACxC,OAKC;IAED,MAAM,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC;IACtE,MAAM,QAAQ,GAAoB,EAAE,CAAC;IACrC,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;IACvC,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAU,CAAC;IACnC,MAAM,MAAM,GAAG,CAAC,OAAsB,EAAE,EAAE;QACxC,IAAI,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC;YAAE,OAAO;QACvC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3B,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC,CAAC;IACF,MAAM,KAAK,GAAG,CACZ,IAAY,EACZ,IAAY,EACZ,GAAwB,EACxB,MAA2B,EAC3B,WAAgC,EAChC,SAA8B,EAC9B,eAAuB,EACvB,EAAE;QACF,MAAM,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YACvB,OAAO;QACT,CAAC;QACD,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC;YACvD,MAAM,SAAS,GAAG,CAAC,OAAO,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;YACtC,MAAM,CAAC;gBACL,IAAI,EAAE,gBAAgB,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,EAAE,GAAG,IAAI,CAAC,CAAC;gBACjF,QAAQ,EAAE,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,EAAE,GAAG,IAAI,CAAC;gBACrE,OAAO,EAAE,IAAI;gBACb,IAAI;gBACJ,MAAM;aACP,CAAC,CAAC;QACL,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,UAAU,GAAG,aAAa,CAAC,UAAU,IAAI,EAAE,CAAC;IAClD,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ,IAAI,EAAE,CAAC;IAC9C,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC;QACvD,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;YAAE,SAAS;QACtC,MAAM,IAAI,GAAG,iBAAiB,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;QAChF,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,GAAG,UAAU,EAAE,GAAG,OAAO,EAAE,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,YAAY,CAAC,CAAC;IAClH,CAAC;IACD,0FAA0F;IAC1F,KAAK,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,kBAAkB,IAAI,EAAE,CAAC,EAAE,CAAC;QAC/E,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,QAAQ,CAAC,IAAI,CAAC,KAAK,SAAS;YAAE,SAAS;QACtE,MAAM,IAAI,GAAG,iBAAiB,CAAC,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC;QAC/G,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,YAAY,CAAC,CAAC;IACzF,CAAC;IAED,MAAM,KAAK,GAAG,aAAa,CAAC,KAAK,IAAI,EAAE,CAAC;IACxC,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC;QACjB,MAAM,MAAM,GAAG,yBAAyB,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,aAAa,CAAC,SAAS,EAAE,EAAE,iBAAiB,CAAC,CAAC;QAC3G,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;YAC5B,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,GAAG,EAAE,GAAG,IAAI,CAAC;YAC3C,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC1C,KAAK,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,CAAC,SAAS,IAAI,GAAG,CAAC,EAAE,WAAW,CAAC,CAAC;QACrF,CAAC,CAAC,CAAC;IACL,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,CAAC,GAAG,YAAY,CAAC,EAAE,CAAC;AACvD,CAAC"}
|
|
@@ -29,14 +29,16 @@ export interface ServiceCommandInfo {
|
|
|
29
29
|
/**
|
|
30
30
|
* Lifecycle phase declared by each service providing this command, in the
|
|
31
31
|
* same order as `services`. Values are one of:
|
|
32
|
+
* - `"application"`: service declared phase "application", a static method called without Core.
|
|
32
33
|
* - `"resolved"`: service declared phase "resolved" (e.g. via `@BuildCommand`).
|
|
33
34
|
* - `"initialized"`: service declared phase "initialized".
|
|
34
35
|
* - `undefined`: service did not declare a phase (treat as "initialized").
|
|
35
36
|
*
|
|
36
37
|
* The CLI dispatcher uses this to decide whether to skip `Core.init()`:
|
|
37
|
-
* all-"resolved" → resolve-only; all-"initialized"/undefined → full init;
|
|
38
|
+
* all-"application" → no Core; all-"resolved" → resolve-only; all-"initialized"/undefined → full init;
|
|
39
|
+
* mixed → error.
|
|
38
40
|
*/
|
|
39
|
-
phases: Array<"resolved" | "initialized" | undefined>;
|
|
41
|
+
phases: Array<"application" | "resolved" | "initialized" | undefined>;
|
|
40
42
|
}
|
|
41
43
|
/**
|
|
42
44
|
* Collect all CLI commands declared by services across all loaded modules.
|
|
@@ -73,14 +75,16 @@ export declare function collectServiceCommands(app: Application): {
|
|
|
73
75
|
* (supports suffix matching).
|
|
74
76
|
*
|
|
75
77
|
* Each service's command handler is called with the parsed arguments as
|
|
76
|
-
* positional parameters.
|
|
78
|
+
* positional parameters. A handler returning a number sets the exit code: the
|
|
79
|
+
* highest one wins, any other result counts as `0`.
|
|
77
80
|
*
|
|
78
81
|
* @param cmdName - The command name to execute (e.g., `"serve"`, `"migrate"`)
|
|
79
82
|
* @param cmdInfo - The merged command definition from {@link collectServiceCommands}
|
|
80
83
|
* @param args - Parsed argument values keyed by argument name
|
|
81
84
|
* @param services - Map of service name to service instance (from Core.getServices())
|
|
82
85
|
* @param serviceFilter - Optional list of service names to filter to (supports suffix matching)
|
|
83
|
-
* @returns `0` on success, `1` if no services match the filter,
|
|
86
|
+
* @returns the highest exit code returned by the handlers (`0` on success), `1` if no services match the filter,
|
|
87
|
+
* a method is missing or no service instance ran
|
|
84
88
|
*
|
|
85
89
|
* @example
|
|
86
90
|
* ```typescript
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"servicecommands.d.ts","sourceRoot":"","sources":["../../src/services/servicecommands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAqB,MAAM,iBAAiB,CAAC;AAC/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGrD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,QAAQ,EAAE,oBAAoB,EAAE,CAAC;IACjC,oDAAoD;IACpD,IAAI,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CAAA;KAAE,CAAC;IAC/C,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB
|
|
1
|
+
{"version":3,"file":"servicecommands.d.ts","sourceRoot":"","sources":["../../src/services/servicecommands.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAqB,MAAM,iBAAiB,CAAC;AAC/E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AACjE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGrD;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,0EAA0E;IAC1E,QAAQ,EAAE,oBAAoB,EAAE,CAAC;IACjC,oDAAoD;IACpD,IAAI,EAAE;QAAE,CAAC,IAAI,EAAE,MAAM,GAAG,oBAAoB,CAAA;KAAE,CAAC;IAC/C,8EAA8E;IAC9E,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB;;;;;;;;;;;OAWG;IACH,MAAM,EAAE,KAAK,CAAC,aAAa,GAAG,UAAU,GAAG,aAAa,GAAG,SAAS,CAAC,CAAC;CACvE;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,WAAW,GAAG;IAAE,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,CAAA;CAAE,CAoC/F;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,kBAAkB,EAC3B,IAAI,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;CAAE,EAC5B,QAAQ,EAAE;IAAE,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,CAAA;CAAE,EAC5C,aAAa,CAAC,EAAE,MAAM,EAAE,GACvB,OAAO,CAAC,MAAM,CAAC,CAsFjB"}
|
|
@@ -67,14 +67,16 @@ export function collectServiceCommands(app) {
|
|
|
67
67
|
* (supports suffix matching).
|
|
68
68
|
*
|
|
69
69
|
* Each service's command handler is called with the parsed arguments as
|
|
70
|
-
* positional parameters.
|
|
70
|
+
* positional parameters. A handler returning a number sets the exit code: the
|
|
71
|
+
* highest one wins, any other result counts as `0`.
|
|
71
72
|
*
|
|
72
73
|
* @param cmdName - The command name to execute (e.g., `"serve"`, `"migrate"`)
|
|
73
74
|
* @param cmdInfo - The merged command definition from {@link collectServiceCommands}
|
|
74
75
|
* @param args - Parsed argument values keyed by argument name
|
|
75
76
|
* @param services - Map of service name to service instance (from Core.getServices())
|
|
76
77
|
* @param serviceFilter - Optional list of service names to filter to (supports suffix matching)
|
|
77
|
-
* @returns `0` on success, `1` if no services match the filter,
|
|
78
|
+
* @returns the highest exit code returned by the handlers (`0` on success), `1` if no services match the filter,
|
|
79
|
+
* a method is missing or no service instance ran
|
|
78
80
|
*
|
|
79
81
|
* @example
|
|
80
82
|
* ```typescript
|
|
@@ -95,6 +97,13 @@ export async function executeServiceCommand(cmdName, cmdInfo, args, services, se
|
|
|
95
97
|
const commandArgs = Object.keys(cmdInfo.args).map(argName => args[argName] !== undefined ? args[argName] : cmdInfo.args[argName].default);
|
|
96
98
|
// Count executed handlers: a command where every provider was skipped did nothing
|
|
97
99
|
let executed = 0;
|
|
100
|
+
// Highest exit code returned by a handler
|
|
101
|
+
let exitCode = 0;
|
|
102
|
+
const recordExitCode = (result) => {
|
|
103
|
+
if (typeof result === "number" && result > exitCode) {
|
|
104
|
+
exitCode = result;
|
|
105
|
+
}
|
|
106
|
+
};
|
|
98
107
|
// Long-running handlers (serve, worker) return a cancelable promise that stays
|
|
99
108
|
// pending while they run: start them all, then wait for every one to settle.
|
|
100
109
|
const running = [];
|
|
@@ -137,7 +146,7 @@ export async function executeServiceCommand(cmdName, cmdInfo, args, services, se
|
|
|
137
146
|
running.push(result);
|
|
138
147
|
}
|
|
139
148
|
else {
|
|
140
|
-
await result;
|
|
149
|
+
recordExitCode(await result);
|
|
141
150
|
}
|
|
142
151
|
executed++;
|
|
143
152
|
}
|
|
@@ -151,12 +160,12 @@ export async function executeServiceCommand(cmdName, cmdInfo, args, services, se
|
|
|
151
160
|
return 1;
|
|
152
161
|
}
|
|
153
162
|
// Cancelling a long-running command (SIGINT, SIGTERM) is a clean stop
|
|
154
|
-
await Promise.all(running.map(p => Promise.resolve(p).
|
|
163
|
+
await Promise.all(running.map(p => Promise.resolve(p).then(recordExitCode, err => {
|
|
155
164
|
if (err !== "Cancelled") {
|
|
156
165
|
throw err;
|
|
157
166
|
}
|
|
158
167
|
})));
|
|
159
|
-
return
|
|
168
|
+
return exitCode;
|
|
160
169
|
}
|
|
161
170
|
/**
|
|
162
171
|
* Whether a command handler returned a long-running cancelable promise
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"servicecommands.js","sourceRoot":"","sources":["../../src/services/servicecommands.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"servicecommands.js","sourceRoot":"","sources":["../../src/services/servicecommands.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type CryptoService } from "../services/cryptoservice.service.js";
|
|
2
2
|
import { JWTOptions } from "../services/icryptoservice.js";
|
|
3
3
|
import { Service } from "../services/service.js";
|
|
4
4
|
import { CookieOptions } from "./cookie.js";
|
|
@@ -51,6 +51,8 @@ export declare class SessionModel extends UuidModel {
|
|
|
51
51
|
export declare class CookieSessionParameters extends ServiceParameters {
|
|
52
52
|
/**
|
|
53
53
|
* Options for issue JWT token
|
|
54
|
+
*
|
|
55
|
+
* `secretOrPublicKey` can be encrypted with `webda config encrypt`
|
|
54
56
|
*/
|
|
55
57
|
jwt?: JWTOptions;
|
|
56
58
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"manager.model.d.ts","sourceRoot":"","sources":["../../src/session/manager.model.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"manager.model.d.ts","sourceRoot":"","sources":["../../src/session/manager.model.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,aAAa,EAAgB,MAAM,sCAAsC,CAAC;AACxF,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,EAAU,OAAO,EAAE,MAAM,wBAAwB,CAAC;AAEzD,OAAO,EAAE,aAAa,EAAgB,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAgB,MAAM,yBAAyB,CAAC;AAEhE,OAAO,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAGvC,OAAO,EAAE,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE5E;;GAEG;AACH,8BAAsB,cAAc,CAAC,CAAC,SAAS,iBAAiB,GAAG,iBAAiB,CAAE,SAAQ,OAAO,CAAC,CAAC,CAAC;IACtG;;;OAGG;IACH,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClD;;;;OAIG;IACH,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjE;;;;;OAKG;IACG,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAcrE;IAED;;;;;;;OAOG;IACH,UAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAY7D;CACF;AAED,2DAA2D;AAC3D,qBAAa,YAAa,SAAQ,SAAS;IACzC,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,GAAG,CAAC;IACb;;OAEG;IACH,YAAY,IAAI,EAAE,GAAG,EAIpB;CACF;AAED,sDAAsD;AACtD,qBAAa,uBAAwB,SAAQ,iBAAiB;IAC5D;;;;OAIG;IACH,GAAG,CAAC,EAAE,UAAU,CAAC;IACjB;;OAEG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;IAEvB;;;;OAIG;IACH,IAAI,CAAC,MAAM,GAAE,GAAQ,GAAG,IAAI,CAI3B;CACF;AAED;;;;;;;GAOG;AACH,qBAAa,oBAAoB,CAC/B,CAAC,SAAS,uBAAuB,GAAG,uBAAuB,CAC3D,SAAQ,cAAc,CAAC,CAAC,CAAC;IAEzB,aAAa,EAAE,aAAa,CAAC;IAE7B,YAAY,EAAE,UAAU,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC;IAEnD;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CA8B7C;IAED;;OAEG;IACG,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,iBAsC5C;CACF"}
|
|
@@ -32,6 +32,7 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
|
|
|
32
32
|
}
|
|
33
33
|
return useValue ? value : void 0;
|
|
34
34
|
};
|
|
35
|
+
import { SecretString } from "../services/cryptoservice.service.js";
|
|
35
36
|
import { Inject, Service } from "../services/service.js";
|
|
36
37
|
import { CookieOptions, SecureCookie } from "./cookie.js";
|
|
37
38
|
import { isWebContext } from "../contexts/icontext.js";
|
|
@@ -106,6 +107,8 @@ export class SessionModel extends UuidModel {
|
|
|
106
107
|
export class CookieSessionParameters extends ServiceParameters {
|
|
107
108
|
/**
|
|
108
109
|
* Options for issue JWT token
|
|
110
|
+
*
|
|
111
|
+
* `secretOrPublicKey` can be encrypted with `webda config encrypt`
|
|
109
112
|
*/
|
|
110
113
|
jwt;
|
|
111
114
|
/**
|
|
@@ -158,7 +161,7 @@ let CookieSessionManager = (() => {
|
|
|
158
161
|
return this.loadFromToken(context, authorization.substring(7).trim());
|
|
159
162
|
}
|
|
160
163
|
const session = new Session();
|
|
161
|
-
const cookie = await SecureCookie.load(this.parameters.cookie.name, session, context, this.parameters.jwt);
|
|
164
|
+
const cookie = await SecureCookie.load(this.parameters.cookie.name, session, context, SecretString.unwrap(this.parameters.jwt));
|
|
162
165
|
if (this.sessionModel) {
|
|
163
166
|
if (cookie.sub) {
|
|
164
167
|
Object.assign(session, (await this.sessionModel.get(cookie.sub))?.session);
|
|
@@ -201,10 +204,10 @@ let CookieSessionManager = (() => {
|
|
|
201
204
|
ttl: Date.now() + this.parameters.cookie.maxAge * 1000
|
|
202
205
|
});
|
|
203
206
|
}
|
|
204
|
-
SecureCookie.save(this.parameters.cookie.name, context, {}, { ...this.parameters.jwt, subject: session.uuid.toString() }, this.parameters.cookie);
|
|
207
|
+
SecureCookie.save(this.parameters.cookie.name, context, {}, SecretString.unwrap({ ...this.parameters.jwt, subject: session.uuid.toString() }), this.parameters.cookie);
|
|
205
208
|
return;
|
|
206
209
|
}
|
|
207
|
-
SecureCookie.save(this.parameters.cookie.name, context, session, this.parameters.jwt, this.parameters.cookie);
|
|
210
|
+
SecureCookie.save(this.parameters.cookie.name, context, session, SecretString.unwrap(this.parameters.jwt), this.parameters.cookie);
|
|
208
211
|
}
|
|
209
212
|
};
|
|
210
213
|
})();
|