UNPKG

@docusaurus/core

Version:

Easy to Maintain Open Source Documentation Websites

122 lines (121 loc) 4.92 kB
"use strict"; /** * 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; }