diff --git a/utils/apparmor/profile_list.py b/utils/apparmor/profile_list.py index 0ea23d55e..99e8ccfed 100644 --- a/utils/apparmor/profile_list.py +++ b/utils/apparmor/profile_list.py @@ -14,6 +14,7 @@ from apparmor.aare import AARE from apparmor.common import AppArmorBug, AppArmorException +from apparmor.rule.include import IncludeRule, IncludeRuleset # setup module translations from apparmor.translations import init_translation @@ -21,7 +22,12 @@ _ = init_translation() class ProfileList: - ''' Stores the list of profiles (both name and attachment) and in which files they live ''' + ''' Stores the preamble section and the list of profile(s) (both name and + attachment) that live in profile files. + + Also allows "reverse" lookups to find out in which file a profile + lives. + ''' def __init__(self): self.profile_names = {} # profile name -> filename @@ -34,6 +40,7 @@ class ProfileList: return # don't re-initialize / overwrite existing data self.files[filename] = { + 'inc_ie': IncludeRuleset(), 'profiles': [], } @@ -66,6 +73,33 @@ class ProfileList: else: self.files[filename]['profiles'].append(attachment) + def add_inc_ie(self, filename, inc_rule): + ''' Store the given include / include if exists rule for the given profile filename preamble ''' + if type(inc_rule) is not IncludeRule: + raise AppArmorBug('Wrong type given to ProfileList: %s' % inc_rule) + + self.init_file(filename) + + self.files[filename]['inc_ie'].add(inc_rule) + + def get_raw(self, filename, depth=0): + ''' Get the preamble for the given profile filename (in original formatting) ''' + if not self.files.get(filename): + raise AppArmorBug('%s not listed in ProfileList files' % filename) + + data = [] + data += self.files[filename]['inc_ie'].get_raw(depth) + return data + + def get_clean(self, filename, depth=0): + ''' Get the preamble for the given profile filename (in clean formatting) ''' + if not self.files.get(filename): + raise AppArmorBug('%s not listed in ProfileList files' % filename) + + data = [] + data += self.files[filename]['inc_ie'].get_clean_unsorted(depth) + return data + def filename_from_profile_name(self, name): ''' Return profile filename for the given profile name, or None ''' diff --git a/utils/test/test-profile-list.py b/utils/test/test-profile-list.py index 21b6f28c8..cd96c47e3 100644 --- a/utils/test/test-profile-list.py +++ b/utils/test/test-profile-list.py @@ -14,6 +14,7 @@ from common_test import AATest, setup_all_loops from apparmor.common import AppArmorBug, AppArmorException from apparmor.profile_list import ProfileList +from apparmor.rule.include import IncludeRule class TestAdd_profile(AATest): def AASetup(self): @@ -114,6 +115,40 @@ class TestFilename_from_attachment(AATest): with self.assertRaises(AppArmorBug): self.pl.filename_from_attachment('foo') +class TestAdd_inc_ie(AATest): + def AASetup(self): + self.pl = ProfileList() + + def testAdd_inc_ie_1(self): + self.pl.add_inc_ie('/etc/apparmor.d/bin.foo', IncludeRule('tunables/global', False, True)) + self.assertEqual(list(self.pl.files.keys()), ['/etc/apparmor.d/bin.foo']) + self.assertEqual(self.pl.get_clean('/etc/apparmor.d/bin.foo'), ['include ', '']) + self.assertEqual(self.pl.get_raw('/etc/apparmor.d/bin.foo'), ['include ', '']) + + def testAdd_inc_ie_2(self): + self.pl.add_inc_ie('/etc/apparmor.d/bin.foo', IncludeRule('tunables/global', False, True)) + self.pl.add_inc_ie('/etc/apparmor.d/bin.foo', IncludeRule('tunables/dovecot', False, True)) + self.assertEqual(list(self.pl.files.keys()), ['/etc/apparmor.d/bin.foo']) + self.assertEqual(self.pl.get_clean('/etc/apparmor.d/bin.foo'), ['include ', 'include ', '']) + self.assertEqual(self.pl.get_raw('/etc/apparmor.d/bin.foo'), ['include ', 'include ', '']) + + def testAdd_inc_ie_error_1(self): + with self.assertRaises(AppArmorBug): + self.pl.add_inc_ie('/etc/apparmor.d/bin.foo', 'tunables/global') # str insteadd of IncludeRule + self.assertEqual(list(self.pl.files.keys()), []) + +class TestGet(AATest): + def AASetup(self): + self.pl = ProfileList() + + def testGet_clean_error(self): + with self.assertRaises(AppArmorBug): + self.pl.get_clean('/etc/apparmor.d/not.found') + + def testGet_raw_error(self): + with self.assertRaises(AppArmorBug): + self.pl.get_raw('/etc/apparmor.d/not.found') + setup_all_loops(__name__) if __name__ == '__main__':