nixos/please: init module

Co-authored-by: Cole Helbling <cole.e.helbling@outlook.com>
This commit is contained in:
Azat Bahawi 2022-09-30 00:12:29 +03:00 committed by Cole Helbling
parent be795c6a84
commit e04579e7cd
7 changed files with 201 additions and 0 deletions

View file

@ -216,6 +216,13 @@
<link xlink:href="options.html#opt-services.hadoop.hbase.enable">services.hadoop.hbase</link>.
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/edneville/please">Please</link>,
a Sudo clone written in Rust. Available as
<link linkend="opt-security.please.enable">security.please</link>
</para>
</listitem>
<listitem>
<para>
<link xlink:href="https://github.com/messagebird/sachet/">Sachet</link>,

View file

@ -79,6 +79,8 @@ In addition to numerous new and upgraded packages, this release has the followin
- [HBase cluster](https://hbase.apache.org/), a distributed, scalable, big data store. Available as [services.hadoop.hbase](options.html#opt-services.hadoop.hbase.enable).
- [Please](https://github.com/edneville/please), a Sudo clone written in Rust. Available as [security.please](#opt-security.please.enable)
- [Sachet](https://github.com/messagebird/sachet/), an SMS alerting tool for the Prometheus Alertmanager. Available as [services.prometheus.sachet](#opt-services.prometheus.sachet.enable).
- [infnoise](https://github.com/leetronics/infnoise), a hardware True Random Number Generator dongle.

View file

@ -263,6 +263,7 @@
./security/pam.nix
./security/pam_usb.nix
./security/pam_mount.nix
./security/please.nix
./security/polkit.nix
./security/rngd.nix
./security/rtkit.nix

View file

@ -0,0 +1,122 @@
{ config, lib, pkgs, ... }:
with lib;
let
cfg = config.security.please;
ini = pkgs.formats.ini { };
in
{
options.security.please = {
enable = mkEnableOption (mdDoc ''
please, a Sudo clone which allows a users to execute a command or edit a
file as another user
'');
package = mkOption {
type = types.package;
default = pkgs.please;
defaultText = literalExpression "pkgs.please";
description = mdDoc ''
Which package to use for {command}`please`.
'';
};
wheelNeedsPassword = mkOption {
type = types.bool;
default = true;
description = lib.mdDoc ''
Whether users of the `wheel` group must provide a password to run
commands or edit files with {command}`please` and
{command}`pleaseedit` respectively.
'';
};
settings = mkOption {
type = ini.type;
default = { };
example = {
jim_run_any_as_root = {
name = "jim";
type = "run";
target = "root";
rule = ".*";
require_pass = false;
};
jim_edit_etc_hosts_as_root = {
name = "jim";
type = "edit";
target = "root";
rule = "/etc/hosts";
editmode = 644;
require_pass = true;
};
};
description = mdDoc ''
Please configuration. Refer to
<https://github.com/edneville/please/blob/master/please.ini.md> for
details.
'';
};
};
config = mkIf cfg.enable {
security.wrappers =
let
owner = "root";
group = "root";
setuid = true;
in
{
please = {
source = "${cfg.package}/bin/please";
inherit owner group setuid;
};
pleaseedit = {
source = "${cfg.package}/bin/pleaseedit";
inherit owner group setuid;
};
};
security.please.settings = rec {
# The "wheel" group is allowed to do anything by default but this can be
# overridden.
wheel_run_as_any = {
type = "run";
group = true;
name = "wheel";
target = ".*";
rule = ".*";
require_pass = cfg.wheelNeedsPassword;
};
wheel_edit_as_any = wheel_run_as_any // { type = "edit"; };
wheel_list_as_any = wheel_run_as_any // { type = "list"; };
};
environment = {
systemPackages = [ cfg.package ];
etc."please.ini".source = ini.generate "please.ini"
(cfg.settings // (rec {
# The "root" user is allowed to do anything by default and this cannot
# be overridden.
root_run_as_any = {
type = "run";
name = "root";
target = ".*";
rule = ".*";
require_pass = false;
};
root_edit_as_any = root_run_as_any // { type = "edit"; };
root_list_as_any = root_run_as_any // { type = "list"; };
}));
};
security.pam.services.please = {
sshAgentAuth = true;
usshAuth = true;
};
meta.maintainers = with maintainers; [ azahi ];
};
}

View file

@ -491,6 +491,7 @@ in {
plasma5 = handleTest ./plasma5.nix {};
plasma5-systemd-start = handleTest ./plasma5-systemd-start.nix {};
plausible = handleTest ./plausible.nix {};
please = handleTest ./please.nix {};
pleroma = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./pleroma.nix {};
plikd = handleTest ./plikd.nix {};
plotinus = handleTest ./plotinus.nix {};

66
nixos/tests/please.nix Normal file
View file

@ -0,0 +1,66 @@
import ./make-test-python.nix ({ lib, ... }:
{
name = "please";
meta.maintainers = with lib.maintainers; [ azahi ];
nodes.machine =
{ ... }:
{
users.users = with lib; mkMerge [
(listToAttrs (map
(n: nameValuePair n { isNormalUser = true; })
(genList (x: "user${toString x}") 6)))
{
user0.extraGroups = [ "wheel" ];
}
];
security.please = {
enable = true;
wheelNeedsPassword = false;
settings = {
user2_run_true_as_root = {
name = "user2";
target = "root";
rule = "/run/current-system/sw/bin/true";
require_pass = false;
};
user4_edit_etc_hosts_as_root = {
name = "user4";
type = "edit";
target = "root";
rule = "/etc/hosts";
editmode = 644;
require_pass = false;
};
};
};
};
testScript = ''
with subtest("root: can run anything by default"):
machine.succeed('please true')
with subtest("root: can edit anything by default"):
machine.succeed('EDITOR=cat pleaseedit /etc/hosts')
with subtest("user0: can run as root because it's in the wheel group"):
machine.succeed('su - user0 -c "please -u root true"')
with subtest("user1: cannot run as root because it's not in the wheel group"):
machine.fail('su - user1 -c "please -u root true"')
with subtest("user0: can edit as root"):
machine.succeed('su - user0 -c "EDITOR=cat pleaseedit /etc/hosts"')
with subtest("user1: cannot edit as root"):
machine.fail('su - user1 -c "EDITOR=cat pleaseedit /etc/hosts"')
with subtest("user2: can run 'true' as root"):
machine.succeed('su - user2 -c "please -u root true"')
with subtest("user3: cannot run 'true' as root"):
machine.fail('su - user3 -c "please -u root true"')
with subtest("user4: can edit /etc/hosts"):
machine.succeed('su - user4 -c "EDITOR=cat pleaseedit /etc/hosts"')
with subtest("user5: cannot edit /etc/hosts"):
machine.fail('su - user5 -c "EDITOR=cat pleaseedit /etc/hosts"')
'';
})

View file

@ -29,6 +29,8 @@ rustPlatform.buildRustPackage rec {
installManPage man/*
'';
passthru.tests = { inherit (nixosTests) please; };
meta = with lib; {
description = "A polite regex-first sudo alternative";
longDescription = ''