2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-31 06:16:03 +00:00

add get_all_merged_variables()

This function returns a dict with all variables and their values for a
given profile file. It also checks for redefined variables, and adding
to non-existing variables, and errors out in both cases. Note that it
does not check the include order and is therefore more forgiving than
apparmor_parser.

Also add some tests for get_all_merged_variables().

Note: the tests are based on reading "real" profiles, therefore we need
to initialize apparmor.aa and call some of its functions.

The alternative would be to construct ProfileList objects for some
profiles and includes manually, but doing that in a way that can replace
the tests with "real" profiles would be quite some work, and I'm not
bored enough for that ;-)
This commit is contained in:
Christian Boltz
2020-05-23 00:02:49 +02:00
parent b13037e36d
commit 7451c341a6
2 changed files with 132 additions and 1 deletions

View File

@@ -10,7 +10,11 @@
# ------------------------------------------------------------------
import unittest
from common_test import AATest, setup_all_loops
from common_test import AATest, setup_aa, setup_all_loops, write_file
import apparmor.aa
import os
import shutil
from apparmor.common import AppArmorBug, AppArmorException
from apparmor.profile_list import ProfileList
@@ -285,7 +289,74 @@ class TestGet(AATest):
with self.assertRaises(AppArmorBug):
self.pl.get_raw('/etc/apparmor.d/not.found')
class AaTest_get_all_merged_variables(AATest):
tests = []
def AASetup(self):
self.createTmpdir()
# copy the local profiles to the test directory
self.profile_dir = '%s/profiles' % self.tmpdir
apparmor.aa.profile_dir = self.profile_dir
shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True)
def _load_profiles(self):
apparmor.aa.reset_aa()
# load the profiles and abstractions
apparmor.aa.profiledir = self.profile_dir
apparmor.aa.loadincludes()
apparmor.aa.read_profiles()
def test_unchanged(self):
self._load_profiles()
prof_filename = os.path.join(self.profile_dir, 'usr.sbin.dnsmasq')
vars = apparmor.aa.active_profiles.get_all_merged_variables(os.path.join(self.profile_dir, 'usr.sbin.dnsmasq'), apparmor.aa.include_list_recursive(apparmor.aa.active_profiles.files[prof_filename]), self.profile_dir)
self.assertEqual(vars['@{TFTP_DIR}'], {'/var/tftp', '/srv/tftp', '/srv/tftpboot'})
self.assertEqual(vars['@{HOME}'], {'@{HOMEDIRS}/*/', '/root/'})
def test_extended_home(self):
write_file(self.profile_dir, 'tunables/home.d/extend_home', '@{HOME} += /my/castle/')
self._load_profiles()
prof_filename = os.path.join(self.profile_dir, 'usr.sbin.dnsmasq')
vars = apparmor.aa.active_profiles.get_all_merged_variables(os.path.join(self.profile_dir, 'usr.sbin.dnsmasq'), apparmor.aa.include_list_recursive(apparmor.aa.active_profiles.files[prof_filename]), self.profile_dir)
self.assertEqual(vars['@{TFTP_DIR}'], {'/var/tftp', '/srv/tftp', '/srv/tftpboot'})
self.assertEqual(vars['@{HOME}'], {'@{HOMEDIRS}/*/', '/root/', '/my/castle/'})
def test_extended_home_2(self):
write_file(self.profile_dir, 'tunables/home.d/extend_home', '@{HOME} += /my/castle/')
write_file(self.profile_dir, 'tunables/home.d/moving_around', '@{HOME} += /on/the/road/')
self._load_profiles()
prof_filename = os.path.join(self.profile_dir, 'usr.sbin.dnsmasq')
vars = apparmor.aa.active_profiles.get_all_merged_variables(os.path.join(self.profile_dir, 'usr.sbin.dnsmasq'), apparmor.aa.include_list_recursive(apparmor.aa.active_profiles.files[prof_filename]), self.profile_dir)
self.assertEqual(vars['@{TFTP_DIR}'], {'/var/tftp', '/srv/tftp', '/srv/tftpboot'})
self.assertEqual(vars['@{HOME}'], {'@{HOMEDIRS}/*/', '/root/', '/my/castle/', '/on/the/road/'})
def test_extend_home_in_mainfile(self):
write_file(self.profile_dir, 'tunables/home.d/extend_home', '@{HOME} += /my/castle/')
write_file(self.profile_dir, 'dummy_profile', 'include <tunables/global>\n@{HOME} += /in/the/profile/')
self._load_profiles()
prof_filename = os.path.join(self.profile_dir, 'dummy_profile')
vars = apparmor.aa.active_profiles.get_all_merged_variables(os.path.join(self.profile_dir, 'dummy_profile'), apparmor.aa.include_list_recursive(apparmor.aa.active_profiles.files[prof_filename]), self.profile_dir)
self.assertEqual(vars.get('@{TFTP_DIR}', None), None)
self.assertEqual(vars['@{HOME}'], {'@{HOMEDIRS}/*/', '/root/', '/my/castle/', '/in/the/profile/'})
def test_redefine_home(self):
write_file(self.profile_dir, 'tunables/home.d/overwrite_home', '@{HOME} = /my/castle/') # note: =, not +=
self._load_profiles()
prof_filename = os.path.join(self.profile_dir, 'usr.sbin.dnsmasq')
with self.assertRaises(AppArmorException):
apparmor.aa.active_profiles.get_all_merged_variables(os.path.join(self.profile_dir, 'usr.sbin.dnsmasq'), apparmor.aa.include_list_recursive(apparmor.aa.active_profiles.files[prof_filename]), self.profile_dir)
def test_add_to_nonexisting(self):
write_file(self.profile_dir, 'tunables/home.d/no_such_var', '@{NO_SUCH_HOME} += /my/castle/') # add to non-existing variable
self._load_profiles()
prof_filename = os.path.join(self.profile_dir, 'usr.sbin.dnsmasq')
with self.assertRaises(AppArmorException):
apparmor.aa.active_profiles.get_all_merged_variables(os.path.join(self.profile_dir, 'usr.sbin.dnsmasq'), apparmor.aa.include_list_recursive(apparmor.aa.active_profiles.files[prof_filename]), self.profile_dir)
setup_aa(apparmor.aa)
setup_all_loops(__name__)
if __name__ == '__main__':
unittest.main(verbosity=1)