programs/ssh: backport knownHosts changes (#1517)
This commit is contained in:
commit
0d71cbf88d
2 changed files with 61 additions and 47 deletions
|
|
@ -113,7 +113,7 @@
|
|||
./programs/man.nix
|
||||
./programs/info
|
||||
./programs/nix-index
|
||||
./programs/ssh
|
||||
./programs/ssh.nix
|
||||
./programs/tmux.nix
|
||||
./programs/vim.nix
|
||||
./programs/zsh
|
||||
|
|
|
|||
|
|
@ -1,14 +1,12 @@
|
|||
{ config, lib, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
let
|
||||
cfg = config.programs.ssh;
|
||||
|
||||
knownHosts = map (h: getAttr h cfg.knownHosts) (attrNames cfg.knownHosts);
|
||||
knownHosts = builtins.attrValues cfg.knownHosts;
|
||||
|
||||
host =
|
||||
{ name, ... }:
|
||||
{ name, config, ... }:
|
||||
{
|
||||
options = {
|
||||
certAuthority = lib.mkOption {
|
||||
|
|
@ -19,17 +17,30 @@ let
|
|||
individual host's key.
|
||||
'';
|
||||
};
|
||||
hostNames = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [];
|
||||
hostNames = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [ name ] ++ config.extraHostNames;
|
||||
description = ''
|
||||
A list of host names and/or IP numbers used for accessing
|
||||
the host's ssh service.
|
||||
The set of system-wide known SSH hosts. To make simple setups more
|
||||
convenient the name of an attribute in this set is used as a host name
|
||||
for the entry. This behaviour can be disabled by setting
|
||||
`hostNames` explicitly. You can use
|
||||
`extraHostNames` to add additional host names without
|
||||
disabling this default.
|
||||
'';
|
||||
};
|
||||
publicKey = mkOption {
|
||||
extraHostNames = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
A list of additional host names and/or IP numbers used for
|
||||
accessing the host's ssh service. This list is ignored if
|
||||
`hostNames` is set explicitly.
|
||||
'';
|
||||
};
|
||||
publicKey = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.str;
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
example = "ecdsa-sha2-nistp521 AAAAE2VjZHN...UEPg==";
|
||||
description = ''
|
||||
The public key data for the host. You can fetch a public key
|
||||
|
|
@ -38,9 +49,9 @@ let
|
|||
the key type and the key itself.
|
||||
'';
|
||||
};
|
||||
publicKeyFile = mkOption {
|
||||
publicKeyFile = lib.mkOption {
|
||||
default = null;
|
||||
type = types.nullOr types.path;
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
description = ''
|
||||
The path to the public key file for the host. The public
|
||||
key file is read at build time and saved in the Nix store.
|
||||
|
|
@ -51,16 +62,13 @@ let
|
|||
'';
|
||||
};
|
||||
};
|
||||
config = {
|
||||
hostNames = mkDefault [ name ];
|
||||
};
|
||||
};
|
||||
# Taken from: https://github.com/NixOS/nixpkgs/blob/f4aa6afa5f934ece2d1eb3157e392d056be01617/nixos/modules/services/networking/ssh/sshd.nix#L46-L93
|
||||
userOptions = {
|
||||
|
||||
options.openssh.authorizedKeys = {
|
||||
keys = mkOption {
|
||||
type = types.listOf types.str;
|
||||
keys = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.str;
|
||||
default = [];
|
||||
description = ''
|
||||
A list of verbatim OpenSSH public keys that should be added to the
|
||||
|
|
@ -73,8 +81,8 @@ let
|
|||
'';
|
||||
};
|
||||
|
||||
keyFiles = mkOption {
|
||||
type = types.listOf types.path;
|
||||
keyFiles = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.path;
|
||||
default = [];
|
||||
description = ''
|
||||
A list of files each containing one OpenSSH public key that should be
|
||||
|
|
@ -89,29 +97,29 @@ let
|
|||
};
|
||||
|
||||
authKeysFiles = let
|
||||
mkAuthKeyFile = u: nameValuePair "ssh/nix_authorized_keys.d/${u.name}" {
|
||||
mkAuthKeyFile = u: lib.nameValuePair "ssh/nix_authorized_keys.d/${u.name}" {
|
||||
text = ''
|
||||
${concatStringsSep "\n" u.openssh.authorizedKeys.keys}
|
||||
${concatMapStrings (f: readFile f + "\n") u.openssh.authorizedKeys.keyFiles}
|
||||
${builtins.concatStringsSep "\n" u.openssh.authorizedKeys.keys}
|
||||
${lib.concatMapStrings (f: builtins.readFile f + "\n") u.openssh.authorizedKeys.keyFiles}
|
||||
'';
|
||||
};
|
||||
usersWithKeys = attrValues (flip filterAttrs config.users.users (n: u:
|
||||
length u.openssh.authorizedKeys.keys != 0 || length u.openssh.authorizedKeys.keyFiles != 0
|
||||
usersWithKeys = builtins.attrValues (lib.flip lib.filterAttrs config.users.users (n: u:
|
||||
lib.length u.openssh.authorizedKeys.keys != 0 || lib.length u.openssh.authorizedKeys.keyFiles != 0
|
||||
));
|
||||
in listToAttrs (map mkAuthKeyFile usersWithKeys);
|
||||
in lib.listToAttrs (map mkAuthKeyFile usersWithKeys);
|
||||
|
||||
oldAuthorizedKeysHash = "5a5dc1e20e8abc162ad1cc0259bfd1dbb77981013d87625f97d9bd215175fc0a";
|
||||
in
|
||||
|
||||
{
|
||||
imports = [
|
||||
(mkRemovedOptionModule [ "services" "openssh" "authorizedKeysFiles" ] "No `nix-darwin` equivalent to this NixOS option.")
|
||||
(lib.mkRemovedOptionModule [ "services" "openssh" "authorizedKeysFiles" ] "No `nix-darwin` equivalent to this NixOS option.")
|
||||
];
|
||||
|
||||
options = {
|
||||
|
||||
users.users = mkOption {
|
||||
type = with types; attrsOf (submodule userOptions);
|
||||
users.users = lib.mkOption {
|
||||
type = with lib.types; attrsOf (submodule userOptions);
|
||||
};
|
||||
|
||||
programs.ssh.extraConfig = lib.mkOption {
|
||||
|
|
@ -123,41 +131,47 @@ in
|
|||
'';
|
||||
};
|
||||
|
||||
programs.ssh.knownHosts = mkOption {
|
||||
programs.ssh.knownHosts = lib.mkOption {
|
||||
default = {};
|
||||
type = types.attrsOf (types.submodule host);
|
||||
type = lib.types.attrsOf (lib.types.submodule host);
|
||||
description = ''
|
||||
The set of system-wide known SSH hosts.
|
||||
The set of system-wide known SSH hosts. To make simple setups more
|
||||
convenient the name of an attribute in this set is used as a host name
|
||||
for the entry. This behaviour can be disabled by setting
|
||||
`hostNames` explicitly. You can use
|
||||
`extraHostNames` to add additional host names without
|
||||
disabling this default.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
[
|
||||
{
|
||||
hostNames = [ "myhost" "myhost.mydomain.com" "10.10.1.4" ];
|
||||
example = lib.literalExpression ''
|
||||
{
|
||||
myhost = {
|
||||
extraHostNames = [ "myhost.mydomain.com" "10.10.1.4" ];
|
||||
publicKeyFile = ./pubkeys/myhost_ssh_host_dsa_key.pub;
|
||||
}
|
||||
{
|
||||
hostNames = [ "myhost2" ];
|
||||
};
|
||||
"myhost2.net".publicKey = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILIRuJ8p1Fi+m6WkHV0KWnRfpM1WxoW8XAS+XvsSKsTK";
|
||||
"myhost2.net/dsa" = {
|
||||
hostNames = [ "myhost2.net" ];
|
||||
publicKeyFile = ./pubkeys/myhost2_ssh_host_dsa_key.pub;
|
||||
}
|
||||
]
|
||||
};
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
|
||||
assertions = flip mapAttrsToList cfg.knownHosts (name: data: {
|
||||
assertions = lib.flip lib.mapAttrsToList cfg.knownHosts (name: data: {
|
||||
assertion = (data.publicKey == null && data.publicKeyFile != null) ||
|
||||
(data.publicKey != null && data.publicKeyFile == null);
|
||||
message = "knownHost ${name} must contain either a publicKey or publicKeyFile";
|
||||
});
|
||||
|
||||
environment.etc = authKeysFiles //
|
||||
{ "ssh/ssh_known_hosts" = mkIf (builtins.length knownHosts > 0) {
|
||||
text = (flip (concatMapStringsSep "\n") knownHosts
|
||||
{ "ssh/ssh_known_hosts" = lib.mkIf (builtins.length knownHosts > 0) {
|
||||
text = (lib.flip (lib.concatMapStringsSep "\n") knownHosts
|
||||
(h: assert h.hostNames != [];
|
||||
lib.optionalString h.certAuthority "@cert-authority " + concatStringsSep "," h.hostNames + " "
|
||||
+ (if h.publicKey != null then h.publicKey else readFile h.publicKeyFile)
|
||||
lib.optionalString h.certAuthority "@cert-authority " + builtins.concatStringsSep "," h.hostNames + " "
|
||||
+ (if h.publicKey != null then h.publicKey else builtins.readFile h.publicKeyFile)
|
||||
)) + "\n";
|
||||
};
|
||||
"ssh/ssh_config.d/100-nix-darwin.conf".text = config.programs.ssh.extraConfig;
|
||||
Loading…
Add table
Add a link
Reference in a new issue