mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 16:35:02 +01:00
[23/38] Add get_file_perms() to aa.py
get_file_perms() collects the existing permissions for a file from various rules (exact matches, wildcards) in the main profile and the included abstractions. It will be used to get displaying the current permissions back, and also to propose rules with merged permissions (next patch). Also add some tests to make sure it does what it promises ;-) Acked-by: Steve Beattie <steve@nxnw.org>
This commit is contained in:
parent
435281f018
commit
f2a60f67e3
2 changed files with 99 additions and 1 deletions
|
@ -3758,6 +3758,40 @@ def is_known_rule(profile, rule_type, rule_obj):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def get_file_perms(profile, path, audit, deny):
|
||||||
|
'''get the current permissions for the given path'''
|
||||||
|
|
||||||
|
perms = profile['file'].get_perms_for_path(path, audit, deny)
|
||||||
|
|
||||||
|
includelist = list(profile['include'].keys())
|
||||||
|
checked = []
|
||||||
|
|
||||||
|
while includelist:
|
||||||
|
incname = includelist.pop(0)
|
||||||
|
|
||||||
|
if incname in checked:
|
||||||
|
continue
|
||||||
|
checked.append(incname)
|
||||||
|
|
||||||
|
if os.path.isdir(profile_dir + '/' + incname):
|
||||||
|
includelist += include_dir_filelist(profile_dir, incname)
|
||||||
|
else:
|
||||||
|
incperms = include[incname][incname]['file'].get_perms_for_path(path, audit, deny)
|
||||||
|
|
||||||
|
for allow_or_deny in ['allow', 'deny']:
|
||||||
|
for owner_or_all in ['all', 'owner']:
|
||||||
|
for perm in incperms[allow_or_deny][owner_or_all]:
|
||||||
|
perms[allow_or_deny][owner_or_all].add(perm)
|
||||||
|
|
||||||
|
for incpath in incperms['paths']:
|
||||||
|
perms['paths'].add(incpath)
|
||||||
|
|
||||||
|
for childinc in include[incname][incname]['include'].keys():
|
||||||
|
if childinc not in checked:
|
||||||
|
includelist += [childinc]
|
||||||
|
|
||||||
|
return perms
|
||||||
|
|
||||||
def reload_base(bin_path):
|
def reload_base(bin_path):
|
||||||
if not check_for_apparmor():
|
if not check_for_apparmor():
|
||||||
return None
|
return None
|
||||||
|
|
|
@ -21,8 +21,9 @@ import apparmor.aa # needed to set global vars in some tests
|
||||||
from apparmor.aa import (check_for_apparmor, get_output, get_reqs, get_interpreter_and_abstraction, create_new_profile,
|
from apparmor.aa import (check_for_apparmor, get_output, get_reqs, get_interpreter_and_abstraction, create_new_profile,
|
||||||
get_profile_flags, set_profile_flags, is_skippable_file, is_skippable_dir,
|
get_profile_flags, set_profile_flags, is_skippable_file, is_skippable_dir,
|
||||||
parse_profile_start, parse_profile_data, separate_vars, store_list_var, write_header,
|
parse_profile_start, parse_profile_data, separate_vars, store_list_var, write_header,
|
||||||
var_transform, serialize_parse_profile_start)
|
var_transform, serialize_parse_profile_start, get_file_perms)
|
||||||
from apparmor.common import AppArmorException, AppArmorBug
|
from apparmor.common import AppArmorException, AppArmorBug
|
||||||
|
from apparmor.rule.file import FileRule
|
||||||
|
|
||||||
class AaTestWithTempdir(AATest):
|
class AaTestWithTempdir(AATest):
|
||||||
def AASetup(self):
|
def AASetup(self):
|
||||||
|
@ -735,6 +736,69 @@ class AaTestInvalid_serialize_parse_profile_start(AATest):
|
||||||
# 'correct' is always True in the code that uses serialize_parse_profile_start() (set some lines above the function call)
|
# 'correct' is always True in the code that uses serialize_parse_profile_start() (set some lines above the function call)
|
||||||
serialize_parse_profile_start(line, 'somefile', 1, profile, hat, prof_data_profile, prof_data_external, True)
|
serialize_parse_profile_start(line, 'somefile', 1, profile, hat, prof_data_profile, prof_data_external, True)
|
||||||
|
|
||||||
|
class AaTest_get_file_perms_1(AATest):
|
||||||
|
tests = [
|
||||||
|
('/usr/share/common-licenses/foo/bar', {'allow': {'all': set(), 'owner': {'w'} }, 'deny': {'all':set(), 'owner': set()}, 'paths': {'/usr/share/common-licenses/**'} }),
|
||||||
|
('/dev/null', {'allow': {'all': {'r', 'w', 'k'}, 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': {'/dev/null'} }),
|
||||||
|
('/foo/bar', {'allow': {'all': {'r', 'w'}, 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': {'/foo/bar'} }), # exec perms not included
|
||||||
|
('/no/thing', {'allow': {'all': set(), 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': set() }),
|
||||||
|
('/usr/lib/ispell/', {'allow': {'all': set(), 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': set() }),
|
||||||
|
('/usr/lib/aspell/*.so', {'allow': {'all': set(), 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': set() }),
|
||||||
|
]
|
||||||
|
|
||||||
|
def _run_test(self, params, expected):
|
||||||
|
self.createTmpdir()
|
||||||
|
|
||||||
|
#copy the local profiles to the test directory
|
||||||
|
self.profile_dir = '%s/profiles' % self.tmpdir
|
||||||
|
shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True)
|
||||||
|
|
||||||
|
profile = apparmor.aa.profile_storage('/test', '/test', 'test-aa.py')
|
||||||
|
|
||||||
|
# simple profile without any includes
|
||||||
|
profile['file'].add(FileRule.parse('owner /usr/share/common-licenses/** w,'))
|
||||||
|
profile['file'].add(FileRule.parse('/dev/null rwk,'))
|
||||||
|
profile['file'].add(FileRule.parse('/foo/bar rwix,'))
|
||||||
|
|
||||||
|
perms = get_file_perms(profile, params, False, False) # only testing with audit and deny = False
|
||||||
|
self.assertEqual(perms, expected)
|
||||||
|
|
||||||
|
class AaTest_get_file_perms_2(AATest):
|
||||||
|
tests = [
|
||||||
|
('/usr/share/common-licenses/foo/bar', {'allow': {'all': {'r'}, 'owner': {'w'} }, 'deny': {'all':set(), 'owner': set()}, 'paths': {'/usr/share/common-licenses/**'} }),
|
||||||
|
('/dev/null', {'allow': {'all': {'r', 'w', 'k'}, 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': {'/dev/null'} }),
|
||||||
|
('/foo/bar', {'allow': {'all': {'r', 'w'}, 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': {'/foo/bar'} }), # exec perms not included
|
||||||
|
('/no/thing', {'allow': {'all': set(), 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': set() }),
|
||||||
|
('/usr/lib/ispell/', {'allow': {'all': {'r'}, 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': {'/usr/lib/ispell/', '/usr/lib{,32,64}/**'} }), # from abstractions/enchant
|
||||||
|
('/usr/lib/aspell/*.so', {'allow': {'all': {'m', 'r'}, 'owner': set() }, 'deny': {'all':set(), 'owner': set()}, 'paths': {'/usr/lib/aspell/*', '/usr/lib/aspell/*.so', '/usr/lib{,32,64}/**'} }), # from abstractions/aspell via abstractions/enchant
|
||||||
|
]
|
||||||
|
|
||||||
|
def _run_test(self, params, expected):
|
||||||
|
self.createTmpdir()
|
||||||
|
|
||||||
|
#copy the local profiles to the test directory
|
||||||
|
self.profile_dir = '%s/profiles' % self.tmpdir
|
||||||
|
shutil.copytree('../../profiles/apparmor.d/', self.profile_dir, symlinks=True)
|
||||||
|
|
||||||
|
# load the abstractions we need in the test
|
||||||
|
apparmor.aa.profiledir = self.profile_dir
|
||||||
|
apparmor.aa.load_include('abstractions/base')
|
||||||
|
apparmor.aa.load_include('abstractions/bash')
|
||||||
|
apparmor.aa.load_include('abstractions/enchant')
|
||||||
|
apparmor.aa.load_include('abstractions/aspell')
|
||||||
|
|
||||||
|
profile = apparmor.aa.profile_storage('/test', '/test', 'test-aa.py')
|
||||||
|
profile['include']['abstractions/base'] = True
|
||||||
|
profile['include']['abstractions/bash'] = True
|
||||||
|
profile['include']['abstractions/enchant'] = True # includes abstractions/aspell
|
||||||
|
|
||||||
|
profile['file'].add(FileRule.parse('owner /usr/share/common-licenses/** w,'))
|
||||||
|
profile['file'].add(FileRule.parse('/dev/null rwk,'))
|
||||||
|
profile['file'].add(FileRule.parse('/foo/bar rwix,'))
|
||||||
|
|
||||||
|
perms = get_file_perms(profile, params, False, False) # only testing with audit and deny = False
|
||||||
|
self.assertEqual(perms, expected)
|
||||||
|
|
||||||
|
|
||||||
setup_all_loops(__name__)
|
setup_all_loops(__name__)
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
Loading…
Add table
Reference in a new issue