tabby/terminus-ssh/src/api.ts

148 lines
3.8 KiB
TypeScript
Raw Normal View History

import { BaseSession } from 'terminus-terminal'
2018-08-27 04:24:12 +00:00
export interface LoginScript {
2019-09-18 18:56:59 +00:00
expect: string
2018-08-27 04:24:12 +00:00
send: string
2018-09-28 05:45:40 +00:00
isRegex?: boolean
2018-09-28 06:46:32 +00:00
optional?: boolean
2018-08-27 04:24:12 +00:00
}
export enum SSHAlgorithmType {
HMAC = 'hmac',
KEX = 'kex',
CIPHER = 'cipher',
HOSTKEY = 'serverHostKey'
}
export interface SSHConnection {
2019-09-18 18:56:59 +00:00
name: string
host: string
port: number
user: string
password?: string
privateKey?: string
2019-11-26 14:11:26 +00:00
group: string | null
2018-08-27 04:24:12 +00:00
scripts?: LoginScript[]
2018-09-12 02:39:18 +00:00
keepaliveInterval?: number
keepaliveCountMax?: number
readyTimeout?: number
algorithms?: {[t: string]: string[]}
}
export class SSHSession extends BaseSession {
2018-08-27 04:24:12 +00:00
scripts?: LoginScript[]
shell: any
2018-08-27 04:24:12 +00:00
constructor (public connection: SSHConnection) {
super()
this.scripts = connection.scripts || []
}
start () {
this.open = true
this.shell.on('data', data => {
2019-06-14 15:49:42 +00:00
const dataString = data.toString()
2018-08-27 04:24:12 +00:00
this.emitOutput(dataString)
2018-09-04 20:49:12 +00:00
if (this.scripts) {
2018-08-27 04:24:12 +00:00
let found = false
2019-06-14 15:49:42 +00:00
for (const script of this.scripts) {
2018-09-28 06:46:32 +00:00
let match = false
2018-10-08 06:01:13 +00:00
let cmd = ''
2018-09-28 05:45:40 +00:00
if (script.isRegex) {
2019-06-14 15:49:42 +00:00
const re = new RegExp(script.expect, 'g')
2018-09-28 05:45:40 +00:00
if (dataString.match(re)) {
2018-09-28 06:46:32 +00:00
cmd = dataString.replace(re, script.send)
match = true
2018-09-28 05:45:40 +00:00
found = true
}
2018-10-08 06:01:13 +00:00
} else {
2018-09-28 05:45:40 +00:00
if (dataString.includes(script.expect)) {
2018-09-28 06:46:32 +00:00
cmd = script.send
match = true
2018-09-28 05:45:40 +00:00
found = true
2018-09-28 06:46:32 +00:00
}
}
if (match) {
console.log('Executing script: "' + cmd + '"')
this.shell.write(cmd + '\n')
this.scripts = this.scripts.filter(x => x !== script)
2018-10-08 06:01:13 +00:00
} else {
2018-09-28 06:46:32 +00:00
if (script.optional) {
2018-10-08 06:01:13 +00:00
console.log('Skip optional script: ' + script.expect)
2018-09-28 06:46:32 +00:00
found = true
this.scripts = this.scripts.filter(x => x !== script)
2018-10-08 06:01:13 +00:00
} else {
2018-09-28 05:45:40 +00:00
break
}
2018-08-27 04:24:12 +00:00
}
}
2018-08-29 09:02:02 +00:00
if (found) {
2018-09-04 20:49:12 +00:00
this.executeUnconditionalScripts()
2018-08-27 04:24:12 +00:00
}
}
})
this.shell.on('end', () => {
if (this.open) {
this.destroy()
}
})
2018-08-27 04:24:12 +00:00
2018-09-04 20:49:12 +00:00
this.executeUnconditionalScripts()
}
resize (columns, rows) {
if (this.shell) {
this.shell.setWindow(rows, columns)
}
}
write (data) {
if (this.shell) {
this.shell.write(data)
}
}
kill (signal?: string) {
if (this.shell) {
this.shell.signal(signal || 'TERM')
}
}
async getChildProcesses (): Promise<any[]> {
return []
}
async gracefullyKillProcess (): Promise<void> {
this.kill('TERM')
}
2019-09-18 18:56:59 +00:00
async getWorkingDirectory (): Promise<string|null> {
return null
}
2018-09-04 20:49:12 +00:00
private executeUnconditionalScripts () {
if (this.scripts) {
2019-06-14 15:49:42 +00:00
for (const script of this.scripts) {
2018-09-04 20:49:12 +00:00
if (!script.expect) {
console.log('Executing script:', script.send)
this.shell.write(script.send + '\n')
this.scripts = this.scripts.filter(x => x !== script)
} else {
break
}
}
}
}
}
2018-09-04 20:39:00 +00:00
2019-06-14 21:47:48 +00:00
export interface SSHConnectionGroup {
2018-09-04 20:39:00 +00:00
name: string
connections: SSHConnection[]
}