Skip to content

Commit

Permalink
Merge pull request #436 from steelbrain/steelbrain/separate-key-and-path
Browse files Browse the repository at this point in the history
Separate private key and private key path
  • Loading branch information
steelbrain committed Jul 26, 2022
2 parents 5347152 + ba6554b commit 1c0a6f7
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 25 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
#### Upcoming

- BREAKING: `privateKey` config parameter no longer accepts file system paths. Please use the new `privateKeyPath` parameter instead

#### 12.0.5

- Fixed manifest config for Typescript typings. #431 (Thanks @Sikarii)
Expand Down
20 changes: 10 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,16 @@ const ssh = new NodeSSH()
ssh.connect({
host: 'localhost',
username: 'steel',
privateKey: '/home/steel/.ssh/id_rsa'
privateKeyPath: '/home/steel/.ssh/id_rsa'
})

// or with inline privateKey

ssh.connect({
host: 'localhost',
username: 'steel',
privateKey: Buffer.from('...')
})
/*
Or
ssh.connect({
host: 'localhost',
username: 'steel',
privateKey: fs.readFileSync('/home/steel/.ssh/id_rsa', 'utf8')
})
if you want to use the raw string as private key
*/
.then(function() {
// Local, Remote
ssh.putFile('/home/steel/Lab/localPath/fileName', '/home/steel/Lab/remotePath/fileName').then(function() {
Expand Down Expand Up @@ -110,6 +109,7 @@ declare type Config = ConnectConfig & {
port?: number;
username?: string;
password?: string;
privateKeyPath?: string;
privateKey?: string;
passphrase?: string;
tryKeyboard?: boolean;
Expand Down
31 changes: 20 additions & 11 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { Prompt, Stats, TransferOptions } from 'ssh2-streams'
export type Config = ConnectConfig & {
password?: string
privateKey?: string
privateKeyPath?: string
tryKeyboard?: boolean
onKeyboardInteractive?: (
name: string,
Expand Down Expand Up @@ -161,25 +162,33 @@ export class NodeSSH {
throw new AssertionError({ message: 'Either config.host or config.sock must be provided' })
}

if (config.privateKey != null) {
invariant(typeof config.privateKey === 'string', 'config.privateKey must be a valid string')
if (config.privateKey != null || config.privateKeyPath != null) {
if (config.privateKey != null) {
invariant(typeof config.privateKey === 'string', 'config.privateKey must be a valid string')
invariant(
config.privateKeyPath == null,
'config.privateKeyPath must not be specified when config.privateKey is specified',
)
} else if (config.privateKeyPath != null) {
invariant(typeof config.privateKeyPath === 'string', 'config.privateKeyPath must be a valid string')
invariant(
config.privateKey == null,
'config.privateKey must not be specified when config.privateKeyPath is specified',
)
}

invariant(
config.passphrase == null || typeof config.passphrase === 'string',
'config.passphrase must be a valid string',
'config.passphrase must be null or a valid string',
)

if (
!(
(config.privateKey.includes('BEGIN') && config.privateKey.includes('KEY')) ||
config.privateKey.includes('PuTTY-User-Key-File-2')
)
) {
if (config.privateKeyPath != null) {
// Must be an fs path
try {
config.privateKey = await readFile(config.privateKey)
config.privateKey = await readFile(config.privateKeyPath)
} catch (err) {
if (err != null && err.code === 'ENOENT') {
throw new AssertionError({ message: 'config.privateKey does not exist at given fs path' })
throw new AssertionError({ message: 'config.privateKeyPath does not exist at given fs path' })
}
throw err
}
Expand Down
2 changes: 1 addition & 1 deletion test/main-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ async function connectWithPrivateKey(port, client) {
host: '127.0.0.1',
port,
username: 'steel',
privateKey: PRIVATE_KEY_PATH,
privateKeyPath: PRIVATE_KEY_PATH,
})
}
async function connectWithInlinePrivateKey(port, client) {
Expand Down
20 changes: 17 additions & 3 deletions test/validation-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,10 +313,24 @@ test('throws if privateKey is a file and does not exist', async function (t) {
await normalizeConfig({
username: 'asd',
host: 'localhost',
privateKey: keyPath,
privateKeyPath: keyPath,
})
},
`config.privateKey does not exist at given fs path`,
`config.privateKeyPath does not exist at given fs path`,
)
})
test('throws if privateKey is specified and so is privateKeyPath', async function (t) {
await throwsAsync(
t,
async function () {
await normalizeConfig({
username: 'asd',
host: 'localhost',
privateKey: 'x',
privateKeyPath: 'y',
})
},
`config.privateKeyPath must not be specified when config.privateKey is specified`,
)
})
test('does not throw if privateKey is valid', async function (t) {
Expand Down Expand Up @@ -348,7 +362,7 @@ test('does not throw if privateKey is valid', async function (t) {
await normalizeConfig({
username: 'asd',
host: 'localhost',
privateKey: PRIVATE_KEY_PATH,
privateKeyPath: PRIVATE_KEY_PATH,
})
},
'connect ECONNREFUSED 127.0.0.1:22',
Expand Down

0 comments on commit 1c0a6f7

Please sign in to comment.