1{
2 config,
3 lib,
4 pkgs,
5 ...
6}:
7let
8 cfg = config.security.please;
9 ini = pkgs.formats.ini { };
10in
11{
12 options.security.please = {
13 enable = lib.mkEnableOption ''
14 please, a Sudo clone which allows a users to execute a command or edit a
15 file as another user
16 '';
17
18 package = lib.mkPackageOption pkgs "please" { };
19
20 wheelNeedsPassword = lib.mkOption {
21 type = lib.types.bool;
22 default = true;
23 description = ''
24 Whether users of the `wheel` group must provide a password to run
25 commands or edit files with {command}`please` and
26 {command}`pleaseedit` respectively.
27 '';
28 };
29
30 settings = lib.mkOption {
31 type = ini.type;
32 default = { };
33 example = {
34 jim_run_any_as_root = {
35 name = "jim";
36 type = "run";
37 target = "root";
38 rule = ".*";
39 require_pass = false;
40 };
41 jim_edit_etc_hosts_as_root = {
42 name = "jim";
43 type = "edit";
44 target = "root";
45 rule = "/etc/hosts";
46 editmode = 644;
47 require_pass = true;
48 };
49 };
50 description = ''
51 Please configuration. Refer to
52 <https://github.com/edneville/please/blob/master/please.ini.md> for
53 details.
54 '';
55 };
56 };
57
58 config = lib.mkIf cfg.enable {
59 security.wrappers =
60 let
61 owner = "root";
62 group = "root";
63 setuid = true;
64 in
65 {
66 please = {
67 source = "${cfg.package}/bin/please";
68 inherit owner group setuid;
69 };
70 pleaseedit = {
71 source = "${cfg.package}/bin/pleaseedit";
72 inherit owner group setuid;
73 };
74 };
75
76 security.please.settings = rec {
77 # The "wheel" group is allowed to do anything by default but this can be
78 # overridden.
79 wheel_run_as_any = {
80 type = "run";
81 group = true;
82 name = "wheel";
83 target = ".*";
84 rule = ".*";
85 require_pass = cfg.wheelNeedsPassword;
86 };
87 wheel_edit_as_any = wheel_run_as_any // {
88 type = "edit";
89 };
90 wheel_list_as_any = wheel_run_as_any // {
91 type = "list";
92 };
93 };
94
95 environment = {
96 systemPackages = [ cfg.package ];
97
98 etc."please.ini".source = ini.generate "please.ini" (
99 cfg.settings
100 // (rec {
101 # The "root" user is allowed to do anything by default and this cannot
102 # be overridden.
103 root_run_as_any = {
104 type = "run";
105 name = "root";
106 target = ".*";
107 rule = ".*";
108 require_pass = false;
109 };
110 root_edit_as_any = root_run_as_any // {
111 type = "edit";
112 };
113 root_list_as_any = root_run_as_any // {
114 type = "list";
115 };
116 })
117 );
118 };
119
120 security.pam.services.please = {
121 sshAgentAuth = true;
122 usshAuth = true;
123 };
124 };
125}