feat: passphrase encrypted private key authentication #382
This commit is contained in:
parent
056e87b40d
commit
796145186b
5 changed files with 70 additions and 15 deletions
39
CONFIG.md
39
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` and passphrase encrypted private keys via `user.passphrase`
|
||||
- Removed `user.overridebasic` option
|
||||
- Added keyboard-interactive authentication controls
|
||||
|
||||
|
@ -128,7 +128,8 @@ These settings are now managed client-side.
|
|||
"user": {
|
||||
"name": null,
|
||||
"password": null,
|
||||
"privateKey": null
|
||||
"privateKey": null,
|
||||
"passphrase": null
|
||||
},
|
||||
"ssh": {
|
||||
"host": null,
|
||||
|
@ -138,7 +139,39 @@ These settings are now managed client-side.
|
|||
"keepaliveInterval": 120000,
|
||||
"keepaliveCountMax": 10,
|
||||
"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": {
|
||||
|
|
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
|
||||
|
||||
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
|
||||
|
||||
|
@ -215,13 +215,17 @@ Private key authentication can only be configured through the `config.json` file
|
|||
#### Key Requirements
|
||||
|
||||
- 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 key in `config.json` must be on a single line with `\n` as line separators
|
||||
- Must include the appropriate header and footer:
|
||||
```
|
||||
-----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
|
||||
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
|
||||
|
||||
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
|
||||
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:
|
||||
|
|
|
@ -22,7 +22,9 @@ const defaultConfig = {
|
|||
},
|
||||
user: {
|
||||
name: null,
|
||||
password: null
|
||||
password: null,
|
||||
privateKey: null,
|
||||
passphrase: null
|
||||
},
|
||||
ssh: {
|
||||
host: null,
|
||||
|
|
|
@ -27,7 +27,8 @@ const configSchema = {
|
|||
properties: {
|
||||
name: { type: ["string", "null"] },
|
||||
password: { type: ["string", "null"] },
|
||||
privateKey: { type: ["string", "null"] }
|
||||
privateKey: { type: ["string", "null"] },
|
||||
passphrase: { type: ["string", "null"] }
|
||||
},
|
||||
required: ["name", "password"]
|
||||
},
|
||||
|
|
27
app/ssh.js
27
app/ssh.js
|
@ -40,6 +40,15 @@ class SSHConnection extends EventEmitter {
|
|||
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")
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to connect using the provided credentials
|
||||
* @param {Object} creds - The credentials object
|
||||
|
@ -207,9 +216,9 @@ class SSHConnection extends EventEmitter {
|
|||
|
||||
/**
|
||||
* Generates the SSH configuration object based on credentials.
|
||||
* @param {Object} creds - The credentials object containing host, port, username, and optional password/privateKey/passphrase.
|
||||
* @param {Object} creds - The credentials object
|
||||
* @param {boolean} useKey - Whether to attempt key authentication
|
||||
* @returns {Object} - The SSH configuration object.
|
||||
* @returns {Object} - The SSH configuration object
|
||||
*/
|
||||
getSSHConfig(creds, useKey) {
|
||||
const config = {
|
||||
|
@ -235,10 +244,16 @@ class SSHConnection extends EventEmitter {
|
|||
|
||||
config.privateKey = privateKey
|
||||
|
||||
// Add passphrase if provided
|
||||
if (creds.passphrase) {
|
||||
debug("Passphrase provided for private key")
|
||||
config.passphrase = creds.passphrase
|
||||
// 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) {
|
||||
debug("Using password authentication")
|
||||
|
|
Loading…
Reference in a new issue