UNPKG

s-bit-agent

Version:

s.BitAgent is a simple Bitwarden CLI wrapper which provides a SSH2 Key Agent solution for Bitwarden.

245 lines 9.95 kB
"use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DaemonCommand = void 0; const nest_commander_1 = require("nest-commander"); const session_service_1 = require("../bitwarden/session.service"); const agent_service_1 = require("../icp/agent.service"); const client_service_1 = require("../icp/client.service"); const log_service_1 = require("../shared/log.service"); const child_process_1 = require("child_process"); const message_1 = require("../icp/types/message"); const cache_service_1 = require("../shared/cache.service"); let DaemonCommand = class DaemonCommand extends nest_commander_1.CommandRunner { constructor(logService, agentService, clientService, sessionService, cacheService) { super(); this.logService = logService; this.agentService = agentService; this.clientService = clientService; this.sessionService = sessionService; this.cacheService = cacheService; } parseLogToFile(logToFile) { return logToFile; } parseSilent(silent) { return !!silent; } parseVerbose(verbose) { return !!verbose; } parseSessionTimeout(timeout) { return Number(timeout); } parseIpcTimeout(timeout) { return Number(timeout); } parseAuthRetries(retries) { return Number(retries); } parseNoWatchdog() { return false; } parseCachePublicKeys(cachePublicKeys) { return cachePublicKeys; } parseCacheTimeout(cacheTimeout) { return Number(cacheTimeout); } async run(params, options) { if (options.watchdog) { this.logService.setPrefix('[watchdog]'); let pid = 0; const restart = () => { if (pid) { this.logService.log('Killing old daemon...'); process.kill(pid); } const child = (0, child_process_1.spawn)(process.argv[0], [ ...process.argv.slice(1), '--no-watchdog', ], { detached: true, stdio: 'pipe', }); pid = child.pid; child.stdout.pipe(process.stdout); child.stderr.pipe(process.stderr); this.logService.log('Started new daemon with PID', pid); }; restart(); ['SIGINT', 'SIGTERM'].forEach(signal => process.on(signal, () => { if (pid) process.kill(pid, signal); })); setInterval(async () => { try { process.kill(pid, 0); const res = await this.clientService.sendMessage(new message_1.RequestPing()); if (res.type === message_1.SBitAgentMessageType.RESPONSE_OK) return; this.logService.fatal('Daemon did not respond to ping, restarting...'); } catch (ignored) { this.logService.fatal('Daemon is not running, restarting...'); } restart(); }, 15000); return; } if (options.log) this.logService.setLogToFile(options.log); if (options.silent) this.logService.setLogToConsole(false); if (options.verbose) this.agentService.setLogging(true); if (options.cachePublicKeys) { this.cacheService.setPath(options.cachePublicKeys); if (options.cacheTimeout) this.cacheService.setTTL(options.cacheTimeout * 1000); } this.agentService.setTimeout(options.ipcTimeout * 1000); this.sessionService.updateConfig({ timeout: options.sessionTimeout * 1000, retrys: options.authRetries, }); this.agentService.start(); } }; exports.DaemonCommand = DaemonCommand; __decorate([ (0, nest_commander_1.Option)({ flags: '-l, --log-to-file <path>', name: 'log', description: 'Log to file instead of console', }), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", void 0) ], DaemonCommand.prototype, "parseLogToFile", null); __decorate([ (0, nest_commander_1.Option)({ flags: '-s, --silent', description: 'Do not log to console', }), __metadata("design:type", Function), __metadata("design:paramtypes", [Boolean]), __metadata("design:returntype", void 0) ], DaemonCommand.prototype, "parseSilent", null); __decorate([ (0, nest_commander_1.Option)({ flags: '-v, --verbose', description: 'Log more information', }), __metadata("design:type", Function), __metadata("design:paramtypes", [Boolean]), __metadata("design:returntype", void 0) ], DaemonCommand.prototype, "parseVerbose", null); __decorate([ (0, nest_commander_1.Option)({ flags: '--session-timeout <timeout>', description: [ 'Session timeout in seconds, zero for no timeout.', 'This influnces how long the daemon waits for the user to be required to', 'enter the password again. This is a security feature, as it prevents', 'the daemon from being used by someone else if you leave your computer', 'unattended.', ].join('\n'), defaultValue: 60 * 15, }), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", void 0) ], DaemonCommand.prototype, "parseSessionTimeout", null); __decorate([ (0, nest_commander_1.Option)({ flags: '--ipc-timeout <timeout>', description: [ 'IPC timeout in seconds, zero for no timeout.', 'This influnces how long the daemon waits for example for', 'the password to be entered. To be more exact at the moment your', 'client connects a timout is started, its recommendet to keep', 'this on as its a absolute clean up for the daemon, which also', 'removes any died auth cycles.', ].join('\n'), defaultValue: 60 * 5, }), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", void 0) ], DaemonCommand.prototype, "parseIpcTimeout", null); __decorate([ (0, nest_commander_1.Option)({ flags: '--auth-retries <retries>', description: [ 'How many times the daemon should retry to authenticate the user', 'before it gives up and denys the request. This is NOT a', 'bruteforce protection!', ].join('\n'), defaultValue: 3, }), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", void 0) ], DaemonCommand.prototype, "parseAuthRetries", null); __decorate([ (0, nest_commander_1.Option)({ flags: '--no-watchdog', name: 'watchdog', description: [ 'Disable the watchdog, which restarts the daemon if it crashes or', 'becomes unresponsive.', ].join('\n'), }), __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], DaemonCommand.prototype, "parseNoWatchdog", null); __decorate([ (0, nest_commander_1.Option)({ flags: '--cache-public-keys <file>', description: [ 'Cache the public keys in a local file. This prevents the daemon from', 'asking for the password every time the ssh-agent is used, even if no', 'key is available for that connection.', ].join('\n'), }), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", void 0) ], DaemonCommand.prototype, "parseCachePublicKeys", null); __decorate([ (0, nest_commander_1.Option)({ flags: '--cache-timeout <timeout>', description: [ 'Cache timeout in seconds.', 'This influnces how long the daemon caches the public keys before it', 'insists on a password again. Default is 0, which means the daemon will', 'only update the cache after you for example use a private key.', 'Alternatively you can run the "s-bit-agent key cache update" command.', ].join('\n'), }), __metadata("design:type", Function), __metadata("design:paramtypes", [String]), __metadata("design:returntype", void 0) ], DaemonCommand.prototype, "parseCacheTimeout", null); exports.DaemonCommand = DaemonCommand = __decorate([ (0, nest_commander_1.Command)({ name: 'daemon', description: 'Start the KeyAgent daemon and start the IPC socket.', }), __metadata("design:paramtypes", [log_service_1.LogService, agent_service_1.AgentService, client_service_1.ClientService, session_service_1.SessionService, cache_service_1.CacheService]) ], DaemonCommand); //# sourceMappingURL=daemon.command.js.map