ssh: add generic Match support for matchBlocks (#2992)
* ssh: add generic Match support for matchBlocks Introduce conservative support for actual `Match` blocks in ssh config. "Conservative" means this PR doesn'tt try to process the `match` expression and simply uses it as a string provided by the user. If set, `match` has precedence over `host` meaning if both are set, `match` is used and `host` is ignored. * Add news entry
This commit is contained in:
parent
7ae7250df8
commit
1bdbebc3f8
|
@ -843,6 +843,15 @@ in
|
|||
export MOZ_ALLOW_DOWNGRADE=1
|
||||
'';
|
||||
}
|
||||
|
||||
{
|
||||
time = "2022-11-27T13:14:01+00:00";
|
||||
message = ''
|
||||
'programs.ssh.matchBlocks.*' now supports literal 'Match' blocks via
|
||||
'programs.ssh.matchBlocks.*.match' option as an alternative to plain
|
||||
'Host' blocks
|
||||
'';
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -60,10 +60,37 @@ let
|
|||
matchBlockModule = types.submodule ({ dagName, ... }: {
|
||||
options = {
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "*.example.org";
|
||||
description = ''
|
||||
The host pattern used by this conditional block.
|
||||
<literal>Host</literal> pattern used by this conditional block.
|
||||
See
|
||||
<citerefentry>
|
||||
<refentrytitle>ssh_config</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry>
|
||||
for <literal>Host</literal> block details.
|
||||
This option is ignored if
|
||||
<option>ssh.matchBlocks.*.matcht</option>
|
||||
if defined.
|
||||
'';
|
||||
};
|
||||
|
||||
match = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
example = "host <hostname> canonical\nhost <hostname> exec \"ping -c1 -q 192.168.17.1\"";
|
||||
description = ''
|
||||
<literal>Match</literal> block conditions used by this block. See
|
||||
<citerefentry>
|
||||
<refentrytitle>ssh_config</refentrytitle>
|
||||
<manvolnum>5</manvolnum>
|
||||
</citerefentry>
|
||||
for <literal>Match</literal> block details.
|
||||
This option takes precedence over
|
||||
<option>ssh.matchBlocks.*.host</option>
|
||||
if defined.
|
||||
'';
|
||||
};
|
||||
|
||||
|
@ -276,11 +303,16 @@ let
|
|||
};
|
||||
};
|
||||
|
||||
config.host = mkDefault dagName;
|
||||
# config.host = mkDefault dagName;
|
||||
});
|
||||
|
||||
matchBlockStr = cf: concatStringsSep "\n" (
|
||||
["Host ${cf.host}"]
|
||||
matchBlockStr = key: cf: concatStringsSep "\n" (
|
||||
let
|
||||
hostOrDagName = if cf.host != null then cf.host else key;
|
||||
matchHead = if cf.match != null
|
||||
then "Match ${cf.match}"
|
||||
else "Host ${hostOrDagName}";
|
||||
in [ "${matchHead}" ]
|
||||
++ optional (cf.port != null) " Port ${toString cf.port}"
|
||||
++ optional (cf.forwardAgent != null) " ForwardAgent ${lib.hm.booleans.yesNo cf.forwardAgent}"
|
||||
++ optional cf.forwardX11 " ForwardX11 yes"
|
||||
|
@ -492,7 +524,7 @@ in
|
|||
++ (optional (cfg.includes != [ ]) ''
|
||||
Include ${concatStringsSep " " cfg.includes}
|
||||
'')
|
||||
++ (map (block: matchBlockStr block.data) matchBlocks)
|
||||
++ (map (block: matchBlockStr block.name block.data) matchBlocks)
|
||||
)}
|
||||
|
||||
Host *
|
||||
|
@ -508,5 +540,9 @@ in
|
|||
|
||||
${replaceStrings ["\n"] ["\n "] cfg.extraConfig}
|
||||
'';
|
||||
|
||||
warnings = mapAttrsToList
|
||||
(n: v: "The SSH config match block `programs.ssh.matchBlocks.${n}` sets both of the host and match options.\nThe match option takes precedence.")
|
||||
(filterAttrs (n: v: v.data.host != null && v.data.match != null) cfg.matchBlocks);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
ssh-defaults = ./default-config.nix;
|
||||
ssh-includes = ./includes.nix;
|
||||
ssh-match-blocks = ./match-blocks-attrs.nix;
|
||||
ssh-match-blocks-match-and-hosts = ./match-blocks-match-and-hosts.nix;
|
||||
|
||||
ssh-forwards-dynamic-valid-bind-no-asserts =
|
||||
./forwards-dynamic-valid-bind-no-asserts.nix;
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
Host * !github.com
|
||||
Port 516
|
||||
Host abc
|
||||
Port 2222
|
||||
Match host xyz canonical
|
||||
Port 2223
|
||||
|
||||
Host *
|
||||
ForwardAgent no
|
||||
Compression no
|
||||
ServerAliveInterval 0
|
||||
ServerAliveCountMax 3
|
||||
HashKnownHosts no
|
||||
UserKnownHostsFile ~/.ssh/known_hosts
|
||||
ControlMaster no
|
||||
ControlPath ~/.ssh/master-%r@%n:%p
|
||||
ControlPersist no
|
||||
|
||||
|
32
tests/modules/programs/ssh/match-blocks-match-and-hosts.nix
Normal file
32
tests/modules/programs/ssh/match-blocks-match-and-hosts.nix
Normal file
|
@ -0,0 +1,32 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
|
||||
with lib;
|
||||
|
||||
{
|
||||
config = {
|
||||
programs.ssh = {
|
||||
enable = true;
|
||||
matchBlocks = {
|
||||
abc = { port = 2222; };
|
||||
|
||||
xyz = {
|
||||
match = "host xyz canonical";
|
||||
port = 2223;
|
||||
};
|
||||
|
||||
"* !github.com" = { port = 516; };
|
||||
};
|
||||
};
|
||||
|
||||
home.file.assertions.text = builtins.toJSON
|
||||
(map (a: a.message) (filter (a: !a.assertion) config.assertions));
|
||||
|
||||
nmt.script = ''
|
||||
assertFileExists home-files/.ssh/config
|
||||
assertFileContent \
|
||||
home-files/.ssh/config \
|
||||
${./match-blocks-match-and-hosts-expected.conf}
|
||||
assertFileContent home-files/assertions ${./no-assertions.json}
|
||||
'';
|
||||
};
|
||||
}
|
Loading…
Reference in a new issue