mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-11-13 03:08:16 +01:00
147 lines
5.1 KiB
Nix
147 lines
5.1 KiB
Nix
{
|
||
config,
|
||
lib,
|
||
pkgs,
|
||
...
|
||
}:
|
||
let
|
||
cfg = config.security.auditd;
|
||
|
||
settingsType =
|
||
with lib.types;
|
||
nullOr (oneOf [
|
||
bool
|
||
nonEmptyStr
|
||
path
|
||
int
|
||
]);
|
||
|
||
prepareConfigValue =
|
||
v:
|
||
if lib.isBool v then
|
||
(if v then "yes" else "no")
|
||
else if lib.isList v then
|
||
lib.concatStringsSep " " (map prepareConfigValue v)
|
||
else
|
||
builtins.toString v;
|
||
prepareConfigText =
|
||
conf:
|
||
lib.concatLines (
|
||
lib.mapAttrsToList (k: v: if v == null then "#${k} =" else "${k} = ${prepareConfigValue v}") conf
|
||
);
|
||
in
|
||
{
|
||
options.security.auditd = {
|
||
enable = lib.mkEnableOption "the Linux Audit daemon";
|
||
|
||
settings = lib.mkOption {
|
||
type = lib.types.submodule {
|
||
freeformType = lib.types.attrsOf settingsType;
|
||
options = {
|
||
# space_left needs to be larger than admin_space_left, yet they default to be the same if left open.
|
||
space_left = lib.mkOption {
|
||
type = lib.types.either lib.types.int (lib.types.strMatching "[0-9]+%");
|
||
default = 75;
|
||
description = ''
|
||
If the free space in the filesystem containing log_file drops below this value, the audit daemon takes the action specified by
|
||
{option}`space_left_action`. If the value of {option}`space_left` is specified as a whole number, it is interpreted as an absolute size in mebibytes
|
||
(MiB). If the value is specified as a number between 1 and 99 followed by a percentage sign (e.g., 5%), the audit daemon calculates
|
||
the absolute size in megabytes based on the size of the filesystem containing {option}`log_file`. (E.g., if the filesystem containing
|
||
{option}`log_file` is 2 gibibytes in size, and {option}`space_left` is set to 25%, then the audit daemon sets {option}`space_left` to approximately 500 mebibytes.
|
||
|
||
::: {.note}
|
||
This calculation is performed when the audit daemon starts, so if you resize the filesystem containing {option}`log_file` while the
|
||
audit daemon is running, you should send the audit daemon SIGHUP to re-read the configuration file and recalculate the correct per‐
|
||
centage.
|
||
:::
|
||
'';
|
||
};
|
||
admin_space_left = lib.mkOption {
|
||
type = lib.types.either lib.types.int (lib.types.strMatching "[0-9]+%");
|
||
default = 50;
|
||
description = ''
|
||
This is a numeric value in mebibytes (MiB) that tells the audit daemon when to perform a configurable action because the system is running
|
||
low on disk space. This should be considered the last chance to do something before running out of disk space. The numeric value for
|
||
this parameter should be lower than the number for {option}`space_left`. You may also append a percent sign (e.g. 1%) to the number to have
|
||
the audit daemon calculate the number based on the disk partition size.
|
||
'';
|
||
};
|
||
};
|
||
};
|
||
|
||
default = { };
|
||
description = "auditd configuration file contents. See {auditd.conf} for supported values.";
|
||
};
|
||
};
|
||
|
||
config = lib.mkIf cfg.enable {
|
||
assertions = [
|
||
{
|
||
assertion =
|
||
let
|
||
cfg' = cfg.settings;
|
||
in
|
||
(
|
||
(lib.isInt cfg'.space_left && lib.isInt cfg'.admin_space_left)
|
||
-> cfg'.space_left > cfg'.admin_space_left
|
||
)
|
||
&& (
|
||
let
|
||
get_percent = s: lib.toInt (lib.strings.removeSuffix "%" s);
|
||
in
|
||
(lib.isString cfg'.space_left && lib.isString cfg'.admin_space_left)
|
||
-> (get_percent cfg'.space_left) > (get_percent cfg'.admin_space_left)
|
||
);
|
||
message = "`security.auditd.settings.space_left` must be larger than `security.auditd.settings.admin_space_left`";
|
||
}
|
||
];
|
||
|
||
# Starting auditd should also enable loading the audit rules..
|
||
security.audit.enable = lib.mkDefault true;
|
||
|
||
environment.systemPackages = [ pkgs.audit ];
|
||
|
||
environment.etc = {
|
||
"audit/auditd.conf".text = prepareConfigText cfg.settings;
|
||
};
|
||
|
||
systemd.services.auditd = {
|
||
description = "Security Audit Logging Service";
|
||
documentation = [ "man:auditd(8)" ];
|
||
wantedBy = [ "sysinit.target" ];
|
||
after = [
|
||
"local-fs.target"
|
||
"systemd-tmpfiles-setup.service"
|
||
];
|
||
before = [
|
||
"sysinit.target"
|
||
"shutdown.target"
|
||
];
|
||
conflicts = [ "shutdown.target" ];
|
||
|
||
unitConfig = {
|
||
DefaultDependencies = false;
|
||
RefuseManualStop = true;
|
||
ConditionVirtualization = "!container";
|
||
ConditionKernelCommandLine = [
|
||
"!audit=0"
|
||
"!audit=off"
|
||
];
|
||
};
|
||
|
||
serviceConfig = {
|
||
LogsDirectory = "audit";
|
||
ExecStart = "${pkgs.audit}/bin/auditd -l -n -s nochange";
|
||
Restart = "on-failure";
|
||
# Do not restart for intentional exits. See EXIT CODES section in auditd(8).
|
||
RestartPreventExitStatus = "2 4 6";
|
||
|
||
# Upstream hardening settings
|
||
MemoryDenyWriteExecute = true;
|
||
LockPersonality = true;
|
||
RestrictRealtime = true;
|
||
};
|
||
};
|
||
};
|
||
}
|