chore: sync project to current state of bigip-server commit:e3d6ec8
This commit is contained in:
parent
a321eb2f94
commit
17b5ae7552
12 changed files with 211 additions and 32 deletions
39
CONFIG.md
39
CONFIG.md
|
@ -84,7 +84,7 @@ Renamed and expanded options:
|
||||||
## Detailed Changes
|
## Detailed Changes
|
||||||
|
|
||||||
### 1. Authentication Options
|
### 1. Authentication Options
|
||||||
- Added support for SSH private key authentication via `user.privateKey`
|
- Added support for SSH private key authentication via `user.privateKey` and passphrase encrypted private keys via `user.passphrase`
|
||||||
- Removed `user.overridebasic` option
|
- Removed `user.overridebasic` option
|
||||||
- Added keyboard-interactive authentication controls
|
- Added keyboard-interactive authentication controls
|
||||||
|
|
||||||
|
@ -128,7 +128,8 @@ These settings are now managed client-side.
|
||||||
"user": {
|
"user": {
|
||||||
"name": null,
|
"name": null,
|
||||||
"password": null,
|
"password": null,
|
||||||
"privateKey": null
|
"privateKey": null,
|
||||||
|
"passphrase": null
|
||||||
},
|
},
|
||||||
"ssh": {
|
"ssh": {
|
||||||
"host": null,
|
"host": null,
|
||||||
|
@ -138,7 +139,39 @@ These settings are now managed client-side.
|
||||||
"keepaliveInterval": 120000,
|
"keepaliveInterval": 120000,
|
||||||
"keepaliveCountMax": 10,
|
"keepaliveCountMax": 10,
|
||||||
"algorithms": {
|
"algorithms": {
|
||||||
// ... algorithm configurations ...
|
"cipher": [
|
||||||
|
"aes128-ctr",
|
||||||
|
"aes192-ctr",
|
||||||
|
"aes256-ctr",
|
||||||
|
"aes128-gcm",
|
||||||
|
"aes128-gcm@openssh.com",
|
||||||
|
"aes256-gcm",
|
||||||
|
"aes256-gcm@openssh.com",
|
||||||
|
"aes256-cbc"
|
||||||
|
],
|
||||||
|
"compress": [
|
||||||
|
"none",
|
||||||
|
"zlib@openssh.com",
|
||||||
|
"zlib"
|
||||||
|
],
|
||||||
|
"hmac": [
|
||||||
|
"hmac-sha2-256",
|
||||||
|
"hmac-sha2-512",
|
||||||
|
"hmac-sha1"
|
||||||
|
],
|
||||||
|
"kex": [
|
||||||
|
"ecdh-sha2-nistp256",
|
||||||
|
"ecdh-sha2-nistp384",
|
||||||
|
"ecdh-sha2-nistp521",
|
||||||
|
"diffie-hellman-group-exchange-sha256",
|
||||||
|
"diffie-hellman-group14-sha1"
|
||||||
|
],
|
||||||
|
"serverHostKey": [
|
||||||
|
"ecdsa-sha2-nistp256",
|
||||||
|
"ecdsa-sha2-nistp384",
|
||||||
|
"ecdsa-sha2-nistp521",
|
||||||
|
"ssh-rsa"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"options": {
|
"options": {
|
||||||
|
|
42
ChangeLog.md
42
ChangeLog.md
|
@ -2,6 +2,46 @@
|
||||||
|
|
||||||
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
|
||||||
|
|
||||||
|
<a name="0.2.24"></a>
|
||||||
|
## [0.2.24](https://github.com/billchurch/WebSSH2/compare/v0.2.23...v0.2.24) (2024-12-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* config.json.sample had `disableInteractiveAuth` set to `true`, changed to `false` ([0c5de9f](https://github.com/billchurch/WebSSH2/commit/0c5de9f))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="0.2.23"></a>
|
||||||
|
## [0.2.23](https://github.com/billchurch/WebSSH2/compare/v0.2.20...v0.2.23) (2024-12-04)
|
||||||
|
|
||||||
|
|
||||||
|
### Bug Fixes
|
||||||
|
|
||||||
|
* fixes document: config file moved from /usr/src to /usr/src/app [#372](https://github.com/billchurch/WebSSH2/issues/372) ([bc2d018](https://github.com/billchurch/WebSSH2/commit/bc2d018))
|
||||||
|
* bug: support /ssh/host without a hostname [#373](https://github.com/billchurch/WebSSH2/issues/373) ([8c55c83](https://github.com/billchurch/WebSSH2/commit/8c55c83))
|
||||||
|
* config change `privatekey` to `privateKey` for consistency with ssh2 module ([a176167](https://github.com/billchurch/WebSSH2/commit/a176167))
|
||||||
|
* config move algorithims to ssh property ([52a989b](https://github.com/billchurch/WebSSH2/commit/52a989b))
|
||||||
|
* pass full ssh error to browser ([27d9bfb](https://github.com/billchurch/WebSSH2/commit/27d9bfb))
|
||||||
|
* username/password in config file no longer honored [#374](https://github.com/billchurch/WebSSH2/issues/374) ([4185df7](https://github.com/billchurch/WebSSH2/commit/4185df7))
|
||||||
|
|
||||||
|
|
||||||
|
### Features
|
||||||
|
|
||||||
|
* accept private key from client [#381](https://github.com/billchurch/WebSSH2/issues/381) ([829b5cd](https://github.com/billchurch/WebSSH2/commit/829b5cd))
|
||||||
|
* add `ssh.disableInteractiveAuth` feature in support of [#379](https://github.com/billchurch/WebSSH2/issues/379) ([c7dfad0](https://github.com/billchurch/WebSSH2/commit/c7dfad0))
|
||||||
|
* allow passphrase encrypted ssh keys from client [#381](https://github.com/billchurch/WebSSH2/issues/381) ([056e87b](https://github.com/billchurch/WebSSH2/commit/056e87b))
|
||||||
|
* Allow setting environment variables from the URL [#371](https://github.com/billchurch/WebSSH2/issues/371) ([6ec0490](https://github.com/billchurch/WebSSH2/commit/6ec0490))
|
||||||
|
* implement ssh private key auth [#379](https://github.com/billchurch/WebSSH2/issues/379) ([402b678](https://github.com/billchurch/WebSSH2/commit/402b678))
|
||||||
|
* passphrase encrypted private key authentication [#382](https://github.com/billchurch/WebSSH2/issues/382) ([7961451](https://github.com/billchurch/WebSSH2/commit/7961451))
|
||||||
|
* support uploading of ssh-rsa private key from client for authentication [#381](https://github.com/billchurch/WebSSH2/issues/381) ([2f4083f](https://github.com/billchurch/WebSSH2/commit/2f4083f))
|
||||||
|
* update jsmasker to v1.4.0 ([3315df1](https://github.com/billchurch/WebSSH2/commit/3315df1))
|
||||||
|
* update webssh_client to 0.2.26 ([a1b2e56](https://github.com/billchurch/WebSSH2/commit/a1b2e56))
|
||||||
|
* update webssh2_client to 0.2.27 ([b511ce5](https://github.com/billchurch/WebSSH2/commit/b511ce5))
|
||||||
|
* webssh2_client to 0.2.28 ([b4b7429](https://github.com/billchurch/WebSSH2/commit/b4b7429))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a name="0.2.22"></a>
|
<a name="0.2.22"></a>
|
||||||
## [0.2.22](https://github.com/billchurch/WebSSH2/compare/v0.2.21...v0.2.22) (2024-11-30)
|
## [0.2.22](https://github.com/billchurch/WebSSH2/compare/v0.2.21...v0.2.22) (2024-11-30)
|
||||||
|
|
||||||
|
@ -539,4 +579,4 @@ Mostly client (browser) related changes in this release
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Initial proof of concept and release. For historical purposes only.
|
- Initial proof of concept and release. For historical purposes only.
|
|
@ -149,7 +149,7 @@ If you encounter issues:
|
||||||
4. Verify the ports (3000 and 2222) are available
|
4. Verify the ports (3000 and 2222) are available
|
||||||
5. Clear browser cache if changes aren't reflecting
|
5. Clear browser cache if changes aren't reflecting
|
||||||
|
|
||||||
## Building for Production
|
## Building for Production (client)
|
||||||
|
|
||||||
When ready to build for production:
|
When ready to build for production:
|
||||||
|
|
||||||
|
|
12
README.md
12
README.md
|
@ -196,7 +196,7 @@ For more information on SSH keyboard-interactive authentication, refer to [RFC 4
|
||||||
|
|
||||||
### SSH Private Key Authentication
|
### SSH Private Key Authentication
|
||||||
|
|
||||||
WebSSH2 supports SSH private key authentication when using the `/ssh/host/` endpoint with a private key configured in the server settings.
|
WebSSH2 supports SSH private key authentication when using the `/ssh/host/` endpoint with a private key configured in the server settings or via the interactive method with the `/ssh/` endpoint.
|
||||||
|
|
||||||
#### Configuration
|
#### Configuration
|
||||||
|
|
||||||
|
@ -215,13 +215,17 @@ Private key authentication can only be configured through the `config.json` file
|
||||||
#### Key Requirements
|
#### Key Requirements
|
||||||
|
|
||||||
- Only `ssh-rsa` type keys are supported
|
- Only `ssh-rsa` type keys are supported
|
||||||
|
- Passphrase encryption is supported, and if used the `passphrase` must be provided
|
||||||
- The private key must be in PEM format
|
- The private key must be in PEM format
|
||||||
- The key in `config.json` must be on a single line with `\n` as line separators
|
- The key in `config.json` must be on a single line with `\n` as line separators
|
||||||
- Must include the appropriate header and footer:
|
- Must include the appropriate header and footer:
|
||||||
```
|
```
|
||||||
-----BEGIN RSA PRIVATE KEY-----\n[... key content ...]\n-----END RSA PRIVATE KEY-----
|
-----BEGIN RSA PRIVATE KEY-----\n[... key content ...]\n-----END RSA PRIVATE KEY-----
|
||||||
```
|
```
|
||||||
|
or for encrypted keys:
|
||||||
|
```
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----\nProc-Type: 4,ENCRYPTED\nDEK-Info: AES-128-CBC,5930F19760F7FBBC865400940A89D954\n\n[... key content ...]\n-----END RSA PRIVATE KEY-----
|
||||||
|
```
|
||||||
#### Generating a Private Key
|
#### Generating a Private Key
|
||||||
To generate a new SSH private key, you can use the following command:
|
To generate a new SSH private key, you can use the following command:
|
||||||
|
|
||||||
|
@ -231,10 +235,10 @@ ssh-keygen -m PEM -t rsa -b 4096 -f ~/.ssh/id_rsa
|
||||||
|
|
||||||
#### Converting Your Private Key
|
#### Converting Your Private Key
|
||||||
|
|
||||||
To convert your existing SSH private key into the correct format for `config.json`, you can use this bash command:
|
Keys uploaded or pasted using the interactive mode through the `/ssh` endpoint can work as-is, however if using a key with `config.json` you must convert your existing SSH private key into the correct format (single line). A bash one-liner you can to accomplish this is:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
echo '"'$(cat ~/.ssh/id_rsa | tr '\n' '~' | sed 's/~/\\n/g')'"'
|
echo ' "privateKey": "'$(cat ~/.ssh/id_rsa | tr '\n' '~' | sed 's/~/\\n/g')'"'
|
||||||
```
|
```
|
||||||
|
|
||||||
This command:
|
This command:
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
import express from 'express'
|
import express from 'express'
|
||||||
import config from './config.js'
|
import config from './config.js'
|
||||||
|
import SSHConnection from './ssh.js'
|
||||||
import socketHandler from './socket.js'
|
import socketHandler from './socket.js'
|
||||||
import { createRoutes } from './routes.js'
|
import { createRoutes } from './routes.js'
|
||||||
import { applyMiddleware } from './middleware.js'
|
import { applyMiddleware } from './middleware.js'
|
||||||
|
@ -52,7 +53,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)
|
||||||
|
|
|
@ -23,6 +23,8 @@ const defaultConfig = {
|
||||||
user: {
|
user: {
|
||||||
name: null,
|
name: null,
|
||||||
password: null,
|
password: null,
|
||||||
|
privateKey: null,
|
||||||
|
passphrase: null,
|
||||||
},
|
},
|
||||||
ssh: {
|
ssh: {
|
||||||
host: null,
|
host: null,
|
||||||
|
|
|
@ -28,6 +28,7 @@ const configSchema = {
|
||||||
name: { type: ['string', 'null'] },
|
name: { type: ['string', 'null'] },
|
||||||
password: { type: ['string', 'null'] },
|
password: { type: ['string', 'null'] },
|
||||||
privateKey: { type: ['string', 'null'] },
|
privateKey: { type: ['string', 'null'] },
|
||||||
|
passphrase: { type: ['string', 'null'] },
|
||||||
},
|
},
|
||||||
required: ['name', 'password'],
|
required: ['name', 'password'],
|
||||||
},
|
},
|
||||||
|
|
|
@ -3,20 +3,27 @@
|
||||||
|
|
||||||
import validator from 'validator'
|
import validator from 'validator'
|
||||||
import { EventEmitter } from 'events'
|
import { EventEmitter } from 'events'
|
||||||
import SSHConnection from './ssh.js'
|
|
||||||
import { createNamespacedDebug } from './logger.js'
|
import { createNamespacedDebug } from './logger.js'
|
||||||
import { SSHConnectionError, handleError } from './errors.js'
|
import { SSHConnectionError, handleError } from './errors.js'
|
||||||
|
|
||||||
const debug = createNamespacedDebug('socket')
|
|
||||||
import { isValidCredentials, maskSensitiveData, validateSshTerm } from './utils.js'
|
import { isValidCredentials, maskSensitiveData, validateSshTerm } from './utils.js'
|
||||||
import { MESSAGES } from './constants.js'
|
import { MESSAGES } from './constants.js'
|
||||||
|
|
||||||
|
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,
|
||||||
|
@ -58,10 +65,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)
|
||||||
})
|
})
|
||||||
|
@ -129,6 +132,14 @@ class WebSSH2Socket extends EventEmitter {
|
||||||
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(() => {
|
||||||
|
@ -342,6 +353,6 @@ class WebSSH2Socket extends EventEmitter {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function (io, config) {
|
export default function (io, config, SSHConnectionClass) {
|
||||||
io.on('connection', (socket) => new WebSSH2Socket(socket, config))
|
io.on('connection', (socket) => new WebSSH2Socket(socket, config, SSHConnectionClass))
|
||||||
}
|
}
|
||||||
|
|
92
app/ssh.js
92
app/ssh.js
|
@ -25,14 +25,30 @@ class SSHConnection extends EventEmitter {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validates the format of an RSA private key
|
* Validates the format of an RSA private key, supporting both standard and encrypted keys
|
||||||
* @param {string} key - The private key string to validate
|
* @param {string} key - The private key string to validate
|
||||||
* @returns {boolean} - Whether the key appears to be valid
|
* @returns {boolean} - Whether the key appears to be valid
|
||||||
*/
|
*/
|
||||||
validatePrivateKey(key) {
|
validatePrivateKey(key) {
|
||||||
const keyPattern =
|
// Pattern for standard RSA private key
|
||||||
|
const standardKeyPattern =
|
||||||
/^-----BEGIN (?:RSA )?PRIVATE KEY-----\r?\n([A-Za-z0-9+/=\r\n]+)\r?\n-----END (?:RSA )?PRIVATE KEY-----\r?\n?$/
|
/^-----BEGIN (?:RSA )?PRIVATE KEY-----\r?\n([A-Za-z0-9+/=\r\n]+)\r?\n-----END (?:RSA )?PRIVATE KEY-----\r?\n?$/
|
||||||
return keyPattern.test(key)
|
|
||||||
|
// Pattern for encrypted RSA private key
|
||||||
|
const encryptedKeyPattern =
|
||||||
|
/^-----BEGIN RSA PRIVATE KEY-----\r?\n(?:Proc-Type: 4,ENCRYPTED\r?\nDEK-Info: ([^\r\n]+)\r?\n\r?\n)([A-Za-z0-9+/=\r\n]+)\r?\n-----END RSA PRIVATE KEY-----\r?\n?$/
|
||||||
|
|
||||||
|
// Test for either standard or encrypted key format
|
||||||
|
return standardKeyPattern.test(key) || encryptedKeyPattern.test(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a private key is encrypted
|
||||||
|
* @param {string} key - The private key to check
|
||||||
|
* @returns {boolean} - Whether the key is encrypted
|
||||||
|
*/
|
||||||
|
isEncryptedKey(key) {
|
||||||
|
return key.includes('Proc-Type: 4,ENCRYPTED')
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -126,12 +142,68 @@ class SSHConnection extends EventEmitter {
|
||||||
this.handleKeyboardInteractive(name, instructions, lang, prompts, finish)
|
this.handleKeyboardInteractive(name, instructions, lang, prompts, finish)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Handles keyboard-interactive authentication prompts.
|
||||||
|
* @param {string} name - The name of the authentication request.
|
||||||
|
* @param {string} instructions - The instructions for the keyboard-interactive prompt.
|
||||||
|
* @param {string} lang - The language of the prompt.
|
||||||
|
* @param {Array<Object>} prompts - The list of prompts provided by the server.
|
||||||
|
* @param {Function} finish - The callback to complete the keyboard-interactive authentication.
|
||||||
|
*/
|
||||||
|
|
||||||
|
handleKeyboardInteractive(name, instructions, lang, prompts, finish) {
|
||||||
|
debug('handleKeyboardInteractive: Keyboard-interactive auth %O', prompts)
|
||||||
|
|
||||||
|
// Check if we should always send prompts to the client
|
||||||
|
if (this.config.ssh.alwaysSendKeyboardInteractivePrompts) {
|
||||||
|
this.sendPromptsToClient(name, instructions, prompts, finish)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const responses = []
|
||||||
|
let shouldSendToClient = false
|
||||||
|
|
||||||
|
for (let i = 0; i < prompts.length; i += 1) {
|
||||||
|
if (prompts[i].prompt.toLowerCase().includes('password') && this.creds.password) {
|
||||||
|
responses.push(this.creds.password)
|
||||||
|
} else {
|
||||||
|
shouldSendToClient = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldSendToClient) {
|
||||||
|
this.sendPromptsToClient(name, instructions, prompts, finish)
|
||||||
|
} else {
|
||||||
|
finish(responses)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends prompts to the client for keyboard-interactive authentication.
|
||||||
|
*
|
||||||
|
* @param {string} name - The name of the authentication method.
|
||||||
|
* @param {string} instructions - The instructions for the authentication.
|
||||||
|
* @param {Array<{ prompt: string, echo: boolean }>} prompts - The prompts to be sent to the client.
|
||||||
|
* @param {Function} finish - The callback function to be called when the client responds.
|
||||||
|
*/
|
||||||
|
sendPromptsToClient(name, instructions, prompts, finish) {
|
||||||
|
this.emit('keyboard-interactive', {
|
||||||
|
name: name,
|
||||||
|
instructions: instructions,
|
||||||
|
prompts: prompts.map((p) => ({ prompt: p.prompt, echo: p.echo })),
|
||||||
|
})
|
||||||
|
|
||||||
|
this.once('keyboard-interactive-response', (responses) => {
|
||||||
|
finish(responses)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates the SSH configuration object based on credentials.
|
* Generates the SSH configuration object based on credentials.
|
||||||
* @param {Object} creds - The credentials object containing host, port, username, and optional password.
|
* @param {Object} creds - The credentials object
|
||||||
* @param {boolean} useKey - Whether to attempt key authentication
|
* @param {boolean} useKey - Whether to attempt key authentication
|
||||||
* @returns {Object} - The SSH configuration object.
|
* @returns {Object} - The SSH configuration object
|
||||||
*/
|
*/
|
||||||
getSSHConfig(creds, useKey) {
|
getSSHConfig(creds, useKey) {
|
||||||
const config = {
|
const config = {
|
||||||
|
@ -154,6 +226,16 @@ class SSHConnection extends EventEmitter {
|
||||||
throw new SSHConnectionError('Invalid private key format')
|
throw new SSHConnectionError('Invalid private key format')
|
||||||
}
|
}
|
||||||
config.privateKey = privateKey
|
config.privateKey = privateKey
|
||||||
|
|
||||||
|
// Check if key is encrypted and passphrase is needed
|
||||||
|
if (this.isEncryptedKey(privateKey)) {
|
||||||
|
const passphrase = creds.passphrase || this.config.user.passphrase
|
||||||
|
if (!passphrase) {
|
||||||
|
throw new SSHConnectionError('Encrypted private key requires a passphrase')
|
||||||
|
}
|
||||||
|
debug('Adding passphrase for encrypted private key')
|
||||||
|
config.passphrase = passphrase
|
||||||
|
}
|
||||||
} else if (creds.password) {
|
} else if (creds.password) {
|
||||||
debug('Using password authentication')
|
debug('Using password authentication')
|
||||||
config.password = creds.password
|
config.password = creds.password
|
||||||
|
|
15
app/utils.js
15
app/utils.js
|
@ -80,7 +80,7 @@ export function getValidatedPort(portInput) {
|
||||||
* - port (number)
|
* - port (number)
|
||||||
* AND either:
|
* AND either:
|
||||||
* - password (string) OR
|
* - password (string) OR
|
||||||
* - privateKey/privateKey (string)
|
* - privateKey (string) with optional passphrase (string)
|
||||||
*
|
*
|
||||||
* @param {Object} creds - The credentials object.
|
* @param {Object} creds - The credentials object.
|
||||||
* @returns {boolean} - Returns true if the credentials are valid, otherwise false.
|
* @returns {boolean} - Returns true if the credentials are valid, otherwise false.
|
||||||
|
@ -97,11 +97,14 @@ export function isValidCredentials(creds) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must have either password or privateKey/privateKey
|
// Must have either password or privateKey
|
||||||
const hasPassword = typeof creds.password === 'string'
|
const hasPassword = typeof creds.password === 'string'
|
||||||
const hasPrivateKey = typeof creds.privateKey === 'string' || typeof creds.privateKey === 'string'
|
const hasPrivateKey = typeof creds.privateKey === 'string'
|
||||||
|
|
||||||
return hasPassword || hasPrivateKey
|
// Passphrase is optional but must be string if provided
|
||||||
|
const hasValidPassphrase = !creds.passphrase || typeof creds.passphrase === 'string'
|
||||||
|
|
||||||
|
return (hasPassword || hasPrivateKey) && hasValidPassphrase
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -171,7 +174,9 @@ export function modifyHtml(html, config) {
|
||||||
* @returns {Object} The masked object
|
* @returns {Object} The masked object
|
||||||
*/
|
*/
|
||||||
export function maskSensitiveData(obj, options) {
|
export function maskSensitiveData(obj, options) {
|
||||||
const defaultOptions = {}
|
const defaultOptions = {
|
||||||
|
properties: ['password', 'privateKey', 'passphrase', 'key', 'secret', 'token'],
|
||||||
|
}
|
||||||
debug('maskSensitiveData')
|
debug('maskSensitiveData')
|
||||||
|
|
||||||
const maskingOptions = Object.assign({}, defaultOptions, options || {})
|
const maskingOptions = Object.assign({}, defaultOptions, options || {})
|
||||||
|
|
|
@ -26,7 +26,7 @@
|
||||||
"keepaliveCountMax": 10,
|
"keepaliveCountMax": 10,
|
||||||
"allowedSubnets": [],
|
"allowedSubnets": [],
|
||||||
"alwaysSendKeyboardInteractivePrompts": false,
|
"alwaysSendKeyboardInteractivePrompts": false,
|
||||||
"disableInteractiveAuth": true,
|
"disableInteractiveAuth": false,
|
||||||
"algorithms": {
|
"algorithms": {
|
||||||
"cipher": [
|
"cipher": [
|
||||||
"aes128-ctr",
|
"aes128-ctr",
|
||||||
|
|
|
@ -51,7 +51,7 @@
|
||||||
"lint:fix": "eslint app --fix",
|
"lint:fix": "eslint app --fix",
|
||||||
"watch": "NODE_ENV=development DEBUG=webssh* node --watch index.js",
|
"watch": "NODE_ENV=development DEBUG=webssh* node --watch index.js",
|
||||||
"test": "node --test tests/*.test.js",
|
"test": "node --test tests/*.test.js",
|
||||||
"release": "standard-version -a -s --release-as patch --commit-all",
|
"release": "npm run lint:fix && npm run test && standard-version -a -s --release-as patch --commit-all --infile ChangeLog.md",
|
||||||
"release:dry-run": "standard-version -a -s --release-as patch --dry-run",
|
"release:dry-run": "standard-version -a -s --release-as patch --dry-run",
|
||||||
"publish:dry-run": "npm publish --dry-run",
|
"publish:dry-run": "npm publish --dry-run",
|
||||||
"publish:npm": "npm publish",
|
"publish:npm": "npm publish",
|
||||||
|
|
Loading…
Reference in a new issue