grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / security / audit.nix
blob403aeff020dc9ba4571a5d9c5606b37f67580c54
1 { config, lib, pkgs, ... }:
3 with lib;
5 let
6   cfg = config.security.audit;
7   enabled = cfg.enable == "lock" || cfg.enable;
9   failureModes = {
10     silent = 0;
11     printk = 1;
12     panic  = 2;
13   };
15   disableScript = pkgs.writeScript "audit-disable" ''
16     #!${pkgs.runtimeShell} -eu
17     # Explicitly disable everything, as otherwise journald might start it.
18     auditctl -D
19     auditctl -e 0 -a task,never
20   '';
22   # TODO: it seems like people like their rules to be somewhat secret, yet they will not be if
23   # put in the store like this. At the same time, it doesn't feel like a huge deal and working
24   # around that is a pain so I'm leaving it like this for now.
25   startScript = pkgs.writeScript "audit-start" ''
26     #!${pkgs.runtimeShell} -eu
27     # Clear out any rules we may start with
28     auditctl -D
30     # Put the rules in a temporary file owned and only readable by root
31     rulesfile="$(mktemp)"
32     ${concatMapStrings (x: "echo '${x}' >> $rulesfile\n") cfg.rules}
34     # Apply the requested rules
35     auditctl -R "$rulesfile"
37     # Enable and configure auditing
38     auditctl \
39       -e ${if cfg.enable == "lock" then "2" else "1"} \
40       -b ${toString cfg.backlogLimit} \
41       -f ${toString failureModes.${cfg.failureMode}} \
42       -r ${toString cfg.rateLimit}
43   '';
45   stopScript = pkgs.writeScript "audit-stop" ''
46     #!${pkgs.runtimeShell} -eu
47     # Clear the rules
48     auditctl -D
50     # Disable auditing
51     auditctl -e 0
52   '';
53 in {
54   options = {
55     security.audit = {
56       enable = mkOption {
57         type        = types.enum [ false true "lock" ];
58         default     = false;
59         description = ''
60           Whether to enable the Linux audit system. The special `lock` value can be used to
61           enable auditing and prevent disabling it until a restart. Be careful about locking
62           this, as it will prevent you from changing your audit configuration until you
63           restart. If possible, test your configuration using build-vm beforehand.
64         '';
65       };
67       failureMode = mkOption {
68         type        = types.enum [ "silent" "printk" "panic" ];
69         default     = "printk";
70         description = "How to handle critical errors in the auditing system";
71       };
73       backlogLimit = mkOption {
74         type        = types.int;
75         default     = 64; # Apparently the kernel default
76         description = ''
77           The maximum number of outstanding audit buffers allowed; exceeding this is
78           considered a failure and handled in a manner specified by failureMode.
79         '';
80       };
82       rateLimit = mkOption {
83         type        = types.int;
84         default     = 0;
85         description = ''
86           The maximum messages per second permitted before triggering a failure as
87           specified by failureMode. Setting it to zero disables the limit.
88         '';
89       };
91       rules = mkOption {
92         type        = types.listOf types.str; # (types.either types.str (types.submodule rule));
93         default     = [];
94         example     = [ "-a exit,always -F arch=b64 -S execve" ];
95         description = ''
96           The ordered audit rules, with each string appearing as one line of the audit.rules file.
97         '';
98       };
99     };
100   };
102   config = {
103     systemd.services.audit = {
104       description = "Kernel Auditing";
105       wantedBy = [ "basic.target" ];
107       unitConfig = {
108         ConditionVirtualization = "!container";
109         ConditionSecurity = [ "audit" ];
110       };
113       path = [ pkgs.audit ];
115       serviceConfig = {
116         Type = "oneshot";
117         RemainAfterExit = true;
118         ExecStart = "@${if enabled then startScript else disableScript} audit-start";
119         ExecStop  = "@${stopScript} audit-stop";
120       };
121     };
122   };