From 411af8e3f754278c5b54dfef7e1bd144a6007c39 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Isma=C3=ABl=20Bouya?= Date: Tue, 4 Jun 2019 09:53:11 +0200 Subject: [PATCH] Add opendmarc openarc and opendkim configuration and packages --- modules/default.nix | 3 ++ modules/myids.nix | 4 ++ modules/openarc.nix | 90 ++++++++++++++++++++++++++++++++ modules/opendmarc.nix | 90 ++++++++++++++++++++++++++++++++ modules/private/mail.nix | 104 +++++++++++++++++++++++++++++++++++++ pkgs/default.nix | 2 + pkgs/openarc/default.nix | 18 +++++++ pkgs/openarc/openarc.json | 15 ++++++ pkgs/opendmarc/default.nix | 26 ++++++++++ pkgs/opendmarc/libspf2.nix | 35 +++++++++++++ 10 files changed, 387 insertions(+) create mode 100644 modules/openarc.nix create mode 100644 modules/opendmarc.nix create mode 100644 pkgs/openarc/default.nix create mode 100644 pkgs/openarc/openarc.json create mode 100644 pkgs/opendmarc/default.nix create mode 100644 pkgs/opendmarc/libspf2.nix diff --git a/modules/default.nix b/modules/default.nix index dd34870..5346956 100644 --- a/modules/default.nix +++ b/modules/default.nix @@ -10,6 +10,9 @@ mediagoblin = ./webapps/mediagoblin.nix; peertube = ./webapps/peertube.nix; + opendmarc = ./opendmarc.nix; + openarc = ./openarc.nix; + php-application = ./websites/php-application.nix; websites = ./websites; } // (if builtins.pathExists ./private then import ./private else {}) diff --git a/modules/myids.nix b/modules/myids.nix index 4fb2626..7ec9c0e 100644 --- a/modules/myids.nix +++ b/modules/myids.nix @@ -3,6 +3,8 @@ # Check that there is no clash with nixos/modules/misc/ids.nix config = { ids.uids = { + opendarc = 391; + opendmarc = 392; peertube = 394; redis = 395; nullmailer = 396; @@ -11,6 +13,8 @@ mastodon = 399; }; ids.gids = { + opendarc = 392; + opendmarc = 392; peertube = 394; redis = 395; nullmailer = 396; diff --git a/modules/openarc.nix b/modules/openarc.nix new file mode 100644 index 0000000..9dc49de --- /dev/null +++ b/modules/openarc.nix @@ -0,0 +1,90 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.openarc; + + defaultSock = "local:/run/openarc/openarc.sock"; + + args = [ "-f" + "-p" cfg.socket + ] ++ optionals (cfg.configFile != null) [ "-c" cfg.configFile ]; + +in { + + ###### interface + + options = { + + services.openarc = { + + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable the OpenARC sender authentication system."; + }; + + socket = mkOption { + type = types.str; + default = defaultSock; + description = "Socket which is used for communication with OpenARC."; + }; + + user = mkOption { + type = types.str; + default = "opendmarc"; + description = "User for the daemon."; + }; + + group = mkOption { + type = types.str; + default = "opendmarc"; + description = "Group for the daemon."; + }; + + configFile = mkOption { + type = types.nullOr types.path; + default = null; + description = "Additional OpenARC configuration."; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + users.users = optionalAttrs (cfg.user == "openarc") (singleton + { name = "openarc"; + group = cfg.group; + uid = config.ids.uids.openarc; + }); + + users.groups = optionalAttrs (cfg.group == "openarc") (singleton + { name = "openarc"; + gid = config.ids.gids.openarc; + }); + + environment.systemPackages = [ pkgs.openarc ]; + + systemd.services.openarc = { + description = "OpenARC daemon"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + ExecStart = "${pkgs.openarc}/bin/openarc ${escapeShellArgs args}"; + User = cfg.user; + Group = cfg.group; + RuntimeDirectory = optional (cfg.socket == defaultSock) "openarc"; + PermissionsStartOnly = true; + }; + }; + + }; +} diff --git a/modules/opendmarc.nix b/modules/opendmarc.nix new file mode 100644 index 0000000..e18ec82 --- /dev/null +++ b/modules/opendmarc.nix @@ -0,0 +1,90 @@ +{ config, lib, pkgs, ... }: + +with lib; + +let + + cfg = config.services.opendmarc; + + defaultSock = "local:/run/opendmarc/opendmarc.sock"; + + args = [ "-f" "-l" + "-p" cfg.socket + ] ++ optionals (cfg.configFile != null) [ "-c" cfg.configFile ]; + +in { + + ###### interface + + options = { + + services.opendmarc = { + + enable = mkOption { + type = types.bool; + default = false; + description = "Whether to enable the OpenDMARC sender authentication system."; + }; + + socket = mkOption { + type = types.str; + default = defaultSock; + description = "Socket which is used for communication with OpenDMARC."; + }; + + user = mkOption { + type = types.str; + default = "opendmarc"; + description = "User for the daemon."; + }; + + group = mkOption { + type = types.str; + default = "opendmarc"; + description = "Group for the daemon."; + }; + + configFile = mkOption { + type = types.nullOr types.path; + default = null; + description = "Additional OpenDMARC configuration."; + }; + + }; + + }; + + + ###### implementation + + config = mkIf cfg.enable { + + users.users = optionalAttrs (cfg.user == "opendmarc") (singleton + { name = "opendmarc"; + group = cfg.group; + uid = config.ids.uids.opendmarc; + }); + + users.groups = optionalAttrs (cfg.group == "opendmarc") (singleton + { name = "opendmarc"; + gid = config.ids.gids.opendmarc; + }); + + environment.systemPackages = [ pkgs.opendmarc ]; + + systemd.services.opendmarc = { + description = "OpenDMARC daemon"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + serviceConfig = { + ExecStart = "${pkgs.opendmarc}/bin/opendmarc ${escapeShellArgs args}"; + User = cfg.user; + Group = cfg.group; + RuntimeDirectory = optional (cfg.socket == defaultSock) "opendmarc"; + PermissionsStartOnly = true; + }; + }; + + }; +} diff --git a/modules/private/mail.nix b/modules/private/mail.nix index 611c8b4..eb869ba 100644 --- a/modules/private/mail.nix +++ b/modules/private/mail.nix @@ -10,4 +10,108 @@ remotes = "${myconfig.env.mail.relay} smtp"; }; }; + + config.secrets.keys = [ + { + dest = "opendkim/eldiron.private"; + user = config.services.opendkim.user; + group = config.services.opendkim.group; + permissions = "0400"; + text = myconfig.env.mail.dkim.eldiron.private; + } + { + dest = "opendkim/eldiron.txt"; + user = config.services.opendkim.user; + group = config.services.opendkim.group; + permissions = "0444"; + text = '' + eldiron._domainkey IN TXT ${myconfig.env.mail.dkim.eldiron.public}''; + } + { + dest = "opendmarc/ignore.hosts"; + user = config.services.opendmarc.user; + group = config.services.opendmarc.group; + permissions = "0400"; + text = myconfig.env.mail.dmarc.ignore_hosts; + } + ]; + config.users.users."${config.services.opendkim.user}".extraGroups = [ "keys" ]; + config.services.opendkim = { + enable = true; + domains = builtins.concatStringsSep "," (lib.flatten (map + (zone: map + (e: "${e.domain}${lib.optionalString (e.domain != "") "."}${zone.name}") + (zone.withEmail or []) + ) + myconfig.env.dns.masterZones + )); + keyPath = "${config.secrets.location}/opendkim"; + selector = "eldiron"; + configFile = pkgs.writeText "opendkim.conf" '' + SubDomains yes + UMask 002 + ''; + }; + config.systemd.services.opendkim.preStart = lib.mkBefore '' + # Skip the prestart script as keys are handled in secrets + exit 0 + ''; + config.services.filesWatcher.opendkim = { + restart = true; + paths = [ + config.secrets.fullPaths."opendkim/eldiron.private" + ]; + }; + + config.users.users."${config.services.opendmarc.user}".extraGroups = [ "keys" ]; + config.services.opendmarc = { + enable = true; + configFile = pkgs.writeText "opendmarc.conf" '' + AuthservID HOSTNAME + FailureReports false + FailureReportsBcc postmaster@localhost.immae.eu + FailureReportsOnNone true + FailureReportsSentBy postmaster@immae.eu + IgnoreAuthenticatedClients true + IgnoreHosts ${config.secrets.fullPaths."opendmarc/ignore.hosts"} + SoftwareHeader true + SPFSelfValidate true + TrustedAuthservIDs HOSTNAME, immae.eu, nef2.ens.fr + UMask 002 + ''; + }; + config.services.filesWatcher.opendmarc = { + restart = true; + paths = [ + config.secrets.fullPaths."opendmarc/ignore.hosts" + ]; + }; + + config.services.openarc = { + enable = true; + user = "opendkim"; + group = "opendkim"; + configFile = pkgs.writeText "openarc.conf" '' + AuthservID mail.immae.eu + Domain mail.immae.eu + KeyFile ${config.secrets.fullPaths."opendkim/eldiron.private"} + Mode sv + Selector eldiron + SoftwareHeader yes + Syslog Yes + ''; + }; + config.systemd.services.openarc.postStart = lib.optionalString + (lib.strings.hasPrefix "local:" config.services.openarc.socket) '' + while [ ! -S ${lib.strings.removePrefix "local:" config.services.openarc.socket} ]; do + sleep 0.5 + done + chmod g+w ${lib.strings.removePrefix "local:" config.services.openarc.socket} + ''; + config.services.filesWatcher.openarc = { + restart = true; + paths = [ + config.secrets.fullPaths."opendkim/eldiron.private" + ]; + }; } diff --git a/pkgs/default.nix b/pkgs/default.nix index c91f672..74f9d18 100644 --- a/pkgs/default.nix +++ b/pkgs/default.nix @@ -18,6 +18,8 @@ rec { notmuch-python2 = callPackage ../pkgs/notmuch/notmuch-python { pythonPackages = python2Packages; }; notmuch-python3 = callPackage ../pkgs/notmuch/notmuch-python { pythonPackages = python3Packages; }; notmuch-vim = callPackage ../pkgs/notmuch/notmuch-vim {}; + openarc = callPackage ../pkgs/openarc { inherit mylibs; }; + opendmarc = callPackage ../pkgs/opendmarc { libspf2 = callPackage ../pkgs/opendmarc/libspf2.nix {}; }; pg_activity = callPackage ../pkgs/pg_activity { inherit mylibs; }; pgloader = callPackage ../pkgs/pgloader {}; telegram-cli = callPackage ../pkgs/telegram-cli { inherit mylibs; }; diff --git a/pkgs/openarc/default.nix b/pkgs/openarc/default.nix new file mode 100644 index 0000000..e5c9a81 --- /dev/null +++ b/pkgs/openarc/default.nix @@ -0,0 +1,18 @@ +{ stdenv, autoconf, automake, file, libtool, libbsd, mylibs, openssl, pkg-config, libmilter }: + +stdenv.mkDerivation (mylibs.fetchedGithub ./openarc.json // rec { + buildInputs = [ automake autoconf libbsd libtool openssl pkg-config libmilter ]; + + configureFlags = [ + "--with-milter=${libmilter}" + ]; + preConfigure = '' + autoreconf --force --install + sed -i -e "s@/usr/bin/file@${file}/bin/file@" ./configure + ''; + meta = with stdenv.lib; { + description = "Open source ARC implementation"; + homepage = https://github.com/trusteddomainproject/OpenARC; + platforms = platforms.unix; + }; +}) diff --git a/pkgs/openarc/openarc.json b/pkgs/openarc/openarc.json new file mode 100644 index 0000000..1081b09 --- /dev/null +++ b/pkgs/openarc/openarc.json @@ -0,0 +1,15 @@ +{ + "tag": "355ee2a-master", + "meta": { + "name": "openarc", + "url": "https://github.com/trusteddomainproject/OpenARC", + "branch": "master" + }, + "github": { + "owner": "trusteddomainproject", + "repo": "OpenARC", + "rev": "355ee2a1ca85acccce494478991983b54f794f4e", + "sha256": "0101k6hwwf3pb3jrc88x86d4l698gjmynn9v2rpvxwxv200r2i65", + "fetchSubmodules": true + } +} diff --git a/pkgs/opendmarc/default.nix b/pkgs/opendmarc/default.nix new file mode 100644 index 0000000..1c50248 --- /dev/null +++ b/pkgs/opendmarc/default.nix @@ -0,0 +1,26 @@ +{ stdenv, fetchurl, pkgconfig, libbsd, openssl, libmilter , perl, makeWrapper, libspf2 }: + +stdenv.mkDerivation rec { + name = "opendmarc-${version}"; + version = "1.3.2"; + + src = fetchurl { + url = "mirror://sourceforge/opendmarc/files/${name}.tar.gz"; + sha256 = "1yrggj8yq0915y2i34gfz2xpl1w2lgb1vggp67rwspgzm40lng11"; + }; + + configureFlags= [ + "--with-spf" + "--with-spf2-include=${libspf2}/include/spf2" + "--with-spf2-lib=${libspf2}/lib/" + "--with-milter=${libmilter}" + ]; + + buildInputs = [ libspf2 libbsd openssl libmilter perl ]; + + meta = with stdenv.lib; { + description = "Free open source software implementation of the DMARC specification"; + homepage = http://www.trusteddomain.org/opendmarc/; + platforms = platforms.unix; + }; +} diff --git a/pkgs/opendmarc/libspf2.nix b/pkgs/opendmarc/libspf2.nix new file mode 100644 index 0000000..ca02d59 --- /dev/null +++ b/pkgs/opendmarc/libspf2.nix @@ -0,0 +1,35 @@ +{ stdenv, file, fetchurl, fetchpatch, libnsl }: + +stdenv.mkDerivation rec { + name = "libspf2-${version}"; + version = "1.2.10"; + + patches = [ + (fetchpatch { + name = "fix-variadic-macros.patch"; + url = "https://git.archlinux.org/svntogit/community.git/plain/trunk/fix-variadic-macros.patch?h=packages/libspf2"; + sha256 = "00dqpcgjr9jy2qprgqv2qiyvq8y3wlz4yns9xzabf2064jzqh2ic"; + }) + ]; + preConfigure = '' + sed -i -e "s@/usr/bin/file@${file}/bin/file@" ./configure + ''; + configureFlags = [ + "--enable-static" + ]; + postInstall = '' + rm $out/bin/*_static + ''; + src = fetchurl { + url = "https://www.libspf2.org/spf/${name}.tar.gz"; + sha256 = "1j91p0qiipzf89qxq4m1wqhdf01hpn1h5xj4djbs51z23bl3s7nr"; + }; + + buildInputs = [ libnsl ]; + + meta = with stdenv.lib; { + description = "Sender Policy Framework record checking library"; + homepage = https://www.libspf2.org/; + platforms = platforms.unix; + }; +} -- 2.41.0