navy
Version:
Quick and powerful development environments using Docker and Docker Compose
161 lines (159 loc) • 6.32 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = _default;
var _path = _interopRequireDefault(require("path"));
var _chalk = _interopRequireDefault(require("chalk"));
var _errors = require("../errors");
var _navy = require("../navy");
var _config = require("../config");
var _httpProxy = require("../http-proxy");
var _https = require("../util/https");
var _installRootCa = require("../util/install-root-ca");
var _fs = _interopRequireDefault(require("fs"));
function normaliseServiceArgs(services) {
if (services == null) {
return [];
}
if (Array.isArray(services)) {
const result = [];
for (const s of services) {
if (typeof s === 'string' && s !== '') {
result.push(s);
}
}
return result;
}
if (typeof services === 'string') {
return services ? [services] : [];
}
return [];
}
async function issueHttpsForServices(navy, serviceNames, availableServices) {
const httpsReadyServices = [];
for (const service of serviceNames) {
if (!availableServices.includes(service)) {
console.log(`❌ ${service} not found, skipping`);
continue;
}
const serviceUrl = await navy.url(service);
try {
await (0, _https.createCert)({
serviceUrl
});
httpsReadyServices.push(service);
} catch (error) {
console.log(error);
throw new _errors.NavyError(`Could not generate TLS cert for ${service}`);
}
}
return httpsReadyServices;
}
async function _default(services, opts) {
const tlsRootCaDir = (0, _config.getConfig)().tlsRootCaDir || _config.DEFAULT_TLS_ROOT_CA_DIR;
const configDir = (0, _config.getConfigDir)();
const serviceList = normaliseServiceArgs(services);
const hasIssue = Boolean(opts.issue);
if (opts.disable && (opts.setup || opts.all || hasIssue)) {
throw new _errors.NavyError('`--disable` cannot be combined with `--setup`, `--all`, or `--issue`.');
}
if ([opts.setup, opts.all, hasIssue].filter(Boolean).length > 1) {
throw new _errors.NavyError('Use only one of `--setup`, `--all`, or `--issue`.');
}
if (opts.disable) {
await (0, _https.removeCert)(opts);
// Guard isInitialised so `--disable` still works when the navy has
// never been launched (otherwise getNavyFile throws).
const navy = await (0, _navy.getNavy)(opts.navy);
const navyFile = (await navy.isInitialised()) ? await navy.getNavyFile() : undefined;
await (0, _httpProxy.reconfigureHTTPProxy)({
restart: true,
navyFile
});
console.log();
console.log(_chalk.default.green(`✅ HTTPS for service ${opts.disable} is now disabled`));
console.log();
return;
}
if (opts.setup) {
if (serviceList.length > 0) {
throw new _errors.NavyError('`navy https --setup` does not take service names. Run `navy https <service>…` separately to issue service certificates.');
}
await (0, _https.generateRootCa)();
const caCrt = _path.default.join(tlsRootCaDir, 'ca.crt');
(0, _installRootCa.installRootCaToTrustStore)(caCrt);
console.log();
console.log(_chalk.default.green('✅ Navy root CA is installed in your trust store (where supported).'));
console.log(_chalk.default.dim('Browsers that use their own NSS store (e.g. Firefox) may still need the CA imported there.'));
console.log();
return;
}
if (opts.all) {
if (serviceList.length > 0) {
throw new _errors.NavyError('`navy https --all` does not take service names. Omit them, or name services without `--all`.');
}
if (!_fs.default.existsSync(`${tlsRootCaDir}/ca.crt`) || !_fs.default.existsSync(`${tlsRootCaDir}/ca.key`)) {
await (0, _https.generateRootCa)();
}
const navy = await (0, _navy.getNavy)(opts.navy);
await navy.ensurePluginsLoaded();
const availableServices = await navy.getAvailableServiceNames();
if (availableServices.length === 0) {
console.log();
console.log(_chalk.default.yellow('No services found in this navy; nothing to enable HTTPS for.'));
console.log();
return;
}
const httpsReadyServices = await issueHttpsForServices(navy, availableServices, availableServices);
await (0, _httpProxy.reconfigureHTTPProxy)({
restart: true,
navyFile: await navy.getNavyFile()
});
console.log();
console.log(_chalk.default.green(`✅ Service(s) ${httpsReadyServices.join(', ')} now accessible via HTTPS🔒`));
console.log();
return;
}
if (hasIssue) {
if (serviceList.length > 0) {
throw new _errors.NavyError('`navy https --issue` does not take service names.');
}
const outDir = opts.issueOut ? _path.default.resolve(opts.issueOut) : process.cwd();
const paths = await (0, _https.issueLeafCertForUrl)(String(opts.issue), outDir);
console.log();
console.log(_chalk.default.green('✅ TLS certificate issued for use outside Navy:'));
console.log(` ${paths.certPath}`);
console.log(` ${paths.keyPath}`);
console.log(` ${paths.caCopyPath} (root CA; configure clients to trust this or append as a chain file)`);
console.log();
return;
}
if (serviceList.length === 0) {
if (!_fs.default.existsSync(`${configDir}/tls-certs`)) return;
const files = _fs.default.readdirSync(`${configDir}/tls-certs`);
const urls = files.filter(file => file.endsWith('.crt')).map(crt => {
return `https://${crt.replace('.crt', '')}`;
});
for (const url of urls) {
console.log(`${url}`);
}
return;
}
if (!_fs.default.existsSync(`${tlsRootCaDir}/ca.crt`) || !_fs.default.existsSync(`${tlsRootCaDir}/ca.key`)) {
await (0, _https.generateRootCa)();
}
const navy = await (0, _navy.getNavy)(opts.navy);
await navy.ensurePluginsLoaded();
const availableServices = await navy.getAvailableServiceNames();
const httpsReadyServices = await issueHttpsForServices(navy, serviceList, availableServices);
await (0, _httpProxy.reconfigureHTTPProxy)({
restart: true,
navyFile: await navy.getNavyFile()
});
console.log();
console.log(_chalk.default.green(`✅ Service(s) ${httpsReadyServices.join(', ')} now accessible via HTTPS🔒`));
console.log();
}
module.exports = exports.default;