diff --git a/nixos/modules/services/networking/suricata/default.nix b/nixos/modules/services/networking/suricata/default.nix index a1aee42b26f6..c6f6b3f369eb 100644 --- a/nixos/modules/services/networking/suricata/default.nix +++ b/nixos/modules/services/networking/suricata/default.nix @@ -152,6 +152,14 @@ in List of rules that should be disabled. ''; }; + reloadOnRulesetUpdate = mkOption { + type = types.bool; + default = false; + description = '' + Whether to reload Suricata if it is running after an automated ruleset update. + This is a blocking reload, and may take some time depending on the number of rules and computational power of the host. + ''; + }; }; config = @@ -213,11 +221,20 @@ in }; systemd.services = { + suricata-blocking-reload = lib.mkIf cfg.reloadOnRulesetUpdate { + description = "Refresh Runtime Suricata Ruleset"; + serviceConfig = { + Type = "oneshot"; + ExecCondition = "systemctl is-active --quiet suricata.service"; + ExecStart = "${pkg}/bin/suricatasc -c reload-rules"; + }; + }; suricata-update = { description = "Update Suricata Rules"; wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" ]; after = [ "network-online.target" ]; + onSuccess = lib.mkIf cfg.reloadOnRulesetUpdate [ "suricata-blocking-reload.service" ]; script = let diff --git a/nixos/tests/suricata.nix b/nixos/tests/suricata.nix index c79d0799551b..8353d5547d56 100644 --- a/nixos/tests/suricata.nix +++ b/nixos/tests/suricata.nix @@ -23,6 +23,7 @@ services.suricata = { enable = true; + reloadOnRulesetUpdate = true; settings = { vars.address-groups.HOME_NET = "192.168.1.0/24"; unix-command.enabled = true; @@ -66,7 +67,7 @@ # check that configuration has been applied correctly with suricatasc with subtest("suricata configuration test"): ids.wait_for_unit("suricata.service") - assert '1' in ids.succeed("suricatasc -c 'iface-list' | ${pkgs.jq}/bin/jq .message.count") + assert '1' in ids.wait_until_succeeds("suricatasc -c 'iface-list' | ${pkgs.jq}/bin/jq .message.count", 5) # test detection of events based on a static ruleset (output of id command) with subtest("suricata rule test"): @@ -75,5 +76,9 @@ ids.succeed("curl http://192.168.1.1/id/") assert "id check returned root [**] [Classification: Potentially Bad Traffic]" in ids.succeed("tail -n 1 /var/log/suricata/fast.log"), "Suricata didn't detect the output of id comment" + + with subtest("suricata blocking reload test"): + ids.wait_for_unit("suricata.service") + assert ids.systemctl("start suricata-blocking-reload.service")[0] == 0 ''; }