From 36c29a8371073851ad12780a21b171a528ee2531 Mon Sep 17 00:00:00 2001 From: Ryan Yin Date: Wed, 26 Aug 2026 17:24:27 +0800 Subject: [PATCH] security: enable AppArmor (complain) on all Linux hosts --- hardening/apparmor/default.nix | 58 +++++++++---------- modules/nixos/base/default.nix | 2 +- modules/nixos/server/server-aarch64.nix | 4 ++ .../tests/security-apparmor/expected.nix | 5 ++ .../tests/security-apparmor/expr.nix | 7 +++ .../tests/security-apparmor/expected.nix | 5 ++ .../tests/security-apparmor/expr.nix | 7 +++ 7 files changed, 55 insertions(+), 33 deletions(-) create mode 100644 outputs/aarch64-linux/tests/security-apparmor/expected.nix create mode 100644 outputs/aarch64-linux/tests/security-apparmor/expr.nix create mode 100644 outputs/x86_64-linux/tests/security-apparmor/expected.nix create mode 100644 outputs/x86_64-linux/tests/security-apparmor/expr.nix diff --git a/hardening/apparmor/default.nix b/hardening/apparmor/default.nix index 887ccecb..6b63e2d5 100644 --- a/hardening/apparmor/default.nix +++ b/hardening/apparmor/default.nix @@ -4,56 +4,50 @@ ... }: { + # AppArmor: activate the LSM + load policies. Roll out in complain mode first + # (log violations, never block) so nothing can break; promote profiles to + # "enforce" individually once stable. services.dbus.apparmor = "enabled"; + security.apparmor = { enable = true; - # kill process that are not confined but have apparmor profiles enabled - killUnconfinedConfinables = true; - packages = with pkgs; [ - apparmor-utils - apparmor-profiles - ]; + # Do not SIGTERM running unconfined-but-confinable processes yet. + # Safe to flip to true later now that no global default-deny profile is active. + killUnconfinedConfinables = false; + + # Packages contributing to AppArmor's include path (abstractions). + # NOTE: these are FHS-oriented; nixpkgs adds FHS->NixOS aliases so they mostly work, + # but treat resulting profiles as complain-only until verified. + packages = [ pkgs.apparmor-profiles ]; - # apparmor policies policies = { + # Global default-deny scaffold. DANGEROUS to enable: `/**` matches every binary and + # the empty block allows nothing. Keep disabled until per-app profiles exist. "default_deny" = { - enforce = false; - enable = false; - profile = '' - profile default_deny /** { } - ''; + state = "disable"; + profile = "profile default_deny /** { }"; }; + # Confine sudo; complain mode so a missing rule logs instead of blocking. "sudo" = { - enforce = false; - enable = false; + state = "complain"; profile = '' - ${pkgs.sudo}/bin/sudo { + abi , + include + + profile ${pkgs.sudo}/bin/sudo { + include file /** rwlkUx, } ''; }; + # nix runs unconfined (no restriction); inert, kept disabled. "nix" = { - enforce = false; - enable = false; - profile = '' - ${config.nix.package}/bin/nix { - unconfined, - } - ''; + state = "disable"; + profile = "profile ${config.nix.package}/bin/nix { unconfined, }"; }; }; }; - - environment.systemPackages = with pkgs; [ - apparmor-bin-utils - apparmor-profiles - apparmor-parser - libapparmor - apparmor-kernel-patches - apparmor-pam - apparmor-utils - ]; } diff --git a/modules/nixos/base/default.nix b/modules/nixos/base/default.nix index 049dda93..8b8274f3 100644 --- a/modules/nixos/base/default.nix +++ b/modules/nixos/base/default.nix @@ -1,4 +1,4 @@ { mylib, ... }: { - imports = mylib.scanPaths ./.; + imports = mylib.scanPaths ./. ++ [ (mylib.relativeToRoot "hardening/apparmor") ]; } diff --git a/modules/nixos/server/server-aarch64.nix b/modules/nixos/server/server-aarch64.nix index ce56dc4a..7ac802cb 100644 --- a/modules/nixos/server/server-aarch64.nix +++ b/modules/nixos/server/server-aarch64.nix @@ -1,6 +1,7 @@ { lib, pkgs, + mylib, ... }: { @@ -15,6 +16,9 @@ ../base/user-group.nix ../../base + # AppArmor is wired via modules/nixos/base/default.nix for other hosts; this + # aarch64 server imports base files individually, so add it explicitly. + (mylib.relativeToRoot "hardening/apparmor") ]; # Servers run on the trusted internal LAN (NAT'd; WAN protected at the router). diff --git a/outputs/aarch64-linux/tests/security-apparmor/expected.nix b/outputs/aarch64-linux/tests/security-apparmor/expected.nix new file mode 100644 index 00000000..81b3fbb5 --- /dev/null +++ b/outputs/aarch64-linux/tests/security-apparmor/expected.nix @@ -0,0 +1,5 @@ +{ + lib, + outputs, +}: +lib.genAttrs (builtins.attrNames outputs.nixosConfigurations) (_: true) diff --git a/outputs/aarch64-linux/tests/security-apparmor/expr.nix b/outputs/aarch64-linux/tests/security-apparmor/expr.nix new file mode 100644 index 00000000..2b76bf01 --- /dev/null +++ b/outputs/aarch64-linux/tests/security-apparmor/expr.nix @@ -0,0 +1,7 @@ +{ + lib, + outputs, +}: +lib.genAttrs (builtins.attrNames outputs.nixosConfigurations) ( + name: outputs.nixosConfigurations.${name}.config.security.apparmor.enable +) diff --git a/outputs/x86_64-linux/tests/security-apparmor/expected.nix b/outputs/x86_64-linux/tests/security-apparmor/expected.nix new file mode 100644 index 00000000..81b3fbb5 --- /dev/null +++ b/outputs/x86_64-linux/tests/security-apparmor/expected.nix @@ -0,0 +1,5 @@ +{ + lib, + outputs, +}: +lib.genAttrs (builtins.attrNames outputs.nixosConfigurations) (_: true) diff --git a/outputs/x86_64-linux/tests/security-apparmor/expr.nix b/outputs/x86_64-linux/tests/security-apparmor/expr.nix new file mode 100644 index 00000000..2b76bf01 --- /dev/null +++ b/outputs/x86_64-linux/tests/security-apparmor/expr.nix @@ -0,0 +1,7 @@ +{ + lib, + outputs, +}: +lib.genAttrs (builtins.attrNames outputs.nixosConfigurations) ( + name: outputs.nixosConfigurations.${name}.config.security.apparmor.enable +)