mirror of
https://github.com/NixOS/nixpkgs.git
synced 2025-07-13 21:50:33 +03:00
nixos/apparmor: profile activation tristate and profile path support
This commit is contained in:
parent
1f750cfa3d
commit
e87b9b1f3e
2 changed files with 61 additions and 40 deletions
|
@ -162,6 +162,9 @@
|
|||
| virtualBoxOVA | virtualbox-vagrant.box | nixos-image-vagrant-virtualbox-25.05pre-git-x86_64-linux.ova |
|
||||
| vmwareImage | nixos-25.05pre-git-x86_64-linux.vmdk | nixos-image-vmware-25.05pre-git-x86_64-linux.vmdk |
|
||||
|
||||
- `security.apparmor.policies.<name>.enforce` and `security.apparmor.policies.<name>.enable` were removed.
|
||||
Configuring the state of apparmor policies must now be done using `security.apparmor.policies.<name>.state` tristate option.
|
||||
|
||||
- the notmuch vim plugin now lives in a separate output of the `notmuch`
|
||||
package. Installing `notmuch` will not bring the notmuch vim package anymore,
|
||||
add `vimPlugins.notmuch-vim` to your (Neo)vim configuration if you want the
|
||||
|
|
|
@ -5,24 +5,16 @@
|
|||
...
|
||||
}:
|
||||
let
|
||||
inherit (builtins)
|
||||
attrNames
|
||||
head
|
||||
map
|
||||
match
|
||||
readFile
|
||||
;
|
||||
inherit (lib) types;
|
||||
inherit (config.environment) etc;
|
||||
cfg = config.security.apparmor;
|
||||
mkDisableOption =
|
||||
name:
|
||||
lib.mkEnableOption name
|
||||
// {
|
||||
default = true;
|
||||
example = false;
|
||||
};
|
||||
enabledPolicies = lib.filterAttrs (n: p: p.enable) cfg.policies;
|
||||
enabledPolicies = lib.filterAttrs (n: p: p.state != "disable") cfg.policies;
|
||||
buildPolicyPath = n: p: lib.defaultTo (pkgs.writeText n p.profile) p.path;
|
||||
|
||||
# Accessing submodule options when not defined results in an error thunk rather than a regular option object
|
||||
# We can emulate the behavior of `<option>.isDefined` by attempting to evaluate it instead
|
||||
# This is required because getting isDefined on a submodule is not possible in global module asserts.
|
||||
submoduleOptionIsDefined = value: (builtins.tryEval value).success;
|
||||
in
|
||||
|
||||
{
|
||||
|
@ -31,7 +23,7 @@ in
|
|||
"security"
|
||||
"apparmor"
|
||||
"confineSUIDApplications"
|
||||
] "Please use the new options: `security.apparmor.policies.<policy>.enable'.")
|
||||
] "Please use the new options: `security.apparmor.policies.<policy>.state'.")
|
||||
(lib.mkRemovedOptionModule [
|
||||
"security"
|
||||
"apparmor"
|
||||
|
@ -65,20 +57,32 @@ in
|
|||
AppArmor policies.
|
||||
'';
|
||||
type = types.attrsOf (
|
||||
types.submodule (
|
||||
{ name, config, ... }:
|
||||
{
|
||||
types.submodule {
|
||||
options = {
|
||||
enable = mkDisableOption "loading of the profile into the kernel";
|
||||
enforce = mkDisableOption "enforcing of the policy or only complain in the logs";
|
||||
state = lib.mkOption {
|
||||
description = "How strictly this policy should be enforced";
|
||||
type = types.enum [
|
||||
"disable"
|
||||
"complain"
|
||||
"enforce"
|
||||
];
|
||||
# should enforce really be the default?
|
||||
# the docs state that this should only be used once one is REALLY sure nothing's gonna break
|
||||
default = "enforce";
|
||||
};
|
||||
|
||||
profile = lib.mkOption {
|
||||
description = "The policy of the profile.";
|
||||
description = "The profile file contents. Incompatible with path.";
|
||||
type = types.lines;
|
||||
apply = pkgs.writeText name;
|
||||
};
|
||||
|
||||
path = lib.mkOption {
|
||||
description = "A path of a profile file to include. Incompatible with profile.";
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
};
|
||||
};
|
||||
}
|
||||
)
|
||||
);
|
||||
default = { };
|
||||
};
|
||||
|
@ -117,12 +121,20 @@ in
|
|||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
assertions = map (policy: {
|
||||
assertion = match ".*/.*" policy == null;
|
||||
message = "`security.apparmor.policies.\"${policy}\"' must not contain a slash.";
|
||||
assertions = lib.concatLists (
|
||||
lib.mapAttrsToList (policyName: policyCfg: [
|
||||
{
|
||||
assertion = builtins.match ".*/.*" policyName == null;
|
||||
message = "`security.apparmor.policies.\"${policyName}\"' must not contain a slash.";
|
||||
# Because, for instance, aa-remove-unknown uses profiles_names_list() in rc.apparmor.functions
|
||||
# which does not recurse into sub-directories.
|
||||
}) (attrNames cfg.policies);
|
||||
}
|
||||
{
|
||||
assertion = lib.xor (policyCfg.path != null) (submoduleOptionIsDefined policyCfg.profile);
|
||||
message = "`security.apparmor.policies.\"${policyName}\"` must define exactly one of either path or profile.";
|
||||
}
|
||||
]) cfg.policies
|
||||
);
|
||||
|
||||
environment.systemPackages = [
|
||||
pkgs.apparmor-utils
|
||||
|
@ -133,7 +145,7 @@ in
|
|||
# because aa-remove-unknown reads profiles from all /etc/apparmor.d/*
|
||||
lib.mapAttrsToList (name: p: {
|
||||
inherit name;
|
||||
path = p.profile;
|
||||
path = buildPolicyPath name p;
|
||||
}) enabledPolicies
|
||||
++ lib.mapAttrsToList (name: path: { inherit name path; }) cfg.includes
|
||||
);
|
||||
|
@ -226,21 +238,24 @@ in
|
|||
kill
|
||||
'';
|
||||
commonOpts =
|
||||
p: "--verbose --show-cache ${lib.optionalString (!p.enforce) "--complain "}${p.profile}";
|
||||
n: p:
|
||||
"--verbose --show-cache ${
|
||||
lib.optionalString (p.state == "complain") "--complain "
|
||||
}${buildPolicyPath n p}";
|
||||
in
|
||||
{
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = "yes";
|
||||
ExecStartPre = "${pkgs.apparmor-utils}/bin/aa-teardown";
|
||||
ExecStart = lib.mapAttrsToList (
|
||||
n: p: "${pkgs.apparmor-parser}/bin/apparmor_parser --add ${commonOpts p}"
|
||||
n: p: "${pkgs.apparmor-parser}/bin/apparmor_parser --add ${commonOpts n p}"
|
||||
) enabledPolicies;
|
||||
ExecStartPost = lib.optional cfg.killUnconfinedConfinables killUnconfinedConfinables;
|
||||
ExecReload =
|
||||
# Add or replace into the kernel profiles in enabledPolicies
|
||||
# (because AppArmor can do that without stopping the processes already confined).
|
||||
lib.mapAttrsToList (
|
||||
n: p: "${pkgs.apparmor-parser}/bin/apparmor_parser --replace ${commonOpts p}"
|
||||
n: p: "${pkgs.apparmor-parser}/bin/apparmor_parser --replace ${commonOpts n p}"
|
||||
) enabledPolicies
|
||||
++
|
||||
# Remove from the kernel any profile whose name is not
|
||||
|
@ -262,5 +277,8 @@ in
|
|||
};
|
||||
};
|
||||
|
||||
meta.maintainers = with lib.maintainers; [ julm grimmauld ];
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
julm
|
||||
grimmauld
|
||||
];
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue