Nix is an extremely powerful tool for security research, especially because of quite simple impermanence, both on metal and in VMs. Spinning up clean VMs with all the nice tool is a matter of one command and a second to execute. However, i currently can not seriously recommend NixOS for that kind of stuff, as hardening features are currently quite lacking. Mandatory Access Control (MAC) is one of the things that can improve that state.
AppArmor will be shorted to aa. I will link articles and issues, but i can not guarantee they will all stay up forever. These lists won’t be complete either, i’ll try to update them as i do work and come across new issues.
Roadmap
adopt apparmor package, NixOS module and NixOS test (PR merged)
improve NixOS test coverage (PR open)
- catch profiles actually containing processes and denying certain access
- catch profiles actually allowing certain resources
- catch state of profile applying properly (enforce/complain/disable)
- match profile placement in /etc/apparmor.d to have expected file contents
- format
- move to folder to be extendable later
Clean up the many booleans to define profile state (PR open)
- This is a breaking change!!
- This prepares to later expand the state definition to allow states kill, prompt, unconfined without breaking user configs again
Allow defining policy paths to link, instead of relying on a lines-type NixOS config option being written to store (PR open)
- This is ideally a non-breaking change
- Previously, including existing policy paths would have been done either with readFile (dangerous IFD territory, especially doing it on lots of files gets slow. Especially because it’ll immediately be written to the store again), or defining security.apparmor.policies.<name>.profile = ''include "${./path/to/file}",'' (which leaves it to the aa parser to realize that include directive, which is also potentially slow.)
- Including profiles by path instead of by content is important to make apparmor rules packages work in the future
Fix roddhjav-apparmor-rules package
- very broken currently
- does not follow upstream build script
- Introduced in #319286
> This is meant to be used with AppArmor module: security.apparmor.packages = with pkgs; [ roddhjav-apparmor-rules ];
This never worked. Includes link the files, but don’t make the apparmor parser read those profiles.
- Rules packages either need extensive patching or an entirely new design to accomodate them. NixOS is not FHS-compliant. This means all the profiles matching against /bin/something or usr/share/something and similar won’t ever just work. I outlined that problem in my hedgedoc posts before. The original contributor of that package also realized these issues later in #331645 (comment)
- Conclusion: full rewrite of that package.
Set up Nix-compatible development environment to work on AppArmor
- expose latest git packages
- make upstream contribution easier
- running tests
- compiling apparmor and components
Contribute on apparmor upstream
- more test cases testing things we rely on in nix
- improving the alias system as outlined in aa #460 (comment)
- needs a design doc of how exactly aliases should work first. I am working on that.
Is there anywhere to discuss/collaborate on this? I’ve been looking into and vaguely following the process of your efforts, but I would love to help out with this if possible!
Hello, and i appreciate the offer to help! I intended this as a tracker, but turns out posts on discourse are not editable 24h after posting them. So i will probably move to a github tracking issue soon.
This list is basically a non-exhaustive list of things that need doing. Some of those things simple, some complex, and some depend on others.
Imo the immediate focus should be two things:
get apparmor to a state where future changes to the module are likely not breaking (this means extendable enough, both in profile state definitions and profile content definitions)
improve test coverage, including integration tests and package tests.
Organizing work:
i am open to suggestions about organizing. But it seems i misunderstood what discourse is good for. Tracking doesn’t work well at least. I’d be happy with both a github project board or a github tracking issue. Project board would be editable by anyone working on this, but i am not sure what the agreed procedures about project boards are. Maybe @hexa can give some insight? Just a short “yeah sure make a project”/“tracking issue would be best because …” would be amazing! Is there precedent in the security team about long-term projects like this?
Sidenote: It seems regular nixos org members can’t just create projects in nixpkgs. So if that were to be the decided organizing platform, i wouldn’t be the one who is able to start that.
Tracking issue has the benefit: I can actually open it!
Next steps/Where i am stuck
the alias rework: try and make the alias solution work (i am currently still testing against globs, which is not ideal). This needs a design document that is flexible enough for nix to use aliases, but well-defined in a way where it is reasonable to upstream those things.
regression tests: for the life of me i can not figure out how to get the regression tests working. It needs root to test, because it tests on a running system. This means this test would have to be built in a nixos VM and run as a VM check. But even then, i did not have any luck. I’d be happy to have anyone more familiar have a go at it. HOWEVER: This is non-critical. Tests are nice to spot issues, but not immediately crucial for getting stuff working.
dev shells: I expect we’ll be upstreaming quite a bit to apparmor. A dev shell is on my list of things to do, but i am open to someone else writing one too. Good shells are magic.
some consideration about python + perl in apparmor. Python is needed, but we might be able to reduce perl useage to check inputs only. This does however need more testing.
Nixos module/Overlays: It’d be nice to use a flake to pull and test git versions of apparmor on a real system or reuse the nixos VM test i implemented in #356796. Ideally, the flake would live outside of the apparmor repo to not bother the apparmor maintainers with nix stuff, and have some github bot to update the apparmor repo it pulls or something. I didn’t yet fully consider the architecture here, this’d need discussion.
I did a bit of tinkering, and i have almost all tests passing, and those that don’t pass blacklisted.
Thing is: these tests still need a running system to run, they don’t actually run in a build sandbox. So next up is throwing this into a nixos VM test. But, i am making progress!
This is (imo) the first usable state for apparmor git packages, and now i can work on improving testing (reg tests still need a vm test output) as well as finally doing dev shells.
I did have to switch the flake tracking branch over to my nixkgs fork with the apparmor test cases fixed, but i will drop that as soon as my module/test fix PR is merged.
I am happy if people try it and open issue reports for issues they come across. But as always, keep backups and fallbacks (e.g. a specialization that disables apparmor) so you don’t brick your system.
With #356796 merged and the apparmor-dev packages/overlay being mostly tested and ready, it is now time to move ahead and clean up the apparmor packages. I’ll soon open a draft PR, but i am not super familiar with how multiple packages from one source set with shared patches is supposed to be implemented.
The current plan is to have one source derivation applying patches, and a “shared” file applying things like check enable and meta definitions, with the actual packages being separate files. But if anyone has good pointers, this is definitely something for which i’d appreciate some help.
If someone wanted to test AppArmor rules in a self-packaged application, is there a suggested way to do so or place to start?
Edit after posting: I’m not sure if this is actually the right place for this question or not (and apologies if so), unfortunately. I figured that this would be good to ask considering the changes to AppArmor being done here!
Testing rules is hard because you basically need to run through all the functions of the app to be certain the rules don’t break stuff. Doing this well is not trivial, sadly.
For some apps, rules can be tested by running their nixos tests in a VM test that you extend with the apparmor-specific things. Hijacking a nixos test and modifying the config it runs with isn’t easy either, but with enough headaches you can do it. An example can be found here: apparmor-dev/flake.nix at 032cb3469176411d5bda5642049abc468073e18a · LordGrimmauld/apparmor-dev · GitHub [sidenote: improvements are welcome, i really don’t like the hacks i do there…]. That might be a good benchmark if you want automated testing for your profiles.
The next best thing is just manual testing. You’d define the apparmor profile in the exact same way, but test the app for all its (core) features manually. This is largely how i test my own profiles for now.
Shipping apparmor profiles with an app is not trivial either: profiles need maintenance and testing. In an ideal world, every package maintainer would be diligent enough and care enough to do that. But i am under no illusions: that simply won’t happen. And i am not exactly keen on the idea of maintaining 120k profiles by myself. Until a sustainable model for maintaining profiles is found (which, imo, requires making profiles compatible with profiles not specifically designed for nixos systems) then we can start work on improving profile coverage imo. I am not the only person who has a say in that though. Just not my concern (yet).
As to place to ask: AppArmor is neglected. I don’t know of any other place on this forum actually taking aa serious. So eh, fine to bring it up here.
This is basically the same problem as systemd hardening and we have been able to roll that out to NixOS modules’ services to a decent degree on a best-effort basis.
In the long term, I’d ideally like to see upstreams maintain the aa profiles for their apps because they know best what those should and shouldn’t be able to do. (Just like with systemd hardening.)
I feel like that should become more prevalent because I see the Zeitgeist moving towards more hardening as we become aware of just how insecure our (in other respects awesome) systems are.
I’m under no illusion that we won’t get every upstream to do so though, so I think an independent collection of permissively licensed (i.e. apache-20) profiles would be the next best thing.
This should ideally be a cross-distro effort as, for any given program, the associated aa profile should dictate the same policy on basically any distro.
It’s also not like we need to provide complete aa profiles for each and every program. You could provide default rules for all programs that provide some basic hardening and work for 99% of them and then manually fix the remaining 1%. That 1% would be much more manageable.
What I mean by “basic hardening” would be preventing any old program from accessing high-value targets such as SSH keys, GPG keys, browser cookies, executables (user bin, bashrc, systemd user services) or perhaps even personal documents.
If we could produce profiles that only allow the few % of programs that actually need to be able to access these, that would be an immense security benefit already IMHO.
It would be cool to have some baseline rule that a nix store path can only execute things and also only load shared libs in its closure.
Another useful rule would be that a caller of a nix store path can pass elements of its closure down to callees.
For example systemd service for nginx has nginx in its closure so systemd can spawn nginx. Systemd service has config in its closure so it can pass down read access to the config down to nginx. But nginx doesn’t have permission to read sshd config from nix store.
This would divert from a model where we assume the whole nix store is readable. Instead we can use (transformations) over the nix store closure property to define access control efficiently.
I have no idea how to implement this. My first thought was storing closure info in xattrs so that SELinux can access closure info or something.
Maybe something similar is possible in Apparmor too.
Any how my point is my feeling is that the model of the nix store and the explicit dependencies should in theory allow for very elegant access control. Much more elegant than any existing distros.