From ad9295157901e218f9e27b0cb14a9cb791d139d4 Mon Sep 17 00:00:00 2001 From: nicoo Date: Mon, 4 Sep 2023 21:01:09 +0000 Subject: [PATCH 1/7] nixos/sudo: Don't include empty sections This makes the generated sudoers a touch easier to read. --- nixos/modules/security/sudo.nix | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/nixos/modules/security/sudo.nix b/nixos/modules/security/sudo.nix index c665c15242a5..4728a697de86 100644 --- a/nixos/modules/security/sudo.nix +++ b/nixos/modules/security/sudo.nix @@ -203,7 +203,7 @@ in } ]; - security.sudo.configFile = + security.sudo.configFile = concatStringsSep "\n" (filter (s: s != "") [ '' # Don't edit this file. Set the NixOS options ‘security.sudo.configFile’ # or ‘security.sudo.extraRules’ instead. @@ -213,7 +213,8 @@ in # "root" is allowed to do anything. root ALL=(ALL:ALL) SETENV: ALL - + '' + (optionalString (cfg.extraRules != []) '' # extraRules ${concatStringsSep "\n" ( lists.flatten ( @@ -225,9 +226,12 @@ in ) cfg.extraRules ) )} - + '') + (optionalString (cfg.extraConfig != "") '' + # extraConfig ${cfg.extraConfig} - ''; + '') + ]); security.wrappers = let owner = "root"; From 19e1420e138b5a89f00eb3d7adbdf99f97ad4d57 Mon Sep 17 00:00:00 2001 From: nicoo Date: Mon, 4 Sep 2023 21:06:12 +0000 Subject: [PATCH 2/7] nixos/sudo: Move support for `pam_ssh_agent_auth(8)` to PAM's NixOS module --- nixos/modules/security/pam.nix | 6 +++++- nixos/modules/security/sudo.nix | 8 ++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/nixos/modules/security/pam.nix b/nixos/modules/security/pam.nix index 709bb8b94a65..b7e1ea526535 100644 --- a/nixos/modules/security/pam.nix +++ b/nixos/modules/security/pam.nix @@ -1531,6 +1531,10 @@ in (map (module: "mr ${module},")) concatLines ]); - }; + security.sudo.extraConfig = optionalString config.security.pam.enableSSHAgentAuth '' + # Keep SSH_AUTH_SOCK so that pam_ssh_agent_auth.so can do its magic. + Defaults env_keep+=SSH_AUTH_SOCK + ''; + }; } diff --git a/nixos/modules/security/sudo.nix b/nixos/modules/security/sudo.nix index 4728a697de86..75dc2b52a52c 100644 --- a/nixos/modules/security/sudo.nix +++ b/nixos/modules/security/sudo.nix @@ -6,6 +6,8 @@ let cfg = config.security.sudo; + inherit (config.security.pam) enableSSHAgentAuth; + toUserString = user: if (isInt user) then "#${toString user}" else "${user}"; toGroupString = group: if (isInt group) then "%#${toString group}" else "%${group}"; @@ -207,10 +209,8 @@ in '' # Don't edit this file. Set the NixOS options ‘security.sudo.configFile’ # or ‘security.sudo.extraRules’ instead. - - # Keep SSH_AUTH_SOCK so that pam_ssh_agent_auth.so can do its magic. - Defaults env_keep+=SSH_AUTH_SOCK - + '' + '' # "root" is allowed to do anything. root ALL=(ALL:ALL) SETENV: ALL '' From 77ed368b2088833540c6317aa267ee8e75363d21 Mon Sep 17 00:00:00 2001 From: nicoo Date: Thu, 7 Sep 2023 11:57:20 +0000 Subject: [PATCH 3/7] nixos/sudo: Refactor option definitions --- nixos/modules/security/sudo.nix | 73 +++++++++++++-------------------- 1 file changed, 29 insertions(+), 44 deletions(-) diff --git a/nixos/modules/security/sudo.nix b/nixos/modules/security/sudo.nix index 75dc2b52a52c..9ba0f2849707 100644 --- a/nixos/modules/security/sudo.nix +++ b/nixos/modules/security/sudo.nix @@ -30,41 +30,27 @@ in ###### interface - options = { + options.security.sudo = { - security.sudo.enable = mkOption { + enable = mkEnableOption (mdDoc '' + the {command}`sudo` command, which allows non-root users to execute commands as root. + ''); + + package = mkPackageOption pkgs "sudo" { }; + + wheelNeedsPassword = mkOption { type = types.bool; default = true; - description = - lib.mdDoc '' - Whether to enable the {command}`sudo` command, which - allows non-root users to execute commands as root. - ''; - }; - - security.sudo.package = mkOption { - type = types.package; - default = pkgs.sudo; - defaultText = literalExpression "pkgs.sudo"; - description = lib.mdDoc '' - Which package to use for `sudo`. + description = mdDoc '' + Whether users of the `wheel` group must + provide a password to run commands as super user via {command}`sudo`. ''; - }; - - security.sudo.wheelNeedsPassword = mkOption { - type = types.bool; - default = true; - description = - lib.mdDoc '' - Whether users of the `wheel` group must - provide a password to run commands as super user via {command}`sudo`. - ''; }; - security.sudo.execWheelOnly = mkOption { + execWheelOnly = mkOption { type = types.bool; default = false; - description = lib.mdDoc '' + description = mdDoc '' Only allow members of the `wheel` group to execute sudo by setting the executable's permissions accordingly. This prevents users that are not members of `wheel` from @@ -72,19 +58,18 @@ in ''; }; - security.sudo.configFile = mkOption { + configFile = mkOption { type = types.lines; # Note: if syntax errors are detected in this file, the NixOS # configuration will fail to build. - description = - lib.mdDoc '' - This string contains the contents of the - {file}`sudoers` file. - ''; + description = mdDoc '' + This string contains the contents of the + {file}`sudoers` file. + ''; }; - security.sudo.extraRules = mkOption { - description = lib.mdDoc '' + extraRules = mkOption { + description = mdDoc '' Define specific rules to be in the {file}`sudoers` file. More specific rules should come after more general ones in order to yield the expected behavior. You can use mkBefore/mkAfter to ensure @@ -114,7 +99,7 @@ in options = { users = mkOption { type = with types; listOf (either str int); - description = lib.mdDoc '' + description = mdDoc '' The usernames / UIDs this rule should apply for. ''; default = []; @@ -122,7 +107,7 @@ in groups = mkOption { type = with types; listOf (either str int); - description = lib.mdDoc '' + description = mdDoc '' The groups / GIDs this rule should apply for. ''; default = []; @@ -131,7 +116,7 @@ in host = mkOption { type = types.str; default = "ALL"; - description = lib.mdDoc '' + description = mdDoc '' For what host this rule should apply. ''; }; @@ -139,7 +124,7 @@ in runAs = mkOption { type = with types; str; default = "ALL:ALL"; - description = lib.mdDoc '' + description = mdDoc '' Under which user/group the specified command is allowed to run. A user can be specified using just the username: `"foo"`. @@ -149,7 +134,7 @@ in }; commands = mkOption { - description = lib.mdDoc '' + description = mdDoc '' The commands for which the rule should apply. ''; type = with types; listOf (either str (submodule { @@ -157,7 +142,7 @@ in options = { command = mkOption { type = with types; str; - description = lib.mdDoc '' + description = mdDoc '' A command being either just a path to a binary to allow any arguments, the full command with arguments pre-set or with `""` used as the argument, not allowing arguments to the command at all. @@ -166,7 +151,7 @@ in options = mkOption { type = with types; listOf (enum [ "NOPASSWD" "PASSWD" "NOEXEC" "EXEC" "SETENV" "NOSETENV" "LOG_INPUT" "NOLOG_INPUT" "LOG_OUTPUT" "NOLOG_OUTPUT" ]); - description = lib.mdDoc '' + description = mdDoc '' Options for running the command. Refer to the [sudo manual](https://www.sudo.ws/man/1.7.10/sudoers.man.html). ''; default = []; @@ -179,10 +164,10 @@ in }); }; - security.sudo.extraConfig = mkOption { + extraConfig = mkOption { type = types.lines; default = ""; - description = lib.mdDoc '' + description = mdDoc '' Extra configuration text appended to {file}`sudoers`. ''; }; From 097115485a06318e17d1298bd2c231e4fe0f267c Mon Sep 17 00:00:00 2001 From: nicoo Date: Sun, 22 Oct 2023 17:58:58 +0000 Subject: [PATCH 4/7] nixos/terminfo: Simplify sudo-related option --- nixos/modules/config/terminfo.nix | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/nixos/modules/config/terminfo.nix b/nixos/modules/config/terminfo.nix index d1dbc4e0d059..ebd1aaea8f04 100644 --- a/nixos/modules/config/terminfo.nix +++ b/nixos/modules/config/terminfo.nix @@ -16,10 +16,7 @@ with lib; }; security.sudo.keepTerminfo = mkOption { - default = config.security.sudo.package.pname != "sudo-rs"; - defaultText = literalMD '' - `true` unless using `sudo-rs` - ''; + default = true; type = types.bool; description = lib.mdDoc '' Whether to preserve the `TERMINFO` and `TERMINFO_DIRS` From 93011e31bddcd11765eff62defb796cc2d373acb Mon Sep 17 00:00:00 2001 From: nicoo Date: Thu, 7 Sep 2023 12:46:04 +0000 Subject: [PATCH 5/7] nixos/sudo: Handle `root`'s default rule through `extraRules` This makes things more uniform; moreover, users can now inject rules before this. --- nixos/modules/security/sudo.nix | 55 +++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 24 deletions(-) diff --git a/nixos/modules/security/sudo.nix b/nixos/modules/security/sudo.nix index 9ba0f2849707..aab5213d6dc5 100644 --- a/nixos/modules/security/sudo.nix +++ b/nixos/modules/security/sudo.nix @@ -182,36 +182,43 @@ in message = "The NixOS `sudo` module does not work with `sudo-rs` yet."; } ]; - # We `mkOrder 600` so that the default rule shows up first, but there is - # still enough room for a user to `mkBefore` it. - security.sudo.extraRules = mkOrder 600 [ - { groups = [ "wheel" ]; - commands = [ { command = "ALL"; options = (if cfg.wheelNeedsPassword then [ "SETENV" ] else [ "NOPASSWD" "SETENV" ]); } ]; - } - ]; + security.sudo.extraRules = + let + defaultRule = { users ? [], groups ? [], opts ? [] }: [ { + inherit users groups; + commands = [ { + command = "ALL"; + options = opts ++ [ "SETENV" ]; + } ]; + } ]; + in mkMerge [ + # This is ordered before users' `mkBefore` rules, + # so as not to introduce unexpected changes. + (mkOrder 400 (defaultRule { users = [ "root" ]; })) + + # This is ordered to show before (most) other rules, but + # late-enough for a user to `mkBefore` it. + (mkOrder 600 (defaultRule { + groups = [ "wheel" ]; + opts = (optional (!cfg.wheelNeedsPassword) "NOPASSWD"); + })) + ]; security.sudo.configFile = concatStringsSep "\n" (filter (s: s != "") [ '' # Don't edit this file. Set the NixOS options ‘security.sudo.configFile’ # or ‘security.sudo.extraRules’ instead. '' - '' - # "root" is allowed to do anything. - root ALL=(ALL:ALL) SETENV: ALL - '' - (optionalString (cfg.extraRules != []) '' - # extraRules - ${concatStringsSep "\n" ( - lists.flatten ( - map ( - rule: optionals (length rule.commands != 0) [ - (map (user: "${toUserString user} ${rule.host}=(${rule.runAs}) ${toCommandsString rule.commands}") rule.users) - (map (group: "${toGroupString group} ${rule.host}=(${rule.runAs}) ${toCommandsString rule.commands}") rule.groups) - ] - ) cfg.extraRules - ) - )} - '') + (concatStringsSep "\n" ( + lists.flatten ( + map ( + rule: optionals (length rule.commands != 0) [ + (map (user: "${toUserString user} ${rule.host}=(${rule.runAs}) ${toCommandsString rule.commands}") rule.users) + (map (group: "${toGroupString group} ${rule.host}=(${rule.runAs}) ${toCommandsString rule.commands}") rule.groups) + ] + ) cfg.extraRules + ) + ) + "\n") (optionalString (cfg.extraConfig != "") '' # extraConfig ${cfg.extraConfig} From 1852b67bc60e34ae6e7d3cba51892668a83e1a1d Mon Sep 17 00:00:00 2001 From: nicoo Date: Thu, 7 Sep 2023 12:50:48 +0000 Subject: [PATCH 6/7] nixos/sudo: Make the default rules' options configurable --- nixos/modules/security/sudo.nix | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/nixos/modules/security/sudo.nix b/nixos/modules/security/sudo.nix index aab5213d6dc5..03f38b543d66 100644 --- a/nixos/modules/security/sudo.nix +++ b/nixos/modules/security/sudo.nix @@ -32,6 +32,15 @@ in options.security.sudo = { + defaultOptions = mkOption { + type = with types; listOf str; + default = [ "SETENV" ]; + description = mdDoc '' + Options used for the default rules, granting `root` and the + `wheel` group permission to run any command as any user. + ''; + }; + enable = mkEnableOption (mdDoc '' the {command}`sudo` command, which allows non-root users to execute commands as root. ''); @@ -188,8 +197,8 @@ in inherit users groups; commands = [ { command = "ALL"; - options = opts ++ [ "SETENV" ]; - } ]; + options = opts ++ cfg.defaultOptions; + } ]; } ]; in mkMerge [ # This is ordered before users' `mkBefore` rules, From b9423822168bdd885208e5f92bf69d64db30374e Mon Sep 17 00:00:00 2001 From: nicoo Date: Wed, 25 Oct 2023 22:24:04 +0000 Subject: [PATCH 7/7] nixos/sudo: refactor processing of `cfg.extraRules` --- nixos/modules/security/sudo.nix | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/nixos/modules/security/sudo.nix b/nixos/modules/security/sudo.nix index 03f38b543d66..4e4f186758e9 100644 --- a/nixos/modules/security/sudo.nix +++ b/nixos/modules/security/sudo.nix @@ -218,16 +218,16 @@ in # Don't edit this file. Set the NixOS options ‘security.sudo.configFile’ # or ‘security.sudo.extraRules’ instead. '' - (concatStringsSep "\n" ( - lists.flatten ( - map ( - rule: optionals (length rule.commands != 0) [ - (map (user: "${toUserString user} ${rule.host}=(${rule.runAs}) ${toCommandsString rule.commands}") rule.users) - (map (group: "${toGroupString group} ${rule.host}=(${rule.runAs}) ${toCommandsString rule.commands}") rule.groups) - ] - ) cfg.extraRules - ) - ) + "\n") + (pipe cfg.extraRules [ + (filter (rule: length rule.commands != 0)) + (map (rule: [ + (map (user: "${toUserString user} ${rule.host}=(${rule.runAs}) ${toCommandsString rule.commands}") rule.users) + (map (group: "${toGroupString group} ${rule.host}=(${rule.runAs}) ${toCommandsString rule.commands}") rule.groups) + ])) + flatten + (concatStringsSep "\n") + ]) + "\n" (optionalString (cfg.extraConfig != "") '' # extraConfig ${cfg.extraConfig}