Unverified Commit 01d0b0b6 authored by Martin Weinelt's avatar Martin Weinelt
Browse files

nixos/logrotate: harden systemd unit

Logrotate is a service that runs as root and moves logfiles around while
keeping ownership of these files intact. This means we can and should
severely limit the scope of what can be done during its runtime.
parent 8588b159
Loading
Loading
Loading
Loading
+48 −3
Original line number Diff line number Diff line
@@ -97,6 +97,8 @@ in
        defaultText = lib.literalExpression "cfg.settings != {}";
      };

      allowNetworking = lib.mkEnableOption "network access for logrotate";

      settings = lib.mkOption {
        default = { };
        description = ''
@@ -240,12 +242,55 @@ in
  config = lib.mkIf cfg.enable {
    systemd.services.logrotate = {
      description = "Logrotate Service";
      documentation = [
        "man:logrotate(8)"
        "man:logrotate(5)"
      ];
      startAt = "hourly";

      serviceConfig = {
        Restart = "no";
        User = "root";
        ExecStart = "${pkgs.logrotate}/sbin/logrotate ${utils.escapeSystemdExecArgs cfg.extraArgs} ${mailOption} ${cfg.configFile}";
        Type = "oneshot";
        ExecStart = "${lib.getExe pkgs.logrotate} ${utils.escapeSystemdExecArgs cfg.extraArgs} ${mailOption} ${cfg.configFile}";

        # performance
        Nice = 19;
        IOSchedulingClass = "best-effort";
        IOSchedulingPriority = 7;

        # hardening
        CapabilityBoundingSet = [
          "CAP_CHOWN"
          "CAP_SETGID"
        ];
        DevicePolicy = "closed";
        LockPersonality = true;
        MemoryDenyWriteExecute = true;
        NoNewPrivileges = true;
        PrivateDevices = true;
        PrivateTmp = true;
        ProcSubset = "pid";
        ProtectClock = true;
        ProtectControlGroups = true;
        ProtectHome = true;
        ProtectHostname = true;
        ProtectKernelLogs = true;
        ProtectKernelModules = true;
        ProtectKernelTunables = true;
        ProtectProc = "invisible";
        ProtectSystem = "full";
        RestrictNamespaces = true;
        RestrictRealtime = true;
        RestrictSUIDSGID = true;
        SystemCallArchitectures = "native";
        SystemCallFilter = [
          "@system-service"
          "~@privileged @resources"
          "@chown"
        ];
        UMask = "0027";
      } // lib.optionalAttrs (!cfg.allowNetworking) {
        PrivateNetwork = true;
        RestrictAddressFamilies = "none";
      };
    };
    systemd.services.logrotate-checkconf = {
+2 −0
Original line number Diff line number Diff line
@@ -127,5 +127,7 @@ import ./make-test-python.nix ({ pkgs, ... }: rec {
          if info["ActiveState"] != "failed":
              raise Exception('logrotate-checkconf.service was not failed')

      machine.log(machine.execute("systemd-analyze security logrotate.service | grep -v ✓")[1])

    '';
})