Skip to content

Config format for known machines and ssh keys

Martin Pitt edited this page Mar 3, 2017 · 8 revisions

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 into machines.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

  1. 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.

  2. 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.
  1. 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.
Clone this wiki locally