about summary refs log tree commit diff
path: root/nixos/tests/systemd-confinement
AgeCommit message (Collapse)AuthorFilesLines
2024-05-13nixos/systemd-confinement: Make / read-onlyaszlig1-8/+7
Our more thorough parametrised tests uncovered that with the changes for supporting DynamicUser, we now have the situation that for static users the root directory within the confined environment is now writable for the user in question. This is obviously not what we want and I'd consider that a regression. However while discussing this with @ju1m and my suggestion being to set TemporaryFileSystem to "/" (as we had previously), they had an even better idea[1]: > The goal is to deny write access to / to non-root users, > > * TemporaryFileSystem=/ gives us that through the ownership of / by > root (instead of the service's user inherited from > RuntimeDirectory=). > * ProtectSystem=strict gives us that by mounting / read-only (while > keeping its ownership to the service's user). > > To avoid the incompatibilities of TemporaryFileSystem=/ mentioned > above, I suggest to mount / read-only in all cases with > ReadOnlyPaths = [ "+/" ]: > > ... > > I guess this would require at least two changes to the current tests: > > 1. to no longer expect root to be able to write to some paths (like > /bin) (at least not without first remounting / in read-write > mode). > 2. to no longer expect non-root users to fail to write to certain > paths with a "permission denied" error code, but with a > "read-only file system" error code. I like the solution with ReadOnlyPaths even more because it further reduces the attack surface if the user is root. In chroot-only mode this is especially useful, since if there are no other bind-mounted paths involved in the unit configuration, the whole file system within the confined environment is read-only. [1]: https://github.com/NixOS/nixpkgs/pull/289593#discussion_r1586794215 Signed-off-by: aszlig <aszlig@nix.build>
2024-05-13nixos/tests/confinement: Parametrise subtestsaszlig1-124/+65
This is to make sure that we test all of the DynamicUser/User/Group and PrivateTmp options in a uniform way. The reason why we need to do this is because we recently introduced support for the DynamicUser option and since there are some corner cases where we might end up with more elevated privileges (eg. writable directories in some cases), we want to make sure that the environment is as restrictive as with a static User/Group assignment. I also removed various checks that try to os.chown(), since with our new recursive checker those are redundant. Signed-off-by: aszlig <aszlig@nix.build>
2024-05-13nixos/tests/confinement: Run test probes in Pythonaszlig2-222/+398
So far the architecture for the tests was that we would use a systemd socket unit using the Accept option to start a small shell process where we can pipe commands into by connecting to the socket created by the socket unit. This is unnecessary since we can directly use the code snippets from the individual subtests and systemd will take care of checking the return code in case we get any assertions[^1]. Another advantage of this is that tests now run in parallel, so we can do rather expensive things such as looking in /nix to see whether anything is writable. The new assert_permissions() function is the main driver behind this and allows for a more fine-grained way to check whether we got the right permissions whilst also ignoring irrelevant things such as read-only empty directories. Our previous approach also just did a read-only check, which might be fine in full-apivfs mode where the attack surface already is large, but in chroot-only mode we really want to make sure nothing is every writable. A downside of the new approach is that currently the unit names are numbered via lib.imap1, which makes it annoying to track its definition. [^1]: Speaking of assertions, I wrapped the code to be run with pytest's assertion rewriting, so that we get more useful AssertionErrors. Signed-off-by: aszlig <aszlig@nix.build>
2024-05-13nixos/tests/confinement: Move to dedicated diraszlig1-0/+345
When experimenting on ways how to refactor the test, I wrote a significant enough amount of Python to warrant a dedicated Python file. This commit is mainly to prepare for that and make it easier to track renames. Signed-off-by: aszlig <aszlig@nix.build>