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