nixos/ssh: add programs.ssh.knownHostsFiles option

The programs.ssh.knownHosts.*.publicKeyFile is broken, because it's
scoped to a set of host names, but to insert those host names on each
line of the file we'd have to parse out blank lines and comments, so
only the first line works.  It would be much easier all round if users
just provided known hosts files in the normal format, and we pointed
ssh directly to them.  This way, it would be possible to have multiple
keys for a single host (which is extremely common due to multiple
algorithms being commonplace).

We add an option for this instead of relying on extraConfig, because
we need to make sure /etc/ssh/ssh_known_hosts is always included to
ensure programs.ssh.knownHosts keeps working.
/etc/ssh/ssh_known_hosts2 is another OpenSSH default that seems a bit
weird, but there's no real reason to change that so we'll leave it.
This commit is contained in:
Alyssa Ross 2021-11-21 17:25:03 +00:00
parent 810e09c544
commit 262447705c

View file

@ -25,6 +25,9 @@ let
+ (if h.publicKey != null then h.publicKey else readFile h.publicKeyFile)
)) + "\n";
knownHostsFiles = [ "/etc/ssh/ssh_known_hosts" "/etc/ssh/ssh_known_hosts2" ]
++ map pkgs.copyPathToStore cfg.knownHostsFiles;
in
{
###### interface
@ -177,7 +180,9 @@ in
You can fetch a public key file from a running SSH server
with the <command>ssh-keyscan</command> command. The content
of the file should follow the same format as described for
the <literal>publicKey</literal> option.
the <literal>publicKey</literal> option. Only a single key
is supported. If a host has multiple keys, use
<option>programs.ssh.knownHostsFiles</option> instead.
'';
};
};
@ -202,6 +207,28 @@ in
'';
};
knownHostsFiles = mkOption {
default = [];
type = with types; listOf path;
description = ''
Files containing SSH host keys to set as global known hosts.
<literal>/etc/ssh/ssh_known_hosts</literal> (which is
generated by <option>programs.ssh.knownHosts</option>) and
<literal>/etc/ssh/ssh_known_hosts2</literal> are always
included.
'';
example = literalExpression ''
[
./known_hosts
(writeText "github.keys" '''
github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==
github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=
github.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOMqqnkVzrm0SdG6UOoqKLsabgH5C9okWi0dh2l9GKJl
''')
]
'';
};
kexAlgorithms = mkOption {
type = types.nullOr (types.listOf types.str);
default = null;
@ -258,6 +285,7 @@ in
# Generated options from other settings
Host *
AddressFamily ${if config.networking.enableIPv6 then "any" else "inet"}
GlobalKnownHostsFile ${concatStringsSep " " knownHostsFiles}
${optionalString cfg.setXAuthLocation ''
XAuthLocation ${pkgs.xorg.xauth}/bin/xauth