Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

ft: add systemd hardening helpers #288418

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

hauleth
Copy link
Contributor

@hauleth hauleth commented Feb 13, 2024

Description of changes

This module adds systemd.services.<name>.harden set of options that helps with setting basic systemd units hardening. That should help with making more services hardened and responding with better security analysis grade without too much repetition. Most of the set values are marked with mkDefault to allow explicit opt-out for options that aren't needed without resolving to mkForce or similar.

Things done

  • Built on platform(s)
    • x86_64-linux
    • aarch64-linux
    • x86_64-darwin
    • aarch64-darwin
  • For non-Linux: Is sandboxing enabled in nix.conf? (See Nix manual)
    • sandbox = relaxed
    • sandbox = true
  • Tested, as applicable:
  • Tested compilation of all packages that depend on this change using nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD". Note: all changes have to be committed, also see nixpkgs-review usage
  • Tested basic functionality of all binary files (usually in ./result/bin/)
  • 24.05 Release Notes (or backporting 23.05 and 23.11 Release notes)
    • (Package updates) Added a release notes entry if the change is major or breaking
    • (Module updates) Added a release notes entry if the change is significant
    • (Module addition) Added a release notes entry if adding a new NixOS module
  • Fits CONTRIBUTING.md.

Add a 馃憤 reaction to pull requests you find important.

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/hardening-systemd-services/17147/28

@hauleth hauleth force-pushed the ft/add-systemd-hardening-helpers branch from da8220d to 26dfa54 Compare February 13, 2024 11:34
@hauleth
Copy link
Contributor Author

hauleth commented Feb 13, 2024

I have updated the PR with some comments from the forum - now there is harden.enable option that enables everything and each service can opt-out of some hardening features if these are needed by them.

nixos/modules/security/systemd-harden.nix Outdated Show resolved Hide resolved
Comment on lines +12 to +25
enable = lib.mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Basic restrictions for systemd services
'';
};

execOnlyNix = lib.mkOption {
type = types.bool;
default = true;
description = lib.mdDoc ''
Mark whole system as non-executable with exception for `/nix/store`.
'';
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Better use mkEnableOption for these.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem with mkEnableOption is that it has very limited support for docs. Current docs are more of a stub rather than target docs and I would like to expand them more when there will be established syntax for all these options.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see how mkEnableOption would limit your docs in any way? The description is its one and only argument, it's just prefixed by "Whether to enable ..." which applies to all of them.

nixos/modules/security/systemd-harden.nix Outdated Show resolved Hide resolved
Comment on lines +52 to +57
ipSockets = lib.mkOption {
type = types.bool;
default = false;
description = lib.mdDoc ''
Allow using AF_INET and AF_INET6
'';
};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The options are a bit inconsistent. Some are positive (enable, activate, do) and others negative (disable, only, deactivate, restrict).

This should either be a negative option too (i.e. noIpSockets) or all the other options should be flipped to be positive.

Usually, I'd prefer positive options over negative options but I could see the case for negative options specifically for the case of enabling hardening.

OTOH, I think there could be merit in treating our little abstraction like a permissions system for which positive options would fit better.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I prefer these options to have meaningful names. I never really liked negated options and instead I prefer approach that is shown here - we have enable option and then we enable/disable features we do not want. So not everything will be true by default and not everything will be false by default, but rather the "inconsistent mix". But if the NixOS modules approach is to take only one of these routes, then I will oblige.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant negation on another level; the actual effect on the resulting service.

Currently, the options mostly say "enable <hardening>/<restriction>". These then enable restrictions internally which has the effect of disabling the service from doing some things; if you set the option true, the service would lose the ability to do some thing.

What I meant was to turn them into "allow <restricted thing>" instead. For example: fullProc, nonNixExec, ipSockets. Internally, these would disable a set of restrictions but the effect of that is that the service would be enabled to do these things; if you set the option true, the service would gain an ability to do some thing.

Do you see what I mean?

if the NixOS modules approach is to take only one of these routes, then I will oblige.

There is no standard for this that I'm aware of.

This is just about generally designing the interface well and one part of that is consistency. Ideally we would have consistency across all of NixOS but that's a harder problem to solve. Local consistency is achievable though and we should strive for it.

@hauleth hauleth force-pushed the ft/add-systemd-hardening-helpers branch from 26dfa54 to 6cb1804 Compare February 13, 2024 14:17
This module adds `systemd.services.<name>.harden` set of options that
helps with setting basic systemd units hardening. That should help with
making more services hardened and responding with better security
analysis grade without too much repetition. Most of the set values are
marked with `mkDefault` to allow explicit opt-out for options that
aren't needed without resolving to `mkForce` or similar.
@hauleth hauleth force-pushed the ft/add-systemd-hardening-helpers branch from 6cb1804 to 3011b77 Compare February 13, 2024 14:19
@networkException
Copy link
Member

networkException commented Feb 13, 2024

I fear this will get extremely complex with lots of services needing edge case configurations. This would lead to a rather unpleasant mix of serviceConfig overrides with some harden attributes set.

As the scope of this option is extremely wide I would propose creating an RFC for discussing a proper design (before it becomes stable and much less easy to change) with considerations for already existing hardening options like confinement.

I don't want to go too much into said design discussion here but I think a better approach would be to have a harden option create a completely unpriviliged service by default with options (and presets) for the service to gain more priviliges. This is easier to extend by individual users accounting for special use cases a service module might not have considered and avoids serviceConfig pollution.

@hauleth
Copy link
Contributor Author

hauleth commented Feb 13, 2024

This would lead to a rather unpleasant mix of serviceConfig overrides with some harden attributes set.

I do not get why that would be unpleasant. We cannot cover everything with just custom helpers without almost literally copying everything into harden. My exact goal there was to provide "sane defaults" with some basic escape hatches and at the same time if someone needs something more custom, then can (and should) use serviceConfig directly.

I think a better approach would be to have a harden option create a completely unpriviliged service by default with options (and presets) for the service to gain more priviliges.

That is pretty much how it works in current PR state.

@aanderse
Copy link
Member

As the scope of this option is extremely wide I would propose creating an RFC for discussing a proper design

+1

@nixos-discourse
Copy link

This pull request has been mentioned on NixOS Discourse. There might be relevant details there:

https://discourse.nixos.org/t/pre-rfc-systemd-hardening/39772/1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants