Config format for known machines and ssh keys - cockpit-project/cockpit GitHub Wiki
⚠ DRAFT: This is currently being discussed.
Summary
A Cockpit service/ws can connect to multiple remote machines which just have the -bridge package installed and manage them remotely through ssh+bridge. We want Cockpit to remember added remote hosts as the common use case for this is to administer a few "pet" machines in your SOHO environment. This specification is about storing these config files.
Status quo
Known cockpit hosts are currently a machine-level concept (i. e. specific to one particular installation of cockpit-system
), as opposed to a per-user concept. The information is spread between (exactly) two global files:
/var/lib/cockpit/machines.json
is a dictionary of name → IP/user name/color/var/lib/cockpit/known_hosts
is a standard ssh "known hosts" file, storing the public SSH host key for a machine name (or IP).
Problems/Ideas for improvement
- Different users who log into cockpit might want a different set of machines to administer (they might have different roles/responsibilities), so the list of known machines should (also) be a per-user concept.
- Users usually already have a
~/.ssh/known_hosts
file which duplicates and possibly even disagrees with cockpit's global file, so users will have to re-verify a host key when logging into it for the first time via cockpit. - SSH also already has a global
/etc/ssh/ssh_known_hosts
file, making the duplication even worse. /var/lib/cockpit/{machines.json,known_hosts}
have the same scope and update characteristics, and splitting it is just done for implementation convenience. It would be structurally better to put the host key intomachines.json
as well.- Cockpit plugins, other packages, admins, VM management software, or config management systems like Ansible/puppet/cloud-init might want to pre-configure machines for cockpit. This is currently racy as each of those and cockpit itself have to open and rewrite the full file. Also, this should be treated as configuration, not state, so we want to move to reading an entire directory in
/etc
.
Implementation
-
Read all
/etc/cockpit/machines.d/*.json
files and merge the dictionaries together. For backwards compatibility, also read/merge/var/lib/cockpit/{machines.json,known_hosts}
. Optionally: When these/var
files are present, immediately write the contents to/etc/cockpit/machines.d/99-webui.json
and delete the original ones in/var
. -
When connecting to a remote host, check if it is already known to the user or global ssh config (
ssh-keygen -F myhost
or... -f /etc/ssh/ssh_known_hosts
)
- yes: all good, just connect
- no: check if is contained in our machines dict (from JSON)
- yes: write a temporary known_hosts file and connect with
ssh -o UserKnownHostsFile=/tmp/known_hosts.XXXXX
- no: connect with ssh the normal way and ask for host key confirmation. Write it into
/etc/ssh/known_hosts
, as we want one admin to be able to set up hosts for all others, and we only allow admins to add servers.
- yes: write a temporary known_hosts file and connect with
- When a new remote is added through the web interface, it gets written to
/etc/cockpit/machines.d/99-webui.json
(suggestions about file name appreciated), so that it overrides earlier drop-ins provided by other packages/config management.