summary refs log tree commit diff
path: root/nixos
diff options
context:
space:
mode:
authorBrian Olsen <brian@maven-group.org>2018-11-01 23:55:44 +0100
committerBrian Olsen <brian@maven-group.org>2018-11-02 01:46:57 +0100
commit0810d631a489fcd819eafc530c45e768570ace8d (patch)
tree906f74dc13ef7837e1d94b9dc5cb737e80f36d27 /nixos
parent89ede978a0614fd7215e0aa2c483df142cc79af9 (diff)
downloadnixlib-0810d631a489fcd819eafc530c45e768570ace8d.tar
nixlib-0810d631a489fcd819eafc530c45e768570ace8d.tar.gz
nixlib-0810d631a489fcd819eafc530c45e768570ace8d.tar.bz2
nixlib-0810d631a489fcd819eafc530c45e768570ace8d.tar.lz
nixlib-0810d631a489fcd819eafc530c45e768570ace8d.tar.xz
nixlib-0810d631a489fcd819eafc530c45e768570ace8d.tar.zst
nixlib-0810d631a489fcd819eafc530c45e768570ace8d.zip
nixos/rspamd: Add support for included files
By default rspamd will look for multiple files in /etc/rspamd/local.d
and /etc/rspamd/override.d to be included in subsections of the merged
final config for rspamd. Most of the config snippets in the official
rspamd documentation are made to these files and so it makes sense for
NixOS to support them and this is what this commit does.

As part of rspamd 1.8.1 support was added for having custom Lua
rules stored in $LOCAL_CONFDIR/rspamd.local.lua which means that it is
now possible for NixOS to support such rules and so this commit also
adds support for this to the rspamd module.
Diffstat (limited to 'nixos')
-rw-r--r--nixos/modules/services/mail/rspamd.nix79
-rw-r--r--nixos/tests/rspamd.nix77
2 files changed, 151 insertions, 5 deletions
diff --git a/nixos/modules/services/mail/rspamd.nix b/nixos/modules/services/mail/rspamd.nix
index ff01a5dee53d..d83d6f1f750c 100644
--- a/nixos/modules/services/mail/rspamd.nix
+++ b/nixos/modules/services/mail/rspamd.nix
@@ -127,11 +127,15 @@ let
       options {
         pidfile = "$RUNDIR/rspamd.pid";
         .include "$CONFDIR/options.inc"
+        .include(try=true; priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/options.inc"
+        .include(try=true; priority=10) "$LOCAL_CONFDIR/override.d/options.inc"
       }
 
       logging {
         type = "syslog";
         .include "$CONFDIR/logging.inc"
+        .include(try=true; priority=1,duplicate=merge) "$LOCAL_CONFDIR/local.d/logging.inc"
+        .include(try=true; priority=10) "$LOCAL_CONFDIR/override.d/logging.inc"
       }
 
       ${concatStringsSep "\n" (mapAttrsToList (name: value: ''
@@ -149,6 +153,41 @@ let
       ${cfg.extraConfig}
    '';
 
+  rspamdDir = pkgs.linkFarm "etc-rspamd-dir" (
+    (mapAttrsToList (name: file: { name = "local.d/${name}"; path = file.source; }) cfg.locals) ++
+    (mapAttrsToList (name: file: { name = "override.d/${name}"; path = file.source; }) cfg.overrides) ++
+    (optional (cfg.localLuaRules != null) { name = "rspamd.local.lua"; path = cfg.localLuaRules; }) ++
+    [ { name = "rspamd.conf"; path = rspamdConfFile; } ]
+  );
+
+  configFileModule = prefix: { name, config, ... }: {
+    options = {
+      enable = mkOption {
+        type = types.bool;
+        default = true;
+        description = ''
+          Whether this file ${prefix} should be generated.  This
+          option allows specific ${prefix} files to be disabled.
+        '';
+      };
+
+      text = mkOption {
+        default = null;
+        type = types.nullOr types.lines;
+        description = "Text of the file.";
+      };
+
+      source = mkOption {
+        type = types.path;
+        description = "Path of the source file.";
+      };
+    };
+    config = {
+      source = mkIf (config.text != null) (
+        let name' = "rspamd-${prefix}-" + baseNameOf name;
+        in mkDefault (pkgs.writeText name' config.text));
+    };
+  };
 in
 
 {
@@ -167,6 +206,41 @@ in
         description = "Whether to run the rspamd daemon in debug mode.";
       };
 
+      locals = mkOption {
+        type = with types; loaOf (submodule (configFileModule "locals"));
+        default = {};
+        description = ''
+          Local configuration files, written into <filename>/etc/rspamd/local.d/{name}</filename>.
+        '';
+        example = literalExample ''
+          { "redis.conf".source = "/nix/store/.../etc/dir/redis.conf";
+            "arc.conf".text = "allow_envfrom_empty = true;";
+          }
+        '';
+      };
+
+      overrides = mkOption {
+        type = with types; loaOf (submodule (configFileModule "overrides"));
+        default = {};
+        description = ''
+          Overridden configuration files, written into <filename>/etc/rspamd/override.d/{name}</filename>.
+        '';
+        example = literalExample ''
+          { "redis.conf".source = "/nix/store/.../etc/dir/redis.conf";
+            "arc.conf".text = "allow_envfrom_empty = true;";
+          }
+        '';
+      };
+
+      localLuaRules = mkOption {
+        default = null;
+        type = types.nullOr types.path;
+        description = ''
+          Path of file to link to <filename>/etc/rspamd/rspamd.local.lua</filename> for local
+          rules written in Lua
+        '';
+      };
+
       workers = mkOption {
         type = with types; attrsOf (submodule workerOpts);
         description = ''
@@ -242,16 +316,17 @@ in
       gid = config.ids.gids.rspamd;
     };
 
-    environment.etc."rspamd.conf".source = rspamdConfFile;
+    environment.etc."rspamd".source = rspamdDir;
 
     systemd.services.rspamd = {
       description = "Rspamd Service";
 
       wantedBy = [ "multi-user.target" ];
       after = [ "network.target" ];
+      restartTriggers = [ rspamdDir ];
 
       serviceConfig = {
-        ExecStart = "${pkgs.rspamd}/bin/rspamd ${optionalString cfg.debug "-d"} --user=${cfg.user} --group=${cfg.group} --pid=/run/rspamd.pid -c ${rspamdConfFile} -f";
+        ExecStart = "${pkgs.rspamd}/bin/rspamd ${optionalString cfg.debug "-d"} --user=${cfg.user} --group=${cfg.group} --pid=/run/rspamd.pid -c /etc/rspamd/rspamd.conf -f";
         Restart = "always";
         RuntimeDirectory = "rspamd";
         PrivateTmp = true;
diff --git a/nixos/tests/rspamd.nix b/nixos/tests/rspamd.nix
index a12622b6aa0b..af765f37b91b 100644
--- a/nixos/tests/rspamd.nix
+++ b/nixos/tests/rspamd.nix
@@ -27,7 +27,7 @@ let
       $machine->succeed("id \"rspamd\" >/dev/null");
       ${checkSocket "/run/rspamd/rspamd.sock" "rspamd" "rspamd" "660" }
       sleep 10;
-      $machine->log($machine->succeed("cat /etc/rspamd.conf"));
+      $machine->log($machine->succeed("cat /etc/rspamd/rspamd.conf"));
       $machine->log($machine->succeed("systemctl cat rspamd.service"));
       $machine->log($machine->succeed("curl http://localhost:11334/auth"));
       $machine->log($machine->succeed("curl http://127.0.0.1:11334/auth"));
@@ -55,7 +55,7 @@ in
       $machine->waitForFile("/run/rspamd.sock");
       ${checkSocket "/run/rspamd.sock" "root" "root" "600" }
       ${checkSocket "/run/rspamd-worker.sock" "root" "root" "666" }
-      $machine->log($machine->succeed("cat /etc/rspamd.conf"));
+      $machine->log($machine->succeed("cat /etc/rspamd/rspamd.conf"));
       $machine->log($machine->succeed("rspamc -h /run/rspamd-worker.sock stat"));
       $machine->log($machine->succeed("curl --unix-socket /run/rspamd-worker.sock http://localhost/ping"));
     '';
@@ -86,9 +86,80 @@ in
       $machine->waitForFile("/run/rspamd.sock");
       ${checkSocket "/run/rspamd.sock" "root" "root" "600" }
       ${checkSocket "/run/rspamd-worker.sock" "root" "root" "666" }
-      $machine->log($machine->succeed("cat /etc/rspamd.conf"));
+      $machine->log($machine->succeed("cat /etc/rspamd/rspamd.conf"));
       $machine->log($machine->succeed("rspamc -h /run/rspamd-worker.sock stat"));
       $machine->log($machine->succeed("curl --unix-socket /run/rspamd-worker.sock http://localhost/ping"));
     '';
   };
+  customLuaRules = makeTest {
+    name = "rspamd-custom-lua-rules";
+    machine = {
+      environment.etc."tests/no-muh.eml".text = ''
+        From: Sheep1<bah@example.com>
+        To: Sheep2<mah@example.com>
+        Subject: Evil cows
+
+        I find cows to be evil don't you?
+      '';
+      environment.etc."tests/muh.eml".text = ''
+        From: Cow<cow@example.com>
+        To: Sheep2<mah@example.com>
+        Subject: Evil cows
+
+        Cows are majestic creatures don't Muh agree?
+      '';
+      services.rspamd = {
+        enable = true;
+        locals."groups.conf".text = ''
+          group "cows" {
+            symbol {
+              NO_MUH = {
+                weight = 1.0;
+                description = "Mails should not muh";
+              }
+            }
+          }
+        '';
+        localLuaRules = pkgs.writeText "rspamd.local.lua" ''
+          local rspamd_logger = require "rspamd_logger"
+          rspamd_config.NO_MUH = {
+            callback = function (task)
+              local parts = task:get_text_parts()
+              if parts then
+                for _,part in ipairs(parts) do
+                  local content = tostring(part:get_content())
+                  rspamd_logger.infox(rspamd_config, 'Found content %s', content)
+                  local found = string.find(content, "Muh");
+                  rspamd_logger.infox(rspamd_config, 'Found muh %s', tostring(found))
+                  if found then
+                    return true
+                  end
+                end
+              end
+              return false
+            end,
+            score = 5.0,
+	          description = 'Allow no cows',
+            group = "cows",
+          }
+          rspamd_logger.infox(rspamd_config, 'Work dammit!!!')
+        '';
+      };
+    };
+    testScript = ''
+      ${initMachine}
+      $machine->waitForOpenPort(11334);
+      $machine->log($machine->succeed("cat /etc/rspamd/rspamd.conf"));
+      $machine->log($machine->succeed("cat /etc/rspamd/rspamd.local.lua"));
+      $machine->log($machine->succeed("cat /etc/rspamd/local.d/groups.conf"));
+      ${checkSocket "/run/rspamd/rspamd.sock" "rspamd" "rspamd" "660" }
+      $machine->log($machine->succeed("curl --unix-socket /run/rspamd/rspamd.sock http://localhost/ping"));
+      $machine->log($machine->succeed("rspamc -h 127.0.0.1:11334 stat"));
+      $machine->log($machine->succeed("cat /etc/tests/no-muh.eml | rspamc -h 127.0.0.1:11334"));
+      $machine->log($machine->succeed("cat /etc/tests/muh.eml | rspamc -h 127.0.0.1:11334 symbols"));
+      $machine->waitUntilSucceeds("journalctl -u rspamd | grep -i muh >&2");
+      $machine->log($machine->fail("cat /etc/tests/no-muh.eml | rspamc -h 127.0.0.1:11334 symbols | grep NO_MUH"));
+      $machine->log($machine->succeed("cat /etc/tests/muh.eml | rspamc -h 127.0.0.1:11334 symbols | grep NO_MUH"));
+    '';
+  };
 }