From 060517bfa0ebc0e48627191c1a9b53c7cc13d1c8 Mon Sep 17 00:00:00 2001 From: arcnmx Date: Wed, 21 Feb 2024 03:15:00 -0800 Subject: [PATCH] feat(nixos): ssh Match User blocks --- modules/nixos/users.nix | 67 ++++++++++++++++++++++++++++++++++ systems/hakurei/reisen-ssh.nix | 10 ++--- 2 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 modules/nixos/users.nix diff --git a/modules/nixos/users.nix b/modules/nixos/users.nix new file mode 100644 index 00000000..17385b39 --- /dev/null +++ b/modules/nixos/users.nix @@ -0,0 +1,67 @@ +{ + config, + lib, + ... +}: let + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.modules) mkMerge mkAfter mkOptionDefault; + inherit (lib.attrsets) mapAttrsToList attrValues; + inherit (lib.lists) filter; + inherit (lib.strings) concatStringsSep; + opensshMatchUsers = filter (user: user.openssh.matchBlock.enable) (attrValues config.users.users); + toSshdCriteria = key: value: "${key} ${value}"; + userMatchBlock = user: let + inherit (user.openssh) matchBlock; + criteria = mapAttrsToList toSshdCriteria matchBlock.criteria; + in mkAfter '' + Match ${concatStringsSep " " criteria} + ${matchBlock.settingsConfig} + ''; + userModule = { config, ... }: let + toSshdValue = value: + if value == true then "yes" + else if value == false then "no" + else toString value; + toSshdConf = key: value: "${key} ${toSshdValue value}"; + in { + options = with lib.types; { + openssh.matchBlock = { + enable = mkEnableOption "match block" // { + default = config.openssh.matchBlock.settings != { }; + }; + criteria = mkOption { + type = attrsOf str; + }; + settings = mkOption { + type = attrsOf (oneOf [ str path bool int ]); + default = { }; + }; + settingsConfig = mkOption { + type = lines; + default = ""; + }; + }; + }; + config = { + openssh.matchBlock = { + criteria = { + User = mkOptionDefault config.name; + }; + settingsConfig = mkMerge ( + mapAttrsToList toSshdConf config.openssh.matchBlock.settings + ); + }; + }; + }; +in { + options = with lib.types; { + users.users = mkOption { + type = attrsOf (submodule userModule); + }; + }; + config = { + services.openssh.extraConfig = mkMerge ( + map userMatchBlock opensshMatchUsers + ); + }; +} diff --git a/systems/hakurei/reisen-ssh.nix b/systems/hakurei/reisen-ssh.nix index 73fbb0e2..8667f830 100644 --- a/systems/hakurei/reisen-ssh.nix +++ b/systems/hakurei/reisen-ssh.nix @@ -21,6 +21,11 @@ in { isNormalUser = true; autoSubUidGidRange = false; group = username; + openssh.matchBlock.settings = { + # PasswordAuthentication works too + KbdInteractiveAuthentication = true; + ForceCommand = sshJump; + }; }; users.groups.${username} = { gid = config.users.users.${username}.uid; @@ -28,11 +33,6 @@ in { services.openssh = { ports = mkAfter [ sshPort ]; - extraConfig = mkAfter '' - Match User ${username} - KbdInteractiveAuthentication yes - ForceCommand ${sshJump} - ''; }; # required for kbd or password authentication security.pam.services.sshd.unixAuth = mkForce true;