vuls: init at 0.27.0
[NixPkgs.git] / nixos / modules / services / monitoring / certspotter.nix
blob5551f0e37c512ee077805edd6d34fd13e7c4ee87
1 { config
2 , lib
3 , pkgs
4 , ... }:
6 let
7   cfg = config.services.certspotter;
9   configDir = pkgs.linkFarm "certspotter-config" (
10     lib.toList {
11       name = "watchlist";
12       path = pkgs.writeText "certspotter-watchlist" (builtins.concatStringsSep "\n" cfg.watchlist);
13     }
14     ++ lib.optional (cfg.emailRecipients != [ ]) {
15       name = "email_recipients";
16       path = pkgs.writeText "certspotter-email_recipients" (builtins.concatStringsSep "\n" cfg.emailRecipients);
17     }
18     # always generate hooks dir when no emails are provided to allow running cert spotter with no hooks/emails
19     ++ lib.optional (cfg.emailRecipients == [ ] || cfg.hooks != [ ]) {
20       name = "hooks.d";
21       path = pkgs.linkFarm "certspotter-hooks" (lib.imap1 (i: path: {
22         inherit path;
23         name = "hook${toString i}";
24       }) cfg.hooks);
25     });
28   options.services.certspotter = {
29     enable = lib.mkEnableOption "Cert Spotter, a Certificate Transparency log monitor";
31     package = lib.mkPackageOption pkgs "certspotter" { };
33     startAtEnd = lib.mkOption {
34       type = lib.types.bool;
35       description = ''
36         Whether to skip certificates issued before the first launch of Cert Spotter.
37         Setting this to `false` will cause Cert Spotter to download tens of terabytes of data.
38       '';
39       default = true;
40     };
42     sendmailPath = lib.mkOption {
43       type = with lib.types; nullOr path;
44       description = ''
45         Path to the `sendmail` binary. By default, the local sendmail wrapper is used
46         (see {option}`services.mail.sendmailSetuidWrapper`}).
47       '';
48       example = lib.literalExpression ''"''${pkgs.system-sendmail}/bin/sendmail"'';
49     };
51     watchlist = lib.mkOption {
52       type = with lib.types; listOf str;
53       description = "Domain names to watch. To monitor a domain with all subdomains, prefix its name with `.` (e.g. `.example.org`).";
54       default = [ ];
55       example = [ ".example.org" "another.example.com" ];
56     };
58     emailRecipients = lib.mkOption {
59       type = with lib.types; listOf str;
60       description = "A list of email addresses to send certificate updates to.";
61       default = [ ];
62     };
64     hooks = lib.mkOption {
65       type = with lib.types; listOf path;
66       description = ''
67         Scripts to run upon the detection of a new certificate. See `man 8 certspotter-script` or
68         [the GitHub page](https://github.com/SSLMate/certspotter/blob/${pkgs.certspotter.src.rev or "master"}/man/certspotter-script.md)
69         for more info.
70       '';
71       default = [ ];
72       example = lib.literalExpression ''
73         [
74           (pkgs.writeShellScript "certspotter-hook" '''
75             echo "Event summary: $SUMMARY."
76           ''')
77         ]
78       '';
79     };
81     extraFlags = lib.mkOption {
82       type = with lib.types; listOf str;
83       description = "Extra command-line arguments to pass to Cert Spotter";
84       example = [ "-no_save" ];
85       default = [ ];
86     };
87   };
89   config = lib.mkIf cfg.enable {
90     assertions = [
91       {
92         assertion = (cfg.emailRecipients != [ ]) -> (cfg.sendmailPath != null);
93         message = ''
94           You must configure the sendmail setuid wrapper (services.mail.sendmailSetuidWrapper)
95           or services.certspotter.sendmailPath
96         '';
97       }
98     ];
100     services.certspotter.sendmailPath = let
101       inherit (config.security) wrapperDir;
102       inherit (config.services.mail) sendmailSetuidWrapper;
103     in lib.mkMerge [
104       (lib.mkIf (sendmailSetuidWrapper != null) (lib.mkOptionDefault "${wrapperDir}/${sendmailSetuidWrapper.program}"))
105       (lib.mkIf (sendmailSetuidWrapper == null) (lib.mkOptionDefault null))
106     ];
108     users.users.certspotter = {
109       description = "Cert Spotter user";
110       group = "certspotter";
111       home = "/var/lib/certspotter";
112       isSystemUser = true;
113     };
114     users.groups.certspotter = { };
116     systemd.services.certspotter = {
117       description = "Cert Spotter - Certificate Transparency Monitor";
118       after = [ "network.target" ];
119       wantedBy = [ "multi-user.target" ];
120       environment.CERTSPOTTER_CONFIG_DIR = configDir;
121       environment.SENDMAIL_PATH = if cfg.sendmailPath != null then cfg.sendmailPath else "/run/current-system/sw/bin/false";
122       script = ''
123         export CERTSPOTTER_STATE_DIR="$STATE_DIRECTORY"
124         cd "$CERTSPOTTER_STATE_DIR"
125         ${lib.optionalString cfg.startAtEnd ''
126           if [[ ! -d logs ]]; then
127             # Don't download certificates issued before the first launch
128             exec ${cfg.package}/bin/certspotter -start_at_end ${lib.escapeShellArgs cfg.extraFlags}
129           fi
130         ''}
131         exec ${cfg.package}/bin/certspotter ${lib.escapeShellArgs cfg.extraFlags}
132       '';
133       serviceConfig = {
134         User = "certspotter";
135         Group = "certspotter";
136         StateDirectory = "certspotter";
137       };
138     };
139   };
141   meta.maintainers = with lib.maintainers; [ chayleaf ];
142   meta.doc = ./certspotter.md;