SSH Config Parser & Stringifier
Usage
var sshConfig = require('ssh-config')
var heredoc = require('heredoc')
var expect = require('expect.js')
var config = sshConfig.parse(heredoc(function() {}))
let section = sshConfig.find({ Host: 'tahoe2' })
section.config.some(line => {
if (line.param === 'HostName') {
line.value = 'tahoe2.com.cn'
return true
}
})
console.log(sshConfig.stringify(config))
Iterating Sections
Take the config above as an example, to iterator over sections, a simple for
loop will suffice.
for (let i = 0; i < config.length; i++) {
let line = config[i]
if (line.config) {}
if (line.param === 'Host' || line.param === 'Match') {}
}
You can do it in ES2015 fashion too:
config.filter(line => !!line.config)
A section is an object that looks like below:
{
"param": "Host",
"value": "*",
"config": [
{
"param": "User",
"value": "nil"
},
{
"param": "ProxyCommand",
"value": "ssh -q gateway -W %h:%p"
},
{
"param": "ForwardAgent",
"value": "true"
}
]
}
.compute
Parameters by Host
But iterating over sections and wild parameters to find the parameters you need
is boring and less efficient. You can use config.compute
method to compute
apllied parameters of certain host.
expect(config.compute('tahoe2')).to.eql({
ControlMaster: 'auto',
ControlPath: '~/.ssh/master-%r@%h:%p',
IdentityFile: [
'~/.ssh/id_rsa'
],
ServerAliveInterval: '80',
Host: 'tahoe2',
HostName: 'tahoe2.com',
User: 'nil',
ProxyCommand: 'ssh -q gateway -W %h:%p',
ForwardAgent: 'true'
})
NOTICE According to ssh_config(5), the first obtained
parameter value will be used. So we cannot override existing parameters. It is
suggested that the general settings shall be at the end of your config file.
The IdentityFile
parameter always contain an array to make possible multiple
IdentityFile
settings to be able to coexist.
.find
sections by Host or Match
To ditch boilerplate codes like the for loop shown earlier, we can use the
.find(opts)
available in the parsed config object.
config.find({ Host: 'example1' })
Or you can just brew it yourself:
config.filter(line => line.param === 'Host' && line.value === 'example1').shift()
.remove
sections by Host or other criteria
To remove sections, we can pass the section to .remove(opts)
.
var config = sshConfig.parse()
var section = config.find({ Host: 'example1' })
config.remove(section)
config.remove({ Host: 'example1' })
.append
sections
Starting from version 1.0.0, there's no more .append
method. Since the config
is now a sub class if Array, you can append with methods like .push
or .concat
.
let newSection = sshConfig.parse(`
Host *
User keanu
`)
config = config.concat(newSection)
config.find({ Host: '*' })
References