Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
"ava": "^5.3.1",
"eslint-config-steelbrain": "^11.0.0",
"node-pty": "^1.0.0",
"ssh2": "^1.14.0",
"ssh2": "github:m-team-kit/ssh2#add-certificate-support",
"ssh2-streams": "^0.4.10",
"ts-node": "^10.9.1",
"typescript": "^5.1.6"
Expand All @@ -60,7 +60,7 @@
"sb-promise-queue": "^2.1.0",
"sb-scandir": "^3.1.0",
"shell-escape": "^0.2.0",
"ssh2": "^1.14.0"
"ssh2": "github:m-team-kit/ssh2#add-certificate-support"
},
"ava": {
"files": [
Expand Down
32 changes: 32 additions & 0 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export type Config = ConnectConfig & {
password?: string
privateKey?: string
privateKeyPath?: string
certificate?: string
certificatePath?: string
tryKeyboard?: boolean
onKeyboardInteractive?: (
name: string,
Expand Down Expand Up @@ -230,6 +232,36 @@ export class NodeSSH {
invariant(typeof config.password === 'string', 'config.password must be a valid string')
}

// SSH certificate authentication (OpenSSH PROTOCOL.certkeys)
// Certificates are used with a private key for CA-signed authentication
if (config.certificate != null || config.certificatePath != null) {
if (config.certificate != null) {
invariant(typeof config.certificate === 'string', 'config.certificate must be a valid string')
invariant(
config.certificatePath == null,
'config.certificatePath must not be specified when config.certificate is specified',
)
} else if (config.certificatePath != null) {
invariant(typeof config.certificatePath === 'string', 'config.certificatePath must be a valid string')
invariant(
config.certificate == null,
'config.certificate must not be specified when config.certificatePath is specified',
)
}

if (config.certificatePath != null) {
// Must be an fs path
try {
config.certificate = await readFile(config.certificatePath)
} catch (err) {
if (err != null && err.code === 'ENOENT') {
throw new AssertionError({ message: 'config.certificatePath does not exist at given fs path' })
}
throw err
}
}
}

if (config.tryKeyboard != null) {
invariant(typeof config.tryKeyboard === 'boolean', 'config.tryKeyboard must be a valid boolean')
}
Expand Down