2017-11-27 15:30:59 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2019-02-09 17:52:09 +00:00
|
|
|
export enum SSHAlgorithmType {
|
|
|
|
HMAC = 'hmac',
|
|
|
|
KEX = 'kex',
|
|
|
|
CIPHER = 'cipher',
|
|
|
|
HOSTKEY = 'serverHostKey'
|
|
|
|
}
|
|
|
|
|
2017-11-27 15:30:59 +00:00
|
|
|
export interface SSHConnection {
|
2019-09-18 18:56:59 +00:00
|
|
|
name: string
|
2017-11-27 15:30:59 +00:00
|
|
|
host: string
|
2018-01-04 20:13:46 +00:00
|
|
|
port: number
|
2017-11-27 15:30:59 +00:00
|
|
|
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
|
2019-02-09 17:52:09 +00:00
|
|
|
|
|
|
|
algorithms?: {[t: string]: string[]}
|
2017-11-27 15:30:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export class SSHSession extends BaseSession {
|
2018-08-27 04:24:12 +00:00
|
|
|
scripts?: LoginScript[]
|
2019-01-06 10:14:13 +00:00
|
|
|
shell: any
|
2018-08-27 04:24:12 +00:00
|
|
|
|
2019-01-06 10:14:13 +00:00
|
|
|
constructor (public connection: SSHConnection) {
|
2017-11-27 15:30:59 +00:00
|
|
|
super()
|
2019-01-06 10:14:13 +00:00
|
|
|
this.scripts = connection.scripts || []
|
2018-08-02 21:22:36 +00:00
|
|
|
}
|
2017-11-27 15:30:59 +00:00
|
|
|
|
2018-08-02 21:22:36 +00:00
|
|
|
start () {
|
2017-11-27 15:30:59 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
2017-11-27 15:30:59 +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()
|
2017-11-27 15:30:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
resize (columns, rows) {
|
2019-01-06 10:14:13 +00:00
|
|
|
if (this.shell) {
|
|
|
|
this.shell.setWindow(rows, columns)
|
|
|
|
}
|
2017-11-27 15:30:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
write (data) {
|
2019-01-06 10:14:13 +00:00
|
|
|
if (this.shell) {
|
|
|
|
this.shell.write(data)
|
|
|
|
}
|
2017-11-27 15:30:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
kill (signal?: string) {
|
2019-01-06 10:14:13 +00:00
|
|
|
if (this.shell) {
|
|
|
|
this.shell.signal(signal || 'TERM')
|
|
|
|
}
|
2017-11-27 15:30:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
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> {
|
2017-11-27 15:30:59 +00:00
|
|
|
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
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-11-27 15:30:59 +00:00
|
|
|
}
|
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[]
|
|
|
|
}
|