update-systemd-resolved icon indicating copy to clipboard operation
update-systemd-resolved copied to clipboard

Draft/RFC: polkit rules generation

Open tomeon opened this issue 2 years ago • 1 comments

This is a draft pull request that introduces the ability to dynamically generate polkit rules that allow update-systemd-resolved to perform its various DBus calls when run as an unprivileged user.

Motivation

  1. Make it easier for folks who run their OpenVPN client under unprivileged users to create appropriate polkit rules, minimizing the amount of hand-editing required. On the happiest path, the generated rules can be used without any edits at all.
  2. Make it easier to update polkit rules in the future, if (for instance) update-systemd-resolved adds or removes org.freedesktop.resolve1 DBus call types.
  3. Support automated/on-demand rules generation for use-cases like creating appropriate polkit rules as part of building a NixOS system configuration.

Summary of changes

  1. Add the action update-systemd-resolved print-polkit-rules, with various options as documented in the README.md changes.
  2. Add NixOS-based tests intended to exercise the generated polkit ruleset by attempting to perform certain actions that should succeed only if the generated rules work as intended. Note that I implemented the tests using NixOS's test framework because (a) I'm familiar with it and (b) it's the easiest option I know of for performing systems-level testing that requires multiple machines and nontrivial setup steps. I'd be happy to re-implement the tests using whatever tooling the update-systemd-resolved maintainers prefer.

Caveats

  1. My facility with JavaScript is basic, at best. The generated polkit rules work (on my machine ;)), but I am not confident they are free of glaring style gaffes or other problems.
  2. The rules generation process involves printing the contents of an argument vector ("$@") as a JSON array. jq is used for this, if available, falling back to a pure-shell implementation on systems where jq is absent. This fallback implementation is, to put it kindly, dodgy in the extreme: it escapes " characters and passes everything else through untouched. This is a potential security hole, if a bad actor can somehow influence the list of arguments passed to the JSON-generating function. I could implement other fallback functions (e.g., using Python and the json or simplejson module, if available, using Perl and JSON::PP, JSON::XS, etc., if available, and so on). WDYT?

TODO

  1. Help text. Omitted for the time being because update-systemd-resolved does not yet implement --help for existing options.
  2. Developer documentation. For example, how to use niv to update the locked Nix dependencies in nix/sources.{json,nix}. Would appreciate guidance here -- could be something as simple as adding doc/HACKING.md and linking to it somewhere in README.md.
  3. Reconsider certain diagnostics. With the current changeset, update-systemd-resolved dumps a polkit rules definition to the system journal when certain operations fail (to let the user know that how they may need to update their polkit rules to allow update-systemd-resolved to do its thing). Instead, maybe update-systemd-resolved could print the polkit rules generation command to the journal -- e.g., update-system-resolved --polkit-allowed-user <uid> --polkit-allowed-group <gid>.

Thanks in advance for your consideration!

tomeon avatar Apr 01 '22 14:04 tomeon

Also: having trouble with my personal Travis CI account, so here's a link to a passing build on builds.sr.ht.

tomeon avatar Apr 01 '22 16:04 tomeon

@piotr-dobrogost -- since you gave this PR a :+1: a while back, any chance I could impose upon you for a review? Please and thank you :smiley: .

tomeon avatar Jul 20 '23 16:07 tomeon

The rules generation process involves printing the contents of an argument vector ("$@") as a JSON array. jq is used for this, if available, falling back to a pure-shell implementation on systems where jq is absent. This fallback implementation is, to put it kindly, dodgy in the extreme: it escapes " characters and passes everything else through untouched. This is a potential security hole, if a bad actor can somehow influence the list of arguments passed to the JSON-generating function. I could implement other fallback functions (e.g., using Python and the json or simplejson module, if available, using Perl and JSON::PP, JSON::XS, etc., if available, and so on). WDYT?

I have implemented JSON serialization using Perl and Python.

tomeon avatar Jul 20 '23 18:07 tomeon