From e844e4bd34a918cf0a323ec269880fa6ec85a854 Mon Sep 17 00:00:00 2001 From: John Knox Date: Mon, 16 Jul 2018 07:11:04 -0700 Subject: [PATCH] Detect expired server certificates Summary: We have a check for whenever the server cert is expiring within 1 day, however this turns out it doesn't count certificates that have already expired. So adding a check for those that have already expired, and regenerating them if so. We can safely handle parse failures by assuming the cert has expired. Reviewed By: passy Differential Revision: D8858740 fbshipit-source-id: 6e06f9b267bcaec497b7eedd3d6c1974c788aea2 --- src/utils/CertificateProvider.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/utils/CertificateProvider.js b/src/utils/CertificateProvider.js index b753f2be3..2f9dc7604 100644 --- a/src/utils/CertificateProvider.js +++ b/src/utils/CertificateProvider.js @@ -351,6 +351,11 @@ export default class CertificateProvider { if (!fs.existsSync(filename)) { return Promise.reject(); } + // openssl checkend is a nice feature but it only checks for certificates + // expiring in the future, not those that have already expired. + // So we need a separate check for certificates that have already expired + // but since this involves parsing date outputs from openssl, which is less + // reliable, keeping both checks for safety. return openssl('x509', { checkend: minCertExpiryWindowSeconds, in: filename, @@ -359,6 +364,31 @@ export default class CertificateProvider { .catch(e => { console.warn(`Certificate will expire soon: ${filename}`, logTag); throw e; + }) + .then(_ => + openssl('x509', { + enddate: true, + in: filename, + noout: true, + }), + ) + .then(endDateOutput => { + const dateString = endDateOutput + .trim() + .split('=')[1] + .trim(); + const expiryDate = Date.parse(dateString); + if (isNaN(expiryDate)) { + console.error( + 'Unable to parse certificate expiry date: ' + endDateOutput, + ); + throw new Error( + 'Cannot parse certificate expiry date. Assuming it has expired.', + ); + } + if (expiryDate <= Date.now() + minCertExpiryWindowSeconds * 1000) { + throw new Error('Certificate has expired or will expire soon.'); + } }); }