at 16.09-beta 6.4 kB view raw
1{ config, lib, pkgs, ... }: 2 3with lib; 4 5let 6 cfg = config.services.logcheck; 7 8 defaultRules = pkgs.runCommand "logcheck-default-rules" {} '' 9 cp -prd ${pkgs.logcheck}/etc/logcheck $out 10 chmod u+w $out 11 rm $out/logcheck.* 12 ''; 13 14 rulesDir = pkgs.symlinkJoin 15 { name = "logcheck-rules-dir"; 16 paths = ([ defaultRules ] ++ cfg.extraRulesDirs); 17 }; 18 19 configFile = pkgs.writeText "logcheck.conf" cfg.config; 20 21 logFiles = pkgs.writeText "logcheck.logfiles" cfg.files; 22 23 flags = "-r ${rulesDir} -c ${configFile} -L ${logFiles} -${levelFlag} -m ${cfg.mailTo}"; 24 25 levelFlag = getAttrFromPath [cfg.level] 26 { "paranoid" = "p"; 27 "server" = "s"; 28 "workstation" = "w"; 29 }; 30 31 cronJob = '' 32 @reboot logcheck env PATH=/var/setuid-wrappers:$PATH nice -n10 ${pkgs.logcheck}/sbin/logcheck -R ${flags} 33 2 ${cfg.timeOfDay} * * * logcheck env PATH=/var/setuid-wrappers:$PATH nice -n10 ${pkgs.logcheck}/sbin/logcheck ${flags} 34 ''; 35 36 writeIgnoreRule = name: {level, regex, ...}: 37 pkgs.writeTextFile 38 { inherit name; 39 destination = "/ignore.d.${level}/${name}"; 40 text = '' 41 ^\w{3} [ :[:digit:]]{11} [._[:alnum:]-]+ ${regex} 42 ''; 43 }; 44 45 writeIgnoreCronRule = name: {level, user, regex, cmdline, ...}: 46 let escapeRegex = escape (stringToCharacters "\\[]{}()^$?*+|."); 47 cmdline_ = builtins.unsafeDiscardStringContext cmdline; 48 re = if regex != "" then regex else if cmdline_ == "" then ".*" else escapeRegex cmdline_; 49 in writeIgnoreRule "cron-${name}" { 50 inherit level; 51 regex = '' 52 (/usr/bin/)?cron\[[0-9]+\]: \(${user}\) CMD \(${re}\)$ 53 ''; 54 }; 55 56 levelOption = mkOption { 57 default = "server"; 58 type = types.str; 59 description = '' 60 Set the logcheck level. Either "workstation", "server", or "paranoid". 61 ''; 62 }; 63 64 ignoreOptions = { 65 level = levelOption; 66 67 regex = mkOption { 68 default = ""; 69 type = types.str; 70 description = '' 71 Regex specifying which log lines to ignore. 72 ''; 73 }; 74 }; 75 76 ignoreCronOptions = { 77 user = mkOption { 78 default = "root"; 79 type = types.str; 80 description = '' 81 User that runs the cronjob. 82 ''; 83 }; 84 85 cmdline = mkOption { 86 default = ""; 87 type = types.str; 88 description = '' 89 Command line for the cron job. Will be turned into a regex for the logcheck ignore rule. 90 ''; 91 }; 92 93 timeArgs = mkOption { 94 default = null; 95 type = types.nullOr (types.str); 96 example = "02 06 * * *"; 97 description = '' 98 "min hr dom mon dow" crontab time args, to auto-create a cronjob too. 99 Leave at null to not do this and just add a logcheck ignore rule. 100 ''; 101 }; 102 }; 103 104in 105{ 106 options = { 107 services.logcheck = { 108 enable = mkOption { 109 default = false; 110 type = types.bool; 111 description = '' 112 Enable the logcheck cron job. 113 ''; 114 }; 115 116 user = mkOption { 117 default = "logcheck"; 118 type = types.str; 119 description = '' 120 Username for the logcheck user. 121 ''; 122 }; 123 124 timeOfDay = mkOption { 125 default = "*"; 126 example = "6"; 127 type = types.str; 128 description = '' 129 Time of day to run logcheck. A logcheck will be scheduled at xx:02 each day. 130 Leave default (*) to run every hour. Of course when nothing special was logged, 131 logcheck will be silent. 132 ''; 133 }; 134 135 mailTo = mkOption { 136 default = "root"; 137 example = "you@domain.com"; 138 type = types.str; 139 description = '' 140 Email address to send reports to. 141 ''; 142 }; 143 144 level = mkOption { 145 default = "server"; 146 type = types.str; 147 description = '' 148 Set the logcheck level. Either "workstation", "server", or "paranoid". 149 ''; 150 }; 151 152 config = mkOption { 153 default = "FQDN=1"; 154 type = types.string; 155 description = '' 156 Config options that you would like in logcheck.conf. 157 ''; 158 }; 159 160 files = mkOption { 161 default = [ "/var/log/messages" ]; 162 type = types.listOf types.path; 163 example = [ "/var/log/messages" "/var/log/mail" ]; 164 description = '' 165 Which log files to check. 166 ''; 167 }; 168 169 extraRulesDirs = mkOption { 170 default = []; 171 example = "/etc/logcheck"; 172 type = types.listOf types.path; 173 description = '' 174 Directories with extra rules. 175 ''; 176 }; 177 178 ignore = mkOption { 179 default = {}; 180 description = '' 181 This option defines extra ignore rules. 182 ''; 183 type = types.loaOf types.optionSet; 184 options = [ ignoreOptions ]; 185 }; 186 187 ignoreCron = mkOption { 188 default = {}; 189 description = '' 190 This option defines extra ignore rules for cronjobs. 191 ''; 192 type = types.loaOf types.optionSet; 193 options = [ ignoreOptions ignoreCronOptions ]; 194 }; 195 196 extraGroups = mkOption { 197 default = []; 198 type = types.listOf types.str; 199 example = [ "postdrop" "mongodb" ]; 200 description = '' 201 Extra groups for the logcheck user, for example to be able to use sendmail, 202 or to access certain log files. 203 ''; 204 }; 205 206 }; 207 }; 208 209 config = mkIf cfg.enable { 210 services.logcheck.extraRulesDirs = 211 mapAttrsToList writeIgnoreRule cfg.ignore 212 ++ mapAttrsToList writeIgnoreCronRule cfg.ignoreCron; 213 214 users.extraUsers = optionalAttrs (cfg.user == "logcheck") (singleton 215 { name = "logcheck"; 216 uid = config.ids.uids.logcheck; 217 shell = "/bin/sh"; 218 description = "Logcheck user account"; 219 extraGroups = cfg.extraGroups; 220 }); 221 222 system.activationScripts.logcheck = '' 223 mkdir -m 700 -p /var/{lib,lock}/logcheck 224 chown ${cfg.user} /var/{lib,lock}/logcheck 225 ''; 226 227 services.cron.systemCronJobs = 228 let withTime = name: {timeArgs, ...}: ! (builtins.isNull timeArgs); 229 mkCron = name: {user, cmdline, timeArgs, ...}: '' 230 ${timeArgs} ${user} ${cmdline} 231 ''; 232 in mapAttrsToList mkCron (filterAttrs withTime cfg.ignoreCron) 233 ++ [ cronJob ]; 234 }; 235}