Refactor SSL certificate creation

Rewrite the generateSSLcert lib to be async, use the sslCert and
sslPrivKey config entries and invoke it only if needed during master
server startup instead of in the post install script.  Also add note to
the changelog covering both this and the fix in c645fac.
This commit is contained in:
Hornwitser committed 2019-08-23 17:24:39 +02:00
1 parent cc87654742
commit 44b7d0aa19
5 files changed
+58 -52

No files matched your search

+3
View File
@@ -1,6 +1,9 @@
Version 2.0.0
=============
- Fixed sslCert and sslPrivKey entries being ignored in the config.
- Changed ssl key creation to be done at startup instead of on npm install.
Breaking Changes
----------------
- Node.js versions below 10 are no longer supported.
+23 -28
View File
@@ -1,49 +1,44 @@
var forge = require("node-forge");
forge.options.usePureJavaScript = true;
var fs = require("fs");
var mkdirp = require("mkdirp");
const forge = require("node-forge");
const fs = require("fs-extra");
const util = require("util");
var pki = forge.pki;
var rsa = forge.pki.rsa;
var startTime, endTime;
const hrtime = process.hrtime.bigint;
module.exports = function({
module.exports = async function({
bits = 2048,
certificatePath = "database/certificate",
sslCertPath,
sslPrivKeyPath,
doLogging = false,
} = {}){
function log(t){
function log(t) {
if(doLogging) console.log("lib/generateSSLcert.js | "+t);
}
log("Generating SSL certificate with "+bits+" bits at "+certificatePath);
log("Generating SSL certificate with "+bits+" bits at "+sslCertPath);
startTime = Date.now();
var keypair = rsa.generateKeyPair({bits: bits, e: 0x10001});
endTime = Date.now();
log("Generated 2048bit keypair in: "+(endTime-startTime)+" ms");
let startNs = hrtime();
let keypair = await util.promisify(forge.pki.rsa.generateKeyPair)({bits: bits, e: 0x10001});
log("Generated 2048bit keypair in: "+(Number(hrtime()-startNs) / 1e6)+" ms");
startTime = Date.now();
var cert = pki.createCertificate();
startNs = hrtime();
let cert = forge.pki.createCertificate();
cert.publicKey = keypair.publicKey;
cert.serialNumber = "01";
cert.validity.notBefore = new Date();
cert.validity.notAfter = new Date(Date.now()+(1000*60*60*24*365)); // valid for one year
// XXX This should probably be limited to the actual hostname
let attrs = [{ name: "commonName", value: "*" }];
cert.setSubject(attrs);
cert.setIssuer(attrs);
// self-sign certificate
cert.sign(keypair.privateKey);
// Convert certificate to pem type and write it to a file
if(certificatePath[certificatePath.length-1] != "/") certificatePath += "/";
if(!fs.existsSync(certificatePath)) {
mkdirp.sync(certificatePath);
console.log("Created directory: "+certificatePath);
}
fs.writeFileSync(certificatePath+ "cert.key", pki.privateKeyToPem(keypair.privateKey));
fs.writeFileSync(certificatePath+ "cert.crt", pki.certificateToPem(cert));
// Write certificate and private key to pem files
await fs.outputFile(sslPrivKeyPath, forge.pki.privateKeyToPem(keypair.privateKey));
await fs.outputFile(sslCertPath, forge.pki.certificateToPem(cert));
endTime = Date.now();
log("Generated certificate in: "+(endTime-startTime)+" ms");
log("Generated certificate in: "+(Number(hrtime()-startNs) / 1e6)+" ms");
}
+13 -12
View File
@@ -1,25 +1,26 @@
var assert = require("assert");
var fs = require("fs");
var fs = require("fs-extra");
var fileOps = require("lib/fileOps");
var generateSSLcert = require("./generateSSLcert.js")
var generateSSLcert = require("lib/generateSSLcert.js")
describe("generateSSLcert.js(options)", ()=>{
it("Creates a folder with a .crt and .key file in it", ()=>{
let certPath = "lib/certTestPlsDelete";
assert(!fs.existsSync(certPath)); // if it already exsits, the test might pass because of leftover data (which is bad)
it("Creates a folder with a .crt and .key file in it", async function() {
let certPath = "lib/certTestPlsDelete/cert.crt";
let privKeyPath = "lib/certTestPlsDelete/cert.key";
assert(!await fs.exists(certPath)); // if it already exsits, the test might pass because of leftover data (which is bad)
generateSSLcert({
await generateSSLcert({
// bits:512, // supported, but I just use the default of 2048 for this test
certificatePath:certPath,
sslCertPath: certPath,
sslPrivKeyPath: privKeyPath,
doLogging: false,
});
assert(fs.existsSync(certPath));
assert(fs.existsSync(certPath+"/cert.key")); // private key
assert(fs.existsSync(certPath+"/cert.crt")); // certificate file
assert(await fs.exists(certPath)); // private key
assert(await fs.exists(privKeyPath)); // certificate file
// remove certificates and data from the test
fileOps.deleteFolderRecursiveSync(certPath);
fileOps.deleteFolderRecursiveSync("lib/certTestPlsDelete");
}).timeout(10000);
});
});
-10
View File
@@ -123,13 +123,3 @@ function processDownloadRecursive(callback){
}
});
}
// generate SSL certificates if they are missing
if(!fs.existsSync("database/certificates") || !fs.existsSync("database/certificates/cert.crt") || !fs.existsSync("database/certificates/cert.key")){
var generateSSLcert = require("./generateSSLcert.js");
generateSSLcert({
certificatePath: "database/certificates",
doLogging: true,
});
}
+19 -2
View File
@@ -41,6 +41,7 @@ mkdirp.sync(config.databaseDirectory);
mkdirp.sync(masterModFolder);
// homebrew modules
const generateSSLcert = require("lib/generateSSLcert");
const getFactorioLocale = require("lib/getFactorioLocale");
// homemade express middleware for token auth
@@ -1005,6 +1006,15 @@ async function startServer() {
process.exit(1);
}
// Create a self signed certificate if the certificate files doesn't exist
if (httpsPort && !await fs.exists(config.sslCert) && !await fs.exists(config.sslPrivKey)) {
await generateSSLcert({
sslCertPath: config.sslCert,
sslPrivKeyPath: config.sslPrivKey,
doLogging: true,
});
}
// Load plugins
await pluginManagement();
@@ -1016,8 +1026,15 @@ async function startServer() {
}
if (httpsPort) {
var certificate = fs.readFileSync(config.sslCert);
var privateKey = fs.readFileSync(config.sslPrivKey);
let certificate, privateKey;
try {
certificate = await fs.readFile(config.sslCert);
privateKey = await fs.readFile(config.sslPrivKey);
} catch (err) {
console.error(`Error loading ssl certificate: ${err.message}`);
await shutdown()
}
let httpsServer = require("https").createServer({
key: privateKey,