Skip to content

Commit 717a2f2

Browse files
authored
More graceful failure for expired certs (#1534)
* Relax `isPro` requirement in a few areas and rely upon `isSecured` as primary test condition * Trap TLS failure if certs are already expired * Change some verbiage so we know which routine tripped it. e.g. `...ing` vs `...ed`. This routine didn't work last time however things are of course different this year. This use case is finite to detect. Post #1532 #1533 and #37 Auto-merge
1 parent 1dd3737 commit 717a2f2

File tree

1 file changed

+64
-24
lines changed

1 file changed

+64
-24
lines changed

app.js

+64-24
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ app.use(function (aReq, aRes, aNext) {
269269
});
270270

271271
// Force HTTPS
272-
if (app.get('securePort') && isSecured) {
272+
if (isSecured) {
273273
sslOptions = {
274274
key: fs.readFileSync(privkey, 'utf8'),
275275
cert: fs.readFileSync(fullchain, 'utf8'),
@@ -300,26 +300,55 @@ if (app.get('securePort') && isSecured) {
300300
honorCipherOrder: true,
301301
secureOptions: crypto.constants.SSL_OP_NO_TLSv1
302302
};
303-
secureServer = https.createServer(sslOptions, app);
304303

305-
app.use(function (aReq, aRes, aNext) {
306-
aRes.setHeader('Strict-Transport-Security',
307-
'max-age=31536000000; includeSubDomains');
304+
try {
305+
secureServer = https.createServer(sslOptions, app);
308306

309-
if (!aReq.secure) {
310-
aRes.redirect(301, 'https://' + aReq.headers.host + encodeURI(aReq.url));
311-
return;
307+
app.use(function (aReq, aRes, aNext) {
308+
aRes.setHeader('Strict-Transport-Security',
309+
'max-age=31536000000; includeSubDomains');
310+
311+
if (!aReq.secure) {
312+
aRes.redirect(301, 'https://' + aReq.headers.host + encodeURI(aReq.url));
313+
return;
314+
}
315+
316+
aNext();
317+
});
318+
319+
secureServer.listen(app.get('securePort'));
320+
321+
} catch (aE) {
322+
console.error(colors.red('Server is NOT secured. Certificates may already be expired'));
323+
isSecured = false;
324+
console.warn(colors.cyan('Attempting to rename certificates'));
325+
try {
326+
fs.renameSync(privkey, privkey + '.expired')
327+
fs.renameSync(fullchain, fullchain + '.expired');
328+
fs.renameSync(chain, chain + '.expired');
329+
330+
console.warn(colors.green('Certificates renamed'));
331+
332+
// NOTE: Cached modules and/or callbacks may not reflect this change immediately
333+
// so must conclude with server trip
334+
335+
} catch (aE) {
336+
console.warn(colors.red('Error renaming certificates'));
312337
}
313338

314-
aNext();
315-
});
339+
// Trip the server now to try any alternate fallback certificates
340+
// If there aren't any it should run in http mode however usually no access through web
341+
// This should prevent logging DoS
316342

317-
server.listen(app.get('port'));
318-
secureServer.listen(app.get('securePort'));
319-
} else {
320-
server.listen(app.get('port'));
343+
beforeExit(); // NOTE: Event not triggered for direct `process.exit()`
344+
345+
process.exit(1);
346+
}
321347
}
322348

349+
// Always listen here but will usually be forwarded via FW
350+
server.listen(app.get('port'));
351+
323352
if (isDev || isDbg) {
324353
app.use(morgan('dev'));
325354
} else if (process.env.FORCE_MORGAN_PREDEF_FORMAT) {
@@ -351,7 +380,7 @@ app.use(session({
351380
unset: 'destroy',
352381
cookie: {
353382
maxAge: 5 * 60 * 1000, // minutes in ms NOTE: Expanded after successful auth
354-
secure: (isPro && isSecured ? true : false),
383+
secure: (isSecured ? true : false),
355384
sameSite: 'lax' // NOTE: Current auth necessity
356385
},
357386
rolling: true,
@@ -438,21 +467,32 @@ function tripServerOnCertExpire(aValidToString) {
438467
var tripDate = new Date(tlsDate.getTime() - (2 * 60 * 60 * 1000)); // ~2 hours before fault
439468

440469
if (nowDate.getTime() >= tripDate.getTime()) {
441-
console.warn(colors.red('Attempting server restart'));
442-
try {
443-
fs.renameSync(privkey, privkey + '.expired')
444-
fs.renameSync(fullchain, fullchain + '.expired');
445-
fs.renameSync(chain, chain + '.expired');
470+
console.error(colors.red('Certificates expiring very soon. Tripping server to unsecure mode'));
446471

447-
console.warn(colors.red('TLS (SSL) EXPIRING VERY SOON... TRIPPING SERVER TO HTTP!'));
472+
isSecured = false;
473+
474+
console.warn(colors.cyan('Attempting to rename certificates'));
475+
try {
476+
fs.renameSync(privkey, privkey + '.expiring')
477+
fs.renameSync(fullchain, fullchain + '.expiring');
478+
fs.renameSync(chain, chain + '.expiring');
448479

449-
beforeExit(); // NOTE: Event not triggered for direct `process.exit()`
480+
console.log(colors.green('Certificates renamed'));
450481

451-
process.exit(1);
482+
// NOTE: Cached modules and/or callbacks may not reflect this change immediately
483+
// so must conclude with server trip
452484

453485
} catch (aE) {
454-
// noop
486+
console.warn(colors.red('Error renaming certificates'));
455487
}
488+
489+
// Trip the server now to try any alternate fallback certificates
490+
// If there aren't any it should run in http mode however usually no access through web
491+
// This should prevent logging DoS
492+
493+
beforeExit(); // NOTE: Event not triggered for direct `process.exit()`
494+
495+
process.exit(1);
456496
}
457497
}
458498

0 commit comments

Comments
 (0)