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