From ac4b47f82368a9529a53b0b04fed4b685a9e12e0 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Thu, 29 Apr 2021 18:40:36 +0200 Subject: [PATCH 1/5] nixos/pinnwand: improve settings behaviour Individual settings would previously overwrite the whole config, but now individual values can be overwritten. Fix missing slash to make the database path an absolute path per https://docs.sqlalchemy.org/en/14/core/engines.html#sqlite. Drop preferred_lexers, it's not set to anything meaningful anyway. --- nixos/modules/services/misc/pinnwand.nix | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/nixos/modules/services/misc/pinnwand.nix b/nixos/modules/services/misc/pinnwand.nix index aa1ee5cfaa77..ca378847a20c 100644 --- a/nixos/modules/services/misc/pinnwand.nix +++ b/nixos/modules/services/misc/pinnwand.nix @@ -24,22 +24,22 @@ in Your pinnwand.toml as a Nix attribute set. Look up possible options in the pinnwand.toml-example. ''; - default = { - # https://github.com/supakeen/pinnwand/blob/master/pinnwand.toml-example - database_uri = "sqlite:///var/lib/pinnwand/pinnwand.db"; - preferred_lexeres = []; - paste_size = 262144; - paste_help = '' -

Welcome to pinnwand, this site is a pastebin. It allows you to share code with others. If you write code in the text area below and press the paste button you will be given a link you can share with others so they can view your code as well.

People with the link can view your pasted code, only you can remove your paste and it expires automatically. Note that anyone could guess the URI to your paste so don't rely on it being private.

- ''; - footer = '' - View source code, the removal or expiry stories, or read the about page. - ''; - }; + default = {}; }; }; config = mkIf cfg.enable { + services.pinnwand.settings = { + database_uri = mkDefault "sqlite:////var/lib/pinnwand/pinnwand.db"; + paste_size = mkDefault 262144; + paste_help = mkDefault '' +

Welcome to pinnwand, this site is a pastebin. It allows you to share code with others. If you write code in the text area below and press the paste button you will be given a link you can share with others so they can view your code as well.

People with the link can view your pasted code, only you can remove your paste and it expires automatically. Note that anyone could guess the URI to your paste so don't rely on it being private.

+ ''; + footer = mkDefault '' + View source code, the removal or expiry stories, or read the about page. + ''; + }; + systemd.services.pinnwand = { description = "Pinnwannd HTTP Server"; after = [ "network.target" ]; From fda2ff4edc2c0b897011eff4dffc5d777d07f4c8 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Thu, 29 Apr 2021 23:02:59 +0200 Subject: [PATCH 2/5] nixos/pinnwand: add reaper systemd unit/timer The reap function culls expired pastes outside of the process serving the pastes. Previously the database could accumulate a large number of pastes and while they were expired they would not be deleted unless accessed from the frontend. --- nixos/modules/services/misc/pinnwand.nix | 45 ++++++++++++++++++------ 1 file changed, 35 insertions(+), 10 deletions(-) diff --git a/nixos/modules/services/misc/pinnwand.nix b/nixos/modules/services/misc/pinnwand.nix index ca378847a20c..cbc796c9a7c8 100644 --- a/nixos/modules/services/misc/pinnwand.nix +++ b/nixos/modules/services/misc/pinnwand.nix @@ -40,39 +40,64 @@ in ''; }; - systemd.services.pinnwand = { - description = "Pinnwannd HTTP Server"; - after = [ "network.target" ]; - wantedBy = [ "multi-user.target" ]; + systemd.services = let + hardeningOptions = { + User = "pinnwand"; + DynamicUser = true; - unitConfig.Documentation = "https://pinnwand.readthedocs.io/en/latest/"; - serviceConfig = { - ExecStart = "${pkgs.pinnwand}/bin/pinnwand --configuration-path ${configFile} http --port ${toString(cfg.port)}"; StateDirectory = "pinnwand"; StateDirectoryMode = "0700"; AmbientCapabilities = []; CapabilityBoundingSet = ""; DevicePolicy = "closed"; - DynamicUser = true; LockPersonality = true; MemoryDenyWriteExecute = true; PrivateDevices = true; PrivateUsers = true; + ProcSubset = "pid"; ProtectClock = true; ProtectControlGroups = true; - ProtectKernelLogs = true; ProtectHome = true; ProtectHostname = true; + ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; - RestrictAddressFamilies = [ "AF_UNIX" "AF_INET" "AF_INET6" ]; + ProtectProc = "invisible"; + RestrictAddressFamilies = [ + "AF_UNIX" + "AF_INET" + "AF_INET6" + ]; RestrictNamespaces = true; RestrictRealtime = true; SystemCallArchitectures = "native"; SystemCallFilter = "@system-service"; UMask = "0077"; }; + + command = "${pkgs.pinnwand}/bin/pinnwand --configuration-path ${configFile}"; + in { + pinnwand = { + description = "Pinnwannd HTTP Server"; + after = [ "network.target" ]; + wantedBy = [ "multi-user.target" ]; + + unitConfig.Documentation = "https://pinnwand.readthedocs.io/en/latest/"; + + serviceConfig = { + ExecStart = "${command} http --port ${toString(cfg.port)}"; + } // hardeningOptions; + }; + + pinnwand-reaper = { + description = "Pinnwand Reaper"; + startAt = "daily"; + + serviceConfig = { + ExecStart = "${command} -vvvv reap"; # verbosity increased to show number of deleted pastes + } // hardeningOptions; + }; }; }; } From f1c32c28096f565c0d977bce6cc3a0adb113d267 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Thu, 29 Apr 2021 23:12:20 +0200 Subject: [PATCH 3/5] nixos/tests/pinnwand: show systemd-analyze security Easy way to revisit the hardening setup of the systemd unit. --- nixos/tests/pinnwand.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/nixos/tests/pinnwand.nix b/nixos/tests/pinnwand.nix index 0c583e1104de..7f6075c3c742 100644 --- a/nixos/tests/pinnwand.nix +++ b/nixos/tests/pinnwand.nix @@ -82,5 +82,7 @@ in # remove paste and check that it's not available any more client.succeed(f"curl {removal_link}") client.fail(f"curl --fail {raw_url}") + + server.log(server.succeed("systemd-analyze security pinnwand")) ''; }) From 7b2bc43dba0f705987cc8c1f35620a4021838ac8 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Thu, 29 Apr 2021 23:53:37 +0200 Subject: [PATCH 4/5] nixos/tests/pinnwand: add negative-test for the reaper The reaper, at this point, should not delete a freshly created paste. --- nixos/tests/pinnwand.nix | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nixos/tests/pinnwand.nix b/nixos/tests/pinnwand.nix index 7f6075c3c742..dc8c2744a81f 100644 --- a/nixos/tests/pinnwand.nix +++ b/nixos/tests/pinnwand.nix @@ -75,6 +75,12 @@ in if line.startswith("Removal link:"): removal_link = line.split(":", 1)[1] + + # start the reaper, it shouldn't do anything meaningful here + server.systemctl("start pinnwand-reaper.service") + server.wait_until_fails("systemctl is-active -q pinnwand-reaper.service") + server.log(server.execute("journalctl -u pinnwand-reaper -e --no-pager")[1]) + # check whether paste matches what we sent client.succeed(f"curl {raw_url} > /tmp/machine-id") client.succeed("diff /tmp/machine-id /etc/machine-id") From b208338c3669648f03e7dda5d4107e5e79993907 Mon Sep 17 00:00:00 2001 From: Martin Weinelt Date: Fri, 30 Apr 2021 00:03:43 +0200 Subject: [PATCH 5/5] nixos/tests/pinnwand: use wait_for_open_port instead of direct sockstat call --- nixos/tests/pinnwand.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/tests/pinnwand.nix b/nixos/tests/pinnwand.nix index dc8c2744a81f..0391c4133111 100644 --- a/nixos/tests/pinnwand.nix +++ b/nixos/tests/pinnwand.nix @@ -61,7 +61,7 @@ in client.wait_until_succeeds("ping -c1 server") # make sure pinnwand is listening - server.wait_until_succeeds("ss -lnp | grep ${toString port}") + server.wait_for_open_port(${toString port}) # send the contents of /etc/machine-id response = client.succeed("steck paste /etc/machine-id")