sshush
I wanted an infrastructure as code utility that would allow for the storage of SSH configs in plain text, so it could be put into Git repos.
Here's a general example, showing some of the options.
You can define the options in multiple files and supply them either through a glob or individually to sshush. I keep a bash alias for this:
alias compilessh='sshush -s /home/ben/.ssh/config.d/*.yml'
Global options
global
is a special directive that sets Host *
and will place the options at the end of the resulting SSH config file.
global:
UseRoaming: "no"
This results in:
Host *
UseRoaming no
Default options
Defaults are inherited from and merged with configs with a higher specificity (think along the lines of Ansible variables' order of preference).
default:
User: ben
IdentityFile: ~/.ssh/id_rsa
All the other config options will pick up these defaults and then allow you to override them as and when.
Groups
Group together related items as you see fit. For example, Cisco devices may need a bunch of similar Ciphers to be set, you might have one specific key for all your AWS projects, or by AWS tenancy, etc.
In this example, all the web servers use port 2201, and they'll all use the Digital Ocean key apart from the projects-aws
node.
The shortened host names is handy with Ansible, as you would refer to the hosts by SSH config host name in your Ansible inventories.
web_servers:
Config:
Port: 2201
IdentityFile: ~/.ssh/digital_ocean
Hosts:
projects-do-1: projects-do-1.example.com
projects-do-2: projects-do-2.example.com
projects-aws:
HostName: projects-aws.example.com
IdentityFile: ~/.ssh/aws
With our global config, defaults and the web servers, this is what sshush will generate for us:
# Generated by sshush v1.4.0 (/usr/local/bin/sshush)
# From ['test.yml']
# web_servers
Host projects-do-1
User ben
IdentityFile ~/.ssh/digital_ocean
Port 2201
HostName projects-do-1.example.com
Host projects-do-2
User ben
IdentityFile ~/.ssh/digital_ocean
Port 2201
HostName projects-do-2.example.com
Host projects-aws
User ben
IdentityFile ~/.ssh/aws
Port 2201
HostName projects-aws.example.com
Host *
UseRoaming no
As programmers we don't want to repeat ourselves, and managing one big SSH config file where we must specify things repeatedly is error prone. It's also not easy to share it with colleagues. You can choose to gitignore your globals or defaults, so that individuals can supply their own default keys and usernames.
Extends
The extends
directive allows for groups to inherit config from each other.
Here's an example showing accessing older Cisco devices that have various older SSH options, such as out of date ciphers:
---
ciscos:
Config:
Ciphers: aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
KexAlgorithms: +diffie-hellman-group1-sha1
HostKeyAlgorithms: ssh-rsa,ssh-dss
PubkeyAuthentication: "no"
Hosts:
- oldas*.adm
- oldcs*.adm
- cs1.office.adm
- cs2.office.adm
- ms1.office.adm
- as1.office.adm
- as2.office.adm
- as3.office.adm
- as4.office.adm
- ps1.office.adm
- ps2.office.adm
older_ciscos:
Extends: ciscos
Config:
Ciphers: aes128-cbc,3des-cbc,aes192-cbc,aes256-cbc
Hosts:
- es*.office.adm
- cr1.office2.adm
The Extends
directive tells the older_ciscos
group to inherit its base config from the plain ciscos
group. The ciphers
option is then overridden, a wildcard set of hosts matching es*.office.adm
is supplied, in addition to the core router, cr1.office.2.adm
.
That was a big list of hosts, so what do we have now?
$ sshush --source {global,cisco}.yml --path output.txt
sshush running with path "output.txt" and source YAML "['global.yml', 'cisco.yml']"
output.txt written successfully
# Generated by sshush v1.4.0 (/usr/local/bin/sshush)
# From ['global.yml', 'cisco.yml']
# ciscos
Host oldas*.adm
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
KexAlgorithms +diffie-hellman-group1-sha1
HostKeyAlgorithms ssh-rsa,ssh-dss
PubkeyAuthentication no
Host oldcs*.adm
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
KexAlgorithms +diffie-hellman-group1-sha1
HostKeyAlgorithms ssh-rsa,ssh-dss
PubkeyAuthentication no
Host cs1.office.adm
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
KexAlgorithms +diffie-hellman-group1-sha1
HostKeyAlgorithms ssh-rsa,ssh-dss
PubkeyAuthentication no
HostName cs1.office.adm
Host cs2.office.adm
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
KexAlgorithms +diffie-hellman-group1-sha1
HostKeyAlgorithms ssh-rsa,ssh-dss
PubkeyAuthentication no
HostName cs2.office.adm
Host ms1.office.adm
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
KexAlgorithms +diffie-hellman-group1-sha1
HostKeyAlgorithms ssh-rsa,ssh-dss
PubkeyAuthentication no
HostName ms1.office.adm
Host as1.office.adm
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
KexAlgorithms +diffie-hellman-group1-sha1
HostKeyAlgorithms ssh-rsa,ssh-dss
PubkeyAuthentication no
HostName as1.office.adm
Host as2.office.adm
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
KexAlgorithms +diffie-hellman-group1-sha1
HostKeyAlgorithms ssh-rsa,ssh-dss
PubkeyAuthentication no
HostName as2.office.adm
Host as3.office.adm
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
KexAlgorithms +diffie-hellman-group1-sha1
HostKeyAlgorithms ssh-rsa,ssh-dss
PubkeyAuthentication no
HostName as3.office.adm
Host as4.office.adm
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
KexAlgorithms +diffie-hellman-group1-sha1
HostKeyAlgorithms ssh-rsa,ssh-dss
PubkeyAuthentication no
HostName as4.office.adm
Host ps1.office.adm
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
KexAlgorithms +diffie-hellman-group1-sha1
HostKeyAlgorithms ssh-rsa,ssh-dss
PubkeyAuthentication no
HostName ps1.office.adm
Host ps2.office.adm
Ciphers aes128-ctr,aes192-ctr,aes256-ctr,aes128-cbc,3des-cbc
KexAlgorithms +diffie-hellman-group1-sha1
HostKeyAlgorithms ssh-rsa,ssh-dss
PubkeyAuthentication no
HostName ps2.office.adm
# older_ciscos
Host es*.office.adm
Ciphers aes128-cbc,3des-cbc,aes192-cbc,aes256-cbc
KexAlgorithms +diffie-hellman-group1-sha1
HostKeyAlgorithms ssh-rsa,ssh-dss
PubkeyAuthentication no
Host cr1.office2.adm
Ciphers aes128-cbc,3des-cbc,aes192-cbc,aes256-cbc
KexAlgorithms +diffie-hellman-group1-sha1
HostKeyAlgorithms ssh-rsa,ssh-dss
PubkeyAuthentication no
HostName cr1.office2.adm
Host *
UseRoaming no
The yaml is a lot easier to maintain then the resultant SSH config file!