0
Fork 0
mirror of https://github.com/verdaccio/verdaccio.git synced 2024-12-16 21:56:25 -05:00

feat: ca certificate is optional for https configuration (#1853)

* setup https server

* typed handleHttps

* fix if condition

* generate certificate on the fly

* revert yarn.lock

Co-authored-by: Juan Picado <juanpicado19@gmail.com>
This commit is contained in:
Jian-Chen Chen (jesse) 2020-07-01 01:05:29 +08:00 committed by GitHub
parent dd9b3cff55
commit 912482a5ae
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 54 additions and 17 deletions

View file

@ -72,7 +72,7 @@
"@typescript-eslint/eslint-plugin": "2.12.0",
"@verdaccio/babel-preset": "^9.6.1",
"@verdaccio/eslint-config": "^8.5.0",
"@verdaccio/types": "^9.3.0",
"@verdaccio/types": "^9.7.0",
"all-contributors-cli": "6.16.0",
"codecov": "3.7.0",
"cross-env": "7.0.2",
@ -81,16 +81,17 @@
"fs-extra": "8.1.0",
"get-stdin": "7.0.0",
"husky": "2.7.0",
"lockfile-lint": "4.2.2",
"in-publish": "2.0.1",
"jest": "25.3.0",
"jest-environment-node": "25.3.0",
"jest-junit": "9.0.0",
"lint-staged": "8.2.1",
"lockfile-lint": "4.2.2",
"nock": "11.7.2",
"prettier": "1.19.1",
"puppeteer": "1.8.0",
"rimraf": "3.0.2",
"selfsigned": "1.10.7",
"standard-version": "8.0.0",
"supertest": "4.0.2",
"typescript": "3.7.5",

View file

@ -1,4 +1,5 @@
import { assign, isObject, isFunction } from 'lodash';
import express from 'express';
import URL from 'url';
import fs from 'fs';
import http from 'http';
@ -8,7 +9,7 @@ import endPointAPI from '../api/index';
import { getListListenAddresses, resolveConfigPath } from './cli/utils';
import { API_ERROR, certPem, csrPem, keyPem } from './constants';
import { Callback } from '@verdaccio/types';
import { Callback, ConfigWithHttps, HttpsConfKeyCert, HttpsConfPfx } from '@verdaccio/types';
import { Application } from 'express';
const logger = require('./logger');
@ -47,11 +48,6 @@ function startVerdaccio(config: any, cliListen: string, configPath: string, pkgV
addresses.forEach(function(addr): void {
let webServer;
if (addr.proto === 'https') {
// https must either have key cert and ca or a pfx and (optionally) a passphrase
if (!config.https || !((config.https.key && config.https.cert && config.https.ca) || config.https.pfx)) {
logHTTPSWarning(configPath);
}
webServer = handleHTTPS(app, configPath, config);
} else {
// http
@ -79,7 +75,7 @@ function logHTTPSWarning(storageLocation) {
logger.logger.fatal(
[
'You have enabled HTTPS and need to specify either ',
' "https.key", "https.cert" and "https.ca" or ',
' "https.key" and "https.cert" or ',
' "https.pfx" and optionally "https.passphrase" ',
'to run https server',
'',
@ -98,28 +94,39 @@ function logHTTPSWarning(storageLocation) {
' https:',
` key: ${resolveConfigPath(storageLocation, keyPem)}`,
` cert: ${resolveConfigPath(storageLocation, certPem)}`,
` ca: ${resolveConfigPath(storageLocation, csrPem)}`,
].join('\n')
);
process.exit(2);
}
function handleHTTPS(app, configPath, config) {
function handleHTTPS(app: express.Application, configPath: string, config: ConfigWithHttps): https.Server {
try {
let httpsOptions = {
secureOptions: constants.SSL_OP_NO_SSLv2 | constants.SSL_OP_NO_SSLv3, // disable insecure SSLv2 and SSLv3
};
if (config.https.pfx) {
const keyCertConfig = config.https as HttpsConfKeyCert;
const pfxConfig = config.https as HttpsConfPfx;
// https must either have key and cert or a pfx and (optionally) a passphrase
if (!((keyCertConfig.key && keyCertConfig.cert) || pfxConfig.pfx)) {
logHTTPSWarning(configPath);
}
if (pfxConfig.pfx) {
const { pfx, passphrase } = pfxConfig;
httpsOptions = assign(httpsOptions, {
pfx: fs.readFileSync(config.https.pfx),
passphrase: config.https.passphrase || '',
pfx: fs.readFileSync(pfx),
passphrase: passphrase || '',
});
} else {
const { key, cert, ca } = keyCertConfig;
httpsOptions = assign(httpsOptions, {
key: fs.readFileSync(config.https.key),
cert: fs.readFileSync(config.https.cert),
ca: fs.readFileSync(config.https.ca),
key: fs.readFileSync(key),
cert: fs.readFileSync(cert),
...(ca && {
ca: fs.readFileSync(ca),
}),
});
}
return https.createServer(httpsOptions, app);

View file

@ -1,5 +1,8 @@
import path from 'path';
import _ from 'lodash';
import selfsigned from 'selfsigned';
import os from 'os';
import fs from 'fs';
import startServer from '../../../../src';
import config from '../../partials/config';
@ -140,6 +143,32 @@ describe('startServer via API', () => {
global.process = realProcess;
});
test('should start a https server with key and cert', async (done) => {
const store = path.join(__dirname, 'partials/store');
const serverName = 'verdaccio-test';
const version = '1.0.0';
const address = 'https://www.domain.com:443';
const { private: key, cert } = selfsigned.generate();
const keyPath = path.join(os.tmpdir(), 'key.pem');
const certPath = path.join(os.tmpdir(), 'crt.pem');
fs.writeFileSync(keyPath, key);
fs.writeFileSync(certPath, cert);
const conf = config();
conf.https = {
key: keyPath,
cert: certPath,
};
await startServer(conf, address, store, version, serverName,
(webServer, addrs) => {
expect(webServer).toBeDefined();
expect(addrs).toBeDefined();
expect(addrs.proto).toBe('https');
done();
});
})
test('should fails if config is missing', async () => {
try {
// @ts-ignore

BIN
yarn.lock

Binary file not shown.