1
0
mirror of https://github.com/verdaccio/verdaccio.git synced 2024-12-24 21:15:51 +01:00

feat: add forceEnhancedLegacySignature (#3655)

* feat: add forceEnhancedLegacySignature

* Create rare-planets-travel.md

* Update run-server.spec.ts

* Update run-server.spec.ts
This commit is contained in:
Juan Picado 2023-02-26 22:24:00 +01:00 committed by GitHub
parent ddb6a22396
commit dc571aabd2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 69 additions and 18 deletions

@ -0,0 +1,9 @@
---
'@verdaccio/config': minor
'@verdaccio/core': minor
'@verdaccio/types': minor
'@verdaccio/signature': minor
'@verdaccio/test-helper': minor
---
feat: add forceEnhancedLegacySignature

@ -28,7 +28,6 @@ const debug = buildDebug('verdaccio:config');
* @return {String} the config file path
*/
function findConfigFile(configPath?: string): string {
// console.log(process.env);
if (typeof configPath !== 'undefined') {
return path.resolve(configPath);
}

@ -2,7 +2,8 @@ import assert from 'assert';
import buildDebug from 'debug';
import _ from 'lodash';
import { APP_ERROR } from '@verdaccio/core';
import { APP_ERROR, warningUtils } from '@verdaccio/core';
import { Codes } from '@verdaccio/core/build/warning-utils';
import {
Config as AppConfig,
AuthConf,
@ -45,9 +46,11 @@ class Config implements AppConfig {
public users: any;
public auth: AuthConf;
public server_id: string;
// @deprecated use configPath instead
public config_path: string;
public configPath: string;
/**
* @deprecated use configPath or config.getConfigPath();
*/
public self_path: string;
public storage: string | void;
public plugins: string | void | null;
@ -57,14 +60,24 @@ class Config implements AppConfig {
public secret: string;
public flags: FlagsConfig;
public userRateLimit: RateLimit;
public constructor(config: ConfigYaml & { config_path: string }) {
private configOptions: { forceEnhancedLegacySignature: boolean };
public constructor(
config: ConfigYaml & { config_path: string },
configOptions = { forceEnhancedLegacySignature: true }
) {
const self = this;
this.configOptions = configOptions;
this.storage = process.env.VERDACCIO_STORAGE_PATH || config.storage;
if (!config.configPath) {
throw new Error('config_path is required');
// backport self_path for previous to version 6
// @ts-expect-error
config.configPath = config.config_path ?? config.self_path;
if (!config.configPath) {
throw new Error('configPath property is required');
}
}
this.config_path = config.config_path ?? (config.configPath as string);
this.configPath = config.configPath;
this.self_path = this.configPath;
debug('config path: %s', this.configPath);
this.plugins = config.plugins;
this.security = _.merge(defaultSecurity, config.security);
@ -117,6 +130,10 @@ class Config implements AppConfig {
}
}
public getConfigPath() {
return this.configPath;
}
/**
* Check for package spec
*/
@ -127,18 +144,35 @@ class Config implements AppConfig {
/**
* Store or create whether receive a secret key
* @secret external secret key
*/
public checkSecretKey(secret?: string): string {
debug('check secret key');
if (_.isString(secret) && _.isEmpty(secret) === false) {
if (typeof secret === 'string' && _.isEmpty(secret) === false) {
this.secret = secret;
debug('reusing previous key');
return secret;
}
// it generates a secret key
// generate a new a secret key
// FUTURE: this might be an external secret key, perhaps within config file?
debug('generate a new key');
this.secret = generateRandomSecretKey();
//
if (this.configOptions.forceEnhancedLegacySignature) {
this.secret = generateRandomSecretKey();
} else {
this.secret =
this.security.enhancedLegacySignature === true
? generateRandomSecretKey()
: generateRandomHexString(32);
// set this to false allow use old token signature and is not recommended
// only use for migration reasons, major release will remove this property and
// set it by default
if (this.security.enhancedLegacySignature === false) {
warningUtils.emit(Codes.VERWAR005);
}
}
debug('generated a new secret key %s', this.secret?.length);
return this.secret;
}
}

@ -4,7 +4,6 @@ export const TOKEN_VALID_LENGTH = 32;
/**
* Secret key must have 32 characters.
* @deprecated
*/
export function generateRandomSecretKey(): string {
return randomBytes(TOKEN_VALID_LENGTH).toString('base64').substring(0, TOKEN_VALID_LENGTH);

@ -9,6 +9,9 @@
"references": [
{
"path": "../utils"
},
{
"path": "../core/core"
}
]
}

@ -9,6 +9,7 @@ export enum Codes {
VERWAR002 = 'VERWAR002',
VERWAR003 = 'VERWAR003',
VERWAR004 = 'VERWAR004',
VERWAR005 = 'VERWAR005',
// deprecation warnings
VERDEP003 = 'VERDEP003',
}
@ -39,6 +40,12 @@ host:port (e.g. "localhost:4873") or full url '(e.g. "http://localhost:4873/")
https://verdaccio.org/docs/en/configuration#listen-port`
);
warningInstance.create(
verdaccioWarning,
Codes.VERWAR005,
'disable enhanced legacy signature is considered a security risk, please reconsider enable it'
);
warningInstance.create(
verdaccioDeprecation,
Codes.VERDEP003,

@ -185,6 +185,7 @@ export interface APITokenOptions {
}
export interface Security {
enhancedLegacySignature?: boolean;
web: JWTOptions;
api: APITokenOptions;
}
@ -266,8 +267,6 @@ export interface ConfigYaml {
flags?: FlagsConfig;
userRateLimit?: RateLimit;
// internal objects, added by internal yaml to JS config parser
// @deprecated use configPath instead
config_path?: string;
// save the configuration file path
configPath?: string;
}
@ -282,6 +281,8 @@ export interface Config extends Omit<ConfigYaml, 'packages' | 'security' | 'conf
secret: string;
// save the configuration file path, it's fails without thi configPath
configPath: string;
// @deprecated use configPath
self_path?: string;
// packages from yaml file looks different from packages inside the config file
packages: PackageList;
// security object defaults is added by the config file but optional in the yaml file

@ -11,7 +11,7 @@ describe('startServer via API', () => {
test('should fail on start with empty configuration', async () => {
// @ts-expect-error
await expect(runServer({})).rejects.toThrow('config_path is required');
await expect(runServer({})).rejects.toThrow('configPath property is required');
});
test('should fail on start with null as entry', async () => {

@ -43,8 +43,7 @@ export function aesDecryptDeprecated(buf: Buffer, secret: string): Buffer {
export const TOKEN_VALID_LENGTH_DEPRECATED = 64;
/**
* Genrate a secret key of 64 characters.
* @deprecated keys should be length max of 64
* Generate a secret key of 64 characters.
*/
export function generateRandomSecretKeyDeprecated(): string {
return generateRandomHexString(6);

@ -20,7 +20,7 @@ const VERDACCIO_LEGACY_ENCRYPTION_KEY = process.env.VERDACCIO_LEGACY_ENCRYPTION_
export function aesEncrypt(value: string, key: string): string | void {
// https://nodejs.org/api/crypto.html#crypto_crypto_createcipher_algorithm_password_options
// https://www.grainger.xyz/changing-from-cipher-to-cipheriv/
// https://www.grainger.xyz/posts/changing-from-cipher-to-cipheriv
debug('encrypt %o', value);
debug('algorithm %o', defaultAlgorithm);
// IV must be a buffer of length 16

@ -19,7 +19,7 @@ export async function initializeServer(
Storage
): Promise<Application> {
const app = express();
const config = new Config(configName);
const config = new Config(configName, { forceEnhancedLegacySignature: true });
config.storage = path.join(os.tmpdir(), '/storage', generateRandomHexString());
// httpass would get path.basename() for configPath thus we need to create a dummy folder
// to avoid conflics