at master 10 kB view raw
1{ 2 config, 3 lib, 4 pkgs, 5 ... 6}: 7 8let 9 inherit (lib) 10 mkEnableOption 11 mkIf 12 mkOption 13 mkPackageOption 14 types 15 ; 16 17 cfg = config.services.tlsrpt; 18 19 format = pkgs.formats.ini { }; 20 dropNullValues = lib.filterAttrsRecursive (_: value: value != null); 21 22 commonServiceSettings = { 23 DynamicUser = true; 24 User = "tlsrpt"; 25 Restart = "always"; 26 StateDirectory = "tlsrpt"; 27 StateDirectoryMode = "0700"; 28 29 # Hardening 30 CapabilityBoundingSet = [ "" ]; 31 LockPersonality = true; 32 MemoryDenyWriteExecute = true; 33 PrivateDevices = true; 34 PrivateUsers = false; 35 ProcSubset = "pid"; 36 ProtectControlGroups = true; 37 ProtectClock = true; 38 ProtectHome = true; 39 ProtectHostname = true; 40 ProtectKernelLogs = true; 41 ProtectKernelModules = true; 42 ProtectKernelTunables = true; 43 ProtectProc = "noaccess"; 44 RestrictNamespaces = true; 45 RestrictRealtime = true; 46 SystemCallArchitectures = "native"; 47 SystemCallFilter = [ 48 "@system-service" 49 "~@privileged @resources" 50 ]; 51 }; 52 53 collectdConfigFile = format.generate "tlsrpt-collectd.cfg" { 54 tlsrpt_collectd = dropNullValues cfg.collectd.settings; 55 }; 56 fetcherConfigFile = format.generate "tlsrpt-fetcher.cfg" { 57 tlsrpt_fetcher = dropNullValues cfg.fetcher.settings; 58 }; 59 reportdConfigFile = format.generate "tlsrpt-reportd.cfg" { 60 tlsrpt_reportd = dropNullValues cfg.reportd.settings; 61 }; 62 63 withPostfix = config.services.postfix.enable && cfg.configurePostfix; 64in 65 66{ 67 options.services.tlsrpt = { 68 enable = mkEnableOption "the TLSRPT services"; 69 70 package = mkPackageOption pkgs "tlsrpt-reporter" { }; 71 72 collectd = { 73 settings = mkOption { 74 type = types.submodule { 75 freeformType = format.type; 76 options = { 77 storage = mkOption { 78 type = types.str; 79 default = "sqlite:///var/lib/tlsrpt/collectd.sqlite"; 80 description = '' 81 Storage backend definition. 82 ''; 83 }; 84 85 socketname = mkOption { 86 type = types.path; 87 default = "/run/tlsrpt/collectd.sock"; 88 description = '' 89 Path at which the UNIX socket will be created. 90 ''; 91 }; 92 93 socketmode = mkOption { 94 type = types.str; 95 default = "0220"; 96 description = '' 97 Permissions on the UNIX socket. 98 ''; 99 }; 100 101 log_level = mkOption { 102 type = types.enum [ 103 "debug" 104 "info" 105 "warning" 106 "error" 107 "critical" 108 ]; 109 default = "info"; 110 description = '' 111 Level of log messages to emit. 112 ''; 113 }; 114 }; 115 }; 116 default = { }; 117 description = '' 118 Flags from {manpage}`tlsrpt-collectd(1)` as key-value pairs. 119 ''; 120 }; 121 122 extraFlags = mkOption { 123 type = with types; listOf str; 124 default = [ ]; 125 description = '' 126 List of extra flags to pass to the tlsrpt-reportd executable. 127 128 See {manpage}`tlsrpt-collectd(1)` for possible flags. 129 ''; 130 }; 131 }; 132 133 fetcher = { 134 settings = mkOption { 135 type = types.submodule { 136 freeformType = format.type; 137 options = { 138 storage = mkOption { 139 type = types.str; 140 default = config.services.tlsrpt.collectd.settings.storage; 141 defaultText = lib.literalExpression '' 142 config.services.tlsrpt.collectd.settings.storage 143 ''; 144 description = '' 145 Path to the collectd sqlite database. 146 ''; 147 }; 148 149 log_level = mkOption { 150 type = types.enum [ 151 "debug" 152 "info" 153 "warning" 154 "error" 155 "critical" 156 ]; 157 default = "info"; 158 description = '' 159 Level of log messages to emit. 160 ''; 161 }; 162 }; 163 }; 164 default = { }; 165 description = '' 166 Flags from {manpage}`tlsrpt-fetcher(1)` as key-value pairs. 167 ''; 168 }; 169 }; 170 171 reportd = { 172 settings = mkOption { 173 type = types.submodule { 174 freeformType = format.type; 175 options = { 176 dbname = mkOption { 177 type = types.str; 178 default = "/var/lib/tlsrpt/reportd.sqlite"; 179 description = '' 180 Path to the sqlite database. 181 ''; 182 }; 183 184 fetchers = mkOption { 185 type = types.str; 186 default = lib.getExe' cfg.package "tlsrpt-fetcher"; 187 defaultText = lib.literalExpression '' 188 lib.getExe' cfg.package "tlsrpt-fetcher" 189 ''; 190 description = '' 191 Comma-separated list of fetcher programs that retrieve collectd data. 192 ''; 193 }; 194 195 log_level = mkOption { 196 type = types.enum [ 197 "debug" 198 "info" 199 "warning" 200 "error" 201 "critical" 202 ]; 203 default = "info"; 204 description = '' 205 Level of log messages to emit. 206 ''; 207 }; 208 209 organization_name = mkOption { 210 type = types.str; 211 example = "ACME Corp."; 212 description = '' 213 Name of the organization sending out the reports. 214 ''; 215 }; 216 217 contact_info = mkOption { 218 type = types.str; 219 example = "smtp-tls-reporting@example.com"; 220 description = '' 221 Contact information embedded into the reports. 222 ''; 223 }; 224 225 http_script = mkOption { 226 type = with types; nullOr str; 227 default = "${lib.getExe pkgs.curl} --silent --header 'Content-Type: application/tlsrpt+gzip' --data-binary @-"; 228 defaultText = lib.literalExpression '' 229 ''${lib.getExe pkgs.curl} --silent --header 'Content-Type: application/tlsrpt+gzip' --data-binary @- 230 ''; 231 description = '' 232 Call to an HTTPS client, that accepts the URL on the commandline and the request body from stdin. 233 ''; 234 }; 235 236 sender_address = mkOption { 237 type = types.str; 238 example = "noreply@example.com"; 239 description = '' 240 Sender address used for reports. 241 ''; 242 }; 243 244 sendmail_script = mkOption { 245 type = with types; nullOr str; 246 default = 247 if config.services.postfix.enable && config.services.postfix.setSendmail then 248 "/run/wrappers/bin/sendmail -i -t" 249 else 250 null; 251 defaultText = lib.literalExpression '' 252 if config.services.postfix.enable && config.services.postfix.setSendmail then 253 "/run/wrappers/bin/sendmail -i -t" 254 else 255 null 256 ''; 257 description = '' 258 Path to a sendmail-compatible executable for delivery reports. 259 ''; 260 }; 261 }; 262 }; 263 default = { }; 264 description = '' 265 Flags from {manpage}`tlsrpt-reportd(1)` as key-value pairs. 266 ''; 267 }; 268 269 extraFlags = mkOption { 270 type = with types; listOf str; 271 default = [ ]; 272 description = '' 273 List of extra flags to pass to the tlsrpt-reportd executable. 274 275 See {manpage}`tlsrpt-report(1)` for possible flags. 276 ''; 277 }; 278 }; 279 280 configurePostfix = mkOption { 281 type = types.bool; 282 default = true; 283 description = '' 284 Whether to configure permissions to allow integration with Postfix. 285 ''; 286 }; 287 }; 288 289 config = mkIf cfg.enable { 290 environment.etc = { 291 "tlsrpt/collectd.cfg".source = collectdConfigFile; 292 "tlsrpt/fetcher.cfg".source = fetcherConfigFile; 293 "tlsrpt/reportd.cfg".source = reportdConfigFile; 294 }; 295 296 users.users.tlsrpt = { 297 isSystemUser = true; 298 group = "tlsrpt"; 299 }; 300 users.groups.tlsrpt = { }; 301 302 users.users.postfix.extraGroups = lib.mkIf withPostfix [ 303 "tlsrpt" 304 ]; 305 306 systemd.services.tlsrpt-collectd = { 307 description = "TLSRPT datagram collector"; 308 documentation = [ "man:tlsrpt-collectd(1)" ]; 309 310 wantedBy = [ "multi-user.target" ]; 311 312 restartTriggers = [ collectdConfigFile ]; 313 314 serviceConfig = commonServiceSettings // { 315 ExecStart = toString ( 316 [ 317 (lib.getExe' cfg.package "tlsrpt-collectd") 318 ] 319 ++ cfg.collectd.extraFlags 320 ); 321 IPAddressDeny = "any"; 322 PrivateNetwork = true; 323 RestrictAddressFamilies = [ "AF_UNIX" ]; 324 RuntimeDirectory = "tlsrpt"; 325 RuntimeDirectoryMode = "0750"; 326 UMask = "0157"; 327 }; 328 }; 329 330 systemd.services.tlsrpt-reportd = { 331 description = "TLSRPT report generator"; 332 documentation = [ "man:tlsrpt-reportd(1)" ]; 333 334 wantedBy = [ "multi-user.target" ]; 335 336 restartTriggers = [ reportdConfigFile ]; 337 338 serviceConfig = commonServiceSettings // { 339 ExecStart = toString ( 340 [ 341 (lib.getExe' cfg.package "tlsrpt-reportd") 342 ] 343 ++ cfg.reportd.extraFlags 344 ); 345 RestrictAddressFamilies = [ 346 "AF_INET" 347 "AF_INET6" 348 "AF_NETLINK" 349 ]; 350 ReadWritePaths = lib.optionals withPostfix [ "/var/lib/postfix/queue/maildrop" ]; 351 SupplementaryGroups = lib.optionals withPostfix [ "postdrop" ]; 352 UMask = "0077"; 353 }; 354 }; 355 }; 356}