UNPKG

@adobe/ccweb-add-on-devcert

Version:

Generate trusted local SSL/TLS certificates for local SSL development

128 lines 17.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const debug_1 = tslib_1.__importDefault(require("debug")); const crypto_1 = tslib_1.__importDefault(require("crypto")); const fs_1 = require("fs"); const rimraf_1 = require("rimraf"); const shared_1 = require("./shared"); const utils_1 = require("../utils"); const user_interface_1 = tslib_1.__importDefault(require("../user-interface")); const debug = debug_1.default('devcert:platforms:windows'); let encryptionKey; class WindowsPlatform { constructor() { this.HOST_FILE_PATH = 'C:\\Windows\\System32\\Drivers\\etc\\hosts'; } /** * Windows is at least simple. Like macOS, most applications will delegate to * the system trust store, which is updated with the confusingly named * `certutil` exe (not the same as the NSS/Mozilla certutil). Firefox does it's * own thing as usual, and getting a copy of NSS certutil onto the Windows * machine to try updating the Firefox store is basically a nightmare, so we * don't even try it - we just bail out to the GUI. */ addToTrustStores(certificatePath, options = {}) { return tslib_1.__awaiter(this, void 0, void 0, function* () { // IE, Chrome, system utils debug('adding devcert root to Windows OS trust store'); try { utils_1.run('certutil', ['-addstore', '-user', 'root', certificatePath]); } catch (e) { e.output.map((buffer) => { if (buffer) { console.log(buffer.toString()); } }); } debug('adding devcert root to Firefox trust store'); // Firefox (don't even try NSS certutil, no easy install for Windows) try { yield shared_1.openCertificateInFirefox('start firefox', certificatePath); } catch (_a) { debug('Error opening Firefox, most likely Firefox is not installed'); } }); } removeFromTrustStores(certificatePath) { debug('removing devcert root from Windows OS trust store'); try { console.warn('Removing old certificates from trust stores. You may be prompted to grant permission for this. It\'s safe to delete old devcert certificates.'); utils_1.run('certutil', ['-delstore', '-user', 'root', 'devcert']); } catch (e) { debug(`failed to remove ${certificatePath} from Windows OS trust store, continuing. ${e.toString()}`); } } addDomainToHostFileIfMissing(domain) { return tslib_1.__awaiter(this, void 0, void 0, function* () { if (!fs_1.existsSync(this.HOST_FILE_PATH)) { console.warn('Could not locate the host file in your system.'); console.warn('Please ensure to have:'); console.log(`127.0.0.1 ${domain}`); console.warn("entry in your system's host file."); return; } let hostsFileContents = fs_1.readFileSync(this.HOST_FILE_PATH, 'utf8'); if (!hostsFileContents.includes(domain)) { yield utils_1.sudo(`echo 127.0.0.1 ${domain} >> ${this.HOST_FILE_PATH}`); } }); } deleteProtectedFiles(filepath) { shared_1.assertNotTouchingFiles(filepath, 'delete'); rimraf_1.sync(filepath); } readProtectedFile(filepath) { return tslib_1.__awaiter(this, void 0, void 0, function* () { shared_1.assertNotTouchingFiles(filepath, 'read'); if (!encryptionKey) { encryptionKey = yield user_interface_1.default.getWindowsEncryptionPassword(); } // Try to decrypt the file try { return this.decrypt(fs_1.readFileSync(filepath, 'utf8'), encryptionKey); } catch (e) { // If it's a bad password, clear the cached copy and retry if (e.message.indexOf('bad decrypt') >= -1) { encryptionKey = null; return yield this.readProtectedFile(filepath); } throw e; } }); } writeProtectedFile(filepath, contents) { return tslib_1.__awaiter(this, void 0, void 0, function* () { shared_1.assertNotTouchingFiles(filepath, 'write'); if (!encryptionKey) { encryptionKey = yield user_interface_1.default.getWindowsEncryptionPassword(); } let encryptedContents = this.encrypt(contents, encryptionKey); fs_1.writeFileSync(filepath, encryptedContents); }); } encrypt(text, key) { const algorithm = 'aes-256-cbc'; const iv = crypto_1.default.randomBytes(16); const keyBuffer = crypto_1.default.createHash('sha256').update(key).digest(); const cipher = crypto_1.default.createCipheriv(algorithm, keyBuffer, iv); const encrypted = Buffer.concat([cipher.update(text, 'utf8'), cipher.final()]); return iv.toString('hex') + ':' + encrypted.toString('hex'); } decrypt(encryptedText, key) { const algorithm = 'aes-256-cbc'; const keyBuffer = crypto_1.default.createHash('sha256').update(key).digest(); const [ivHex, encryptedHex] = encryptedText.split(':'); const iv = Buffer.from(ivHex, 'hex'); const encryptedBuffer = Buffer.from(encryptedHex, 'hex'); const decipher = crypto_1.default.createDecipheriv(algorithm, keyBuffer, iv); const decrypted = Buffer.concat([decipher.update(encryptedBuffer), decipher.final()]); return decrypted.toString('utf8'); } } exports.default = WindowsPlatform; //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoid2luMzIuanMiLCJzb3VyY2VSb290IjoiLi8iLCJzb3VyY2VzIjpbInBsYXRmb3Jtcy93aW4zMi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSwwREFBZ0M7QUFDaEMsNERBQTRCO0FBQzVCLDJCQUF3RjtBQUN4RixtQ0FBd0M7QUFFeEMscUNBQTRFO0FBRTVFLG9DQUFxQztBQUNyQywrRUFBbUM7QUFFbkMsTUFBTSxLQUFLLEdBQUcsZUFBVyxDQUFDLDJCQUEyQixDQUFDLENBQUM7QUFFdkQsSUFBSSxhQUFxQixDQUFDO0FBRTFCLE1BQXFCLGVBQWU7SUFBcEM7UUFFVSxtQkFBYyxHQUFHLDRDQUE0QyxDQUFDO0lBZ0h4RSxDQUFDO0lBOUdDOzs7Ozs7O09BT0c7SUFDRyxnQkFBZ0IsQ0FBQyxlQUF1QixFQUFFLFVBQW1CLEVBQUU7O1lBQ25FLDJCQUEyQjtZQUMzQixLQUFLLENBQUMsK0NBQStDLENBQUMsQ0FBQTtZQUN0RCxJQUFJO2dCQUNGLFdBQUcsQ0FBQyxVQUFVLEVBQUUsQ0FBQyxXQUFXLEVBQUUsT0FBTyxFQUFFLE1BQU0sRUFBRSxlQUFlLENBQUMsQ0FBQyxDQUFDO2FBQ2xFO1lBQUMsT0FBTyxDQUFDLEVBQUU7Z0JBQ1YsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxNQUFjLEVBQUUsRUFBRTtvQkFDOUIsSUFBSSxNQUFNLEVBQUU7d0JBQ1YsT0FBTyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQztxQkFDaEM7Z0JBQ0gsQ0FBQyxDQUFDLENBQUM7YUFDSjtZQUNELEtBQUssQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFBO1lBQ25ELHFFQUFxRTtZQUNyRSxJQUFJO2dCQUNGLE1BQU0saUNBQXdCLENBQUMsZUFBZSxFQUFFLGVBQWUsQ0FBQyxDQUFDO2FBQ2xFO1lBQUMsV0FBTTtnQkFDTixLQUFLLENBQUMsNkRBQTZELENBQUMsQ0FBQzthQUN0RTtRQUNILENBQUM7S0FBQTtJQUVELHFC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QyxlQUFlLENBQUMsRUFBRSxRQUFRLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBRXRGLE9BQU8sU0FBUyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUNwQyxDQUFDO0NBQ0Y7QUFsSEQsa0NBa0hDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IGNyZWF0ZURlYnVnIGZyb20gJ2RlYnVnJztcbmltcG9ydCBjcnlwdG8gZnJvbSAnY3J5cHRvJztcbmltcG9ydCB7IGV4aXN0c1N5bmMgYXMgZXhpc3RzLCB3cml0ZUZpbGVTeW5jIGFzIHdyaXRlLCByZWFkRmlsZVN5bmMgYXMgcmVhZCB9IGZyb20gJ2ZzJztcbmltcG9ydCB7IHN5bmMgYXMgcmltcmFmIH0gZnJvbSAncmltcmFmJztcbmltcG9ydCB7IE9wdGlvbnMgfSBmcm9tICcuLi9pbmRleCc7XG5pbXBvcnQgeyBhc3NlcnROb3RUb3VjaGluZ0ZpbGVzLCBvcGVuQ2VydGlmaWNhdGVJbkZpcmVmb3ggfSBmcm9tICcuL3NoYXJlZCc7XG5pbXBvcnQgeyBQbGF0Zm9ybSB9IGZyb20gJy4nO1xuaW1wb3J0IHsgcnVuLCBzdWRvIH0gZnJvbSAnLi4vdXRpbHMnO1xuaW1wb3J0IFVJIGZyb20gJy4uL3VzZXItaW50ZXJmYWNlJztcblxuY29uc3QgZGVidWcgPSBjcmVhdGVEZWJ1ZygnZGV2Y2VydDpwbGF0Zm9ybXM6d2luZG93cycpO1xuXG5sZXQgZW5jcnlwdGlvbktleTogc3RyaW5nO1xuXG5leHBvcnQgZGVmYXVsdCBjbGFzcyBXaW5kb3dzUGxhdGZvcm0gaW1wbGVtZW50cyBQbGF0Zm9ybSB7XG5cbiAgcHJpdmF0ZSBIT1NUX0ZJTEVfUEFUSCA9ICdDOlxcXFxXaW5kb3dzXFxcXFN5c3RlbTMyXFxcXERyaXZlcnNcXFxcZXRjXFxcXGhvc3RzJztcblxuICAvKipcbiAgICogV2luZG93cyBpcyBhdCBsZWFzdCBzaW1wbGUuIExpa2UgbWFjT1MsIG1vc3QgYXBwbGljYXRpb25zIHdpbGwgZGVsZWdhdGUgdG9cbiAgICogdGhlIHN5c3RlbSB0cnVzdCBzdG9yZSwgd2hpY2ggaXMgdXBkYXRlZCB3aXRoIHRoZSBjb25mdXNpbmdseSBuYW1lZFxuICAgKiBgY2VydHV0aWxgIGV4ZSAobm90IHRoZSBzYW1lIGFzIHRoZSBOU1MvTW96aWxsYSBjZXJ0dXRpbCkuIEZpcmVmb3ggZG9lcyBpdCdzXG4gICAqIG93biB0aGluZyBhcyB1c3VhbCwgYW5kIGdldHRpbmcgYSBjb3B5IG9mIE5TUyBjZXJ0dXRpbCBvbnRvIHRoZSBXaW5kb3dzXG4gICAqIG1hY2hpbmUgdG8gdHJ5IHVwZGF0aW5nIHRoZSBGaXJlZm94IHN0b3JlIGlzIGJhc2ljYWxseSBhIG5pZ2h0bWFyZSwgc28gd2VcbiAgICogZG9uJ3QgZXZlbiB0cnkgaXQgLSB3ZSBqdXN0IGJhaWwgb3V0IHRvIHRoZSBHVUkuXG4gICAqL1xuICBhc3luYyBhZGRUb1RydXN0U3RvcmVzKGNlcnRpZmljYXRlUGF0aDogc3RyaW5nLCBvcHRpb25zOiBPcHRpb25zID0ge30pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAvLyBJRSwgQ2hyb21lLCBzeXN0ZW0gdXRpbHNcbiAgICBkZWJ1ZygnYWRkaW5nIGRldmNlcnQgcm9vdCB0byBXaW5kb3dzIE9TIHRydXN0IHN0b3JlJylcbiAgICB0cnkge1xuICAgICAgcnVuKCdjZXJ0dXRpbCcsIFsnLWFkZHN0b3JlJywgJy11c2VyJywgJ3Jvb3QnLCBjZXJ0aWZpY2F0ZVBhdGhdKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICBlLm91dHB1dC5tYXAoKGJ1ZmZlcjogQnVmZmVyKSA9PiB7XG4gICAgICAgIGlmIChidWZmZXIpIHtcbiAgICAgICAgICBjb25zb2xlLmxvZyhidWZmZXIudG9TdHJpbmcoKSk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICAgIH1cbiAgICBkZWJ1ZygnYWRkaW5nIGRldmNlcnQgcm9vdCB0byBGaXJlZm94IHRydXN0IHN0b3JlJylcbiAgICAvLyBGaXJlZm94IChkb24ndCBldmVuIHRyeSBOU1MgY2VydHV0aWwsIG5vIGVhc3kgaW5zdGFsbCBmb3IgV2luZG93cylcbiAgICB0cnkge1xuICAgICAgYXdhaXQgb3BlbkNlcnRpZmljYXRlSW5GaXJlZm94KCdzdGFydCBmaXJlZm94JywgY2VydGlmaWNhdGVQYXRoKTtcbiAgICB9IGNhdGNoIHtcbiAgICAgIGRlYnVnKCdFcnJvciBvcGVuaW5nIEZpcmVmb3gsIG1vc3QgbGlrZWx5IEZpcmVmb3ggaXMgbm90IGluc3RhbGxlZCcpO1xuICAgIH1cbiAgfVxuICBcbiAgcmVtb3ZlRnJvbVRydXN0U3RvcmVzKGNlcnRpZmljYXRlUGF0aDogc3RyaW5nKSB7XG4gICAgZGVidWcoJ3JlbW92aW5nIGRldmNlcnQgcm9vdCBmcm9tIFdpbmRvd3MgT1MgdHJ1c3Qgc3RvcmUnKTtcbiAgICB0cnkge1xuICAgICAgY29uc29sZS53YXJuKCdSZW1vdmluZyBvbGQgY2VydGlmaWNhdGVzIGZyb20gdHJ1c3Qgc3RvcmVzLiBZb3UgbWF5IGJlIHByb21wdGVkIHRvIGdyYW50IHBlcm1pc3Npb24gZm9yIHRoaXMuIEl0XFwncyBzYWZlIHRvIGRlbGV0ZSBvbGQgZGV2Y2VydCBjZXJ0aWZpY2F0ZXMuJyk7XG4gICAgICBydW4oJ2NlcnR1dGlsJywgWyctZGVsc3RvcmUnLCAnLXVzZXInLCAncm9vdCcsICdkZXZjZXJ0J10pO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGRlYnVnKGBmYWlsZWQgdG8gcmVtb3ZlICR7IGNlcnRpZmljYXRlUGF0aCB9IGZyb20gV2luZG93cyBPUyB0cnVzdCBzdG9yZSwgY29udGludWluZy4gJHsgZS50b1N0cmluZygpIH1gKVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGFkZERvbWFpblRvSG9zdEZpbGVJZk1pc3NpbmcoZG9tYWluOiBzdHJpbmcpIHtcbiAgICBpZiAoIWV4aXN0cyh0aGlzLkhPU1RfRklMRV9QQVRIKSkge1xuICAgICAgY29uc29sZS53YXJuKCdDb3VsZCBub3QgbG9jYXRlIHRoZSBob3N0IGZpbGUgaW4geW91ciBzeXN0ZW0uJyk7XG4gICAgICBjb25zb2xlLndhcm4oJ1BsZWFzZSBlbnN1cmUgdG8gaGF2ZTonKTtcbiAgICAgIGNvbnNvbGUubG9nKGAxMjcuMC4wLjEgICR7ZG9tYWlufWApO1xuICAgICAgY29uc29sZS53YXJuKFwiZW50cnkgaW4geW91ciBzeXN0ZW0ncyBob3N0IGZpbGUuXCIpO1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCBob3N0c0ZpbGVDb250ZW50cyA9IHJlYWQodGhpcy5IT1NUX0ZJTEVfUEFUSCwgJ3V0ZjgnKTtcbiAgICBpZiAoIWhvc3RzRmlsZUNvbnRlbnRzLmluY2x1ZGVzKGRvbWFpbikpIHtcbiAgICAgIGF3YWl0IHN1ZG8oYGVjaG8gMTI3LjAuMC4xICAkeyBkb21haW4gfSA+PiAkeyB0aGlzLkhPU1RfRklMRV9QQVRIIH1gKTtcbiAgICB9XG4gIH1cbiAgXG4gIGRlbGV0ZVByb3RlY3RlZEZpbGVzKGZpbGVwYXRoOiBzdHJpbmcpIHtcbiAgICBhc3NlcnROb3RUb3VjaGluZ0ZpbGVzKGZpbGVwYXRoLCAnZGVsZXRlJyk7XG4gICAgcmltcmFmKGZpbGVwYXRoKTtcbiAgfVxuXG4gIGFzeW5jIHJlYWRQcm90ZWN0ZWRGaWxlKGZpbGVwYXRoOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGFzc2VydE5vdFRvdWNoaW5nRmlsZXMoZmlsZXBhdGgsICdyZWFkJyk7XG4gICAgaWYgKCFlbmNyeXB0aW9uS2V5KSB7XG4gICAgICBlbmNyeXB0aW9uS2V5ID0gYXdhaXQgVUkuZ2V0V2luZG93c0VuY3J5cHRpb25QYXNzd29yZCgpO1xuICAgIH1cbiAgICAvLyBUcnkgdG8gZGVjcnlwdCB0aGUgZmlsZVxuICAgIHRyeSB7XG4gICAgICByZXR1cm4gdGhpcy5kZWNyeXB0KHJlYWQoZmlsZXBhdGgsICd1dGY4JyksIGVuY3J5cHRpb25LZXkpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIC8vIElmIGl0J3MgYSBiYWQgcGFzc3dvcmQsIGNsZWFyIHRoZSBjYWNoZWQgY29weSBhbmQgcmV0cnlcbiAgICAgIGlmIChlLm1lc3NhZ2UuaW5kZXhPZignYmFkIGRlY3J5cHQnKSA+PSAtMSkge1xuICAgICAgICBlbmNyeXB0aW9uS2V5ID0gbnVsbDtcbiAgICAgICAgcmV0dXJuIGF3YWl0IHRoaXMucmVhZFByb3RlY3RlZEZpbGUoZmlsZXBhdGgpO1xuICAgICAgfVxuICAgICAgdGhyb3cgZTtcbiAgICB9XG4gIH1cblxuICBhc3luYyB3cml0ZVByb3RlY3RlZEZpbGUoZmlsZXBhdGg6IHN0cmluZywgY29udGVudHM6IHN0cmluZykge1xuICAgIGFzc2VydE5vdFRvdWNoaW5nRmlsZXMoZmlsZXBhdGgsICd3cml0ZScpO1xuICAgIGlmICghZW5jcnlwdGlvbktleSkge1xuICAgICAgZW5jcnlwdGlvbktleSA9IGF3YWl0IFVJLmdldFdpbmRvd3NFbmNyeXB0aW9uUGFzc3dvcmQoKTtcbiAgICB9XG4gICAgbGV0IGVuY3J5cHRlZENvbnRlbnRzID0gdGhpcy5lbmNyeXB0KGNvbnRlbnRzLCBlbmNyeXB0aW9uS2V5KTtcbiAgICB3cml0ZShmaWxlcGF0aCwgZW5jcnlwdGVkQ29udGVudHMpO1xuICB9XG5cbiAgcHJpdmF0ZSBlbmNyeXB0KHRleHQ6IHN0cmluZywga2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIGNvbnN0IGFsZ29yaXRobSA9ICdhZXMtMjU2LWNiYyc7XG4gICAgY29uc3QgaXYgPSBjcnlwdG8ucmFuZG9tQnl0ZXMoMTYpO1xuICAgIGNvbnN0IGtleUJ1ZmZlciA9IGNyeXB0by5jcmVhdGVIYXNoKCdzaGEyNTYnKS51cGRhdGUoa2V5KS5kaWdlc3QoKTtcblxuICAgIGNvbnN0IGNpcGhlciA9IGNyeXB0by5jcmVhdGVDaXBoZXJpdihhbGdvcml0aG0sIGtleUJ1ZmZlciwgaXYpO1xuICAgIGNvbnN0IGVuY3J5cHRlZCA9IEJ1ZmZlci5jb25jYXQoW2NpcGhlci51cGRhdGUodGV4dCwgJ3V0ZjgnKSwgY2lwaGVyLmZpbmFsKCldKTtcblxuICAgIHJldHVybiBpdi50b1N0cmluZygnaGV4JykgKyAnOicgKyBlbmNyeXB0ZWQudG9TdHJpbmcoJ2hleCcpO1xuICB9XG4gIFxuICBwcml2YXRlIGRlY3J5cHQoZW5jcnlwdGVkVGV4dDogc3RyaW5nLCBrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgYWxnb3JpdGhtID0gJ2Flcy0yNTYtY2JjJztcbiAgICBjb25zdCBrZXlCdWZmZXIgPSBjcnlwdG8uY3JlYXRlSGFzaCgnc2hhMjU2JykudXBkYXRlKGtleSkuZGlnZXN0KCk7XG5cbiAgICBjb25zdCBbaXZIZXgsIGVuY3J5cHRlZEhleF0gPSBlbmNyeXB0ZWRUZXh0LnNwbGl0KCc6Jyk7XG4gICAgY29uc3QgaXYgPSBCdWZmZXIuZnJvbShpdkhleCwgJ2hleCcpO1xuICAgIGNvbnN0IGVuY3J5cHRlZEJ1ZmZlciA9IEJ1ZmZlci5mcm9tKGVuY3J5cHRlZEhleCwgJ2hleCcpO1xuXG4gICAgY29uc3QgZGVjaXBoZXIgPSBjcnlwdG8uY3JlYXRlRGVjaXBoZXJpdihhbGdvcml0aG0sIGtleUJ1ZmZlciwgaXYpO1xuICAgIGNvbnN0IGRlY3J5cHRlZCA9IEJ1ZmZlci5jb25jYXQoW2RlY2lwaGVyLnVwZGF0ZShlbmNyeXB0ZWRCdWZmZXIpLCBkZWNpcGhlci5maW5hbCgpXSk7XG5cbiAgICByZXR1cm4gZGVjcnlwdGVkLnRvU3RyaW5nKCd1dGY4Jyk7XG4gIH1cbn1cbiJdfQ==