diff --git a/terminus-ssh/src/services/ssh.service.ts b/terminus-ssh/src/services/ssh.service.ts index d65658d2..ee8098c3 100644 --- a/terminus-ssh/src/services/ssh.service.ts +++ b/terminus-ssh/src/services/ssh.service.ts @@ -22,6 +22,11 @@ try { var windowsProcessTreeNative = require('windows-process-tree/build/Release/windows_process_tree.node') // eslint-disable-line @typescript-eslint/no-var-requires, no-var } catch { } + +// eslint-disable-next-line @typescript-eslint/no-type-alias +export type SSHLogCallback = (message: string) => void + + @Injectable({ providedIn: 'root' }) export class SSHService { private logger: Logger @@ -46,33 +51,24 @@ export class SSHService { return session } - async connectSession (session: SSHSession, logCallback?: (s: any) => void): Promise { + async loadPrivateKeyForSession (session: SSHSession, logCallback?: SSHLogCallback): Promise { let privateKey: string|null = null let privateKeyPath = session.connection.privateKey - if (!logCallback) { - logCallback = () => null - } - - const log = (s: any) => { - logCallback!(s) - this.logger.info(s) - } - if (!privateKeyPath) { const userKeyPath = path.join(process.env.HOME as string, '.ssh', 'id_rsa') if (await fs.exists(userKeyPath)) { - log('Using user\'s default private key') + logCallback?.('Using user\'s default private key') privateKeyPath = userKeyPath } } if (privateKeyPath) { - log('Loading private key from ' + colors.bgWhite.blackBright(' ' + privateKeyPath + ' ')) + logCallback?.('Loading private key from ' + colors.bgWhite.blackBright(' ' + privateKeyPath + ' ')) try { privateKey = (await fs.readFile(privateKeyPath)).toString() } catch (error) { - log(colors.bgRed.black(' X ') + 'Could not read the private key file') + logCallback?.(colors.bgRed.black(' X ') + 'Could not read the private key file') this.toastr.error('Could not read the private key file') } @@ -83,7 +79,7 @@ export class SSHService { } catch (e) { if (e instanceof sshpk.KeyEncryptedError) { const modal = this.ngbModal.open(PromptModalComponent) - log(colors.bgYellow.yellow.black(' ! ') + ' Key requires passphrase') + logCallback?.(colors.bgYellow.yellow.black(' ! ') + ' Key requires passphrase') modal.componentInstance.prompt = 'Private key passphrase' modal.componentInstance.password = true let passphrase = '' @@ -131,6 +127,20 @@ export class SSHService { fs.unlink(temp.path) } } + return privateKey + } + + async connectSession (session: SSHSession, logCallback?: SSHLogCallback): Promise { + if (!logCallback) { + logCallback = () => null + } + + const log = (s: any) => { + logCallback!(s) + this.logger.info(s) + } + + let privateKey: string|null = null const ssh = new Client() session.ssh = ssh @@ -213,6 +223,7 @@ export class SSHService { const authMethodsLeft = ['none'] if (!session.connection.auth || session.connection.auth === 'publicKey') { + privateKey = await this.loadPrivateKeyForSession(session, log) if (!privateKey) { log('\r\nPrivate key auth selected, but no key is loaded\r\n') } else {