From 829b5cdd7570562766469d39fb54c8549246a472 Mon Sep 17 00:00:00 2001 From: Bill Church Date: Mon, 2 Dec 2024 21:13:24 +0000 Subject: [PATCH] feat: accept private key from client #381 --- CONFIG.md | 4 ++-- README.md | 6 +++--- app/configSchema.js | 4 ++-- app/middleware.js | 6 +++--- app/socket.js | 13 ++++--------- app/ssh.js | 4 ++-- app/utils.js | 6 +++--- tests/ssh.test.js | 8 ++++---- tests/utils.test.js | 2 +- 9 files changed, 24 insertions(+), 29 deletions(-) diff --git a/CONFIG.md b/CONFIG.md index fb8f002..299c45a 100644 --- a/CONFIG.md +++ b/CONFIG.md @@ -84,7 +84,7 @@ Renamed and expanded options: ## Detailed Changes ### 1. Authentication Options -- Added support for SSH private key authentication via `user.privatekey` +- Added support for SSH private key authentication via `user.privateKey` - Removed `user.overridebasic` option - Added keyboard-interactive authentication controls @@ -128,7 +128,7 @@ These settings are now managed client-side. "user": { "name": null, "password": null, - "privatekey": null + "privateKey": null }, "ssh": { "host": null, diff --git a/README.md b/README.md index 57e0265..633c84e 100644 --- a/README.md +++ b/README.md @@ -115,7 +115,7 @@ Edit `config.json` to customize the following options: - `user.name` - _string_ - Default SSH username (default: `null`) - `user.password` - _string_ - Default SSH password (default: `null`) - `ssh.host` - _string_ - Default SSH host (default: `null`) -- `user.privatekey` - _string_ - Default SSH private key (default: `null`) +- `user.privateKey` - _string_ - Default SSH private key (default: `null`) - `ssh.port` - _integer_ - Default SSH port (default: `22`) - `ssh.term` - _string_ - Terminal emulation (default: `"xterm-color"`) - `ssh.readyTimeout` - _integer_ - SSH handshake timeout in ms (default: `20000`) @@ -206,7 +206,7 @@ Private key authentication can only be configured through the `config.json` file { "user": { "name": "myuser", - "privatekey": "-----BEGIN RSA PRIVATE KEY-----\nYour-Private-Key-Here\n-----END RSA PRIVATE KEY-----", + "privateKey": "-----BEGIN RSA PRIVATE KEY-----\nYour-Private-Key-Here\n-----END RSA PRIVATE KEY-----", "password": "optional-fallback-password" } } @@ -277,7 +277,7 @@ This command: { "user": { "name": "myuser", - "privatekey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpA...[rest of key]...Yh5Q==\n-----END RSA PRIVATE KEY-----", + "privateKey": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpA...[rest of key]...Yh5Q==\n-----END RSA PRIVATE KEY-----", "password": "fallback-password" } } diff --git a/app/configSchema.js b/app/configSchema.js index 4bd37a3..ec8231a 100644 --- a/app/configSchema.js +++ b/app/configSchema.js @@ -26,7 +26,8 @@ const configSchema = { type: "object", properties: { name: { type: ["string", "null"] }, - password: { type: ["string", "null"] } + password: { type: ["string", "null"] }, + privateKey: { type: ["string", "null"] } }, required: ["name", "password"] }, @@ -39,7 +40,6 @@ const configSchema = { readyTimeout: { type: "integer" }, keepaliveInterval: { type: "integer" }, keepaliveCountMax: { type: "integer" }, - disableInteractiveAuth: { type: "boolean" }, algorithms: { type: "object", properties: { diff --git a/app/middleware.js b/app/middleware.js index 6df3205..3f4185f 100644 --- a/app/middleware.js +++ b/app/middleware.js @@ -32,14 +32,14 @@ function createAuthMiddleware(config) { // eslint-disable-next-line consistent-return return (req, res, next) => { // Check if username and either password or private key is configured - if (config.user.name && (config.user.password || config.user.privatekey)) { + if (config.user.name && (config.user.password || config.user.privateKey)) { req.session.sshCredentials = { username: config.user.name } // Add credentials based on what's available - if (config.user.privatekey) { - req.session.sshCredentials.privatekey = config.user.privatekey + if (config.user.privateKey) { + req.session.sshCredentials.privateKey = config.user.privateKey } if (config.user.password) { req.session.sshCredentials.password = config.user.password diff --git a/app/socket.js b/app/socket.js index 0258707..193b547 100644 --- a/app/socket.js +++ b/app/socket.js @@ -25,7 +25,7 @@ class WebSSH2Socket extends EventEmitter { authenticated: false, username: null, password: null, - privatekey: null, + privateKey: null, keyPassword: null, host: null, port: null, @@ -117,11 +117,6 @@ class WebSSH2Socket extends EventEmitter { ? creds.term : this.config.ssh.term - // Map the client's privateKey field to our internal privatekey field if present - if (creds.privateKey) { - creds.privatekey = creds.privateKey - } - this.initializeConnection(creds) } else { debug(`handleAuthenticate: ${this.socket.id}, CREDENTIALS INVALID`) @@ -139,8 +134,8 @@ class WebSSH2Socket extends EventEmitter { ) // Add private key from config if available and not provided in creds - if (this.config.user.privatekey && !creds.privatekey) { - creds.privatekey = this.config.user.privatekey + if (this.config.user.privateKey && !creds.privateKey) { + creds.privateKey = this.config.user.privateKey } this.ssh @@ -150,7 +145,7 @@ class WebSSH2Socket extends EventEmitter { authenticated: true, username: creds.username, password: creds.password, - privatekey: creds.privatekey, + privateKey: creds.privateKey, keyPassword: creds.keyPassword, host: creds.host, port: creds.port diff --git a/app/ssh.js b/app/ssh.js index 9bd4e50..ad0deba 100644 --- a/app/ssh.js +++ b/app/ssh.js @@ -160,9 +160,9 @@ class SSHConnection extends EventEmitter { } // Try private key first if available and useKey is true - if (useKey && (creds.privatekey || this.config.user.privatekey)) { + if (useKey && (creds.privateKey || this.config.user.privateKey)) { debug("Using private key authentication") - const privateKey = creds.privatekey || this.config.user.privatekey + const privateKey = creds.privateKey || this.config.user.privateKey if (!this.validatePrivateKey(privateKey)) { throw new SSHConnectionError("Invalid private key format") } diff --git a/app/utils.js b/app/utils.js index 9470cdc..286b4db 100644 --- a/app/utils.js +++ b/app/utils.js @@ -87,7 +87,7 @@ function getValidatedPort(portInput) { * - port (number) * AND either: * - password (string) OR - * - privatekey/privateKey (string) + * - privateKey/privateKey (string) * * @param {Object} creds - The credentials object. * @returns {boolean} - Returns true if the credentials are valid, otherwise false. @@ -104,10 +104,10 @@ function isValidCredentials(creds) { return false } - // Must have either password or privatekey/privateKey + // Must have either password or privateKey/privateKey const hasPassword = typeof creds.password === "string" const hasPrivateKey = - typeof creds.privatekey === "string" || typeof creds.privateKey === "string" + typeof creds.privateKey === "string" || typeof creds.privateKey === "string" return hasPassword || hasPrivateKey } diff --git a/tests/ssh.test.js b/tests/ssh.test.js index d41400b..5221716 100644 --- a/tests/ssh.test.js +++ b/tests/ssh.test.js @@ -47,7 +47,7 @@ describe("SSHConnection", () => { user: { name: null, password: null, - privatekey: null + privateKey: null } } @@ -149,7 +149,7 @@ MIIEpTestKeyContentHere port: 22, username: "user", password: "pass", - privatekey: validPrivateKey + privateKey: validPrivateKey } return sshConnection.connect(mockCreds).then(() => { @@ -168,7 +168,7 @@ MIIEpTestKeyContentHere port: 22, username: "user", password: "pass", - privatekey: validPrivateKey + privateKey: validPrivateKey } let authAttempts = 0 @@ -205,7 +205,7 @@ MIIEpTestKeyContentHere host: "localhost", port: 22, username: "user", - privatekey: "invalid-key-format" + privateKey: "invalid-key-format" } return sshConnection.connect(mockCreds).catch((error) => { diff --git a/tests/utils.test.js b/tests/utils.test.js index 4044785..c1867b1 100644 --- a/tests/utils.test.js +++ b/tests/utils.test.js @@ -152,7 +152,7 @@ describe("utils", () => { user: { name: null, password: null, - privatekey: null + privateKey: null }, ssh: { host: null,