From 0e3707191aa0a033d3c09ae4105007ba5bec5fe9 Mon Sep 17 00:00:00 2001 From: Grimmauld Date: Tue, 3 Dec 2024 22:18:24 +0100 Subject: [PATCH] nixos/tests/apparmor: refactor, add tests for profile enforce level, add test for profile path linking and contents --- nixos/tests/all-tests.nix | 2 +- nixos/tests/apparmor.nix | 115 ------------------ nixos/tests/apparmor/default.nix | 104 ++++++++++++++++ nixos/tests/apparmor/makeExpectedPolicies.nix | 66 ++++++++++ nixos/tests/apparmor/sl_profile | 5 + 5 files changed, 176 insertions(+), 116 deletions(-) delete mode 100644 nixos/tests/apparmor.nix create mode 100644 nixos/tests/apparmor/default.nix create mode 100644 nixos/tests/apparmor/makeExpectedPolicies.nix create mode 100644 nixos/tests/apparmor/sl_profile diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 6f941cc254ad46..dbaaf38273ea8a 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -131,7 +131,7 @@ in { apfs = runTest ./apfs.nix; appliance-repart-image = runTest ./appliance-repart-image.nix; appliance-repart-image-verity-store = runTest ./appliance-repart-image-verity-store.nix; - apparmor = handleTest ./apparmor.nix {}; + apparmor = handleTest ./apparmor {}; archi = handleTest ./archi.nix {}; aria2 = handleTest ./aria2.nix {}; armagetronad = handleTest ./armagetronad.nix {}; diff --git a/nixos/tests/apparmor.nix b/nixos/tests/apparmor.nix deleted file mode 100644 index 58566508535dae..00000000000000 --- a/nixos/tests/apparmor.nix +++ /dev/null @@ -1,115 +0,0 @@ -import ./make-test-python.nix ( - { pkgs, lib, ... }: - { - name = "apparmor"; - meta.maintainers = with lib.maintainers; [ julm ]; - - nodes.machine = - { - lib, - pkgs, - config, - ... - }: - { - security.apparmor.enable = lib.mkDefault true; - }; - - testScript = '' - machine.wait_for_unit("multi-user.target") - - with subtest("AppArmor profiles are loaded"): - machine.succeed("systemctl status apparmor.service") - - # AppArmor securityfs - with subtest("AppArmor securityfs is mounted"): - machine.succeed("mountpoint -q /sys/kernel/security") - machine.succeed("cat /sys/kernel/security/apparmor/profiles") - - # Test apparmorRulesFromClosure by: - # 1. Prepending a string of the relevant packages' name and version on each line. - # 2. Sorting according to those strings. - # 3. Removing those prepended strings. - # 4. Using `diff` against the expected output. - with subtest("apparmorRulesFromClosure"): - machine.succeed( - "${pkgs.diffutils}/bin/diff -u ${pkgs.writeText "expected.rules" '' - ixr ${pkgs.bash}/libexec/**, - mr ${pkgs.bash}/lib/**.so*, - mr ${pkgs.bash}/lib64/**.so*, - mr ${pkgs.bash}/share/**, - r ${pkgs.bash}, - r ${pkgs.bash}/etc/**, - r ${pkgs.bash}/lib/**, - r ${pkgs.bash}/lib64/**, - x ${pkgs.bash}/foo/**, - ixr ${pkgs.glibc}/libexec/**, - mr ${pkgs.glibc}/lib/**.so*, - mr ${pkgs.glibc}/lib64/**.so*, - mr ${pkgs.glibc}/share/**, - r ${pkgs.glibc}, - r ${pkgs.glibc}/etc/**, - r ${pkgs.glibc}/lib/**, - r ${pkgs.glibc}/lib64/**, - x ${pkgs.glibc}/foo/**, - ixr ${pkgs.libcap}/libexec/**, - mr ${pkgs.libcap}/lib/**.so*, - mr ${pkgs.libcap}/lib64/**.so*, - mr ${pkgs.libcap}/share/**, - r ${pkgs.libcap}, - r ${pkgs.libcap}/etc/**, - r ${pkgs.libcap}/lib/**, - r ${pkgs.libcap}/lib64/**, - x ${pkgs.libcap}/foo/**, - ixr ${pkgs.libcap.lib}/libexec/**, - mr ${pkgs.libcap.lib}/lib/**.so*, - mr ${pkgs.libcap.lib}/lib64/**.so*, - mr ${pkgs.libcap.lib}/share/**, - r ${pkgs.libcap.lib}, - r ${pkgs.libcap.lib}/etc/**, - r ${pkgs.libcap.lib}/lib/**, - r ${pkgs.libcap.lib}/lib64/**, - x ${pkgs.libcap.lib}/foo/**, - ixr ${pkgs.libidn2.out}/libexec/**, - mr ${pkgs.libidn2.out}/lib/**.so*, - mr ${pkgs.libidn2.out}/lib64/**.so*, - mr ${pkgs.libidn2.out}/share/**, - r ${pkgs.libidn2.out}, - r ${pkgs.libidn2.out}/etc/**, - r ${pkgs.libidn2.out}/lib/**, - r ${pkgs.libidn2.out}/lib64/**, - x ${pkgs.libidn2.out}/foo/**, - ixr ${pkgs.libunistring}/libexec/**, - mr ${pkgs.libunistring}/lib/**.so*, - mr ${pkgs.libunistring}/lib64/**.so*, - mr ${pkgs.libunistring}/share/**, - r ${pkgs.libunistring}, - r ${pkgs.libunistring}/etc/**, - r ${pkgs.libunistring}/lib/**, - r ${pkgs.libunistring}/lib64/**, - x ${pkgs.libunistring}/foo/**, - ixr ${pkgs.glibc.libgcc}/libexec/**, - mr ${pkgs.glibc.libgcc}/lib/**.so*, - mr ${pkgs.glibc.libgcc}/lib64/**.so*, - mr ${pkgs.glibc.libgcc}/share/**, - r ${pkgs.glibc.libgcc}, - r ${pkgs.glibc.libgcc}/etc/**, - r ${pkgs.glibc.libgcc}/lib/**, - r ${pkgs.glibc.libgcc}/lib64/**, - x ${pkgs.glibc.libgcc}/foo/**, - ''} ${ - pkgs.runCommand "actual.rules" { preferLocalBuild = true; } '' - ${pkgs.gnused}/bin/sed -e 's:^[^ ]* ${builtins.storeDir}/[^,/-]*-\([^/,]*\):\1 \0:' ${ - pkgs.apparmorRulesFromClosure { - name = "ping"; - additionalRules = [ "x $path/foo/**" ]; - } [ pkgs.libcap ] - } | - ${pkgs.coreutils}/bin/sort -n -k1 | - ${pkgs.gnused}/bin/sed -e 's:^[^ ]* ::' >$out - '' - }" - ) - ''; - } -) diff --git a/nixos/tests/apparmor/default.nix b/nixos/tests/apparmor/default.nix new file mode 100644 index 00000000000000..a39fd0b6b3a72f --- /dev/null +++ b/nixos/tests/apparmor/default.nix @@ -0,0 +1,104 @@ +import ../make-test-python.nix ( + { pkgs, lib, ... }: + let + helloProfileContents = '' + abi , + include + profile hello ${lib.getExe pkgs.hello} { + include + } + ''; + in + { + name = "apparmor"; + meta.maintainers = with lib.maintainers; [ julm ]; + + nodes.machine = + { + lib, + pkgs, + config, + ... + }: + { + security.apparmor = { + enable = lib.mkDefault true; + + policies.hello = { + # test profile enforce and content definition + state = "enforce"; + profile = helloProfileContents; + }; + + policies.sl = { + # test profile complain and path definition + state = "complain"; + path = ./sl_profile; + }; + }; + }; + + testScript = '' + machine.wait_for_unit("multi-user.target") + + with subtest("AppArmor profiles are loaded"): + machine.succeed("systemctl status apparmor.service") + + # AppArmor securityfs + with subtest("AppArmor securityfs is mounted"): + machine.succeed("mountpoint -q /sys/kernel/security") + machine.succeed("cat /sys/kernel/security/apparmor/profiles") + + # Test apparmorRulesFromClosure by: + # 1. Prepending a string of the relevant packages' name and version on each line. + # 2. Sorting according to those strings. + # 3. Removing those prepended strings. + # 4. Using `diff` against the expected output. + with subtest("apparmorRulesFromClosure"): + machine.succeed( + "${pkgs.diffutils}/bin/diff -u ${ + pkgs.writeText "expected.rules" (import ./makeExpectedPolicies.nix { inherit pkgs; }) + } ${ + pkgs.runCommand "actual.rules" { preferLocalBuild = true; } '' + ${pkgs.gnused}/bin/sed -e 's:^[^ ]* ${builtins.storeDir}/[^,/-]*-\([^/,]*\):\1 \0:' ${ + pkgs.apparmorRulesFromClosure { + name = "ping"; + additionalRules = [ "x $path/foo/**" ]; + } [ pkgs.libcap ] + } | + ${pkgs.coreutils}/bin/sort -n -k1 | + ${pkgs.gnused}/bin/sed -e 's:^[^ ]* ::' >$out + '' + }" + ) + + # Test apparmor profile states by using `diff` against `aa-status` + with subtest("apparmorProfileStates"): + machine.succeed("${pkgs.diffutils}/bin/diff -u <(${pkgs.apparmor-bin-utils}/bin/aa-status) ${pkgs.writeText "expected.states" '' + apparmor module is loaded. + 2 profiles are loaded. + 1 profiles are in enforce mode. + hello + 1 profiles are in complain mode. + sl + 0 profiles are in prompt mode. + 0 profiles are in kill mode. + 0 profiles are in unconfined mode. + 0 processes have profiles defined. + 0 processes are in enforce mode. + 0 processes are in complain mode. + 0 processes are in prompt mode. + 0 processes are in kill mode. + 0 processes are unconfined but have a profile defined. + 0 processes are in mixed mode. + ''}") + + # Test apparmor profile files in /etc/apparmor.d/ to be either a correct symlink (sl) or have the right file contents (hello) + with subtest("apparmorProfileTargets"): + machine.succeed("${pkgs.diffutils}/bin/diff -u <(${pkgs.file}/bin/file /etc/static/apparmor.d/sl) ${pkgs.writeText "expected.link" '' + /etc/static/apparmor.d/sl: symbolic link to ${./sl_profile} + ''}") + machine.succeed("${pkgs.diffutils}/bin/diff -u /etc/static/apparmor.d/hello ${pkgs.writeText "expected.content" helloProfileContents}") + ''; + } +) diff --git a/nixos/tests/apparmor/makeExpectedPolicies.nix b/nixos/tests/apparmor/makeExpectedPolicies.nix new file mode 100644 index 00000000000000..0d9238b6853067 --- /dev/null +++ b/nixos/tests/apparmor/makeExpectedPolicies.nix @@ -0,0 +1,66 @@ +{ pkgs }: +'' + ixr ${pkgs.bash}/libexec/**, + mr ${pkgs.bash}/lib/**.so*, + mr ${pkgs.bash}/lib64/**.so*, + mr ${pkgs.bash}/share/**, + r ${pkgs.bash}, + r ${pkgs.bash}/etc/**, + r ${pkgs.bash}/lib/**, + r ${pkgs.bash}/lib64/**, + x ${pkgs.bash}/foo/**, + ixr ${pkgs.glibc}/libexec/**, + mr ${pkgs.glibc}/lib/**.so*, + mr ${pkgs.glibc}/lib64/**.so*, + mr ${pkgs.glibc}/share/**, + r ${pkgs.glibc}, + r ${pkgs.glibc}/etc/**, + r ${pkgs.glibc}/lib/**, + r ${pkgs.glibc}/lib64/**, + x ${pkgs.glibc}/foo/**, + ixr ${pkgs.libcap}/libexec/**, + mr ${pkgs.libcap}/lib/**.so*, + mr ${pkgs.libcap}/lib64/**.so*, + mr ${pkgs.libcap}/share/**, + r ${pkgs.libcap}, + r ${pkgs.libcap}/etc/**, + r ${pkgs.libcap}/lib/**, + r ${pkgs.libcap}/lib64/**, + x ${pkgs.libcap}/foo/**, + ixr ${pkgs.libcap.lib}/libexec/**, + mr ${pkgs.libcap.lib}/lib/**.so*, + mr ${pkgs.libcap.lib}/lib64/**.so*, + mr ${pkgs.libcap.lib}/share/**, + r ${pkgs.libcap.lib}, + r ${pkgs.libcap.lib}/etc/**, + r ${pkgs.libcap.lib}/lib/**, + r ${pkgs.libcap.lib}/lib64/**, + x ${pkgs.libcap.lib}/foo/**, + ixr ${pkgs.libidn2.out}/libexec/**, + mr ${pkgs.libidn2.out}/lib/**.so*, + mr ${pkgs.libidn2.out}/lib64/**.so*, + mr ${pkgs.libidn2.out}/share/**, + r ${pkgs.libidn2.out}, + r ${pkgs.libidn2.out}/etc/**, + r ${pkgs.libidn2.out}/lib/**, + r ${pkgs.libidn2.out}/lib64/**, + x ${pkgs.libidn2.out}/foo/**, + ixr ${pkgs.libunistring}/libexec/**, + mr ${pkgs.libunistring}/lib/**.so*, + mr ${pkgs.libunistring}/lib64/**.so*, + mr ${pkgs.libunistring}/share/**, + r ${pkgs.libunistring}, + r ${pkgs.libunistring}/etc/**, + r ${pkgs.libunistring}/lib/**, + r ${pkgs.libunistring}/lib64/**, + x ${pkgs.libunistring}/foo/**, + ixr ${pkgs.glibc.libgcc}/libexec/**, + mr ${pkgs.glibc.libgcc}/lib/**.so*, + mr ${pkgs.glibc.libgcc}/lib64/**.so*, + mr ${pkgs.glibc.libgcc}/share/**, + r ${pkgs.glibc.libgcc}, + r ${pkgs.glibc.libgcc}/etc/**, + r ${pkgs.glibc.libgcc}/lib/**, + r ${pkgs.glibc.libgcc}/lib64/**, + x ${pkgs.glibc.libgcc}/foo/**, +'' diff --git a/nixos/tests/apparmor/sl_profile b/nixos/tests/apparmor/sl_profile new file mode 100644 index 00000000000000..f37c80f8e0134d --- /dev/null +++ b/nixos/tests/apparmor/sl_profile @@ -0,0 +1,5 @@ +abi , +include +profile sl /bin/sl { + include +}