diff --git a/nixos/modules/security/audit.nix b/nixos/modules/security/audit.nix index 16d750c8fbed..4bcc6c62d1cb 100644 --- a/nixos/modules/security/audit.nix +++ b/nixos/modules/security/audit.nix @@ -6,7 +6,6 @@ }: let cfg = config.security.audit; - enabled = cfg.enable == "lock" || cfg.enable; failureModes = { silent = 0; @@ -14,43 +13,14 @@ let panic = 2; }; - disableScript = pkgs.writeScript "audit-disable" '' - #!${pkgs.runtimeShell} -eu - # Explicitly disable everything, as otherwise journald might start it. - auditctl -D - auditctl -e 0 -a task,never - ''; - - # TODO: it seems like people like their rules to be somewhat secret, yet they will not be if - # put in the store like this. At the same time, it doesn't feel like a huge deal and working - # around that is a pain so I'm leaving it like this for now. - startScript = pkgs.writeScript "audit-start" '' - #!${pkgs.runtimeShell} -eu - # Clear out any rules we may start with - auditctl -D - - # Put the rules in a temporary file owned and only readable by root - rulesfile="$(mktemp)" - ${lib.concatMapStrings (x: "echo '${x}' >> $rulesfile\n") cfg.rules} - - # Apply the requested rules - auditctl -R "$rulesfile" - - # Enable and configure auditing - auditctl \ - -e ${if cfg.enable == "lock" then "2" else "1"} \ - -b ${toString cfg.backlogLimit} \ - -f ${toString failureModes.${cfg.failureMode}} \ - -r ${toString cfg.rateLimit} - ''; - - stopScript = pkgs.writeScript "audit-stop" '' - #!${pkgs.runtimeShell} -eu - # Clear the rules - auditctl -D - - # Disable auditing - auditctl -e 0 + # The order of the fixed rules is determined by augenrules(8) + rules = pkgs.writeTextDir "audit.rules" '' + -D + -b ${toString cfg.backlogLimit} + -f ${toString failureModes.${cfg.failureMode}} + -r ${toString cfg.rateLimit} + ${lib.concatLines cfg.rules} + -e ${if cfg.enable == "lock" then "2" else "1"} ''; in { @@ -110,23 +80,35 @@ in }; }; - config = { - systemd.services.audit = { - description = "Kernel Auditing"; - wantedBy = [ "basic.target" ]; + config = lib.mkIf (cfg.enable == "lock" || cfg.enable) { + systemd.services.audit-rules = { + description = "Load Audit Rules"; + wantedBy = [ "sysinit.target" ]; + before = [ + "sysinit.target" + "shutdown.target" + ]; + conflicts = [ "shutdown.target" ]; unitConfig = { + DefaultDependencies = false; ConditionVirtualization = "!container"; - ConditionSecurity = [ "audit" ]; + ConditionKernelCommandLine = [ + "!audit=0" + "!audit=off" + ]; }; - path = [ pkgs.audit ]; - serviceConfig = { Type = "oneshot"; RemainAfterExit = true; - ExecStart = "@${if enabled then startScript else disableScript} audit-start"; - ExecStop = "@${stopScript} audit-stop"; + ExecStart = "${lib.getExe' pkgs.audit "auditctl"} -R ${rules}/audit.rules"; + ExecStopPost = [ + # Disable auditing + "${lib.getExe' pkgs.audit "auditctl"} -e 0" + # Delete all rules + "${lib.getExe' pkgs.audit "auditctl"} -D" + ]; }; }; };