ensure fallback certificates of all domains
https://forum.cloudron.io/topic/5683/data-argument-must-be-of-type-received-null-error-during-restore-process
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
'use strict';
|
||||
|
||||
const async = require('async'),
|
||||
reverseProxy = require('../src/reverseproxy.js'),
|
||||
safe = require('safetydance');
|
||||
|
||||
const NGINX_CERT_DIR = '/home/yellowtent/platformdata/nginx/cert';
|
||||
|
||||
// ensure fallbackCertificate of domains are present in database and the cert dir. it seems a bad migration lost them.
|
||||
// https://forum.cloudron.io/topic/5683/data-argument-must-be-of-type-received-null-error-during-restore-process
|
||||
exports.up = function(db, callback) {
|
||||
db.all('SELECT * FROM domains', [ ], function (error, domains) {
|
||||
if (error) return callback(error);
|
||||
|
||||
async.eachSeries(domains, async function (domain, iteratorDone) {
|
||||
let fallbackCertificate = safe.JSON.parse(domain.fallbackCertificateJson);
|
||||
if (!fallbackCertificate || !fallbackCertificate.cert || !fallbackCertificate.key) {
|
||||
let error;
|
||||
[error, fallbackCertificate] = await safe(reverseProxy.generateFallbackCertificate(domain.domain));
|
||||
if (error) return iteratorDone(error);
|
||||
}
|
||||
|
||||
if (!safe.fs.writeFileSync(`${NGINX_CERT_DIR}/${domain.domain}.host.cert`, fallbackCertificate.cert, 'utf8')) return iteratorDone(safe.error);
|
||||
if (!safe.fs.writeFileSync(`${NGINX_CERT_DIR}/${domain.domain}.host.key`, fallbackCertificate.key, 'utf8')) return iteratorDone(safe.error);
|
||||
|
||||
db.runSql('UPDATE domains SET fallbackCertificateJson=? WHERE domain=?', [ JSON.stringify(fallbackCertificate), domain.domain ], iteratorDone);
|
||||
}, callback);
|
||||
});
|
||||
};
|
||||
|
||||
exports.down = function(db, callback) {
|
||||
callback();
|
||||
};
|
||||
@@ -142,7 +142,6 @@ async function add(domain, data, auditSource) {
|
||||
if (error) throw error;
|
||||
} else {
|
||||
fallbackCertificate = await reverseProxy.generateFallbackCertificate(domain);
|
||||
if (fallbackCertificate.error) throw fallbackCertificate.error;
|
||||
}
|
||||
|
||||
let error = validateTlsConfig(tlsConfig, provider);
|
||||
|
||||
+9
-8
@@ -192,36 +192,37 @@ async function reload() {
|
||||
if (error) throw new BoxError(BoxError.NGINX_ERROR, `Error reloading nginx: ${error.message}`);
|
||||
}
|
||||
|
||||
// this is used in migration - 20211006200150-domains-ensure-fallbackCertificate.js
|
||||
async function generateFallbackCertificate(domain) {
|
||||
assert.strictEqual(typeof domain, 'string');
|
||||
|
||||
const certFilePath = path.join(os.tmpdir(), `${domain}-${crypto.randomBytes(4).readUInt32LE(0)}.cert`);
|
||||
const keyFilePath = path.join(os.tmpdir(), `${domain}-${crypto.randomBytes(4).readUInt32LE(0)}.key`);
|
||||
|
||||
let opensslConf = safe.fs.readFileSync('/etc/ssl/openssl.cnf', 'utf8');
|
||||
const opensslConf = safe.fs.readFileSync('/etc/ssl/openssl.cnf', 'utf8');
|
||||
// SAN must contain all the domains since CN check is based on implementation if SAN is found. -checkhost also checks only SAN if present!
|
||||
let opensslConfWithSan;
|
||||
let cn = domain;
|
||||
const cn = domain;
|
||||
|
||||
debug(`generateFallbackCertificateSync: domain=${domain} cn=${cn}`);
|
||||
|
||||
opensslConfWithSan = `${opensslConf}\n[SAN]\nsubjectAltName=DNS:${domain},DNS:*.${cn}\n`;
|
||||
let configFile = path.join(os.tmpdir(), 'openssl-' + crypto.randomBytes(4).readUInt32LE(0) + '.conf');
|
||||
const configFile = path.join(os.tmpdir(), 'openssl-' + crypto.randomBytes(4).readUInt32LE(0) + '.conf');
|
||||
safe.fs.writeFileSync(configFile, opensslConfWithSan, 'utf8');
|
||||
// the days field is chosen to be less than 825 days per apple requirement (https://support.apple.com/en-us/HT210176)
|
||||
let certCommand = util.format(`openssl req -x509 -newkey rsa:2048 -keyout ${keyFilePath} -out ${certFilePath} -days 800 -subj /CN=*.${cn} -extensions SAN -config ${configFile} -nodes`);
|
||||
if (!safe.child_process.execSync(certCommand)) return { error: new BoxError(BoxError.OPENSSL_ERROR, safe.error.message) };
|
||||
const certCommand = util.format(`openssl req -x509 -newkey rsa:2048 -keyout ${keyFilePath} -out ${certFilePath} -days 800 -subj /CN=*.${cn} -extensions SAN -config ${configFile} -nodes`);
|
||||
if (!safe.child_process.execSync(certCommand)) throw new BoxError(BoxError.OPENSSL_ERROR, safe.error.message);
|
||||
safe.fs.unlinkSync(configFile);
|
||||
|
||||
const cert = safe.fs.readFileSync(certFilePath, 'utf8');
|
||||
if (!cert) return { error: new BoxError(BoxError.FS_ERROR, safe.error.message) };
|
||||
if (!cert) throw new BoxError(BoxError.FS_ERROR, safe.error.message);
|
||||
safe.fs.unlinkSync(certFilePath);
|
||||
|
||||
const key = safe.fs.readFileSync(keyFilePath, 'utf8');
|
||||
if (!key) return { error: new BoxError(BoxError.FS_ERROR, safe.error.message) };
|
||||
if (!key) throw new BoxError(BoxError.FS_ERROR, safe.error.message);
|
||||
safe.fs.unlinkSync(keyFilePath);
|
||||
|
||||
return { cert: cert, key: key, error: null };
|
||||
return { cert, key };
|
||||
}
|
||||
|
||||
async function setFallbackCertificate(domain, fallback) {
|
||||
|
||||
@@ -131,7 +131,6 @@ describe('Reverse Proxy', function () {
|
||||
it('can generate fallback certs', async function () {
|
||||
result = await reverseProxy.generateFallbackCertificate(domainObject.domain);
|
||||
expect(result).to.be.ok();
|
||||
expect(result.error).to.be(null);
|
||||
});
|
||||
|
||||
it('can validate the certs', function () {
|
||||
|
||||
Reference in New Issue
Block a user