Loading nixos/modules/services/security/paretosecurity.nix +77 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,25 @@ in default = true; description = "Set to false to disable the tray icon and run as a CLI tool only."; }; users = lib.mkOption { type = lib.types.attrsOf ( lib.types.submodule { options = { inviteId = lib.mkOption { type = lib.types.str; description = '' A unique ID that links the agent to Pareto Cloud. Get it from the Join Team page on `https://cloud.paretosecurity.com/team/join/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`. In Step 2, under Linux tab, enter your email then copy it from the generated command. ''; example = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; }; }; } ); default = { }; description = "Per-user Pareto Security configuration."; }; }; config = lib.mkIf cfg.enable { Loading @@ -38,9 +57,64 @@ in # if one is installed. # The `paretosecurity-user` timer service that is configured lower has # the same need. systemd.services.paretosecurity.serviceConfig.Environment = [ systemd.services = { paretosecurity.serviceConfig.Environment = [ "PATH=${config.system.path}/bin:${config.system.path}/sbin" ]; } // ( # Each user can set their inviteID, which creates a systemd service # that runs `paretosecurity link ...` to link their device to Pareto Cloud. lib.mapAttrs' ( username: userConfig: lib.nameValuePair "paretosecurity-link-${username}" { description = "Link Pareto Desktop to Pareto Cloud for user ${username}"; after = [ "network-online.target" ]; wants = [ "network-online.target" ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; User = username; StateDirectory = "paretosecurity/${username}"; ExecStart = pkgs.writeShellScript "paretosecurity-link-${username}" '' set -euo pipefail INVITE_ID="${userConfig.inviteId}" STATE_FILE="/var/lib/paretosecurity/${username}/linked-$INVITE_ID" CONFIG_FILE="$HOME/.config/pareto.toml" # Check if already linked with this specific invite if [ -f "$STATE_FILE" ]; then echo "Device already linked with invite $INVITE_ID for user ${username}" exit 0 fi # Ensure config directory exists mkdir -p "$(dirname "$CONFIG_FILE")" # Perform linking echo "Linking device to Pareto Cloud for user ${username}..." ${cfg.package}/bin/paretosecurity link \ "paretosecurity://linkDevice/?invite_id=$INVITE_ID" # Verify linking succeeded if [ -f "$CONFIG_FILE" ] && grep -q "TeamID" "$CONFIG_FILE"; then echo "Successfully linked to Pareto Cloud for user ${username}" touch "$STATE_FILE" else echo "Failed to link to Pareto Cloud for user ${username}" exit 1 fi ''; }; wantedBy = [ "multi-user.target" ]; } ) cfg.users ); # Enable the tray icon and timer services if the trayIcon option is enabled systemd.user = lib.mkIf cfg.trayIcon { Loading nixos/tests/paretosecurity.nix +48 −42 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ imports = [ ./common/user-account.nix ]; services.paretosecurity.enable = true; services.paretosecurity.users.alice.inviteId = "test-invite-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; }; nodes.xfce = Loading Loading @@ -46,10 +46,10 @@ terminal.systemctl("start network-online.target") terminal.wait_for_unit("network-online.target") # Test 1: Test the systemd socket is installed & enabled with subtest("Test the systemd socket is installed & enabled"): terminal.succeed('systemctl is-enabled paretosecurity.socket') # Test 2: Test running checks with subtest("Test running checks"): terminal.succeed( "su - alice -c 'paretosecurity check" # Disable some checks that need intricate test setup so that this test Loading @@ -63,7 +63,13 @@ + "'" ) # Test 3: Test the tray icon with subtest("Test linking to Pareto Cloud"): # The linking service will fail because there is no Internet, # but we can check that it tried terminal.succeed('systemctl list-units --type=service | grep paretosecurity-link-alice') terminal.succeed('journalctl -u paretosecurity-link-alice.service | grep "Linking device to Pareto Cloud for user alice"') with subtest("Test 3: Test the tray icon"): xfce.wait_for_x() for unit in [ 'paretosecurity-trayicon', Loading @@ -77,7 +83,7 @@ xfce.succeed("xdotool click 1") xfce.wait_for_text("Run Checks") # Test 4: Desktop entry with subtest("Test 4: Desktop entry"): xfce.succeed("xdotool mousemove 10 10") xfce.succeed("xdotool click 1") # hide the tray icon window xfce.succeed("xdotool click 1") # show the Applications menu Loading @@ -85,7 +91,7 @@ xfce.succeed("xdotool click 1") xfce.wait_for_text("Pareto Security") # Test 5: paretosecurity:// URL handler is registered with subtest("Test 5: paretosecurity:// URL handler is registered"): xfce.succeed("su - alice -c 'xdg-open paretosecurity://foo'") ''; } pkgs/by-name/pa/paretosecurity/package.nix +12 −8 Original line number Diff line number Diff line Loading @@ -78,13 +78,15 @@ buildGoModule (finalAttrs: { }; meta = { description = "Agent that makes sure your laptop is correctly configured for security"; description = "A simple trayicon app that makes sure your laptop is correctly configured for security"; longDescription = '' The Pareto Security agent is a free and open source app to help you make sure that your laptop is configured for security. [Pareto Desktop](https://paretosecurity.com/linux) is a free and open source trayicon app to help you configure your laptop for security. It nudges you to take care of 20% of security-related tasks that bring 80% of protection. By default, it's a CLI command that prints out a report on basic security settings such as if you have disk encryption and firewall enabled. In it's simplest form, it's a CLI command that prints out a report on basic security 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 that allows you to run the checker in userspace. Some checks Loading @@ -96,9 +98,11 @@ buildGoModule (finalAttrs: { once per hour. If you want to use just the CLI mode, set `services.paretosecurity.trayIcon` to `false`. Finally, you can run `paretosecurity link` to configure the agent to send the status of checks to https://dash.paretosecurity.com to make compliance people happy. No sending happens until your device is linked. Finally, if you set `users.users.alice.paretosecurity.inviteId = "..."` to the `inviteId` you get on [Pareto Cloud](https://cloud.paretosecurity.com/), then Pareto Desktop acts as a read-only and push-only agent that sends the status of checks to https://cloud.paretosecurity.com which makes compliance people happy and your privacy intact. ''; homepage = "https://github.com/ParetoSecurity/agent"; license = lib.licenses.gpl3Only; Loading Loading
nixos/modules/services/security/paretosecurity.nix +77 −3 Original line number Diff line number Diff line Loading @@ -17,6 +17,25 @@ in default = true; description = "Set to false to disable the tray icon and run as a CLI tool only."; }; users = lib.mkOption { type = lib.types.attrsOf ( lib.types.submodule { options = { inviteId = lib.mkOption { type = lib.types.str; description = '' A unique ID that links the agent to Pareto Cloud. Get it from the Join Team page on `https://cloud.paretosecurity.com/team/join/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx`. In Step 2, under Linux tab, enter your email then copy it from the generated command. ''; example = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; }; }; } ); default = { }; description = "Per-user Pareto Security configuration."; }; }; config = lib.mkIf cfg.enable { Loading @@ -38,9 +57,64 @@ in # if one is installed. # The `paretosecurity-user` timer service that is configured lower has # the same need. systemd.services.paretosecurity.serviceConfig.Environment = [ systemd.services = { paretosecurity.serviceConfig.Environment = [ "PATH=${config.system.path}/bin:${config.system.path}/sbin" ]; } // ( # Each user can set their inviteID, which creates a systemd service # that runs `paretosecurity link ...` to link their device to Pareto Cloud. lib.mapAttrs' ( username: userConfig: lib.nameValuePair "paretosecurity-link-${username}" { description = "Link Pareto Desktop to Pareto Cloud for user ${username}"; after = [ "network-online.target" ]; wants = [ "network-online.target" ]; serviceConfig = { Type = "oneshot"; RemainAfterExit = true; User = username; StateDirectory = "paretosecurity/${username}"; ExecStart = pkgs.writeShellScript "paretosecurity-link-${username}" '' set -euo pipefail INVITE_ID="${userConfig.inviteId}" STATE_FILE="/var/lib/paretosecurity/${username}/linked-$INVITE_ID" CONFIG_FILE="$HOME/.config/pareto.toml" # Check if already linked with this specific invite if [ -f "$STATE_FILE" ]; then echo "Device already linked with invite $INVITE_ID for user ${username}" exit 0 fi # Ensure config directory exists mkdir -p "$(dirname "$CONFIG_FILE")" # Perform linking echo "Linking device to Pareto Cloud for user ${username}..." ${cfg.package}/bin/paretosecurity link \ "paretosecurity://linkDevice/?invite_id=$INVITE_ID" # Verify linking succeeded if [ -f "$CONFIG_FILE" ] && grep -q "TeamID" "$CONFIG_FILE"; then echo "Successfully linked to Pareto Cloud for user ${username}" touch "$STATE_FILE" else echo "Failed to link to Pareto Cloud for user ${username}" exit 1 fi ''; }; wantedBy = [ "multi-user.target" ]; } ) cfg.users ); # Enable the tray icon and timer services if the trayIcon option is enabled systemd.user = lib.mkIf cfg.trayIcon { Loading
nixos/tests/paretosecurity.nix +48 −42 Original line number Diff line number Diff line Loading @@ -9,7 +9,7 @@ imports = [ ./common/user-account.nix ]; services.paretosecurity.enable = true; services.paretosecurity.users.alice.inviteId = "test-invite-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"; }; nodes.xfce = Loading Loading @@ -46,10 +46,10 @@ terminal.systemctl("start network-online.target") terminal.wait_for_unit("network-online.target") # Test 1: Test the systemd socket is installed & enabled with subtest("Test the systemd socket is installed & enabled"): terminal.succeed('systemctl is-enabled paretosecurity.socket') # Test 2: Test running checks with subtest("Test running checks"): terminal.succeed( "su - alice -c 'paretosecurity check" # Disable some checks that need intricate test setup so that this test Loading @@ -63,7 +63,13 @@ + "'" ) # Test 3: Test the tray icon with subtest("Test linking to Pareto Cloud"): # The linking service will fail because there is no Internet, # but we can check that it tried terminal.succeed('systemctl list-units --type=service | grep paretosecurity-link-alice') terminal.succeed('journalctl -u paretosecurity-link-alice.service | grep "Linking device to Pareto Cloud for user alice"') with subtest("Test 3: Test the tray icon"): xfce.wait_for_x() for unit in [ 'paretosecurity-trayicon', Loading @@ -77,7 +83,7 @@ xfce.succeed("xdotool click 1") xfce.wait_for_text("Run Checks") # Test 4: Desktop entry with subtest("Test 4: Desktop entry"): xfce.succeed("xdotool mousemove 10 10") xfce.succeed("xdotool click 1") # hide the tray icon window xfce.succeed("xdotool click 1") # show the Applications menu Loading @@ -85,7 +91,7 @@ xfce.succeed("xdotool click 1") xfce.wait_for_text("Pareto Security") # Test 5: paretosecurity:// URL handler is registered with subtest("Test 5: paretosecurity:// URL handler is registered"): xfce.succeed("su - alice -c 'xdg-open paretosecurity://foo'") ''; }
pkgs/by-name/pa/paretosecurity/package.nix +12 −8 Original line number Diff line number Diff line Loading @@ -78,13 +78,15 @@ buildGoModule (finalAttrs: { }; meta = { description = "Agent that makes sure your laptop is correctly configured for security"; description = "A simple trayicon app that makes sure your laptop is correctly configured for security"; longDescription = '' The Pareto Security agent is a free and open source app to help you make sure that your laptop is configured for security. [Pareto Desktop](https://paretosecurity.com/linux) is a free and open source trayicon app to help you configure your laptop for security. It nudges you to take care of 20% of security-related tasks that bring 80% of protection. By default, it's a CLI command that prints out a report on basic security settings such as if you have disk encryption and firewall enabled. In it's simplest form, it's a CLI command that prints out a report on basic security 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 that allows you to run the checker in userspace. Some checks Loading @@ -96,9 +98,11 @@ buildGoModule (finalAttrs: { once per hour. If you want to use just the CLI mode, set `services.paretosecurity.trayIcon` to `false`. Finally, you can run `paretosecurity link` to configure the agent to send the status of checks to https://dash.paretosecurity.com to make compliance people happy. No sending happens until your device is linked. Finally, if you set `users.users.alice.paretosecurity.inviteId = "..."` to the `inviteId` you get on [Pareto Cloud](https://cloud.paretosecurity.com/), then Pareto Desktop acts as a read-only and push-only agent that sends the status of checks to https://cloud.paretosecurity.com which makes compliance people happy and your privacy intact. ''; homepage = "https://github.com/ParetoSecurity/agent"; license = lib.licenses.gpl3Only; Loading