@verdaccio/config 7.0.0-next-7.13 → 7.0.0-next-7.15
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/CHANGELOG.md +19 -0
- package/build/config.d.ts +13 -5
- package/build/config.js +70 -34
- package/build/config.js.map +1 -1
- package/build/security.js +2 -1
- package/build/security.js.map +1 -1
- package/build/token.d.ts +1 -0
- package/build/token.js +2 -0
- package/build/token.js.map +1 -1
- package/package.json +3 -3
- package/src/config.ts +79 -35
- package/src/security.ts +1 -0
- package/src/token.ts +2 -0
- package/test/config.spec.ts +70 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# @verdaccio/config
|
|
2
2
|
|
|
3
|
+
## 7.0.0-next-7.15
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- bd8703e: feat: add migrateToSecureLegacySignature and remove enhancedLegacySignature property
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [bd8703e]
|
|
12
|
+
- @verdaccio/core@7.0.0-next-7.15
|
|
13
|
+
- @verdaccio/utils@7.0.0-next-7.15
|
|
14
|
+
|
|
15
|
+
## 7.0.0-next-7.14
|
|
16
|
+
|
|
17
|
+
### Patch Changes
|
|
18
|
+
|
|
19
|
+
- @verdaccio/core@7.0.0-next-7.14
|
|
20
|
+
- @verdaccio/utils@7.0.0-next-7.14
|
|
21
|
+
|
|
3
22
|
## 7.0.0-next-7.13
|
|
4
23
|
|
|
5
24
|
### Patch Changes
|
package/build/config.d.ts
CHANGED
|
@@ -4,6 +4,7 @@ export declare const defaultUserRateLimiting: {
|
|
|
4
4
|
windowMs: number;
|
|
5
5
|
max: number;
|
|
6
6
|
};
|
|
7
|
+
export declare function isNodeVersionGreaterThan21(): boolean;
|
|
7
8
|
/**
|
|
8
9
|
* Coordinates the application configuration
|
|
9
10
|
*/
|
|
@@ -23,23 +24,30 @@ declare class Config implements AppConfig {
|
|
|
23
24
|
plugins: string | void | null;
|
|
24
25
|
security: Security;
|
|
25
26
|
serverSettings: ServerSettingsConf;
|
|
27
|
+
private configOverrideOptions;
|
|
26
28
|
secret: string;
|
|
27
29
|
flags: FlagsConfig;
|
|
28
30
|
userRateLimit: RateLimit;
|
|
29
|
-
private configOptions;
|
|
30
31
|
constructor(config: ConfigYaml & {
|
|
31
32
|
config_path: string;
|
|
32
|
-
},
|
|
33
|
-
|
|
33
|
+
}, configOverrideOptions?: {
|
|
34
|
+
forceMigrateToSecureLegacySignature: boolean;
|
|
34
35
|
});
|
|
35
|
-
|
|
36
|
+
getMigrateToSecureLegacySignature(): boolean;
|
|
36
37
|
getConfigPath(): string;
|
|
37
38
|
/**
|
|
38
39
|
* Check for package spec
|
|
39
40
|
*/
|
|
40
41
|
getMatchedPackagesSpec(pkgName: string): PackageAccess | void;
|
|
41
42
|
/**
|
|
42
|
-
*
|
|
43
|
+
* Verify if the secret complies with the required structure
|
|
44
|
+
* - If the secret is not provided, it will generate a new one
|
|
45
|
+
* - For any Node.js version the new secret will be 32 characters long (to allow compatibility with modern Node.js versions)
|
|
46
|
+
* - If the secret is provided:
|
|
47
|
+
* - If Node.js 22 or higher, the secret must be 32 characters long thus the application will fail on startup
|
|
48
|
+
* - If Node.js 21 or lower, the secret will be used as is but will display a deprecation warning
|
|
49
|
+
* - If the property `security.api.migrateToSecureLegacySignature` is provided and set to true, the secret will be
|
|
50
|
+
* generated with the new signature model
|
|
43
51
|
* @secret external secret key
|
|
44
52
|
*/
|
|
45
53
|
checkSecretKey(secret?: string): string;
|
package/build/config.js
CHANGED
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.defaultUserRateLimiting = exports.WEB_TITLE = exports.Config = void 0;
|
|
7
|
+
exports.isNodeVersionGreaterThan21 = isNodeVersionGreaterThan21;
|
|
7
8
|
var _assert = _interopRequireDefault(require("assert"));
|
|
8
9
|
var _debug = _interopRequireDefault(require("debug"));
|
|
9
10
|
var _lodash = _interopRequireDefault(require("lodash"));
|
|
@@ -28,6 +29,11 @@ const defaultUserRateLimiting = exports.defaultUserRateLimiting = {
|
|
|
28
29
|
// 15 minutes
|
|
29
30
|
max: 1000
|
|
30
31
|
};
|
|
32
|
+
function isNodeVersionGreaterThan21() {
|
|
33
|
+
const [major, minor] = process.versions.node.split('.').map(Number);
|
|
34
|
+
return major > 21 || major === 21 && minor >= 0;
|
|
35
|
+
}
|
|
36
|
+
const TOKEN_VALID_LENGTH = 32;
|
|
31
37
|
|
|
32
38
|
/**
|
|
33
39
|
* Coordinates the application configuration
|
|
@@ -44,12 +50,11 @@ class Config {
|
|
|
44
50
|
// allows switch a new legacy aes signature token signature
|
|
45
51
|
// for older versions do not want to have this new signature model
|
|
46
52
|
// this property must be false
|
|
47
|
-
|
|
48
|
-
|
|
53
|
+
configOverrideOptions = {
|
|
54
|
+
forceMigrateToSecureLegacySignature: true
|
|
49
55
|
}) {
|
|
50
56
|
var _config$flags$searchR, _config$flags, _config$flags$changeP, _config$flags2;
|
|
51
57
|
const self = this;
|
|
52
|
-
this.configOptions = configOptions;
|
|
53
58
|
this.storage = process.env.VERDACCIO_STORAGE_PATH || config.storage;
|
|
54
59
|
if (!config.configPath) {
|
|
55
60
|
var _config$config_path;
|
|
@@ -60,11 +65,18 @@ class Config {
|
|
|
60
65
|
throw new Error('configPath property is required');
|
|
61
66
|
}
|
|
62
67
|
}
|
|
68
|
+
this.configOverrideOptions = configOverrideOptions;
|
|
63
69
|
this.configPath = config.configPath;
|
|
64
70
|
this.self_path = this.configPath;
|
|
65
71
|
debug('config path: %s', this.configPath);
|
|
66
72
|
this.plugins = config.plugins;
|
|
67
|
-
this.security = _lodash.default.merge(
|
|
73
|
+
this.security = _lodash.default.merge(
|
|
74
|
+
// override the default security configuration via constructor
|
|
75
|
+
_lodash.default.merge(_security.defaultSecurity, {
|
|
76
|
+
api: {
|
|
77
|
+
migrateToSecureLegacySignature: this.configOverrideOptions.forceMigrateToSecureLegacySignature
|
|
78
|
+
}
|
|
79
|
+
}), config.security);
|
|
68
80
|
this.serverSettings = _serverSettings.default;
|
|
69
81
|
this.flags = {
|
|
70
82
|
searchRemote: (_config$flags$searchR = (_config$flags = config.flags) === null || _config$flags === void 0 ? void 0 : _config$flags.searchRemote) !== null && _config$flags$searchR !== void 0 ? _config$flags$searchR : true,
|
|
@@ -112,14 +124,8 @@ class Config {
|
|
|
112
124
|
this.server_id = (0, _utils.generateRandomHexString)(6);
|
|
113
125
|
}
|
|
114
126
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (this.security.enhancedLegacySignature === true) {
|
|
118
|
-
return true;
|
|
119
|
-
}
|
|
120
|
-
return false;
|
|
121
|
-
}
|
|
122
|
-
return this.configOptions.forceEnhancedLegacySignature;
|
|
127
|
+
getMigrateToSecureLegacySignature() {
|
|
128
|
+
return this.security.api.migrateToSecureLegacySignature;
|
|
123
129
|
}
|
|
124
130
|
getConfigPath() {
|
|
125
131
|
return this.configPath;
|
|
@@ -134,35 +140,65 @@ class Config {
|
|
|
134
140
|
}
|
|
135
141
|
|
|
136
142
|
/**
|
|
137
|
-
*
|
|
143
|
+
* Verify if the secret complies with the required structure
|
|
144
|
+
* - If the secret is not provided, it will generate a new one
|
|
145
|
+
* - For any Node.js version the new secret will be 32 characters long (to allow compatibility with modern Node.js versions)
|
|
146
|
+
* - If the secret is provided:
|
|
147
|
+
* - If Node.js 22 or higher, the secret must be 32 characters long thus the application will fail on startup
|
|
148
|
+
* - If Node.js 21 or lower, the secret will be used as is but will display a deprecation warning
|
|
149
|
+
* - If the property `security.api.migrateToSecureLegacySignature` is provided and set to true, the secret will be
|
|
150
|
+
* generated with the new signature model
|
|
138
151
|
* @secret external secret key
|
|
139
152
|
*/
|
|
140
153
|
checkSecretKey(secret) {
|
|
141
|
-
|
|
142
|
-
debug('check secret key');
|
|
154
|
+
debug('checking secret key init');
|
|
143
155
|
if (typeof secret === 'string' && _lodash.default.isEmpty(secret) === false) {
|
|
156
|
+
debug('checking secret key length %s', secret.length);
|
|
157
|
+
if (secret.length > TOKEN_VALID_LENGTH) {
|
|
158
|
+
if (isNodeVersionGreaterThan21()) {
|
|
159
|
+
debug('is node version greater than 21');
|
|
160
|
+
if (this.getMigrateToSecureLegacySignature() === true) {
|
|
161
|
+
this.secret = (0, _token.generateRandomSecretKey)();
|
|
162
|
+
debug('rewriting secret key with length %s', this.secret.length);
|
|
163
|
+
return this.secret;
|
|
164
|
+
}
|
|
165
|
+
// oops, user needs to generate a new secret key
|
|
166
|
+
debug('secret does not comply with the required length, current length %d, application will fail on startup', secret.length);
|
|
167
|
+
throw new Error(`Invalid storage secret key length, must be 32 characters long but is ${secret.length}.
|
|
168
|
+
The secret length in Node.js 22 or higher must be 32 characters long. Please consider generate a new one.
|
|
169
|
+
Learn more at https://verdaccio.org/docs/configuration/#.verdaccio-db`);
|
|
170
|
+
} else {
|
|
171
|
+
debug('is node version lower than 22');
|
|
172
|
+
if (this.getMigrateToSecureLegacySignature() === true) {
|
|
173
|
+
this.secret = (0, _token.generateRandomSecretKey)();
|
|
174
|
+
debug('rewriting secret key with length %s', this.secret.length);
|
|
175
|
+
return this.secret;
|
|
176
|
+
}
|
|
177
|
+
debug('triggering deprecation warning for secret key length %s', secret.length);
|
|
178
|
+
// still using Node.js versions previous to 22, but we need to emit a deprecation warning
|
|
179
|
+
// deprecation warning, secret key is too long and must be 32
|
|
180
|
+
// this will be removed in the next major release and will produce an error
|
|
181
|
+
_core.warningUtils.emit(_warningUtils.Codes.VERWAR007);
|
|
182
|
+
this.secret = secret;
|
|
183
|
+
return this.secret;
|
|
184
|
+
}
|
|
185
|
+
} else if (secret.length === TOKEN_VALID_LENGTH) {
|
|
186
|
+
debug('detected valid secret key length %s', secret.length);
|
|
187
|
+
this.secret = secret;
|
|
188
|
+
return this.secret;
|
|
189
|
+
}
|
|
190
|
+
debug('reusing previous key with length %s', secret.length);
|
|
144
191
|
this.secret = secret;
|
|
145
|
-
|
|
146
|
-
return secret;
|
|
147
|
-
}
|
|
148
|
-
// generate a new a secret key
|
|
149
|
-
// FUTURE: this might be an external secret key, perhaps within config file?
|
|
150
|
-
debug('generating a new secret key');
|
|
151
|
-
if (this.getEnhancedLegacySignature()) {
|
|
152
|
-
debug('key generated with "enhanced" legacy signature user config');
|
|
153
|
-
this.secret = (0, _token.generateRandomSecretKey)();
|
|
192
|
+
return this.secret;
|
|
154
193
|
} else {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
_core.warningUtils.emit(_warningUtils.Codes.VERWAR005);
|
|
194
|
+
var _this$secret;
|
|
195
|
+
// generate a new a secret key
|
|
196
|
+
// FUTURE: this might be an external secret key, perhaps within config file?
|
|
197
|
+
debug('generating a new secret key');
|
|
198
|
+
this.secret = (0, _token.generateRandomSecretKey)();
|
|
199
|
+
debug('generated a new secret key length %s', (_this$secret = this.secret) === null || _this$secret === void 0 ? void 0 : _this$secret.length);
|
|
200
|
+
return this.secret;
|
|
163
201
|
}
|
|
164
|
-
debug('generated a new secret key length %s', (_this$secret = this.secret) === null || _this$secret === void 0 ? void 0 : _this$secret.length);
|
|
165
|
-
return this.secret;
|
|
166
202
|
}
|
|
167
203
|
}
|
|
168
204
|
exports.Config = Config;
|
package/build/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","names":["_assert","_interopRequireDefault","require","_debug","_lodash","_core","_warningUtils","_utils","_agent","_packageAccess","_security","_serverSettings","_token","_uplinks","obj","__esModule","default","strategicConfigProps","allowedEnvConfig","debug","buildDebug","WEB_TITLE","exports","defaultUserRateLimiting","windowMs","max","Config","constructor","config","configOptions","forceEnhancedLegacySignature","_config$flags$searchR","_config$flags","_config$flags$changeP","_config$flags2","self","storage","process","env","VERDACCIO_STORAGE_PATH","configPath","_config$config_path","config_path","self_path","Error","plugins","security","_","merge","defaultSecurity","serverSettings","flags","searchRemote","changePassword","user_agent","configProp","getUserAgent","userRateLimit","assert","isObject","APP_ERROR","CONFIG_NOT_VALID","forEach","x","uplinks","sanityCheckUplinksProps","uplinkSanityCheck","packages","normalisePackageAccess","envConf","toUpperCase","server_id","generateRandomHexString","getEnhancedLegacySignature","enhancedLegacySignature","getConfigPath","getMatchedPackagesSpec","pkgName","checkSecretKey","secret","_this$security","_this$secret","isEmpty","generateRandomSecretKey","warningUtils","emit","Codes","VERWAR005","length"],"sources":["../src/config.ts"],"sourcesContent":["import assert from 'assert';\nimport buildDebug from 'debug';\nimport _ from 'lodash';\n\nimport { APP_ERROR, warningUtils } from '@verdaccio/core';\nimport { Codes } from '@verdaccio/core/build/warning-utils';\nimport {\n Config as AppConfig,\n AuthConf,\n ConfigYaml,\n FlagsConfig,\n PackageAccess,\n PackageList,\n RateLimit,\n Security,\n ServerSettingsConf,\n} from '@verdaccio/types';\nimport { generateRandomHexString, getMatchedPackagesSpec, isObject } from '@verdaccio/utils';\n\nimport { getUserAgent } from './agent';\nimport { normalisePackageAccess } from './package-access';\nimport { defaultSecurity } from './security';\nimport serverSettings from './serverSettings';\nimport { generateRandomSecretKey } from './token';\nimport { sanityCheckUplinksProps, uplinkSanityCheck } from './uplinks';\n\nconst strategicConfigProps = ['uplinks', 'packages'];\nconst allowedEnvConfig = ['http_proxy', 'https_proxy', 'no_proxy'];\nconst debug = buildDebug('verdaccio:config');\n\nexport const WEB_TITLE = 'Verdaccio';\n\n// we limit max 1000 request per 15 minutes on user endpoints\nexport const defaultUserRateLimiting = {\n windowMs: 15 * 60 * 1000, // 15 minutes\n max: 1000,\n};\n\n/**\n * Coordinates the application configuration\n */\nclass Config implements AppConfig {\n public user_agent: string | undefined;\n public uplinks: any;\n public packages: PackageList;\n public users: any;\n public auth: AuthConf;\n public server_id: string;\n public configPath: string;\n /**\n * @deprecated use configPath or config.getConfigPath();\n */\n public self_path: string;\n public storage: string | void;\n\n public plugins: string | void | null;\n public security: Security;\n public serverSettings: ServerSettingsConf;\n // @ts-ignore\n public secret: string;\n public flags: FlagsConfig;\n public userRateLimit: RateLimit;\n private configOptions: { forceEnhancedLegacySignature: boolean };\n public constructor(\n config: ConfigYaml & { config_path: string },\n // forceEnhancedLegacySignature is a property that\n // allows switch a new legacy aes signature token signature\n // for older versions do not want to have this new signature model\n // this property must be false\n configOptions = { forceEnhancedLegacySignature: true }\n ) {\n const self = this;\n this.configOptions = configOptions;\n this.storage = process.env.VERDACCIO_STORAGE_PATH || config.storage;\n if (!config.configPath) {\n // backport self_path for previous to version 6\n // @ts-expect-error\n config.configPath = config.config_path ?? config.self_path;\n if (!config.configPath) {\n throw new Error('configPath property is required');\n }\n }\n this.configPath = config.configPath;\n this.self_path = this.configPath;\n debug('config path: %s', this.configPath);\n this.plugins = config.plugins;\n this.security = _.merge(defaultSecurity, config.security);\n this.serverSettings = serverSettings;\n this.flags = {\n searchRemote: config.flags?.searchRemote ?? true,\n changePassword: config.flags?.changePassword ?? false,\n };\n this.user_agent = config.user_agent;\n\n for (const configProp in config) {\n if (self[configProp] == null) {\n self[configProp] = config[configProp];\n }\n }\n\n if (typeof this.user_agent === 'undefined') {\n // by default user agent is hidden\n debug('set default user agent');\n this.user_agent = getUserAgent(false);\n }\n\n this.userRateLimit = { ...defaultUserRateLimiting, ...config?.userRateLimit };\n\n // some weird shell scripts are valid yaml files parsed as string\n assert(_.isObject(config), APP_ERROR.CONFIG_NOT_VALID);\n\n // sanity check for strategic config properties\n strategicConfigProps.forEach(function (x): void {\n if (self[x] == null) {\n self[x] = {};\n }\n\n assert(isObject(self[x]), `CONFIG: bad \"${x}\" value (object expected)`);\n });\n\n this.uplinks = sanityCheckUplinksProps(uplinkSanityCheck(this.uplinks));\n this.packages = normalisePackageAccess(self.packages);\n\n // loading these from ENV if aren't in config\n allowedEnvConfig.forEach((envConf): void => {\n if (!(envConf in self)) {\n self[envConf] = process.env[envConf] || process.env[envConf.toUpperCase()];\n }\n });\n\n // unique identifier of self server (or a cluster), used to avoid loops\n // @ts-ignore\n if (!this.server_id) {\n this.server_id = generateRandomHexString(6);\n }\n }\n\n public getEnhancedLegacySignature() {\n if (typeof this?.security.enhancedLegacySignature !== 'undefined') {\n if (this.security.enhancedLegacySignature === true) {\n return true;\n }\n return false;\n }\n return this.configOptions.forceEnhancedLegacySignature;\n }\n\n public getConfigPath() {\n return this.configPath;\n }\n\n /**\n * Check for package spec\n */\n public getMatchedPackagesSpec(pkgName: string): PackageAccess | void {\n // TODO: remove this method and replace by library utils\n return getMatchedPackagesSpec(pkgName, this.packages);\n }\n\n /**\n * Store or create whether receive a secret key\n * @secret external secret key\n */\n public checkSecretKey(secret?: string): string {\n debug('check secret key');\n if (typeof secret === 'string' && _.isEmpty(secret) === false) {\n this.secret = secret;\n debug('reusing previous key');\n return secret;\n }\n // generate a new a secret key\n // FUTURE: this might be an external secret key, perhaps within config file?\n debug('generating a new secret key');\n\n if (this.getEnhancedLegacySignature()) {\n debug('key generated with \"enhanced\" legacy signature user config');\n this.secret = generateRandomSecretKey();\n } else {\n debug('key generated with legacy signature user config');\n this.secret = generateRandomHexString(32);\n }\n // set this to false allow use old token signature and is not recommended\n // only use for migration reasons, major release will remove this property and\n // set it by default\n if (this.security?.enhancedLegacySignature === false) {\n warningUtils.emit(Codes.VERWAR005);\n }\n\n debug('generated a new secret key length %s', this.secret?.length);\n return this.secret;\n }\n}\n\nexport { Config };\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"config.js","names":["_assert","_interopRequireDefault","require","_debug","_lodash","_core","_warningUtils","_utils","_agent","_packageAccess","_security","_serverSettings","_token","_uplinks","obj","__esModule","default","strategicConfigProps","allowedEnvConfig","debug","buildDebug","WEB_TITLE","exports","defaultUserRateLimiting","windowMs","max","isNodeVersionGreaterThan21","major","minor","process","versions","node","split","map","Number","TOKEN_VALID_LENGTH","Config","constructor","config","configOverrideOptions","forceMigrateToSecureLegacySignature","_config$flags$searchR","_config$flags","_config$flags$changeP","_config$flags2","self","storage","env","VERDACCIO_STORAGE_PATH","configPath","_config$config_path","config_path","self_path","Error","plugins","security","_","merge","defaultSecurity","api","migrateToSecureLegacySignature","serverSettings","flags","searchRemote","changePassword","user_agent","configProp","getUserAgent","userRateLimit","assert","isObject","APP_ERROR","CONFIG_NOT_VALID","forEach","x","uplinks","sanityCheckUplinksProps","uplinkSanityCheck","packages","normalisePackageAccess","envConf","toUpperCase","server_id","generateRandomHexString","getMigrateToSecureLegacySignature","getConfigPath","getMatchedPackagesSpec","pkgName","checkSecretKey","secret","isEmpty","length","generateRandomSecretKey","warningUtils","emit","Codes","VERWAR007","_this$secret"],"sources":["../src/config.ts"],"sourcesContent":["import assert from 'assert';\nimport buildDebug from 'debug';\nimport _ from 'lodash';\n\nimport { APP_ERROR, warningUtils } from '@verdaccio/core';\nimport { Codes } from '@verdaccio/core/build/warning-utils';\nimport {\n Config as AppConfig,\n AuthConf,\n ConfigYaml,\n FlagsConfig,\n PackageAccess,\n PackageList,\n RateLimit,\n Security,\n ServerSettingsConf,\n} from '@verdaccio/types';\nimport { generateRandomHexString, getMatchedPackagesSpec, isObject } from '@verdaccio/utils';\n\nimport { getUserAgent } from './agent';\nimport { normalisePackageAccess } from './package-access';\nimport { defaultSecurity } from './security';\nimport serverSettings from './serverSettings';\nimport { generateRandomSecretKey } from './token';\nimport { sanityCheckUplinksProps, uplinkSanityCheck } from './uplinks';\n\nconst strategicConfigProps = ['uplinks', 'packages'];\nconst allowedEnvConfig = ['http_proxy', 'https_proxy', 'no_proxy'];\nconst debug = buildDebug('verdaccio:config');\n\nexport const WEB_TITLE = 'Verdaccio';\n\n// we limit max 1000 request per 15 minutes on user endpoints\nexport const defaultUserRateLimiting = {\n windowMs: 15 * 60 * 1000, // 15 minutes\n max: 1000,\n};\n\nexport function isNodeVersionGreaterThan21() {\n const [major, minor] = process.versions.node.split('.').map(Number);\n return major > 21 || (major === 21 && minor >= 0);\n}\n\nconst TOKEN_VALID_LENGTH = 32;\n\n/**\n * Coordinates the application configuration\n */\nclass Config implements AppConfig {\n public user_agent: string | undefined;\n public uplinks: any;\n public packages: PackageList;\n public users: any;\n public auth: AuthConf;\n public server_id: string;\n public configPath: string;\n /**\n * @deprecated use configPath or config.getConfigPath();\n */\n public self_path: string;\n public storage: string | void;\n\n public plugins: string | void | null;\n public security: Security;\n public serverSettings: ServerSettingsConf;\n private configOverrideOptions: { forceMigrateToSecureLegacySignature: boolean };\n // @ts-ignore\n public secret: string;\n public flags: FlagsConfig;\n public userRateLimit: RateLimit;\n public constructor(\n config: ConfigYaml & { config_path: string },\n // forceEnhancedLegacySignature is a property that\n // allows switch a new legacy aes signature token signature\n // for older versions do not want to have this new signature model\n // this property must be false\n configOverrideOptions = { forceMigrateToSecureLegacySignature: true }\n ) {\n const self = this;\n this.storage = process.env.VERDACCIO_STORAGE_PATH || config.storage;\n if (!config.configPath) {\n // backport self_path for previous to version 6\n // @ts-expect-error\n config.configPath = config.config_path ?? config.self_path;\n if (!config.configPath) {\n throw new Error('configPath property is required');\n }\n }\n this.configOverrideOptions = configOverrideOptions;\n this.configPath = config.configPath;\n this.self_path = this.configPath;\n debug('config path: %s', this.configPath);\n this.plugins = config.plugins;\n this.security = _.merge(\n // override the default security configuration via constructor\n _.merge(defaultSecurity, {\n api: {\n migrateToSecureLegacySignature:\n this.configOverrideOptions.forceMigrateToSecureLegacySignature,\n },\n }),\n config.security\n );\n this.serverSettings = serverSettings;\n this.flags = {\n searchRemote: config.flags?.searchRemote ?? true,\n changePassword: config.flags?.changePassword ?? false,\n };\n this.user_agent = config.user_agent;\n\n for (const configProp in config) {\n if (self[configProp] == null) {\n self[configProp] = config[configProp];\n }\n }\n\n if (typeof this.user_agent === 'undefined') {\n // by default user agent is hidden\n debug('set default user agent');\n this.user_agent = getUserAgent(false);\n }\n\n this.userRateLimit = { ...defaultUserRateLimiting, ...config?.userRateLimit };\n\n // some weird shell scripts are valid yaml files parsed as string\n assert(_.isObject(config), APP_ERROR.CONFIG_NOT_VALID);\n\n // sanity check for strategic config properties\n strategicConfigProps.forEach(function (x): void {\n if (self[x] == null) {\n self[x] = {};\n }\n\n assert(isObject(self[x]), `CONFIG: bad \"${x}\" value (object expected)`);\n });\n\n this.uplinks = sanityCheckUplinksProps(uplinkSanityCheck(this.uplinks));\n this.packages = normalisePackageAccess(self.packages);\n\n // loading these from ENV if aren't in config\n allowedEnvConfig.forEach((envConf): void => {\n if (!(envConf in self)) {\n self[envConf] = process.env[envConf] || process.env[envConf.toUpperCase()];\n }\n });\n\n // unique identifier of self server (or a cluster), used to avoid loops\n // @ts-ignore\n if (!this.server_id) {\n this.server_id = generateRandomHexString(6);\n }\n }\n\n public getMigrateToSecureLegacySignature() {\n return this.security.api.migrateToSecureLegacySignature;\n }\n\n public getConfigPath() {\n return this.configPath;\n }\n\n /**\n * Check for package spec\n */\n public getMatchedPackagesSpec(pkgName: string): PackageAccess | void {\n // TODO: remove this method and replace by library utils\n return getMatchedPackagesSpec(pkgName, this.packages);\n }\n\n /**\n * Verify if the secret complies with the required structure\n * - If the secret is not provided, it will generate a new one\n * - For any Node.js version the new secret will be 32 characters long (to allow compatibility with modern Node.js versions)\n * - If the secret is provided:\n * - If Node.js 22 or higher, the secret must be 32 characters long thus the application will fail on startup\n * - If Node.js 21 or lower, the secret will be used as is but will display a deprecation warning\n * - If the property `security.api.migrateToSecureLegacySignature` is provided and set to true, the secret will be\n * generated with the new signature model\n * @secret external secret key\n */\n public checkSecretKey(secret?: string): string {\n debug('checking secret key init');\n if (typeof secret === 'string' && _.isEmpty(secret) === false) {\n debug('checking secret key length %s', secret.length);\n if (secret.length > TOKEN_VALID_LENGTH) {\n if (isNodeVersionGreaterThan21()) {\n debug('is node version greater than 21');\n if (this.getMigrateToSecureLegacySignature() === true) {\n this.secret = generateRandomSecretKey();\n debug('rewriting secret key with length %s', this.secret.length);\n return this.secret;\n }\n // oops, user needs to generate a new secret key\n debug(\n 'secret does not comply with the required length, current length %d, application will fail on startup',\n secret.length\n );\n throw new Error(\n `Invalid storage secret key length, must be 32 characters long but is ${secret.length}. \n The secret length in Node.js 22 or higher must be 32 characters long. Please consider generate a new one. \n Learn more at https://verdaccio.org/docs/configuration/#.verdaccio-db`\n );\n } else {\n debug('is node version lower than 22');\n if (this.getMigrateToSecureLegacySignature() === true) {\n this.secret = generateRandomSecretKey();\n debug('rewriting secret key with length %s', this.secret.length);\n return this.secret;\n }\n debug('triggering deprecation warning for secret key length %s', secret.length);\n // still using Node.js versions previous to 22, but we need to emit a deprecation warning\n // deprecation warning, secret key is too long and must be 32\n // this will be removed in the next major release and will produce an error\n warningUtils.emit(Codes.VERWAR007);\n this.secret = secret;\n return this.secret;\n }\n } else if (secret.length === TOKEN_VALID_LENGTH) {\n debug('detected valid secret key length %s', secret.length);\n this.secret = secret;\n return this.secret;\n }\n debug('reusing previous key with length %s', secret.length);\n this.secret = secret;\n return this.secret;\n } else {\n // generate a new a secret key\n // FUTURE: this might be an external secret key, perhaps within config file?\n debug('generating a new secret key');\n this.secret = generateRandomSecretKey();\n debug('generated a new secret key length %s', this.secret?.length);\n\n return this.secret;\n }\n }\n}\n\nexport { Config };\n"],"mappings":"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"}
|
package/build/security.js
CHANGED
package/build/security.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security.js","names":["TIME_EXPIRATION_1H","exports","defaultWebTokenOptions","sign","expiresIn","verify","defaultApiTokenConf","legacy","defaultSecurity","web","api"],"sources":["../src/security.ts"],"sourcesContent":["import { APITokenOptions, JWTOptions, Security } from '@verdaccio/types';\n\n// TODO: get this from core package\nexport const TIME_EXPIRATION_1H = '1h';\n\nconst defaultWebTokenOptions: JWTOptions = {\n sign: {\n // The expiration token for the website is 7 days\n expiresIn: TIME_EXPIRATION_1H,\n },\n verify: {},\n};\n\nconst defaultApiTokenConf: APITokenOptions = {\n legacy: true,\n};\n\nexport const defaultSecurity: Security = {\n web: defaultWebTokenOptions,\n api: defaultApiTokenConf,\n};\n"],"mappings":";;;;;;AAEA;AACO,MAAMA,kBAAkB,GAAAC,OAAA,CAAAD,kBAAA,GAAG,IAAI;AAEtC,MAAME,sBAAkC,GAAG;EACzCC,IAAI,EAAE;IACJ;IACAC,SAAS,EAAEJ;EACb,CAAC;EACDK,MAAM,EAAE,CAAC;AACX,CAAC;AAED,MAAMC,mBAAoC,GAAG;EAC3CC,MAAM,EAAE;
|
|
1
|
+
{"version":3,"file":"security.js","names":["TIME_EXPIRATION_1H","exports","defaultWebTokenOptions","sign","expiresIn","verify","defaultApiTokenConf","legacy","migrateToSecureLegacySignature","defaultSecurity","web","api"],"sources":["../src/security.ts"],"sourcesContent":["import { APITokenOptions, JWTOptions, Security } from '@verdaccio/types';\n\n// TODO: get this from core package\nexport const TIME_EXPIRATION_1H = '1h';\n\nconst defaultWebTokenOptions: JWTOptions = {\n sign: {\n // The expiration token for the website is 7 days\n expiresIn: TIME_EXPIRATION_1H,\n },\n verify: {},\n};\n\nconst defaultApiTokenConf: APITokenOptions = {\n legacy: true,\n migrateToSecureLegacySignature: true,\n};\n\nexport const defaultSecurity: Security = {\n web: defaultWebTokenOptions,\n api: defaultApiTokenConf,\n};\n"],"mappings":";;;;;;AAEA;AACO,MAAMA,kBAAkB,GAAAC,OAAA,CAAAD,kBAAA,GAAG,IAAI;AAEtC,MAAME,sBAAkC,GAAG;EACzCC,IAAI,EAAE;IACJ;IACAC,SAAS,EAAEJ;EACb,CAAC;EACDK,MAAM,EAAE,CAAC;AACX,CAAC;AAED,MAAMC,mBAAoC,GAAG;EAC3CC,MAAM,EAAE,IAAI;EACZC,8BAA8B,EAAE;AAClC,CAAC;AAEM,MAAMC,eAAyB,GAAAR,OAAA,CAAAQ,eAAA,GAAG;EACvCC,GAAG,EAAER,sBAAsB;EAC3BS,GAAG,EAAEL;AACP,CAAC"}
|
package/build/token.d.ts
CHANGED
package/build/token.js
CHANGED
|
@@ -6,10 +6,12 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
6
6
|
exports.TOKEN_VALID_LENGTH = void 0;
|
|
7
7
|
exports.generateRandomSecretKey = generateRandomSecretKey;
|
|
8
8
|
var _crypto = require("crypto");
|
|
9
|
+
// TODO: code duplicated at @verdaccio/signature
|
|
9
10
|
const TOKEN_VALID_LENGTH = exports.TOKEN_VALID_LENGTH = 32;
|
|
10
11
|
|
|
11
12
|
/**
|
|
12
13
|
* Secret key must have 32 characters.
|
|
14
|
+
* // TODO: code duplicated at @verdaccio/signature
|
|
13
15
|
*/
|
|
14
16
|
function generateRandomSecretKey() {
|
|
15
17
|
return (0, _crypto.randomBytes)(TOKEN_VALID_LENGTH).toString('base64').substring(0, TOKEN_VALID_LENGTH);
|
package/build/token.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token.js","names":["_crypto","require","TOKEN_VALID_LENGTH","exports","generateRandomSecretKey","randomBytes","toString","substring"],"sources":["../src/token.ts"],"sourcesContent":["import { randomBytes } from 'crypto';\n\nexport const TOKEN_VALID_LENGTH = 32;\n\n/**\n * Secret key must have 32 characters.\n */\nexport function generateRandomSecretKey(): string {\n return randomBytes(TOKEN_VALID_LENGTH).toString('base64').substring(0, TOKEN_VALID_LENGTH);\n}\n"],"mappings":";;;;;;;AAAA,IAAAA,OAAA,GAAAC,OAAA;
|
|
1
|
+
{"version":3,"file":"token.js","names":["_crypto","require","TOKEN_VALID_LENGTH","exports","generateRandomSecretKey","randomBytes","toString","substring"],"sources":["../src/token.ts"],"sourcesContent":["import { randomBytes } from 'crypto';\n\n// TODO: code duplicated at @verdaccio/signature\nexport const TOKEN_VALID_LENGTH = 32;\n\n/**\n * Secret key must have 32 characters.\n * // TODO: code duplicated at @verdaccio/signature\n */\nexport function generateRandomSecretKey(): string {\n return randomBytes(TOKEN_VALID_LENGTH).toString('base64').substring(0, TOKEN_VALID_LENGTH);\n}\n"],"mappings":";;;;;;;AAAA,IAAAA,OAAA,GAAAC,OAAA;AAEA;AACO,MAAMC,kBAAkB,GAAAC,OAAA,CAAAD,kBAAA,GAAG,EAAE;;AAEpC;AACA;AACA;AACA;AACO,SAASE,uBAAuBA,CAAA,EAAW;EAChD,OAAO,IAAAC,mBAAW,EAACH,kBAAkB,CAAC,CAACI,QAAQ,CAAC,QAAQ,CAAC,CAACC,SAAS,CAAC,CAAC,EAAEL,kBAAkB,CAAC;AAC5F"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@verdaccio/config",
|
|
3
|
-
"version": "7.0.0-next-7.
|
|
3
|
+
"version": "7.0.0-next-7.15",
|
|
4
4
|
"description": "logger",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"node": ">=12"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@verdaccio/core": "7.0.0-next-7.
|
|
33
|
-
"@verdaccio/utils": "7.0.0-next-7.
|
|
32
|
+
"@verdaccio/core": "7.0.0-next-7.15",
|
|
33
|
+
"@verdaccio/utils": "7.0.0-next-7.15",
|
|
34
34
|
"debug": "4.3.4",
|
|
35
35
|
"js-yaml": "4.1.0",
|
|
36
36
|
"lodash": "4.17.21",
|
package/src/config.ts
CHANGED
|
@@ -36,6 +36,13 @@ export const defaultUserRateLimiting = {
|
|
|
36
36
|
max: 1000,
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
+
export function isNodeVersionGreaterThan21() {
|
|
40
|
+
const [major, minor] = process.versions.node.split('.').map(Number);
|
|
41
|
+
return major > 21 || (major === 21 && minor >= 0);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const TOKEN_VALID_LENGTH = 32;
|
|
45
|
+
|
|
39
46
|
/**
|
|
40
47
|
* Coordinates the application configuration
|
|
41
48
|
*/
|
|
@@ -56,21 +63,20 @@ class Config implements AppConfig {
|
|
|
56
63
|
public plugins: string | void | null;
|
|
57
64
|
public security: Security;
|
|
58
65
|
public serverSettings: ServerSettingsConf;
|
|
66
|
+
private configOverrideOptions: { forceMigrateToSecureLegacySignature: boolean };
|
|
59
67
|
// @ts-ignore
|
|
60
68
|
public secret: string;
|
|
61
69
|
public flags: FlagsConfig;
|
|
62
70
|
public userRateLimit: RateLimit;
|
|
63
|
-
private configOptions: { forceEnhancedLegacySignature: boolean };
|
|
64
71
|
public constructor(
|
|
65
72
|
config: ConfigYaml & { config_path: string },
|
|
66
73
|
// forceEnhancedLegacySignature is a property that
|
|
67
74
|
// allows switch a new legacy aes signature token signature
|
|
68
75
|
// for older versions do not want to have this new signature model
|
|
69
76
|
// this property must be false
|
|
70
|
-
|
|
77
|
+
configOverrideOptions = { forceMigrateToSecureLegacySignature: true }
|
|
71
78
|
) {
|
|
72
79
|
const self = this;
|
|
73
|
-
this.configOptions = configOptions;
|
|
74
80
|
this.storage = process.env.VERDACCIO_STORAGE_PATH || config.storage;
|
|
75
81
|
if (!config.configPath) {
|
|
76
82
|
// backport self_path for previous to version 6
|
|
@@ -80,11 +86,21 @@ class Config implements AppConfig {
|
|
|
80
86
|
throw new Error('configPath property is required');
|
|
81
87
|
}
|
|
82
88
|
}
|
|
89
|
+
this.configOverrideOptions = configOverrideOptions;
|
|
83
90
|
this.configPath = config.configPath;
|
|
84
91
|
this.self_path = this.configPath;
|
|
85
92
|
debug('config path: %s', this.configPath);
|
|
86
93
|
this.plugins = config.plugins;
|
|
87
|
-
this.security = _.merge(
|
|
94
|
+
this.security = _.merge(
|
|
95
|
+
// override the default security configuration via constructor
|
|
96
|
+
_.merge(defaultSecurity, {
|
|
97
|
+
api: {
|
|
98
|
+
migrateToSecureLegacySignature:
|
|
99
|
+
this.configOverrideOptions.forceMigrateToSecureLegacySignature,
|
|
100
|
+
},
|
|
101
|
+
}),
|
|
102
|
+
config.security
|
|
103
|
+
);
|
|
88
104
|
this.serverSettings = serverSettings;
|
|
89
105
|
this.flags = {
|
|
90
106
|
searchRemote: config.flags?.searchRemote ?? true,
|
|
@@ -135,14 +151,8 @@ class Config implements AppConfig {
|
|
|
135
151
|
}
|
|
136
152
|
}
|
|
137
153
|
|
|
138
|
-
public
|
|
139
|
-
|
|
140
|
-
if (this.security.enhancedLegacySignature === true) {
|
|
141
|
-
return true;
|
|
142
|
-
}
|
|
143
|
-
return false;
|
|
144
|
-
}
|
|
145
|
-
return this.configOptions.forceEnhancedLegacySignature;
|
|
154
|
+
public getMigrateToSecureLegacySignature() {
|
|
155
|
+
return this.security.api.migrateToSecureLegacySignature;
|
|
146
156
|
}
|
|
147
157
|
|
|
148
158
|
public getConfigPath() {
|
|
@@ -158,36 +168,70 @@ class Config implements AppConfig {
|
|
|
158
168
|
}
|
|
159
169
|
|
|
160
170
|
/**
|
|
161
|
-
*
|
|
171
|
+
* Verify if the secret complies with the required structure
|
|
172
|
+
* - If the secret is not provided, it will generate a new one
|
|
173
|
+
* - For any Node.js version the new secret will be 32 characters long (to allow compatibility with modern Node.js versions)
|
|
174
|
+
* - If the secret is provided:
|
|
175
|
+
* - If Node.js 22 or higher, the secret must be 32 characters long thus the application will fail on startup
|
|
176
|
+
* - If Node.js 21 or lower, the secret will be used as is but will display a deprecation warning
|
|
177
|
+
* - If the property `security.api.migrateToSecureLegacySignature` is provided and set to true, the secret will be
|
|
178
|
+
* generated with the new signature model
|
|
162
179
|
* @secret external secret key
|
|
163
180
|
*/
|
|
164
181
|
public checkSecretKey(secret?: string): string {
|
|
165
|
-
debug('
|
|
182
|
+
debug('checking secret key init');
|
|
166
183
|
if (typeof secret === 'string' && _.isEmpty(secret) === false) {
|
|
184
|
+
debug('checking secret key length %s', secret.length);
|
|
185
|
+
if (secret.length > TOKEN_VALID_LENGTH) {
|
|
186
|
+
if (isNodeVersionGreaterThan21()) {
|
|
187
|
+
debug('is node version greater than 21');
|
|
188
|
+
if (this.getMigrateToSecureLegacySignature() === true) {
|
|
189
|
+
this.secret = generateRandomSecretKey();
|
|
190
|
+
debug('rewriting secret key with length %s', this.secret.length);
|
|
191
|
+
return this.secret;
|
|
192
|
+
}
|
|
193
|
+
// oops, user needs to generate a new secret key
|
|
194
|
+
debug(
|
|
195
|
+
'secret does not comply with the required length, current length %d, application will fail on startup',
|
|
196
|
+
secret.length
|
|
197
|
+
);
|
|
198
|
+
throw new Error(
|
|
199
|
+
`Invalid storage secret key length, must be 32 characters long but is ${secret.length}.
|
|
200
|
+
The secret length in Node.js 22 or higher must be 32 characters long. Please consider generate a new one.
|
|
201
|
+
Learn more at https://verdaccio.org/docs/configuration/#.verdaccio-db`
|
|
202
|
+
);
|
|
203
|
+
} else {
|
|
204
|
+
debug('is node version lower than 22');
|
|
205
|
+
if (this.getMigrateToSecureLegacySignature() === true) {
|
|
206
|
+
this.secret = generateRandomSecretKey();
|
|
207
|
+
debug('rewriting secret key with length %s', this.secret.length);
|
|
208
|
+
return this.secret;
|
|
209
|
+
}
|
|
210
|
+
debug('triggering deprecation warning for secret key length %s', secret.length);
|
|
211
|
+
// still using Node.js versions previous to 22, but we need to emit a deprecation warning
|
|
212
|
+
// deprecation warning, secret key is too long and must be 32
|
|
213
|
+
// this will be removed in the next major release and will produce an error
|
|
214
|
+
warningUtils.emit(Codes.VERWAR007);
|
|
215
|
+
this.secret = secret;
|
|
216
|
+
return this.secret;
|
|
217
|
+
}
|
|
218
|
+
} else if (secret.length === TOKEN_VALID_LENGTH) {
|
|
219
|
+
debug('detected valid secret key length %s', secret.length);
|
|
220
|
+
this.secret = secret;
|
|
221
|
+
return this.secret;
|
|
222
|
+
}
|
|
223
|
+
debug('reusing previous key with length %s', secret.length);
|
|
167
224
|
this.secret = secret;
|
|
168
|
-
|
|
169
|
-
return secret;
|
|
170
|
-
}
|
|
171
|
-
// generate a new a secret key
|
|
172
|
-
// FUTURE: this might be an external secret key, perhaps within config file?
|
|
173
|
-
debug('generating a new secret key');
|
|
174
|
-
|
|
175
|
-
if (this.getEnhancedLegacySignature()) {
|
|
176
|
-
debug('key generated with "enhanced" legacy signature user config');
|
|
177
|
-
this.secret = generateRandomSecretKey();
|
|
225
|
+
return this.secret;
|
|
178
226
|
} else {
|
|
179
|
-
|
|
180
|
-
this
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
// set it by default
|
|
185
|
-
if (this.security?.enhancedLegacySignature === false) {
|
|
186
|
-
warningUtils.emit(Codes.VERWAR005);
|
|
187
|
-
}
|
|
227
|
+
// generate a new a secret key
|
|
228
|
+
// FUTURE: this might be an external secret key, perhaps within config file?
|
|
229
|
+
debug('generating a new secret key');
|
|
230
|
+
this.secret = generateRandomSecretKey();
|
|
231
|
+
debug('generated a new secret key length %s', this.secret?.length);
|
|
188
232
|
|
|
189
|
-
|
|
190
|
-
|
|
233
|
+
return this.secret;
|
|
234
|
+
}
|
|
191
235
|
}
|
|
192
236
|
}
|
|
193
237
|
|
package/src/security.ts
CHANGED
package/src/token.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { randomBytes } from 'crypto';
|
|
2
2
|
|
|
3
|
+
// TODO: code duplicated at @verdaccio/signature
|
|
3
4
|
export const TOKEN_VALID_LENGTH = 32;
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Secret key must have 32 characters.
|
|
8
|
+
* // TODO: code duplicated at @verdaccio/signature
|
|
7
9
|
*/
|
|
8
10
|
export function generateRandomSecretKey(): string {
|
|
9
11
|
return randomBytes(TOKEN_VALID_LENGTH).toString('base64').substring(0, TOKEN_VALID_LENGTH);
|
package/test/config.spec.ts
CHANGED
|
@@ -6,9 +6,12 @@ import {
|
|
|
6
6
|
DEFAULT_REGISTRY,
|
|
7
7
|
DEFAULT_UPLINK,
|
|
8
8
|
ROLES,
|
|
9
|
+
TOKEN_VALID_LENGTH,
|
|
9
10
|
WEB_TITLE,
|
|
10
11
|
defaultSecurity,
|
|
12
|
+
generateRandomSecretKey,
|
|
11
13
|
getDefaultConfig,
|
|
14
|
+
isNodeVersionGreaterThan21,
|
|
12
15
|
parseConfigFile,
|
|
13
16
|
} from '../src';
|
|
14
17
|
import { parseConfigurationFile } from './utils';
|
|
@@ -19,6 +22,8 @@ const resolveConf = (conf) => {
|
|
|
19
22
|
return path.join(__dirname, `../src/conf/${name}${ext.startsWith('.') ? ext : '.yaml'}`);
|
|
20
23
|
};
|
|
21
24
|
|
|
25
|
+
const itif = (condition) => (condition ? it : it.skip);
|
|
26
|
+
|
|
22
27
|
const checkDefaultUplink = (config) => {
|
|
23
28
|
expect(_.isObject(config.uplinks[DEFAULT_UPLINK])).toBeTruthy();
|
|
24
29
|
expect(config.uplinks[DEFAULT_UPLINK].url).toMatch(DEFAULT_REGISTRY);
|
|
@@ -94,32 +99,85 @@ describe('check basic content parsed file', () => {
|
|
|
94
99
|
describe('checkSecretKey', () => {
|
|
95
100
|
test('with default.yaml and pre selected secret', () => {
|
|
96
101
|
const config = new Config(parseConfigFile(resolveConf('default')));
|
|
97
|
-
expect(config.checkSecretKey(
|
|
102
|
+
expect(config.checkSecretKey(generateRandomSecretKey())).toHaveLength(TOKEN_VALID_LENGTH);
|
|
98
103
|
});
|
|
99
104
|
|
|
100
105
|
test('with default.yaml and void secret', () => {
|
|
101
106
|
const config = new Config(parseConfigFile(resolveConf('default')));
|
|
102
|
-
|
|
107
|
+
const secret = config.checkSecretKey();
|
|
108
|
+
expect(typeof secret === 'string').toBeTruthy();
|
|
109
|
+
expect(secret).toHaveLength(TOKEN_VALID_LENGTH);
|
|
103
110
|
});
|
|
104
111
|
|
|
105
|
-
test('with default.yaml and
|
|
112
|
+
test('with default.yaml and empty string secret', () => {
|
|
106
113
|
const config = new Config(parseConfigFile(resolveConf('default')));
|
|
107
|
-
|
|
114
|
+
const secret = config.checkSecretKey('');
|
|
115
|
+
expect(typeof secret === 'string').toBeTruthy();
|
|
116
|
+
expect(secret).toHaveLength(TOKEN_VALID_LENGTH);
|
|
108
117
|
});
|
|
109
118
|
|
|
110
|
-
test('with
|
|
119
|
+
test('with default.yaml and valid string secret length', () => {
|
|
111
120
|
const config = new Config(parseConfigFile(resolveConf('default')));
|
|
112
|
-
config.
|
|
113
|
-
|
|
114
|
-
|
|
121
|
+
expect(typeof config.checkSecretKey(generateRandomSecretKey()) === 'string').toBeTruthy();
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
test('with default.yaml migrate a valid string secret length', () => {
|
|
125
|
+
const config = new Config(parseConfigFile(resolveConf('default')), {
|
|
126
|
+
forceMigrateToSecureLegacySignature: true,
|
|
127
|
+
});
|
|
128
|
+
expect(
|
|
129
|
+
// 64 characters secret long
|
|
130
|
+
config.checkSecretKey('b4982dbb0108531fafb552374d7e83724b6458a2b3ffa97ad0edb899bdaefc4a')
|
|
131
|
+
).toHaveLength(TOKEN_VALID_LENGTH);
|
|
115
132
|
});
|
|
116
133
|
|
|
117
|
-
|
|
134
|
+
// only runs on Node.js 22 or higher
|
|
135
|
+
itif(isNodeVersionGreaterThan21())('with enhanced legacy signature Node 22 or higher', () => {
|
|
136
|
+
const config = new Config(parseConfigFile(resolveConf('default')), {
|
|
137
|
+
forceMigrateToSecureLegacySignature: false,
|
|
138
|
+
});
|
|
139
|
+
// eslint-disable-next-line jest/no-standalone-expect
|
|
140
|
+
expect(() =>
|
|
141
|
+
// 64 characters secret long
|
|
142
|
+
config.checkSecretKey('b4982dbb0108531fafb552374d7e83724b6458a2b3ffa97ad0edb899bdaefc4a')
|
|
143
|
+
).toThrow();
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
itif(isNodeVersionGreaterThan21())('with enhanced legacy signature Node 22 or higher', () => {
|
|
147
|
+
const config = new Config(parseConfigFile(resolveConf('default')), {
|
|
148
|
+
forceMigrateToSecureLegacySignature: false,
|
|
149
|
+
});
|
|
150
|
+
config.security.api.migrateToSecureLegacySignature = true;
|
|
151
|
+
// eslint-disable-next-line jest/no-standalone-expect
|
|
152
|
+
expect(
|
|
153
|
+
config.checkSecretKey('b4982dbb0108531fafb552374d7e83724b6458a2b3ffa97ad0edb899bdaefc4a')
|
|
154
|
+
).toHaveLength(TOKEN_VALID_LENGTH);
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
itif(isNodeVersionGreaterThan21() === false)(
|
|
158
|
+
'with old unsecure legacy signature Node 21 or lower',
|
|
159
|
+
() => {
|
|
160
|
+
const config = new Config(parseConfigFile(resolveConf('default')));
|
|
161
|
+
config.security.api.migrateToSecureLegacySignature = false;
|
|
162
|
+
// 64 characters secret long
|
|
163
|
+
// eslint-disable-next-line jest/no-standalone-expect
|
|
164
|
+
expect(
|
|
165
|
+
config.checkSecretKey('b4982dbb0108531fafb552374d7e83724b6458a2b3ffa97ad0edb899bdaefc4a')
|
|
166
|
+
).toHaveLength(64);
|
|
167
|
+
}
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
test('with migration to new legacy signature Node 21 or lower', () => {
|
|
118
171
|
const config = new Config(parseConfigFile(resolveConf('default')));
|
|
119
|
-
config.security.
|
|
120
|
-
|
|
121
|
-
expect
|
|
172
|
+
config.security.api.migrateToSecureLegacySignature = true;
|
|
173
|
+
// 64 characters secret long
|
|
174
|
+
// eslint-disable-next-line jest/no-standalone-expect
|
|
175
|
+
expect(
|
|
176
|
+
config.checkSecretKey('b4982dbb0108531fafb552374d7e83724b6458a2b3ffa97ad0edb899bdaefc4a')
|
|
177
|
+
).toHaveLength(TOKEN_VALID_LENGTH);
|
|
122
178
|
});
|
|
179
|
+
|
|
180
|
+
test.todo('test emit warning with secret key');
|
|
123
181
|
});
|
|
124
182
|
|
|
125
183
|
describe('getMatchedPackagesSpec', () => {
|