diff options
author | pennae <github@quasiparticle.net> | 2022-01-09 08:46:55 +0100 |
---|---|---|
committer | pennae <github@quasiparticle.net> | 2022-03-12 00:48:52 +0100 |
commit | 40a35299fa30421de85a56f084f6c59d05ea883e (patch) | |
tree | 563048cbb3cb7b4fdc870e1e3406b1738d0ec43a /nixos/tests/systemd-escaping.nix | |
parent | 74f542c42e5bca4f74f53cf7054c8a93d4736f51 (diff) | |
download | nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar.gz nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar.bz2 nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar.lz nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar.xz nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.tar.zst nixpkgs-40a35299fa30421de85a56f084f6c59d05ea883e.zip |
nixos: add functions and documentation for escaping systemd Exec* directives
it's really easy to accidentally write the wrong systemd Exec* directive, ones that works most of the time but fails when users include systemd metacharacters in arguments that are interpolated into an Exec* directive. add a few functions analogous to escapeShellArg{,s} and some documentation on how and when to use them.
Diffstat (limited to 'nixos/tests/systemd-escaping.nix')
-rw-r--r-- | nixos/tests/systemd-escaping.nix | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/nixos/tests/systemd-escaping.nix b/nixos/tests/systemd-escaping.nix new file mode 100644 index 00000000000..7f93eb5e4f7 --- /dev/null +++ b/nixos/tests/systemd-escaping.nix @@ -0,0 +1,45 @@ +import ./make-test-python.nix ({ pkgs, ... }: + +let + echoAll = pkgs.writeScript "echo-all" '' + #! ${pkgs.runtimeShell} + for s in "$@"; do + printf '%s\n' "$s" + done + ''; + # deliberately using a local empty file instead of pkgs.emptyFile to have + # a non-store path in the test + args = [ "a%Nything" "lang=\${LANG}" ";" "/bin/sh -c date" ./empty-file 4.2 23 ]; +in +{ + name = "systemd-escaping"; + + machine = { pkgs, lib, utils, ... }: { + systemd.services.echo = + assert !(builtins.tryEval (utils.escapeSystemdExecArgs [ [] ])).success; + assert !(builtins.tryEval (utils.escapeSystemdExecArgs [ {} ])).success; + assert !(builtins.tryEval (utils.escapeSystemdExecArgs [ null ])).success; + assert !(builtins.tryEval (utils.escapeSystemdExecArgs [ false ])).success; + assert !(builtins.tryEval (utils.escapeSystemdExecArgs [ (_:_) ])).success; + { description = "Echo to the journal"; + serviceConfig.Type = "oneshot"; + serviceConfig.ExecStart = '' + ${echoAll} ${utils.escapeSystemdExecArgs args} + ''; + }; + }; + + testScript = '' + machine.wait_for_unit("multi-user.target") + machine.succeed("systemctl start echo.service") + # skip the first 'Starting <service> ...' line + logs = machine.succeed("journalctl -u echo.service -o cat").splitlines()[1:] + assert "a%Nything" == logs[0] + assert "lang=''${LANG}" == logs[1] + assert ";" == logs[2] + assert "/bin/sh -c date" == logs[3] + assert "/nix/store/ij3gw72f4n5z4dz6nnzl1731p9kmjbwr-empty-file" == logs[4] + assert "4.2" in logs[5] # toString produces extra fractional digits! + assert "23" == logs[6] + ''; +}) |