mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-12 23:04:52 +09:00
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:
1 parent
cc87654742
commit
44b7d0aa19
5 files changed
+58
-52
No files matched your search
@@ -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
@@ -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
@@ -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);
|
||||
});
|
||||
});
|
||||
@@ -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,
|
||||
});
|
||||
}
|
||||
@@ -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,
|
||||
|
||||
Reference in new issue
Block a user