diff options
author | Gregor Kleen <gkleen@yggdrasil.li> | 2018-04-06 13:14:59 +0200 |
---|---|---|
committer | Gregor Kleen <gkleen@yggdrasil.li> | 2018-04-06 13:14:59 +0200 |
commit | e1b0869fde7c084961fb11c80afc8e6fbe7c7afa (patch) | |
tree | 2d7f5ac4f6af66312ff5ee10b926eb59b318656b | |
parent | 3c0f7675064548b9f1c95f1034cb31d517f5dc9c (diff) | |
download | nixos-e1b0869fde7c084961fb11c80afc8e6fbe7c7afa.tar nixos-e1b0869fde7c084961fb11c80afc8e6fbe7c7afa.tar.gz nixos-e1b0869fde7c084961fb11c80afc8e6fbe7c7afa.tar.bz2 nixos-e1b0869fde7c084961fb11c80afc8e6fbe7c7afa.tar.xz nixos-e1b0869fde7c084961fb11c80afc8e6fbe7c7afa.zip |
Overhaul uucp
-rw-r--r-- | custom/uucp-mediaserver.nix | 2 | ||||
-rw-r--r-- | custom/uucp.nix | 114 | ||||
-rw-r--r-- | hel.nix | 29 | ||||
-rw-r--r-- | odin.nix | 24 | ||||
-rw-r--r-- | ymir.nix | 23 |
5 files changed, 119 insertions, 73 deletions
diff --git a/custom/uucp-mediaserver.nix b/custom/uucp-mediaserver.nix index 23b43118..5ed3b5ed 100644 --- a/custom/uucp-mediaserver.nix +++ b/custom/uucp-mediaserver.nix | |||
@@ -61,6 +61,6 @@ in { | |||
61 | environment.systemPackages = [ scripts ]; | 61 | environment.systemPackages = [ scripts ]; |
62 | 62 | ||
63 | services.uucp.commandPath = [ "${scripts}/bin" ]; | 63 | services.uucp.commandPath = [ "${scripts}/bin" ]; |
64 | services.uucp.commands = genAttrs cfg.remoteNodes (name: ["mediaspace.${name}"] ); | 64 | services.uucp.remoteNodes = genAttrs cfg.remoteNodes (name: { commands = ["mediaspace.${name}"]; } ); |
65 | }; | 65 | }; |
66 | } | 66 | } |
diff --git a/custom/uucp.nix b/custom/uucp.nix index f5b89bfe..61e42119 100644 --- a/custom/uucp.nix +++ b/custom/uucp.nix | |||
@@ -3,23 +3,72 @@ | |||
3 | with lib; | 3 | with lib; |
4 | 4 | ||
5 | let | 5 | let |
6 | portSpec = name: '' | 6 | portSpec = name: node: concatStringsSep "\n" (mapAttrsToList (portName: port: '' |
7 | port ${name} | 7 | port ${name}.${portName} |
8 | type pipe | 8 | type pipe |
9 | protocol ${if builtins.hasAttr name cfg.protocols then cfg.protocols."${name}" else cfg.defaultProtocol} | 9 | protocol ${node.protocols} |
10 | reliable true | 10 | reliable true |
11 | command ${pkgs.openssh}/bin/ssh -x -o batchmode=yes ${name} | 11 | command ${pkgs.openssh}/bin/ssh -x -o batchmode=yes ${name}.${portName} |
12 | ''; | 12 | '') node.hostnames); |
13 | sysSpec = name: '' | 13 | sysSpec = name: '' |
14 | system ${name} | 14 | system ${name} |
15 | time Any | 15 | time Any |
16 | port ${name} | ||
17 | chat "" | 16 | chat "" |
18 | protocol ${if builtins.hasAttr name cfg.protocols then cfg.protocols."${name}" else cfg.defaultProtocol} | ||
19 | command-path ${concatStringsSep " " cfg.commandPath} | 17 | command-path ${concatStringsSep " " cfg.commandPath} |
20 | commands ${concatStringsSep " " (if builtins.hasAttr name cfg.commands then unique (cfg.defaultCommands ++ cfg.commands."${name}") else cfg.defaultCommands)} | 18 | commands ${concatStringsSep " " node.commands} |
19 | ${concatStringsSep "\nalternate\n" (mapAttrsToList (portName: port: '' | ||
20 | port ${name}.${portName} | ||
21 | '') node.hostnames)} | ||
22 | ''; | ||
23 | sshConfig = name: node: concatStringsSep "\n" (mapAttrsToList (portName: port: '' | ||
24 | Host ${name}.${portName} | ||
25 | Hostname ${port} | ||
26 | IdentitiesOnly Yes | ||
27 | IdentityFile ${cfg.sshKeyDir}/${name}.pub | ||
28 | '') node.hostnames); | ||
29 | sshKeyGen = name: node: '' | ||
30 | if [[ ! -e ${cfg.sshKeyDir}/${name} ]]; then | ||
31 | ssh-keygen ${escapeShellArgs node.generateKey} -f ${cfg.sshKeyDir}/${name} | ||
32 | fi | ||
33 | ''; | ||
34 | restrictKey = key: '' | ||
35 | restrict,command="${config.security.wrapperDir}/uucico" ${key} | ||
21 | ''; | 36 | ''; |
22 | 37 | ||
38 | nodeCfg = { | ||
39 | options = { | ||
40 | commands = mkOption { | ||
41 | type = types.listOf types.string; | ||
42 | default = cfg.defaultCommands; | ||
43 | description = "Commands to allow for this remote"; | ||
44 | }; | ||
45 | |||
46 | protocols = mkOption { | ||
47 | type = types.string; | ||
48 | default = cfg.defaultProtocols; | ||
49 | description = "UUCP protocols to use for this remote"; | ||
50 | }; | ||
51 | |||
52 | publicKeys = mkOption { | ||
53 | type = types.listOf types.string; | ||
54 | default = []; | ||
55 | description = "SSH public keys for this node"; | ||
56 | }; | ||
57 | |||
58 | generateKey = mkOption { | ||
59 | type = types.listOf types.string; | ||
60 | default = [ "-t ed25519" ]; | ||
61 | description = "Arguments to pass to `ssh-keygen` to generate a keypair for communication with this host"; | ||
62 | }; | ||
63 | |||
64 | hostnames = mkOption { | ||
65 | type = types.attrsOf types.string; | ||
66 | default = {}; | ||
67 | description = ""; | ||
68 | }; | ||
69 | }; | ||
70 | }; | ||
71 | |||
23 | cfg = config.services.uucp; | 72 | cfg = config.services.uucp; |
24 | in { | 73 | in { |
25 | options = { | 74 | options = { |
@@ -44,14 +93,14 @@ in { | |||
44 | description = "Overrides for the local uucp linux-user"; | 93 | description = "Overrides for the local uucp linux-user"; |
45 | }; | 94 | }; |
46 | 95 | ||
47 | sshConfig = mkOption { | 96 | extraSSHConfig = mkOption { |
48 | type = types.str; | 97 | type = types.str; |
49 | default = ""; | 98 | default = ""; |
50 | description = "~uucp/.ssh/config"; | 99 | description = "Extra SSH config"; |
51 | }; | 100 | }; |
52 | 101 | ||
53 | remoteNodes = mkOption { | 102 | remoteNodes = mkOption { |
54 | type = types.listOf types.str; | 103 | type = types.attrsOf (types.submodule nodeCfg); |
55 | default = {}; | 104 | default = {}; |
56 | description = '' | 105 | description = '' |
57 | Ports to set up | 106 | Ports to set up |
@@ -73,22 +122,22 @@ in { | |||
73 | description = "Commands allowed for remotes without explicit override"; | 122 | description = "Commands allowed for remotes without explicit override"; |
74 | }; | 123 | }; |
75 | 124 | ||
76 | commands = mkOption { | 125 | defaultProtocols = mkOption { |
77 | type = types.attrsOf (types.listOf types.string); | ||
78 | default = {}; | ||
79 | description = "Override commands for specific remotes"; | ||
80 | }; | ||
81 | |||
82 | defaultProtocol = mkOption { | ||
83 | type = types.string; | 126 | type = types.string; |
84 | default = "e"; | 127 | default = "e"; |
85 | description = "UUCP protocol to use within ssh unless overriden"; | 128 | description = "UUCP protocol to use within ssh unless overriden"; |
86 | }; | 129 | }; |
87 | 130 | ||
88 | protocols = mkOption { | 131 | homeDir = mkOption { |
89 | type = types.attrsOf types.string; | 132 | type = types.path; |
90 | default = {}; | 133 | default = "/var/uucp"; |
91 | description = "UUCP protocols to use for specific remotes"; | 134 | description = "Home of the uucp user"; |
135 | }; | ||
136 | |||
137 | sshKeyDir = mkOption { | ||
138 | type = types.path; | ||
139 | default = "${cfg.homeDir}/.ssh/"; | ||
140 | description = "Directory to store ssh keypairs"; | ||
92 | }; | 141 | }; |
93 | 142 | ||
94 | spoolDir = mkOption { | 143 | spoolDir = mkOption { |
@@ -184,16 +233,27 @@ in { | |||
184 | isSystemUser = true; | 233 | isSystemUser = true; |
185 | isNormalUser = false; | 234 | isNormalUser = false; |
186 | createHome = true; | 235 | createHome = true; |
187 | home = cfg.spoolDir; | 236 | home = cfg.homeDir; |
188 | description = "User for uucp over ssh"; | 237 | description = "User for uucp over ssh"; |
189 | useDefaultShell = true; | 238 | useDefaultShell = true; |
239 | openssh.authorizedKeys.keys = map restrictKey (concat (mapAttrsToList (name: node: node.publicKeys) cfg.remoteNodes)); | ||
190 | } // cfg.sshUser; | 240 | } // cfg.sshUser; |
191 | 241 | ||
192 | system.activationScripts."uucp-sshconfig" = '' | 242 | system.activationScripts."uucp-sshconfig" = '' |
193 | mkdir -p ${config.users.users."uucp".home}/.ssh | 243 | mkdir -p ${config.users.users."uucp".home}/.ssh |
194 | chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${config.users.users."uucp".home}/.ssh | 244 | chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${config.users.users."uucp".home}/.ssh |
195 | chmod 700 ${config.users.users."uucp".home}/.ssh | 245 | chmod 700 ${config.users.users."uucp".home}/.ssh |
196 | ln -fs ${builtins.toFile "ssh-config" cfg.sshConfig} ${config.users.users."uucp".home}/.ssh/config | 246 | ln -fs ${builtins.toFile "ssh-config" '' |
247 | ${concatStringsSpec "\n" (mapAttrsToList sshConfig cfg.remoteNodes)} | ||
248 | |||
249 | ${cfg.extraSSHConfig} | ||
250 | ''} ${config.users.users."uucp".home}/.ssh/config | ||
251 | |||
252 | mkdir -p ${cfg.sshKeyDir} | ||
253 | chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${cfg.sshKeyDir} | ||
254 | chmod 700 ${config.sshKeyDir} | ||
255 | |||
256 | ${concatStringsSep "\n" (mapAttrsToList sshKeyGen cfg.remoteNodes)} | ||
197 | ''; | 257 | ''; |
198 | 258 | ||
199 | system.activationScripts."uucp-logs" = '' | 259 | system.activationScripts."uucp-logs" = '' |
@@ -213,10 +273,10 @@ in { | |||
213 | port ssh | 273 | port ssh |
214 | type stdin | 274 | type stdin |
215 | protocol e | 275 | protocol e |
216 | '' + concatStringsSep "\n" (map portSpec cfg.remoteNodes); | 276 | '' + concatStringsSep "\n" (mapAttrsToList portSpec cfg.remoteNodes); |
217 | }; | 277 | }; |
218 | environment.etc."uucp/sys" = { | 278 | environment.etc."uucp/sys" = { |
219 | text = cfg.extraSys + "\n" + concatStringsSep "\n" (map sysSpec cfg.remoteNodes); | 279 | text = cfg.extraSys + "\n" + concatStringsSep "\n" (mapAttrsToList sysSpec cfg.remoteNodes); |
220 | }; | 280 | }; |
221 | 281 | ||
222 | security.wrappers = let | 282 | security.wrappers = let |
@@ -301,7 +361,7 @@ in { | |||
301 | 361 | ||
302 | case "''${2}" in | 362 | case "''${2}" in |
303 | (?(vpn-)up) | 363 | (?(vpn-)up) |
304 | ${concatMapStringsSep "\n " (name: "${pkgs.systemd}/bin/systemctl start uucico@${name}.service") cfg.remoteNodes} | 364 | ${concatStringsSep "\n " (mapAttrsToList (name: node: "${pkgs.systemd}/bin/systemctl start uucico@${name}.service") cfg.remoteNodes)} |
305 | ;; | 365 | ;; |
306 | esac | 366 | esac |
307 | ''; | 367 | ''; |
@@ -202,25 +202,20 @@ | |||
202 | uucp = { | 202 | uucp = { |
203 | enable = true; | 203 | enable = true; |
204 | nodeName = "hel"; | 204 | nodeName = "hel"; |
205 | remoteNodes = ["odin" "ymir"]; | 205 | remoteNodes = { |
206 | sshUser = { | 206 | "odin" = { |
207 | openssh.authorizedKeys.keys = [ ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFH1QWdgoC03nzW5GBuCl2pqASHeIXIYtE9IInHdaKcO uucp@ymir'' | 207 | publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKcDj49TqmflGTmtGBqDawxmCBWW1txj61CZ7KT0hTHK uucp@odin"]; |
208 | ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKcDj49TqmflGTmtGBqDawxmCBWW1txj61CZ7KT0hTHK uucp@odin'' | 208 | hostnames = ["odin.asgard.yggdrasil"]; |
209 | ]; | 209 | commands = lib.mkForce ["recv-media" "notify-gkleen"]; |
210 | }; | ||
211 | "ymir" = { | ||
212 | publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFH1QWdgoC03nzW5GBuCl2pqASHeIXIYtE9IInHdaKcO uucp@ymir"]; | ||
213 | hostnames = ["ymir.yggdrasil.li" "ymir.niflheim.yggdrasil"]; | ||
214 | }; | ||
210 | }; | 215 | }; |
211 | sshConfig = '' | 216 | |
212 | Host odin | ||
213 | Hostname odin.asgard.yggdrasil | ||
214 | IdentityFile ~/.ssh/odin | ||
215 | Host ymir | ||
216 | Hostname ymir.niflheim.yggdrasil | ||
217 | IdentityFile ~/.ssh/ymir | ||
218 | ''; | ||
219 | commandPath = [ "${pkgs.callPackage ./hel/recv-media.nix {}}/bin" config.security.wrapperDir ]; | 217 | commandPath = [ "${pkgs.callPackage ./hel/recv-media.nix {}}/bin" config.security.wrapperDir ]; |
220 | defaultCommands = []; | 218 | defaultCommands = lib.mkForce []; |
221 | commands = { | ||
222 | "odin" = ["recv-media" "notify-gkleen"]; | ||
223 | }; | ||
224 | }; | 219 | }; |
225 | 220 | ||
226 | postfix = { | 221 | postfix = { |
@@ -78,22 +78,16 @@ | |||
78 | services.uucp = { | 78 | services.uucp = { |
79 | enable = true; | 79 | enable = true; |
80 | nodeName = "odin"; | 80 | nodeName = "odin"; |
81 | remoteNodes = [ "ymir" "hel" ]; | 81 | remoteNodes = { |
82 | sshUser = { | 82 | "ymir" = { |
83 | openssh.authorizedKeys.keys = [ ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKD8ycFGfVkBL9wjA5Kc33cl6Qt5K2505G/38oH8Cy/e uucp@hel'' | 83 | publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGANj+LJ4CI6VrAgBRocKCGq74kZnwD1PdKr/gdlfVr1 uucp@ymir"]; |
84 | ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGANj+LJ4CI6VrAgBRocKCGq74kZnwD1PdKr/gdlfVr1 uucp@ymir'' | 84 | hostnames = ["ymir.yggdrasil.li" "ymir.niflheim.yggdrasil"]; |
85 | ]; | 85 | }; |
86 | "hel" = { | ||
87 | publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKD8ycFGfVkBL9wjA5Kc33cl6Qt5K2505G/38oH8Cy/e uucp@hel"]; | ||
88 | hostnames = ["hel.asgard.yggdrasil" "hel.midgard.yggdrasil"]; | ||
89 | }; | ||
86 | }; | 90 | }; |
87 | sshConfig = '' | ||
88 | Host ymir | ||
89 | Hostname ymir.niflheim.yggdrasil | ||
90 | IdentityFile ~/.ssh/ymir | ||
91 | Host hel | ||
92 | Hostname hel.midgard.yggdrasil | ||
93 | IdentityFile ~/.ssh/hel | ||
94 | ''; | ||
95 | commandPath = ["${pkgs.rmail}/bin"]; | ||
96 | defaultCommands = ["rmail"]; | ||
97 | 91 | ||
98 | media-server = { | 92 | media-server = { |
99 | enable = true; | 93 | enable = true; |
@@ -852,20 +852,17 @@ in rec { | |||
852 | services.uucp = { | 852 | services.uucp = { |
853 | enable = true; | 853 | enable = true; |
854 | nodeName = "ymir"; | 854 | nodeName = "ymir"; |
855 | remoteNodes = [ "odin" "hel" ]; | 855 | remoteNodes = { |
856 | sshUser = { | 856 | "odin" = { |
857 | openssh.authorizedKeys.keys = [ ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKT/BsAMLJs9NYhKIso4J3EF+VzRBm3c+qCQ5ONKc/1s uucp@odin'' | 857 | publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKT/BsAMLJs9NYhKIso4J3EF+VzRBm3c+qCQ5ONKc/1s uucp@odin"]; |
858 | ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOWBybBQKbPucqBgULQ1phv7IKFWl1Xc4drkCx3D5mIz uucp@hel'' | 858 | hostnames = ["odin.asgard.yggdrasil"]; |
859 | ]; | 859 | }; |
860 | "hel" = { | ||
861 | publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOWBybBQKbPucqBgULQ1phv7IKFWl1Xc4drkCx3D5mIz uucp@hel"]; | ||
862 | hostnames = ["hel.midgard.yggdrasil"]; | ||
863 | }; | ||
860 | }; | 864 | }; |
861 | sshConfig = '' | 865 | |
862 | Host odin | ||
863 | Hostname odin.asgard.yggdrasil | ||
864 | IdentityFile ~/.ssh/odin | ||
865 | Host hel | ||
866 | Hostname hel.midgard.yggdrasil | ||
867 | IdentityFile ~/.ssh/hel | ||
868 | ''; | ||
869 | commandPath = ["${pkgs.rmail}/bin" "${pkgs.push2bin}/bin"]; | 866 | commandPath = ["${pkgs.rmail}/bin" "${pkgs.push2bin}/bin"]; |
870 | defaultCommands = ["rmail" "push2bin"]; | 867 | defaultCommands = ["rmail" "push2bin"]; |
871 | }; | 868 | }; |