chore: refactor SSHConnection as a dependency injection into socket
This commit is contained in:
parent
a6e74bf29a
commit
6b1930da03
3 changed files with 32 additions and 16 deletions
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
const express = require("express")
|
const express = require("express")
|
||||||
const config = require("./config")
|
const config = require("./config")
|
||||||
|
const SSHConnection = require("./ssh")
|
||||||
const socketHandler = require("./socket")
|
const socketHandler = require("./socket")
|
||||||
const sshRoutes = require("./routes")(config)
|
const sshRoutes = require("./routes")(config)
|
||||||
const { applyMiddleware } = require("./middleware")
|
const { applyMiddleware } = require("./middleware")
|
||||||
|
@ -53,7 +54,7 @@ function initializeServer() {
|
||||||
const io = configureSocketIO(server, sessionMiddleware, config)
|
const io = configureSocketIO(server, sessionMiddleware, config)
|
||||||
|
|
||||||
// Set up Socket.IO listeners
|
// Set up Socket.IO listeners
|
||||||
socketHandler(io, config)
|
socketHandler(io, config, SSHConnection)
|
||||||
|
|
||||||
// Start the server
|
// Start the server
|
||||||
startServer(server, config)
|
startServer(server, config)
|
||||||
|
|
|
@ -3,11 +3,8 @@
|
||||||
|
|
||||||
const validator = require("validator")
|
const validator = require("validator")
|
||||||
const EventEmitter = require("events")
|
const EventEmitter = require("events")
|
||||||
const SSHConnection = require("./ssh")
|
|
||||||
const { createNamespacedDebug } = require("./logger")
|
const { createNamespacedDebug } = require("./logger")
|
||||||
const { SSHConnectionError, handleError } = require("./errors")
|
const { SSHConnectionError, handleError } = require("./errors")
|
||||||
|
|
||||||
const debug = createNamespacedDebug("socket")
|
|
||||||
const {
|
const {
|
||||||
isValidCredentials,
|
isValidCredentials,
|
||||||
maskSensitiveData,
|
maskSensitiveData,
|
||||||
|
@ -15,12 +12,21 @@ const {
|
||||||
} = require("./utils")
|
} = require("./utils")
|
||||||
const { MESSAGES } = require("./constants")
|
const { MESSAGES } = require("./constants")
|
||||||
|
|
||||||
|
const debug = createNamespacedDebug("socket")
|
||||||
|
|
||||||
class WebSSH2Socket extends EventEmitter {
|
class WebSSH2Socket extends EventEmitter {
|
||||||
constructor(socket, config) {
|
/**
|
||||||
|
* Creates a new WebSSH2Socket instance
|
||||||
|
* @param {Object} socket - The Socket.IO socket instance
|
||||||
|
* @param {Object} config - The application configuration
|
||||||
|
* @param {Function} SSHConnectionClass - The SSH connection class constructor
|
||||||
|
*/
|
||||||
|
constructor(socket, config, SSHConnectionClass) {
|
||||||
super()
|
super()
|
||||||
this.socket = socket
|
this.socket = socket
|
||||||
this.config = config
|
this.config = config
|
||||||
this.ssh = new SSHConnection(config)
|
this.SSHConnectionClass = SSHConnectionClass
|
||||||
|
this.ssh = null
|
||||||
this.sessionState = {
|
this.sessionState = {
|
||||||
authenticated: false,
|
authenticated: false,
|
||||||
username: null,
|
username: null,
|
||||||
|
@ -62,10 +68,6 @@ class WebSSH2Socket extends EventEmitter {
|
||||||
this.socket.emit("authentication", { action: "request_auth" })
|
this.socket.emit("authentication", { action: "request_auth" })
|
||||||
}
|
}
|
||||||
|
|
||||||
this.ssh.on("keyboard-interactive", data => {
|
|
||||||
this.handleKeyboardInteractive(data)
|
|
||||||
})
|
|
||||||
|
|
||||||
this.socket.on("authenticate", creds => {
|
this.socket.on("authenticate", creds => {
|
||||||
this.handleAuthenticate(creds)
|
this.handleAuthenticate(creds)
|
||||||
})
|
})
|
||||||
|
@ -112,7 +114,6 @@ class WebSSH2Socket extends EventEmitter {
|
||||||
debug(`handleAuthenticate: ${this.socket.id}, %O`, maskSensitiveData(creds))
|
debug(`handleAuthenticate: ${this.socket.id}, %O`, maskSensitiveData(creds))
|
||||||
|
|
||||||
if (isValidCredentials(creds)) {
|
if (isValidCredentials(creds)) {
|
||||||
// Set term if provided, otherwise use config default
|
|
||||||
this.sessionState.term = validateSshTerm(creds.term)
|
this.sessionState.term = validateSshTerm(creds.term)
|
||||||
? creds.term
|
? creds.term
|
||||||
: this.config.ssh.term
|
: this.config.ssh.term
|
||||||
|
@ -135,9 +136,18 @@ class WebSSH2Socket extends EventEmitter {
|
||||||
|
|
||||||
// Add private key from config if available and not provided in creds
|
// Add private key from config if available and not provided in creds
|
||||||
if (this.config.user.privateKey && !creds.privateKey) {
|
if (this.config.user.privateKey && !creds.privateKey) {
|
||||||
|
// eslint-disable-next-line no-param-reassign
|
||||||
creds.privateKey = this.config.user.privateKey
|
creds.privateKey = this.config.user.privateKey
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create new SSH connection instance
|
||||||
|
this.ssh = new this.SSHConnectionClass(this.config)
|
||||||
|
|
||||||
|
// Set up SSH event handlers
|
||||||
|
this.ssh.on("keyboard-interactive", data => {
|
||||||
|
this.handleKeyboardInteractive(data)
|
||||||
|
})
|
||||||
|
|
||||||
this.ssh
|
this.ssh
|
||||||
.connect(creds)
|
.connect(creds)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
|
@ -170,7 +180,7 @@ class WebSSH2Socket extends EventEmitter {
|
||||||
|
|
||||||
this.socket.emit("getTerminal", true)
|
this.socket.emit("getTerminal", true)
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch(err => {
|
||||||
debug(
|
debug(
|
||||||
`initializeConnection: SSH CONNECTION ERROR: ${this.socket.id}, Host: ${creds.host}, Error: ${err.message}`
|
`initializeConnection: SSH CONNECTION ERROR: ${this.socket.id}, Host: ${creds.host}, Error: ${err.message}`
|
||||||
)
|
)
|
||||||
|
@ -217,8 +227,8 @@ class WebSSH2Socket extends EventEmitter {
|
||||||
},
|
},
|
||||||
envVars
|
envVars
|
||||||
)
|
)
|
||||||
.then((stream) => {
|
.then(stream => {
|
||||||
stream.on("data", (data) => {
|
stream.on("data", data => {
|
||||||
this.socket.emit("data", data.toString("utf-8"))
|
this.socket.emit("data", data.toString("utf-8"))
|
||||||
})
|
})
|
||||||
// stream.stderr.on("data", data => debug(`STDERR: ${data}`)) // needed for shell.exec
|
// stream.stderr.on("data", data => debug(`STDERR: ${data}`)) // needed for shell.exec
|
||||||
|
@ -353,6 +363,10 @@ class WebSSH2Socket extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function(io, config) {
|
// Modified export to include dependency injection
|
||||||
io.on("connection", socket => new WebSSH2Socket(socket, config))
|
module.exports = function(io, config, SSHConnectionClass) {
|
||||||
|
io.on(
|
||||||
|
"connection",
|
||||||
|
socket => new WebSSH2Socket(socket, config, SSHConnectionClass)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,6 +239,7 @@ function parseEnvVars(envString) {
|
||||||
|
|
||||||
for (let i = 0; i < pairs.length; i += 1) {
|
for (let i = 0; i < pairs.length; i += 1) {
|
||||||
const pair = pairs[i].split(":")
|
const pair = pairs[i].split(":")
|
||||||
|
// eslint-disable-next-line no-continue
|
||||||
if (pair.length !== 2) continue
|
if (pair.length !== 2) continue
|
||||||
|
|
||||||
const key = pair[0].trim()
|
const key = pair[0].trim()
|
||||||
|
|
Loading…
Reference in a new issue