@docusaurus/core
Version:
Easy to Maintain Open Source Documentation Websites
122 lines (121 loc) • 4.92 kB
JavaScript
;
/**
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.default = getHttpsConfig;
const tslib_1 = require("tslib");
const fs_extra_1 = tslib_1.__importDefault(require("fs-extra"));
const path_1 = tslib_1.__importDefault(require("path"));
const crypto_1 = tslib_1.__importDefault(require("crypto"));
const logger_1 = tslib_1.__importDefault(require("@docusaurus/logger"));
// Ensure the certificate and key provided are valid and if not
// throw an easy to debug error.
//
// Works for any key type (RSA, ECDSA, EdDSA, ...) — parses both PEMs and
// checks that the public key embedded in the cert matches the public key
// derived from the private key.
function validateKeyAndCerts({ cert, key }) {
let certPublicKey;
try {
certPublicKey = new crypto_1.default.X509Certificate(cert.content).publicKey;
}
catch (error) {
throw new Error(logger_1.default.interpolate `The certificate path=${cert.path} is invalid.`, { cause: error });
}
let keyPublicKey;
try {
keyPublicKey = crypto_1.default.createPublicKey(crypto_1.default.createPrivateKey(key.content));
}
catch (error) {
throw new Error(logger_1.default.interpolate `The certificate key path=${key.path} is invalid.`, { cause: error });
}
if (!certPublicKey.equals(keyPublicKey)) {
throw new Error(logger_1.default.interpolate `The certificate path=${cert.path} and key path=${key.path} do not match.`);
}
}
function getExplicitHttps(options) {
return (options.https ??
(typeof process.env.DOCUSAURUS_HTTPS !== 'undefined'
? process.env.DOCUSAURUS_HTTPS === 'true'
: undefined) ??
(typeof process.env.HTTPS !== 'undefined'
? process.env.HTTPS === 'true'
: undefined));
}
async function readCryptoFile(filepath, source) {
if (!(await fs_extra_1.default.pathExists(filepath))) {
throw new Error(logger_1.default.interpolate `You specified ${source}, but file at path path=${filepath} can't be found.`);
}
try {
return {
path: filepath,
source,
content: await fs_extra_1.default.readFile(filepath),
};
}
catch (error) {
throw new Error(logger_1.default.interpolate `You specified ${source}, but file at path path=${filepath} can't be read.`, { cause: error });
}
}
function getCert(options, cwd) {
if (options.sslCert) {
return readCryptoFile(path_1.default.resolve(cwd, options.sslCert), 'CLI arg --ssl-cert');
}
if (process.env.DOCUSAURUS_SSL_CRT_FILE) {
return readCryptoFile(path_1.default.resolve(cwd, process.env.DOCUSAURUS_SSL_CRT_FILE), 'env DOCUSAURUS_SSL_CRT_FILE');
}
if (process.env.SSL_CRT_FILE) {
return readCryptoFile(path_1.default.resolve(cwd, process.env.SSL_CRT_FILE), 'env SSL_CRT_FILE');
}
return null;
}
function getKeyFile(options, cwd) {
if (options.sslKey) {
return readCryptoFile(path_1.default.resolve(cwd, options.sslKey), 'CLI arg --ssl-key');
}
if (process.env.DOCUSAURUS_SSL_KEY_FILE) {
return readCryptoFile(path_1.default.resolve(cwd, process.env.DOCUSAURUS_SSL_KEY_FILE), 'env DOCUSAURUS_SSL_KEY_FILE');
}
if (process.env.SSL_KEY_FILE) {
return readCryptoFile(path_1.default.resolve(cwd, process.env.SSL_KEY_FILE), 'env SSL_KEY_FILE');
}
return null;
}
function ensureCertKeyBothProvided(cert, key) {
if ((cert || key) && !(cert && key)) {
const fileProvided = (cert ?? key);
throw new Error(logger_1.default.interpolate `HTTPS support require proving a certificate and key at the same time.
You only provided a ${cert ? 'certificate' : 'key'} (with ${fileProvided.source}) at path path=${fileProvided.path}.`);
}
}
// Get the https config
// Return cert files if provided via CLI or env, otherwise just true or false.
// CLI options take precedence over env vars.
async function getHttpsConfig(options = {}) {
const cwd = await fs_extra_1.default.realpath(process.cwd());
const [cert, key] = await Promise.all([
getCert(options, cwd),
getKeyFile(options, cwd),
]);
// Providing both cert/key implies HTTPS
const inferredHttps = !!(cert && key);
const https = getExplicitHttps(options) ?? inferredHttps;
if (https && cert && key) {
validateKeyAndCerts({
cert,
key,
});
return {
cert: cert.content,
key: key.content,
};
}
ensureCertKeyBothProvided(cert, key);
// Apparently we can have https without cert/key (historical)
// although I don't know how this works 🤷♂️
return https;
}