Loading nixos/modules/services/security/paretosecurity.nix +17 −28 Original line number Diff line number Diff line Loading @@ -14,38 +14,27 @@ config = lib.mkIf config.services.paretosecurity.enable { environment.systemPackages = [ config.services.paretosecurity.package ]; systemd.packages = [ config.services.paretosecurity.package ]; systemd.sockets."paretosecurity" = { wantedBy = [ "sockets.target" ]; socketConfig = { ListenStream = "/var/run/paretosecurity.sock"; SocketMode = "0666"; }; }; # In traditional Linux distributions, systemd would read the [Install] section from # unit files and automatically create the appropriate symlinks to enable services. # However, in NixOS, due to its immutable nature and the way the Nix store works, # the [Install] sections are not processed during system activation. Instead, we # must explicitly tell NixOS which units to enable by specifying their target # dependencies here. This creates the necessary symlinks in the proper locations. systemd.sockets.paretosecurity.wantedBy = [ "sockets.target" ]; systemd.services."paretosecurity" = { serviceConfig = { ExecStart = "${config.services.paretosecurity.package}/bin/paretosecurity helper"; User = "root"; Group = "root"; StandardInput = "socket"; Type = "oneshot"; RemainAfterExit = "no"; StartLimitInterval = "1s"; StartLimitBurst = 100; ProtectSystem = "full"; ProtectHome = true; StandardOutput = "journal"; StandardError = "journal"; }; # Enable the tray icon and timer services if the trayIcon option is enabled systemd.user = lib.mkIf config.services.paretosecurity.trayIcon { services.paretosecurity-trayicon = { wantedBy = [ "graphical-session.target" ]; }; systemd.user.services."paretosecurity-trayicon" = lib.mkIf config.services.paretosecurity.trayIcon { services.paretosecurity-user = { wantedBy = [ "graphical-session.target" ]; serviceConfig = { ExecStart = "${config.services.paretosecurity.package}/bin/paretosecurity trayicon"; }; timers.paretosecurity-user = { wantedBy = [ "timers.target" ]; }; }; }; } nixos/tests/paretosecurity.nix +68 −3 Original line number Diff line number Diff line Loading @@ -4,11 +4,47 @@ meta.maintainers = [ lib.maintainers.zupo ]; nodes.terminal = { config, pkgs, ... }: { config, pkgs, lib, ... }: let # Create a patched version of the package that points to the local dashboard # for easier testing patchedPareto = pkgs.paretosecurity.overrideAttrs (oldAttrs: { postPatch = '' substituteInPlace team/report.go \ --replace-warn 'const reportURL = "https://dash.paretosecurity.com"' \ 'const reportURL = "http://dashboard"' ''; }); in { imports = [ ./common/user-account.nix ]; services.paretosecurity.enable = true; services.paretosecurity = { enable = true; package = patchedPareto; }; }; nodes.dashboard = { config, pkgs, ... }: { networking.firewall.allowedTCPPorts = [ 80 ]; services.nginx = { enable = true; virtualHosts."dashboard" = { locations."/api/v1/team/".extraConfig = '' add_header Content-Type application/json; return 200 '{"message": "Linked device."}'; ''; }; }; }; nodes.xfce = Loading Loading @@ -38,8 +74,18 @@ enableOCR = true; testScript = '' # Test setup terminal.succeed("su - alice -c 'mkdir -p /home/alice/.config'") for m in [terminal, dashboard]: m.systemctl("start network-online.target") m.wait_for_unit("network-online.target") # Test 1: Test the systemd socket is installed & enabled terminal.succeed('systemctl is-enabled paretosecurity.socket') # Test 2: Test running checks terminal.succeed( "su -- alice -c 'paretosecurity check" "su - alice -c 'paretosecurity check" # Disable some checks that need intricate test setup so that this test # remains simple and fast. Tests for all checks and edge cases available # at https://github.com/ParetoSecurity/agent/tree/main/test/integration Loading @@ -48,10 +94,29 @@ + " --skip 21830a4e-84f1-48fe-9c5b-beab436b2cdb" # Disk encryption + " --skip 44e4754a-0b42-4964-9cc2-b88b2023cb1e" # Pareto Security is up to date + " --skip f962c423-fdf5-428a-a57a-827abc9b253e" # Password manager installed + " --skip 2e46c89a-5461-4865-a92e-3b799c12034a" # Firewall is enabled + "'" ) # Test 3: Test linking terminal.succeed("su - alice -c 'paretosecurity link" + " paretosecurity://enrollTeam/?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." + "eyJ0b2tlbiI6ImR1bW15LXRva2VuIiwidGVhbUlEIjoiZHVtbXktdGVhbS1pZCIsImlhdCI6" + "MTcwMDAwMDAwMCwiZXhwIjoxOTAwMDAwMDAwfQ.WgnL6_S0EBJHwF1wEVUG8GtIcoVvK5IjWbZpUeZr4Qw'") config = terminal.succeed("cat /home/alice/.config/pareto.toml") assert 'AuthToken = "dummy-token"' in config assert 'TeamID = "dummy-team-id"' in config # Test 4: Test the tray icon xfce.wait_for_x() for unit in [ 'paretosecurity-trayicon', 'paretosecurity-user', 'paretosecurity-user.timer' ]: status, out = xfce.systemctl("is-enabled " + unit, "alice") assert status == 0, f"Unit {unit} is not enabled (status: {status}): {out}" xfce.succeed("xdotool mousemove 850 10") xfce.wait_for_text("Pareto Security") xfce.succeed("xdotool click 1") Loading pkgs/by-name/pa/paretosecurity/package.nix +23 −9 Original line number Diff line number Diff line Loading @@ -9,22 +9,18 @@ buildGoModule rec { pname = "paretosecurity"; version = "0.0.91"; version = "0.0.96"; src = fetchFromGitHub { owner = "ParetoSecurity"; repo = "agent"; rev = version; hash = "sha256-/kGwV96Jp7U08jh/wPQMcoV48zQe9ixY7gpNdtFyOkk="; hash = "sha256-SyeIGSDvrnOvyOJ0zC8CulpaMa+iZeRaMTJUSydz2tw="; }; vendorHash = "sha256-kGrYoN0dGcSuQW47Y4LUFdHQYAoY74NOM1LLPdhmLhc="; vendorHash = "sha256-O/OF3Y6HiiikMxf657k9eIM7UfkicIImAUxVVf/TgR8="; proxyVendor = true; subPackages = [ "cmd/paretosecurity" ]; ldflags = [ "-s" "-X=github.com/ParetoSecurity/agent/shared.Version=${version}" Loading @@ -32,6 +28,23 @@ buildGoModule rec { "-X=github.com/ParetoSecurity/agent/shared.Date=1970-01-01T00:00:00Z" ]; postInstall = '' # Install global systemd files install -Dm400 ${src}/apt/paretosecurity.socket $out/lib/systemd/system/paretosecurity.socket install -Dm400 ${src}/apt/paretosecurity.service $out/lib/systemd/system/paretosecurity.service substituteInPlace $out/lib/systemd/system/paretosecurity.service \ --replace-fail "/usr/bin/paretosecurity" "$out/bin/paretosecurity" # Install user systemd files install -Dm444 ${src}/apt/paretosecurity-user.timer $out/lib/systemd/user/paretosecurity-user.timer install -Dm444 ${src}/apt/paretosecurity-user.service $out/lib/systemd/user/paretosecurity-user.service substituteInPlace $out/lib/systemd/user/paretosecurity-user.service \ --replace-fail "/usr/bin/paretosecurity" "$out/bin/paretosecurity" install -Dm444 ${src}/apt/paretosecurity-trayicon.service $out/lib/systemd/user/paretosecurity-trayicon.service substituteInPlace $out/lib/systemd/user/paretosecurity-trayicon.service \ --replace-fail "/usr/bin/paretosecurity" "$out/bin/paretosecurity" ''; passthru.tests = { version = testers.testVersion { version = "${version}"; Loading @@ -50,12 +63,13 @@ buildGoModule rec { settings such as if you have disk encryption and firewall enabled. If you use the `services.paretosecurity` NixOS module, you also get a root helper, so that you can run the checker in userspace. Some checks root helper that allows you to run the checker in userspace. Some checks require root permissions, and the checker asks the helper to run those. Additionally, if you enable `services.paretosecurity.trayIcon`, you get a little Vilfredo Pareto living in your systray showing your the current status of checks. status of checks. This will also enable a systemd timer to update the status of checks once per hour. Finally, you can run `paretosecurity link` to configure the agent to send the status of checks to https://dash.paretosecurity.com to make Loading Loading
nixos/modules/services/security/paretosecurity.nix +17 −28 Original line number Diff line number Diff line Loading @@ -14,38 +14,27 @@ config = lib.mkIf config.services.paretosecurity.enable { environment.systemPackages = [ config.services.paretosecurity.package ]; systemd.packages = [ config.services.paretosecurity.package ]; systemd.sockets."paretosecurity" = { wantedBy = [ "sockets.target" ]; socketConfig = { ListenStream = "/var/run/paretosecurity.sock"; SocketMode = "0666"; }; }; # In traditional Linux distributions, systemd would read the [Install] section from # unit files and automatically create the appropriate symlinks to enable services. # However, in NixOS, due to its immutable nature and the way the Nix store works, # the [Install] sections are not processed during system activation. Instead, we # must explicitly tell NixOS which units to enable by specifying their target # dependencies here. This creates the necessary symlinks in the proper locations. systemd.sockets.paretosecurity.wantedBy = [ "sockets.target" ]; systemd.services."paretosecurity" = { serviceConfig = { ExecStart = "${config.services.paretosecurity.package}/bin/paretosecurity helper"; User = "root"; Group = "root"; StandardInput = "socket"; Type = "oneshot"; RemainAfterExit = "no"; StartLimitInterval = "1s"; StartLimitBurst = 100; ProtectSystem = "full"; ProtectHome = true; StandardOutput = "journal"; StandardError = "journal"; }; # Enable the tray icon and timer services if the trayIcon option is enabled systemd.user = lib.mkIf config.services.paretosecurity.trayIcon { services.paretosecurity-trayicon = { wantedBy = [ "graphical-session.target" ]; }; systemd.user.services."paretosecurity-trayicon" = lib.mkIf config.services.paretosecurity.trayIcon { services.paretosecurity-user = { wantedBy = [ "graphical-session.target" ]; serviceConfig = { ExecStart = "${config.services.paretosecurity.package}/bin/paretosecurity trayicon"; }; timers.paretosecurity-user = { wantedBy = [ "timers.target" ]; }; }; }; }
nixos/tests/paretosecurity.nix +68 −3 Original line number Diff line number Diff line Loading @@ -4,11 +4,47 @@ meta.maintainers = [ lib.maintainers.zupo ]; nodes.terminal = { config, pkgs, ... }: { config, pkgs, lib, ... }: let # Create a patched version of the package that points to the local dashboard # for easier testing patchedPareto = pkgs.paretosecurity.overrideAttrs (oldAttrs: { postPatch = '' substituteInPlace team/report.go \ --replace-warn 'const reportURL = "https://dash.paretosecurity.com"' \ 'const reportURL = "http://dashboard"' ''; }); in { imports = [ ./common/user-account.nix ]; services.paretosecurity.enable = true; services.paretosecurity = { enable = true; package = patchedPareto; }; }; nodes.dashboard = { config, pkgs, ... }: { networking.firewall.allowedTCPPorts = [ 80 ]; services.nginx = { enable = true; virtualHosts."dashboard" = { locations."/api/v1/team/".extraConfig = '' add_header Content-Type application/json; return 200 '{"message": "Linked device."}'; ''; }; }; }; nodes.xfce = Loading Loading @@ -38,8 +74,18 @@ enableOCR = true; testScript = '' # Test setup terminal.succeed("su - alice -c 'mkdir -p /home/alice/.config'") for m in [terminal, dashboard]: m.systemctl("start network-online.target") m.wait_for_unit("network-online.target") # Test 1: Test the systemd socket is installed & enabled terminal.succeed('systemctl is-enabled paretosecurity.socket') # Test 2: Test running checks terminal.succeed( "su -- alice -c 'paretosecurity check" "su - alice -c 'paretosecurity check" # Disable some checks that need intricate test setup so that this test # remains simple and fast. Tests for all checks and edge cases available # at https://github.com/ParetoSecurity/agent/tree/main/test/integration Loading @@ -48,10 +94,29 @@ + " --skip 21830a4e-84f1-48fe-9c5b-beab436b2cdb" # Disk encryption + " --skip 44e4754a-0b42-4964-9cc2-b88b2023cb1e" # Pareto Security is up to date + " --skip f962c423-fdf5-428a-a57a-827abc9b253e" # Password manager installed + " --skip 2e46c89a-5461-4865-a92e-3b799c12034a" # Firewall is enabled + "'" ) # Test 3: Test linking terminal.succeed("su - alice -c 'paretosecurity link" + " paretosecurity://enrollTeam/?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9." + "eyJ0b2tlbiI6ImR1bW15LXRva2VuIiwidGVhbUlEIjoiZHVtbXktdGVhbS1pZCIsImlhdCI6" + "MTcwMDAwMDAwMCwiZXhwIjoxOTAwMDAwMDAwfQ.WgnL6_S0EBJHwF1wEVUG8GtIcoVvK5IjWbZpUeZr4Qw'") config = terminal.succeed("cat /home/alice/.config/pareto.toml") assert 'AuthToken = "dummy-token"' in config assert 'TeamID = "dummy-team-id"' in config # Test 4: Test the tray icon xfce.wait_for_x() for unit in [ 'paretosecurity-trayicon', 'paretosecurity-user', 'paretosecurity-user.timer' ]: status, out = xfce.systemctl("is-enabled " + unit, "alice") assert status == 0, f"Unit {unit} is not enabled (status: {status}): {out}" xfce.succeed("xdotool mousemove 850 10") xfce.wait_for_text("Pareto Security") xfce.succeed("xdotool click 1") Loading
pkgs/by-name/pa/paretosecurity/package.nix +23 −9 Original line number Diff line number Diff line Loading @@ -9,22 +9,18 @@ buildGoModule rec { pname = "paretosecurity"; version = "0.0.91"; version = "0.0.96"; src = fetchFromGitHub { owner = "ParetoSecurity"; repo = "agent"; rev = version; hash = "sha256-/kGwV96Jp7U08jh/wPQMcoV48zQe9ixY7gpNdtFyOkk="; hash = "sha256-SyeIGSDvrnOvyOJ0zC8CulpaMa+iZeRaMTJUSydz2tw="; }; vendorHash = "sha256-kGrYoN0dGcSuQW47Y4LUFdHQYAoY74NOM1LLPdhmLhc="; vendorHash = "sha256-O/OF3Y6HiiikMxf657k9eIM7UfkicIImAUxVVf/TgR8="; proxyVendor = true; subPackages = [ "cmd/paretosecurity" ]; ldflags = [ "-s" "-X=github.com/ParetoSecurity/agent/shared.Version=${version}" Loading @@ -32,6 +28,23 @@ buildGoModule rec { "-X=github.com/ParetoSecurity/agent/shared.Date=1970-01-01T00:00:00Z" ]; postInstall = '' # Install global systemd files install -Dm400 ${src}/apt/paretosecurity.socket $out/lib/systemd/system/paretosecurity.socket install -Dm400 ${src}/apt/paretosecurity.service $out/lib/systemd/system/paretosecurity.service substituteInPlace $out/lib/systemd/system/paretosecurity.service \ --replace-fail "/usr/bin/paretosecurity" "$out/bin/paretosecurity" # Install user systemd files install -Dm444 ${src}/apt/paretosecurity-user.timer $out/lib/systemd/user/paretosecurity-user.timer install -Dm444 ${src}/apt/paretosecurity-user.service $out/lib/systemd/user/paretosecurity-user.service substituteInPlace $out/lib/systemd/user/paretosecurity-user.service \ --replace-fail "/usr/bin/paretosecurity" "$out/bin/paretosecurity" install -Dm444 ${src}/apt/paretosecurity-trayicon.service $out/lib/systemd/user/paretosecurity-trayicon.service substituteInPlace $out/lib/systemd/user/paretosecurity-trayicon.service \ --replace-fail "/usr/bin/paretosecurity" "$out/bin/paretosecurity" ''; passthru.tests = { version = testers.testVersion { version = "${version}"; Loading @@ -50,12 +63,13 @@ buildGoModule rec { settings such as if you have disk encryption and firewall enabled. If you use the `services.paretosecurity` NixOS module, you also get a root helper, so that you can run the checker in userspace. Some checks root helper that allows you to run the checker in userspace. Some checks require root permissions, and the checker asks the helper to run those. Additionally, if you enable `services.paretosecurity.trayIcon`, you get a little Vilfredo Pareto living in your systray showing your the current status of checks. status of checks. This will also enable a systemd timer to update the status of checks once per hour. Finally, you can run `paretosecurity link` to configure the agent to send the status of checks to https://dash.paretosecurity.com to make Loading