diff --git a/src/app.ts b/src/app.ts index b2c0438..030c487 100644 --- a/src/app.ts +++ b/src/app.ts @@ -15,14 +15,14 @@ // limitations under the License. import express from 'express'; -import https from 'https'; +import https, { Server } from 'https'; import http from 'http'; import WebSocket from 'ws'; import { init as initConfig, config } from './lib/config'; -import { init as initCert, key, cert, ca } from './lib/cert'; +import { init as initCert, genTLSContext, loadCAs } from './lib/cert'; import { createLogger, LogLevelString } from 'bunyan'; import * as utils from './lib/utils'; -import { router as apiRouter } from './routers/api'; +import { router as apiRouter, setAddTLSContext } from './routers/api'; import { router as p2pRouter, eventEmitter as p2pEventEmitter } from './routers/p2p'; import RequestError, { errorHandler } from './lib/request-error'; import * as eventsHandler from './handlers/events' @@ -36,8 +36,17 @@ const log = createLogger({ name: 'app.ts', level: utils.constants.LOG_LEVEL as L const swaggerDocument = YAML.load(path.join(__dirname, './swagger.yaml')); +let p2pServer : Server + let delegatedWebSocket: WebSocket | undefined = undefined; +export const addTLSContext = async (hostname: string) => { + await loadCAs() + // The most recent context wins (per the Node.js spec), so to get a reload we just add a wildcard context + p2pServer.addContext(hostname, genTLSContext()) +}; +setAddTLSContext(addTLSContext) + export const start = async () => { await initConfig(); await initCert(); @@ -46,13 +55,7 @@ export const start = async () => { const apiServer = http.createServer(apiApp); const p2pApp = express(); - const p2pServer = https.createServer({ - key, - cert, - ca, - rejectUnauthorized: true, - requestCert: true, - }, p2pApp); + p2pServer = https.createServer(genTLSContext(), p2pApp); const wss = new WebSocket.Server({ server: apiServer, verifyClient: (info, cb) => { diff --git a/src/lib/cert.ts b/src/lib/cert.ts index 03a23f7..52b550e 100644 --- a/src/lib/cert.ts +++ b/src/lib/cert.ts @@ -42,3 +42,13 @@ export const loadCAs = async () => { } log.debug(`Loaded ${ca.length} peer certificate(s)`); }; + +export const genTLSContext = () => { + return { + key, + cert, + ca, + rejectUnauthorized: true, + requestCert: true, + } +} diff --git a/src/routers/api.ts b/src/routers/api.ts index ccf897d..6c09b10 100644 --- a/src/routers/api.ts +++ b/src/routers/api.ts @@ -22,14 +22,21 @@ import RequestError from '../lib/request-error'; import { config, persistConfig } from '../lib/config'; import { IStatus } from '../lib/interfaces'; import https from 'https'; -import { key, cert, ca, loadCAs, peerID } from '../lib/cert'; +import { key, cert, ca, peerID } from '../lib/cert'; import * as eventsHandler from '../handlers/events'; import { promises as fs } from 'fs'; import path from 'path'; import { v4 as uuidV4 } from 'uuid'; +import { URL } from 'url'; export const router = Router(); +let addTLSContext: (hostname: string) => Promise; + +export const setAddTLSContext = (_addTLSContext: (hostname: string) => Promise) => { + addTLSContext = _addTLSContext; +} + router.get('/id', async (_req, res, next) => { try { res.send({ @@ -93,7 +100,8 @@ router.put('/peers/:id', async (req, res, next) => { config.peers.push(peer); } await persistConfig(); - await loadCAs(); + let url = new URL(req.body.endpoint) + await addTLSContext(url.hostname); res.send({ status: 'added' }); } catch (err) { next(err); @@ -114,7 +122,6 @@ router.delete('/peers/:id', async (req, res, next) => { } config.peers = config.peers.filter(peer => peer.id !== req.params.id); await persistConfig(); - await loadCAs(); res.send({ status: 'removed' }); } catch (err) { next(err); diff --git a/src/routers/p2p.ts b/src/routers/p2p.ts index 8d43cea..152d468 100644 --- a/src/routers/p2p.ts +++ b/src/routers/p2p.ts @@ -31,7 +31,7 @@ router.head('/ping', (_req, res) => { router.post('/messages', async (req, res, next) => { try { const cert = req.client.getPeerCertificate(); - const sender = cert.issuer.O + cert.issuer.OU; + const sender = utils.getPeerID(cert.issuer.O, cert.issuer.OU); const message = await utils.extractMessageFromMultipartForm(req); eventEmitter.emit('event', { type: 'message-received',