From e1b0869fde7c084961fb11c80afc8e6fbe7c7afa Mon Sep 17 00:00:00 2001 From: Gregor Kleen Date: Fri, 6 Apr 2018 13:14:59 +0200 Subject: Overhaul uucp --- custom/uucp-mediaserver.nix | 2 +- custom/uucp.nix | 114 +++++++++++++++++++++++++++++++++----------- hel.nix | 29 +++++------ odin.nix | 24 ++++------ 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 { environment.systemPackages = [ scripts ]; services.uucp.commandPath = [ "${scripts}/bin" ]; - services.uucp.commands = genAttrs cfg.remoteNodes (name: ["mediaspace.${name}"] ); + services.uucp.remoteNodes = genAttrs cfg.remoteNodes (name: { commands = ["mediaspace.${name}"]; } ); }; } 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 @@ with lib; let - portSpec = name: '' - port ${name} + portSpec = name: node: concatStringsSep "\n" (mapAttrsToList (portName: port: '' + port ${name}.${portName} type pipe - protocol ${if builtins.hasAttr name cfg.protocols then cfg.protocols."${name}" else cfg.defaultProtocol} + protocol ${node.protocols} reliable true - command ${pkgs.openssh}/bin/ssh -x -o batchmode=yes ${name} - ''; + command ${pkgs.openssh}/bin/ssh -x -o batchmode=yes ${name}.${portName} + '') node.hostnames); sysSpec = name: '' system ${name} time Any - port ${name} chat "" - protocol ${if builtins.hasAttr name cfg.protocols then cfg.protocols."${name}" else cfg.defaultProtocol} command-path ${concatStringsSep " " cfg.commandPath} - commands ${concatStringsSep " " (if builtins.hasAttr name cfg.commands then unique (cfg.defaultCommands ++ cfg.commands."${name}") else cfg.defaultCommands)} + commands ${concatStringsSep " " node.commands} + ${concatStringsSep "\nalternate\n" (mapAttrsToList (portName: port: '' + port ${name}.${portName} + '') node.hostnames)} + ''; + sshConfig = name: node: concatStringsSep "\n" (mapAttrsToList (portName: port: '' + Host ${name}.${portName} + Hostname ${port} + IdentitiesOnly Yes + IdentityFile ${cfg.sshKeyDir}/${name}.pub + '') node.hostnames); + sshKeyGen = name: node: '' + if [[ ! -e ${cfg.sshKeyDir}/${name} ]]; then + ssh-keygen ${escapeShellArgs node.generateKey} -f ${cfg.sshKeyDir}/${name} + fi + ''; + restrictKey = key: '' + restrict,command="${config.security.wrapperDir}/uucico" ${key} ''; + nodeCfg = { + options = { + commands = mkOption { + type = types.listOf types.string; + default = cfg.defaultCommands; + description = "Commands to allow for this remote"; + }; + + protocols = mkOption { + type = types.string; + default = cfg.defaultProtocols; + description = "UUCP protocols to use for this remote"; + }; + + publicKeys = mkOption { + type = types.listOf types.string; + default = []; + description = "SSH public keys for this node"; + }; + + generateKey = mkOption { + type = types.listOf types.string; + default = [ "-t ed25519" ]; + description = "Arguments to pass to `ssh-keygen` to generate a keypair for communication with this host"; + }; + + hostnames = mkOption { + type = types.attrsOf types.string; + default = {}; + description = ""; + }; + }; + }; + cfg = config.services.uucp; in { options = { @@ -44,14 +93,14 @@ in { description = "Overrides for the local uucp linux-user"; }; - sshConfig = mkOption { + extraSSHConfig = mkOption { type = types.str; default = ""; - description = "~uucp/.ssh/config"; + description = "Extra SSH config"; }; remoteNodes = mkOption { - type = types.listOf types.str; + type = types.attrsOf (types.submodule nodeCfg); default = {}; description = '' Ports to set up @@ -73,22 +122,22 @@ in { description = "Commands allowed for remotes without explicit override"; }; - commands = mkOption { - type = types.attrsOf (types.listOf types.string); - default = {}; - description = "Override commands for specific remotes"; - }; - - defaultProtocol = mkOption { + defaultProtocols = mkOption { type = types.string; default = "e"; description = "UUCP protocol to use within ssh unless overriden"; }; - protocols = mkOption { - type = types.attrsOf types.string; - default = {}; - description = "UUCP protocols to use for specific remotes"; + homeDir = mkOption { + type = types.path; + default = "/var/uucp"; + description = "Home of the uucp user"; + }; + + sshKeyDir = mkOption { + type = types.path; + default = "${cfg.homeDir}/.ssh/"; + description = "Directory to store ssh keypairs"; }; spoolDir = mkOption { @@ -184,16 +233,27 @@ in { isSystemUser = true; isNormalUser = false; createHome = true; - home = cfg.spoolDir; + home = cfg.homeDir; description = "User for uucp over ssh"; useDefaultShell = true; + openssh.authorizedKeys.keys = map restrictKey (concat (mapAttrsToList (name: node: node.publicKeys) cfg.remoteNodes)); } // cfg.sshUser; system.activationScripts."uucp-sshconfig" = '' mkdir -p ${config.users.users."uucp".home}/.ssh chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${config.users.users."uucp".home}/.ssh chmod 700 ${config.users.users."uucp".home}/.ssh - ln -fs ${builtins.toFile "ssh-config" cfg.sshConfig} ${config.users.users."uucp".home}/.ssh/config + ln -fs ${builtins.toFile "ssh-config" '' + ${concatStringsSpec "\n" (mapAttrsToList sshConfig cfg.remoteNodes)} + + ${cfg.extraSSHConfig} + ''} ${config.users.users."uucp".home}/.ssh/config + + mkdir -p ${cfg.sshKeyDir} + chown ${config.users.users."uucp".name}:${config.users.users."uucp".group} ${cfg.sshKeyDir} + chmod 700 ${config.sshKeyDir} + + ${concatStringsSep "\n" (mapAttrsToList sshKeyGen cfg.remoteNodes)} ''; system.activationScripts."uucp-logs" = '' @@ -213,10 +273,10 @@ in { port ssh type stdin protocol e - '' + concatStringsSep "\n" (map portSpec cfg.remoteNodes); + '' + concatStringsSep "\n" (mapAttrsToList portSpec cfg.remoteNodes); }; environment.etc."uucp/sys" = { - text = cfg.extraSys + "\n" + concatStringsSep "\n" (map sysSpec cfg.remoteNodes); + text = cfg.extraSys + "\n" + concatStringsSep "\n" (mapAttrsToList sysSpec cfg.remoteNodes); }; security.wrappers = let @@ -301,7 +361,7 @@ in { case "''${2}" in (?(vpn-)up) - ${concatMapStringsSep "\n " (name: "${pkgs.systemd}/bin/systemctl start uucico@${name}.service") cfg.remoteNodes} + ${concatStringsSep "\n " (mapAttrsToList (name: node: "${pkgs.systemd}/bin/systemctl start uucico@${name}.service") cfg.remoteNodes)} ;; esac ''; diff --git a/hel.nix b/hel.nix index 0c1ae69a..c6f02471 100644 --- a/hel.nix +++ b/hel.nix @@ -202,25 +202,20 @@ uucp = { enable = true; nodeName = "hel"; - remoteNodes = ["odin" "ymir"]; - sshUser = { - openssh.authorizedKeys.keys = [ ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFH1QWdgoC03nzW5GBuCl2pqASHeIXIYtE9IInHdaKcO uucp@ymir'' - ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKcDj49TqmflGTmtGBqDawxmCBWW1txj61CZ7KT0hTHK uucp@odin'' - ]; + remoteNodes = { + "odin" = { + publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKcDj49TqmflGTmtGBqDawxmCBWW1txj61CZ7KT0hTHK uucp@odin"]; + hostnames = ["odin.asgard.yggdrasil"]; + commands = lib.mkForce ["recv-media" "notify-gkleen"]; + }; + "ymir" = { + publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFH1QWdgoC03nzW5GBuCl2pqASHeIXIYtE9IInHdaKcO uucp@ymir"]; + hostnames = ["ymir.yggdrasil.li" "ymir.niflheim.yggdrasil"]; + }; }; - sshConfig = '' - Host odin - Hostname odin.asgard.yggdrasil - IdentityFile ~/.ssh/odin - Host ymir - Hostname ymir.niflheim.yggdrasil - IdentityFile ~/.ssh/ymir - ''; + commandPath = [ "${pkgs.callPackage ./hel/recv-media.nix {}}/bin" config.security.wrapperDir ]; - defaultCommands = []; - commands = { - "odin" = ["recv-media" "notify-gkleen"]; - }; + defaultCommands = lib.mkForce []; }; postfix = { diff --git a/odin.nix b/odin.nix index 11a3c934..f92556de 100644 --- a/odin.nix +++ b/odin.nix @@ -78,22 +78,16 @@ services.uucp = { enable = true; nodeName = "odin"; - remoteNodes = [ "ymir" "hel" ]; - sshUser = { - openssh.authorizedKeys.keys = [ ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKD8ycFGfVkBL9wjA5Kc33cl6Qt5K2505G/38oH8Cy/e uucp@hel'' - ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGANj+LJ4CI6VrAgBRocKCGq74kZnwD1PdKr/gdlfVr1 uucp@ymir'' - ]; + remoteNodes = { + "ymir" = { + publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGANj+LJ4CI6VrAgBRocKCGq74kZnwD1PdKr/gdlfVr1 uucp@ymir"]; + hostnames = ["ymir.yggdrasil.li" "ymir.niflheim.yggdrasil"]; + }; + "hel" = { + publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKD8ycFGfVkBL9wjA5Kc33cl6Qt5K2505G/38oH8Cy/e uucp@hel"]; + hostnames = ["hel.asgard.yggdrasil" "hel.midgard.yggdrasil"]; + }; }; - sshConfig = '' - Host ymir - Hostname ymir.niflheim.yggdrasil - IdentityFile ~/.ssh/ymir - Host hel - Hostname hel.midgard.yggdrasil - IdentityFile ~/.ssh/hel - ''; - commandPath = ["${pkgs.rmail}/bin"]; - defaultCommands = ["rmail"]; media-server = { enable = true; diff --git a/ymir.nix b/ymir.nix index c0faba6b..192bc27b 100644 --- a/ymir.nix +++ b/ymir.nix @@ -852,20 +852,17 @@ in rec { services.uucp = { enable = true; nodeName = "ymir"; - remoteNodes = [ "odin" "hel" ]; - sshUser = { - openssh.authorizedKeys.keys = [ ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKT/BsAMLJs9NYhKIso4J3EF+VzRBm3c+qCQ5ONKc/1s uucp@odin'' - ''restrict,command="${config.security.wrapperDir}/uucico" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOWBybBQKbPucqBgULQ1phv7IKFWl1Xc4drkCx3D5mIz uucp@hel'' - ]; + remoteNodes = { + "odin" = { + publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKT/BsAMLJs9NYhKIso4J3EF+VzRBm3c+qCQ5ONKc/1s uucp@odin"]; + hostnames = ["odin.asgard.yggdrasil"]; + }; + "hel" = { + publicKeys = ["ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOWBybBQKbPucqBgULQ1phv7IKFWl1Xc4drkCx3D5mIz uucp@hel"]; + hostnames = ["hel.midgard.yggdrasil"]; + }; }; - sshConfig = '' - Host odin - Hostname odin.asgard.yggdrasil - IdentityFile ~/.ssh/odin - Host hel - Hostname hel.midgard.yggdrasil - IdentityFile ~/.ssh/hel - ''; + commandPath = ["${pkgs.rmail}/bin" "${pkgs.push2bin}/bin"]; defaultCommands = ["rmail" "push2bin"]; }; -- cgit v1.2.3