Merge pull request #262915 from chayleaf/certspotter
certspotter: init at 0.17.0; nixos/certspotter: init
This commit is contained in:
commit
37c7104f53
5 changed files with 259 additions and 0 deletions
|
@ -113,6 +113,8 @@
|
||||||
|
|
||||||
- [tuxedo-rs](https://github.com/AaronErhardt/tuxedo-rs), Rust utilities for interacting with hardware from TUXEDO Computers.
|
- [tuxedo-rs](https://github.com/AaronErhardt/tuxedo-rs), Rust utilities for interacting with hardware from TUXEDO Computers.
|
||||||
|
|
||||||
|
- [certspotter](https://github.com/SSLMate/certspotter), a certificate transparency log monitor. Available as [services.certspotter](#opt-services.certspotter.enable).
|
||||||
|
|
||||||
- [audiobookshelf](https://github.com/advplyr/audiobookshelf/), a self-hosted audiobook and podcast server. Available as [services.audiobookshelf](#opt-services.audiobookshelf.enable).
|
- [audiobookshelf](https://github.com/advplyr/audiobookshelf/), a self-hosted audiobook and podcast server. Available as [services.audiobookshelf](#opt-services.audiobookshelf.enable).
|
||||||
|
|
||||||
- [ZITADEL](https://zitadel.com), a turnkey identity and access management platform. Available as [services.zitadel](#opt-services.zitadel.enable).
|
- [ZITADEL](https://zitadel.com), a turnkey identity and access management platform. Available as [services.zitadel](#opt-services.zitadel.enable).
|
||||||
|
|
|
@ -767,6 +767,7 @@
|
||||||
./services/monitoring/below.nix
|
./services/monitoring/below.nix
|
||||||
./services/monitoring/bosun.nix
|
./services/monitoring/bosun.nix
|
||||||
./services/monitoring/cadvisor.nix
|
./services/monitoring/cadvisor.nix
|
||||||
|
./services/monitoring/certspotter.nix
|
||||||
./services/monitoring/cockpit.nix
|
./services/monitoring/cockpit.nix
|
||||||
./services/monitoring/collectd.nix
|
./services/monitoring/collectd.nix
|
||||||
./services/monitoring/das_watchdog.nix
|
./services/monitoring/das_watchdog.nix
|
||||||
|
|
74
nixos/modules/services/monitoring/certspotter.md
Normal file
74
nixos/modules/services/monitoring/certspotter.md
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
# Cert Spotter {#module-services-certspotter}
|
||||||
|
|
||||||
|
Cert Spotter is a tool for monitoring [Certificate Transparency](https://en.wikipedia.org/wiki/Certificate_Transparency)
|
||||||
|
logs.
|
||||||
|
|
||||||
|
## Service Configuration {#modules-services-certspotter-service-configuration}
|
||||||
|
|
||||||
|
A basic config that notifies you of all certificate changes for your
|
||||||
|
domain would look as follows:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
services.certspotter = {
|
||||||
|
enable = true;
|
||||||
|
# replace example.org with your domain name
|
||||||
|
watchlist = [ ".example.org" ];
|
||||||
|
emailRecipients = [ "webmaster@example.org" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Configure an SMTP client
|
||||||
|
programs.msmtp.enable = true;
|
||||||
|
# Or you can use any other module that provides sendmail, like
|
||||||
|
# services.nullmailer, services.opensmtpd, services.postfix
|
||||||
|
```
|
||||||
|
|
||||||
|
In this case, the leading dot in `".example.org"` means that Cert
|
||||||
|
Spotter should monitor not only `example.org`, but also all of its
|
||||||
|
subdomains.
|
||||||
|
|
||||||
|
## Operation {#modules-services-certspotter-operation}
|
||||||
|
|
||||||
|
**By default, NixOS configures Cert Spotter to skip all certificates
|
||||||
|
issued before its first launch**, because checking the entire
|
||||||
|
Certificate Transparency logs requires downloading tens of terabytes of
|
||||||
|
data. If you want to check the *entire* logs for previously issued
|
||||||
|
certificates, you have to set `services.certspotter.startAtEnd` to
|
||||||
|
`false` and remove all previously saved log state in
|
||||||
|
`/var/lib/certspotter/logs`. The downloaded logs aren't saved, so if you
|
||||||
|
add a new domain to the watchlist and want Cert Spotter to go through
|
||||||
|
the logs again, you will have to remove `/var/lib/certspotter/logs`
|
||||||
|
again.
|
||||||
|
|
||||||
|
After catching up with the logs, Cert Spotter will start monitoring live
|
||||||
|
logs. As of October 2023, it uses around **20 Mbps** of traffic on
|
||||||
|
average.
|
||||||
|
|
||||||
|
## Hooks {#modules-services-certspotter-hooks}
|
||||||
|
|
||||||
|
Cert Spotter supports running custom hooks instead of (or in addition
|
||||||
|
to) sending emails. Hooks are shell scripts that will be passed certain
|
||||||
|
environment variables.
|
||||||
|
|
||||||
|
To see hook documentation, see Cert Spotter's man pages:
|
||||||
|
|
||||||
|
```ShellSession
|
||||||
|
nix-shell -p certspotter --run 'man 8 certspotter-script'
|
||||||
|
```
|
||||||
|
|
||||||
|
For example, you can remove `emailRecipients` and send email
|
||||||
|
notifications manually using the following hook:
|
||||||
|
|
||||||
|
```nix
|
||||||
|
services.certspotter.hooks = [
|
||||||
|
(pkgs.writeShellScript "certspotter-hook" ''
|
||||||
|
function print_email() {
|
||||||
|
echo "Subject: [certspotter] $SUMMARY"
|
||||||
|
echo "Mime-Version: 1.0"
|
||||||
|
echo "Content-Type: text/plain; charset=US-ASCII"
|
||||||
|
echo
|
||||||
|
cat "$TEXT_FILENAME"
|
||||||
|
}
|
||||||
|
print_email | ${config.services.certspotter.sendmailPath} -i webmaster@example.org
|
||||||
|
'')
|
||||||
|
];
|
||||||
|
```
|
143
nixos/modules/services/monitoring/certspotter.nix
Normal file
143
nixos/modules/services/monitoring/certspotter.nix
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
{ config
|
||||||
|
, lib
|
||||||
|
, pkgs
|
||||||
|
, ... }:
|
||||||
|
|
||||||
|
let
|
||||||
|
cfg = config.services.certspotter;
|
||||||
|
|
||||||
|
configDir = pkgs.linkFarm "certspotter-config" (
|
||||||
|
lib.toList {
|
||||||
|
name = "watchlist";
|
||||||
|
path = pkgs.writeText "certspotter-watchlist" (builtins.concatStringsSep "\n" cfg.watchlist);
|
||||||
|
}
|
||||||
|
++ lib.optional (cfg.emailRecipients != [ ]) {
|
||||||
|
name = "email_recipients";
|
||||||
|
path = pkgs.writeText "certspotter-email_recipients" (builtins.concatStringsSep "\n" cfg.emailRecipients);
|
||||||
|
}
|
||||||
|
# always generate hooks dir when no emails are provided to allow running cert spotter with no hooks/emails
|
||||||
|
++ lib.optional (cfg.emailRecipients == [ ] || cfg.hooks != [ ]) {
|
||||||
|
name = "hooks.d";
|
||||||
|
path = pkgs.linkFarm "certspotter-hooks" (lib.imap1 (i: path: {
|
||||||
|
inherit path;
|
||||||
|
name = "hook${toString i}";
|
||||||
|
}) cfg.hooks);
|
||||||
|
});
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options.services.certspotter = {
|
||||||
|
enable = lib.mkEnableOption "Cert Spotter, a Certificate Transparency log monitor";
|
||||||
|
|
||||||
|
package = lib.mkPackageOptionMD pkgs "certspotter" { };
|
||||||
|
|
||||||
|
startAtEnd = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
description = ''
|
||||||
|
Whether to skip certificates issued before the first launch of Cert Spotter.
|
||||||
|
Setting this to `false` will cause Cert Spotter to download tens of terabytes of data.
|
||||||
|
'';
|
||||||
|
default = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
sendmailPath = lib.mkOption {
|
||||||
|
type = with lib.types; nullOr path;
|
||||||
|
description = ''
|
||||||
|
Path to the `sendmail` binary. By default, the local sendmail wrapper is used
|
||||||
|
(see {option}`services.mail.sendmailSetuidWrapper`}).
|
||||||
|
'';
|
||||||
|
example = lib.literalExpression ''"''${pkgs.system-sendmail}/bin/sendmail"'';
|
||||||
|
};
|
||||||
|
|
||||||
|
watchlist = lib.mkOption {
|
||||||
|
type = with lib.types; listOf str;
|
||||||
|
description = "Domain names to watch. To monitor a domain with all subdomains, prefix its name with `.` (e.g. `.example.org`).";
|
||||||
|
default = [ ];
|
||||||
|
example = [ ".example.org" "another.example.com" ];
|
||||||
|
};
|
||||||
|
|
||||||
|
emailRecipients = lib.mkOption {
|
||||||
|
type = with lib.types; listOf str;
|
||||||
|
description = "A list of email addresses to send certificate updates to.";
|
||||||
|
default = [ ];
|
||||||
|
};
|
||||||
|
|
||||||
|
hooks = lib.mkOption {
|
||||||
|
type = with lib.types; listOf path;
|
||||||
|
description = ''
|
||||||
|
Scripts to run upon the detection of a new certificate. See `man 8 certspotter-script` or
|
||||||
|
[the GitHub page](https://github.com/SSLMate/certspotter/blob/${pkgs.certspotter.src.rev or "master"}/man/certspotter-script.md)
|
||||||
|
for more info.
|
||||||
|
'';
|
||||||
|
default = [ ];
|
||||||
|
example = lib.literalExpression ''
|
||||||
|
[
|
||||||
|
(pkgs.writeShellScript "certspotter-hook" '''
|
||||||
|
echo "Event summary: $SUMMARY."
|
||||||
|
''')
|
||||||
|
]
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
extraFlags = lib.mkOption {
|
||||||
|
type = with lib.types; listOf str;
|
||||||
|
description = "Extra command-line arguments to pass to Cert Spotter";
|
||||||
|
example = [ "-no_save" ];
|
||||||
|
default = [ ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = (cfg.emailRecipients != [ ]) -> (cfg.sendmailPath != null);
|
||||||
|
message = ''
|
||||||
|
You must configure the sendmail setuid wrapper (services.mail.sendmailSetuidWrapper)
|
||||||
|
or services.certspotter.sendmailPath
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
services.certspotter.sendmailPath = let
|
||||||
|
inherit (config.security) wrapperDir;
|
||||||
|
inherit (config.services.mail) sendmailSetuidWrapper;
|
||||||
|
in lib.mkMerge [
|
||||||
|
(lib.mkIf (sendmailSetuidWrapper != null) (lib.mkOptionDefault "${wrapperDir}/${sendmailSetuidWrapper.program}"))
|
||||||
|
(lib.mkIf (sendmailSetuidWrapper == null) (lib.mkOptionDefault null))
|
||||||
|
];
|
||||||
|
|
||||||
|
users.users.certspotter = {
|
||||||
|
description = "Cert Spotter user";
|
||||||
|
group = "certspotter";
|
||||||
|
home = "/var/lib/certspotter";
|
||||||
|
isSystemUser = true;
|
||||||
|
};
|
||||||
|
users.groups.certspotter = { };
|
||||||
|
|
||||||
|
systemd.services.certspotter = {
|
||||||
|
description = "Cert Spotter - Certificate Transparency Monitor";
|
||||||
|
after = [ "network.target" ];
|
||||||
|
wantedBy = [ "multi-user.target" ];
|
||||||
|
environment.CERTSPOTTER_CONFIG_DIR = configDir;
|
||||||
|
environment.SENDMAIL_PATH = if cfg.sendmailPath != null then cfg.sendmailPath else "/run/current-system/sw/bin/false";
|
||||||
|
script = ''
|
||||||
|
export CERTSPOTTER_STATE_DIR="$STATE_DIRECTORY"
|
||||||
|
cd "$CERTSPOTTER_STATE_DIR"
|
||||||
|
${lib.optionalString cfg.startAtEnd ''
|
||||||
|
if [[ ! -d logs ]]; then
|
||||||
|
# Don't download certificates issued before the first launch
|
||||||
|
exec ${cfg.package}/bin/certspotter -start_at_end ${lib.escapeShellArgs cfg.extraFlags}
|
||||||
|
fi
|
||||||
|
''}
|
||||||
|
exec ${cfg.package}/bin/certspotter ${lib.escapeShellArgs cfg.extraFlags}
|
||||||
|
'';
|
||||||
|
serviceConfig = {
|
||||||
|
User = "certspotter";
|
||||||
|
Group = "certspotter";
|
||||||
|
StateDirectory = "certspotter";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
meta.maintainers = with lib.maintainers; [ chayleaf ];
|
||||||
|
meta.doc = ./certspotter.md;
|
||||||
|
}
|
39
pkgs/by-name/ce/certspotter/package.nix
Normal file
39
pkgs/by-name/ce/certspotter/package.nix
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{ lib
|
||||||
|
, fetchFromGitHub
|
||||||
|
, buildGoModule
|
||||||
|
, lowdown
|
||||||
|
}:
|
||||||
|
|
||||||
|
buildGoModule rec {
|
||||||
|
pname = "certspotter";
|
||||||
|
version = "0.17.0";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "SSLMate";
|
||||||
|
repo = "certspotter";
|
||||||
|
rev = "v${version}";
|
||||||
|
hash = "sha256-6ghS+9b8FZiYdiTk54XRHP46lOq98sN1RDYvRYTt6eU=";
|
||||||
|
};
|
||||||
|
|
||||||
|
vendorHash = "sha256-6dV9FoPV8UfS0z5RuuopE99fHcT3RAWCdDi7jpHzVRE=";
|
||||||
|
|
||||||
|
ldflags = [ "-s" "-w" ];
|
||||||
|
|
||||||
|
nativeBuildInputs = [ lowdown ];
|
||||||
|
|
||||||
|
postInstall = ''
|
||||||
|
cd man
|
||||||
|
make
|
||||||
|
mkdir -p $out/share/man/man8
|
||||||
|
mv *.8 $out/share/man/man8
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
description = "Certificate Transparency Log Monitor";
|
||||||
|
homepage = "https://github.com/SSLMate/certspotter";
|
||||||
|
changelog = "https://github.com/SSLMate/certspotter/blob/${src.rev}/CHANGELOG.md";
|
||||||
|
license = licenses.mpl20;
|
||||||
|
mainProgram = "certspotter";
|
||||||
|
maintainers = with maintainers; [ chayleaf ];
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in a new issue