UNPKG

navy

Version:

Quick and powerful development environments using Docker and Docker Compose

282 lines (280 loc) 13 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); var _chai = require("chai"); var _sinon = _interopRequireDefault(require("sinon")); var _proxyquire = _interopRequireDefault(require("proxyquire")); var _path = _interopRequireDefault(require("path")); var _errors = require("../../errors"); /* eslint-env mocha */ describe('util/install-root-ca', function () { let sandbox; let fsStub; let osStub; let execFileSyncStub; let installRootCaModule; let platformStub; const caPath = '/tmp/navy/ca.crt'; function certutilPath(systemRoot = 'C:\\Windows') { return _path.default.join(systemRoot, 'System32', 'certutil.exe'); } function expectThrownMessage(fn, messagePattern) { let caught; try { fn(); } catch (err) { caught = err; } (0, _chai.expect)(caught).to.not.equal(undefined); (0, _chai.expect)(String(caught.message)).to.match(messagePattern); } function loadModule() { installRootCaModule = _proxyquire.default.noCallThru()('../install-root-ca', { '../errors': { NavyError: _errors.NavyError }, fs: fsStub, os: osStub, child_process: { execFileSync: execFileSyncStub } }); } beforeEach(function () { sandbox = _sinon.default.createSandbox(); fsStub = { existsSync: sandbox.stub() }; osStub = { homedir: sandbox.stub().returns('/Users/tester') }; execFileSyncStub = sandbox.stub(); platformStub = sandbox.stub(process, 'platform').value('darwin'); loadModule(); }); afterEach(function () { sandbox.restore(); }); describe('caughtErrorMessage', function () { it('should return nullish values as strings', function () { (0, _chai.expect)(installRootCaModule.caughtErrorMessage(null)).to.equal('null'); (0, _chai.expect)(installRootCaModule.caughtErrorMessage(undefined)).to.equal('undefined'); }); it('should return message text when it is present', function () { (0, _chai.expect)(installRootCaModule.caughtErrorMessage({ message: 'object failed' })).to.equal('object failed'); (0, _chai.expect)(installRootCaModule.caughtErrorMessage(new Error('error failed'))).to.equal('error failed'); }); it('should fall back to String(e) when no usable message exists', function () { (0, _chai.expect)(installRootCaModule.caughtErrorMessage('plain failure')).to.equal('plain failure'); (0, _chai.expect)(installRootCaModule.caughtErrorMessage({})).to.equal('[object Object]'); (0, _chai.expect)(installRootCaModule.caughtErrorMessage({ message: '' })).to.equal('[object Object]'); }); }); describe('installRootCaToTrustStore', function () { it('should throw when the CA file does not exist', function () { fsStub.existsSync.returns(false); expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /CA certificate not found/); }); describe('macOS', function () { beforeEach(function () { platformStub.value('darwin'); fsStub.existsSync.callsFake(p => p === caPath || p.endsWith('login.keychain-db')); }); it('should add the CA to the login keychain when found', function () { installRootCaModule.installRootCaToTrustStore(caPath); (0, _chai.expect)(execFileSyncStub.calledOnce).to.equal(true); (0, _chai.expect)(execFileSyncStub.firstCall.args[0]).to.equal('security'); (0, _chai.expect)(execFileSyncStub.firstCall.args[1]).to.eql(['add-trusted-cert', '-d', '-r', 'trustRoot', '-k', '/Users/tester/Library/Keychains/login.keychain-db', caPath]); }); it('should fall back to login.keychain when login.keychain-db is missing', function () { fsStub.existsSync.callsFake(p => p === caPath || p.endsWith('login.keychain')); installRootCaModule.installRootCaToTrustStore(caPath); (0, _chai.expect)(execFileSyncStub.firstCall.args[1][5]).to.equal('/Users/tester/Library/Keychains/login.keychain'); }); it('should throw when no login keychain can be found', function () { fsStub.existsSync.callsFake(p => p === caPath); expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /Could not find your macOS login keychain/); }); it('should wrap security command failures in NavyError', function () { execFileSyncStub.throws(new Error('security failed')); expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /Could not add the Navy root CA/); }); it('should use error.message when the thrown value exposes one', function () { execFileSyncStub.throws({ message: 'security object failed' }); expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /security object failed/); }); it('should stringify non-Error exec failures', function () { execFileSyncStub.throws('plain failure'); expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /plain failure/); }); it('should stringify null exec failures', function () { execFileSyncStub.callsFake(() => { const thrown = null; throw thrown; }); expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /null/); }); }); describe('linux', function () { beforeEach(function () { platformStub.value('linux'); fsStub.existsSync.callsFake(p => p === caPath); }); it('should install via update-ca-certificates on Debian-style systems', function () { fsStub.existsSync.callsFake(p => { if (p === caPath) return true; if (p === '/usr/sbin/update-ca-certificates') return true; return false; }); installRootCaModule.installRootCaToTrustStore(caPath); (0, _chai.expect)(execFileSyncStub.callCount).to.equal(2); (0, _chai.expect)(execFileSyncStub.firstCall.args[0]).to.equal('sudo'); (0, _chai.expect)(execFileSyncStub.firstCall.args[1]).to.eql(['cp', caPath, '/usr/local/share/ca-certificates/navy-dev-ca.crt']); (0, _chai.expect)(execFileSyncStub.secondCall.args[1]).to.eql(['/usr/sbin/update-ca-certificates']); }); it('should wrap Debian install failures in NavyError', function () { fsStub.existsSync.callsFake(p => { if (p === caPath) return true; if (p === '/usr/sbin/update-ca-certificates') return true; return false; }); execFileSyncStub.throws(new Error('sudo denied')); expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /update-ca-certificates/); }); it('should use error.message for Debian install failures when present', function () { fsStub.existsSync.callsFake(p => { if (p === caPath) return true; if (p === '/usr/sbin/update-ca-certificates') return true; return false; }); execFileSyncStub.throws({ message: 'debian object failed' }); expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /debian object failed/); }); it('should stringify null Debian install failures', function () { fsStub.existsSync.callsFake(p => { if (p === caPath) return true; if (p === '/usr/sbin/update-ca-certificates') return true; return false; }); execFileSyncStub.callsFake(() => { const thrown = null; throw thrown; }); expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /null/); }); it('should install via update-ca-trust on Fedora-style systems', function () { fsStub.existsSync.callsFake(p => { if (p === caPath) return true; if (p === '/usr/bin/update-ca-trust') return true; return false; }); installRootCaModule.installRootCaToTrustStore(caPath); (0, _chai.expect)(execFileSyncStub.callCount).to.equal(2); (0, _chai.expect)(execFileSyncStub.secondCall.args[1]).to.eql(['/usr/bin/update-ca-trust', 'extract']); }); it('should wrap Fedora install failures in NavyError', function () { fsStub.existsSync.callsFake(p => { if (p === caPath) return true; if (p === '/usr/bin/update-ca-trust') return true; return false; }); execFileSyncStub.throws(new Error('trust failed')); expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /update-ca-trust/); }); it('should use error.message for Fedora install failures when present', function () { fsStub.existsSync.callsFake(p => { if (p === caPath) return true; if (p === '/usr/bin/update-ca-trust') return true; return false; }); execFileSyncStub.throws({ message: 'fedora object failed' }); expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /fedora object failed/); }); it('should stringify null Fedora install failures', function () { fsStub.existsSync.callsFake(p => { if (p === caPath) return true; if (p === '/usr/bin/update-ca-trust') return true; return false; }); execFileSyncStub.callsFake(() => { const thrown = null; throw thrown; }); expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /null/); }); it('should throw when no supported Linux tooling is present', function () { expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /Automatic Linux install needs/); }); }); describe('windows', function () { beforeEach(function () { platformStub.value('win32'); fsStub.existsSync.callsFake(p => p === caPath); }); it('should add the CA via certutil when available', function () { const certutil = certutilPath(); fsStub.existsSync.callsFake(p => p === caPath || p === certutil); installRootCaModule.installRootCaToTrustStore(caPath); (0, _chai.expect)(execFileSyncStub.calledOnce).to.equal(true); (0, _chai.expect)(execFileSyncStub.firstCall.args[0]).to.equal(certutil); (0, _chai.expect)(execFileSyncStub.firstCall.args[1]).to.eql(['-user', '-addstore', 'Root', caPath]); }); it('should use SystemRoot from the environment when set', function () { const previousSystemRoot = process.env.SystemRoot; process.env.SystemRoot = 'D:\\WinRoot'; const certutil = certutilPath('D:\\WinRoot'); fsStub.existsSync.callsFake(p => p === caPath || p === certutil); try { installRootCaModule.installRootCaToTrustStore(caPath); (0, _chai.expect)(execFileSyncStub.firstCall.args[0]).to.equal(certutil); } finally { if (previousSystemRoot === undefined) { delete process.env.SystemRoot; } else { process.env.SystemRoot = previousSystemRoot; } } }); it('should throw when certutil.exe is missing', function () { expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /certutil.exe not found/); }); it('should wrap certutil failures in NavyError', function () { const certutil = certutilPath(); fsStub.existsSync.callsFake(p => p === caPath || p === certutil); execFileSyncStub.throws(new Error('certutil failed')); expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /Trusted Root store/); }); it('should use error.message for certutil failures when present', function () { const certutil = certutilPath(); fsStub.existsSync.callsFake(p => p === caPath || p === certutil); execFileSyncStub.throws({ message: 'certutil object failed' }); expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /certutil object failed/); }); it('should stringify null certutil failures', function () { const certutil = certutilPath(); fsStub.existsSync.callsFake(p => p === caPath || p === certutil); execFileSyncStub.callsFake(() => { const thrown = null; throw thrown; }); expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /null/); }); }); it('should throw on unsupported platforms', function () { platformStub.value('freebsd'); fsStub.existsSync.returns(true); expectThrownMessage(() => installRootCaModule.installRootCaToTrustStore(caPath), /not supported on freebsd/); }); }); });