mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00
Merge Improve and simplify profile parsing in the tools
This is done by introducing a match_line_against_rule_classes() function to get of repeating code in parse_profile_data(). A side effect is a better separation of preamble and profile data, which needed changes at several places - especially include rules in the preamble were funny\[tm\]. MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/719 Acked-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
commit
3f51877220
6 changed files with 116 additions and 144 deletions
|
@ -46,15 +46,13 @@ from apparmor.regex import (RE_PROFILE_START, RE_PROFILE_END,
|
|||
RE_PROFILE_UNIX, RE_RULE_HAS_COMMA, RE_HAS_COMMENT_SPLIT,
|
||||
strip_quotes, parse_profile_start_line, re_match_include )
|
||||
|
||||
from apparmor.profile_list import ProfileList
|
||||
from apparmor.profile_list import ProfileList, preamble_ruletypes
|
||||
|
||||
from apparmor.profile_storage import ProfileStorage, add_or_remove_flag, ruletypes
|
||||
|
||||
import apparmor.rules as aarules
|
||||
|
||||
from apparmor.rule.abi import AbiRule
|
||||
from apparmor.rule.alias import AliasRule
|
||||
from apparmor.rule.boolean import BooleanRule
|
||||
from apparmor.rule.capability import CapabilityRule
|
||||
from apparmor.rule.change_profile import ChangeProfileRule
|
||||
from apparmor.rule.dbus import DbusRule
|
||||
|
@ -62,9 +60,7 @@ from apparmor.rule.file import FileRule
|
|||
from apparmor.rule.include import IncludeRule
|
||||
from apparmor.rule.network import NetworkRule
|
||||
from apparmor.rule.ptrace import PtraceRule
|
||||
from apparmor.rule.rlimit import RlimitRule
|
||||
from apparmor.rule.signal import SignalRule
|
||||
from apparmor.rule.variable import VariableRule
|
||||
from apparmor.rule import quote_if_needed
|
||||
|
||||
# setup module translations
|
||||
|
@ -871,7 +867,7 @@ def ask_exec(hashlog):
|
|||
|
||||
prof_filename = get_profile_filename_from_profile_name(profile)
|
||||
if prof_filename and active_profiles.files.get(prof_filename):
|
||||
sev_db.set_variables(active_profiles.get_all_merged_variables(prof_filename, include_list_recursive(active_profiles.files[prof_filename])))
|
||||
sev_db.set_variables(active_profiles.get_all_merged_variables(prof_filename, include_list_recursive(active_profiles.files[prof_filename], True)))
|
||||
else:
|
||||
sev_db.set_variables( {} )
|
||||
|
||||
|
@ -1075,7 +1071,7 @@ def ask_the_questions(log_dict):
|
|||
for profile in sorted(log_dict[aamode].keys()):
|
||||
prof_filename = get_profile_filename_from_profile_name(profile)
|
||||
if prof_filename and active_profiles.files.get(prof_filename):
|
||||
sev_db.set_variables(active_profiles.get_all_merged_variables(prof_filename, include_list_recursive(active_profiles.files[prof_filename])))
|
||||
sev_db.set_variables(active_profiles.get_all_merged_variables(prof_filename, include_list_recursive(active_profiles.files[prof_filename], True)))
|
||||
else:
|
||||
sev_db.set_variables( {} )
|
||||
|
||||
|
@ -1728,7 +1724,7 @@ def read_profile(file, active_profile):
|
|||
debug_logger.debug("read_profile: can't read %s - skipping" % file)
|
||||
return None
|
||||
|
||||
profile_data = parse_profile_data(data, file, 0)
|
||||
profile_data = parse_profile_data(data, file, 0, True)
|
||||
|
||||
if profile_data and active_profile:
|
||||
attach_profile_data(aa, profile_data)
|
||||
|
@ -1826,7 +1822,7 @@ def parse_profile_start_to_storage(line, file, lineno, profile, hat):
|
|||
|
||||
return (profile, hat, prof_storage)
|
||||
|
||||
def parse_profile_data(data, file, do_include):
|
||||
def parse_profile_data(data, file, do_include, in_preamble):
|
||||
profile_data = hasher()
|
||||
profile = None
|
||||
hat = None
|
||||
|
@ -1835,6 +1831,8 @@ def parse_profile_data(data, file, do_include):
|
|||
initial_comment = ''
|
||||
lastline = None
|
||||
|
||||
active_profiles.init_file(file)
|
||||
|
||||
if do_include:
|
||||
profile = file
|
||||
hat = file
|
||||
|
@ -1849,8 +1847,20 @@ def parse_profile_data(data, file, do_include):
|
|||
if lastline:
|
||||
line = '%s %s' % (lastline, line)
|
||||
lastline = None
|
||||
# Starting line of a profile
|
||||
if RE_PROFILE_START.search(line):
|
||||
|
||||
# is line handled by a *Rule class?
|
||||
(rule_name, rule_obj) = match_line_against_rule_classes(line, profile, file, lineno, in_preamble)
|
||||
if rule_name:
|
||||
if in_preamble:
|
||||
active_profiles.add_rule(file, rule_name, rule_obj)
|
||||
else:
|
||||
profile_data[profile][hat][rule_name].add(rule_obj)
|
||||
|
||||
if rule_name == 'inc_ie':
|
||||
for incname in rule_obj.get_full_paths(profile_dir):
|
||||
load_include(incname, in_preamble)
|
||||
|
||||
elif RE_PROFILE_START.search(line): # Starting line of a profile
|
||||
# in_contained_hat is needed to know if we are already in a profile or not. (Simply checking if we are in a hat doesn't work,
|
||||
# because something like "profile foo//bar" will set profile and hat at once, and later (wrongfully) expect another "}".
|
||||
# The logic is simple and resembles a "poor man's stack" (with limited/hardcoded height).
|
||||
|
@ -1859,6 +1869,8 @@ def parse_profile_data(data, file, do_include):
|
|||
else:
|
||||
in_contained_hat = False
|
||||
|
||||
in_preamble = False
|
||||
|
||||
(profile, hat, prof_storage) = parse_profile_start_to_storage(line, file, lineno, profile, hat)
|
||||
|
||||
if profile_data[profile].get(hat, False):
|
||||
|
@ -1884,48 +1896,10 @@ def parse_profile_data(data, file, do_include):
|
|||
else:
|
||||
parsed_profiles.append(profile)
|
||||
profile = None
|
||||
in_preamble = True
|
||||
|
||||
initial_comment = ''
|
||||
|
||||
elif CapabilityRule.match(line):
|
||||
if not profile:
|
||||
raise AppArmorException(_('Syntax Error: Unexpected capability entry found in file: %(file)s line: %(line)s') % { 'file': file, 'line': lineno + 1 })
|
||||
|
||||
profile_data[profile][hat]['capability'].add(CapabilityRule.parse(line))
|
||||
|
||||
elif ChangeProfileRule.match(line):
|
||||
if not profile:
|
||||
raise AppArmorException(_('Syntax Error: Unexpected change profile entry found in file: %(file)s line: %(line)s') % { 'file': file, 'line': lineno + 1 })
|
||||
|
||||
profile_data[profile][hat]['change_profile'].add(ChangeProfileRule.parse(line))
|
||||
|
||||
elif AliasRule.match(line):
|
||||
if profile and not do_include:
|
||||
raise AppArmorException(_('Syntax Error: Unexpected alias definition found inside profile in file: %(file)s line: %(line)s') % {
|
||||
'file': file, 'line': lineno + 1 })
|
||||
else:
|
||||
active_profiles.add_alias(file, AliasRule.parse(line))
|
||||
|
||||
elif RlimitRule.match(line):
|
||||
if not profile:
|
||||
raise AppArmorException(_('Syntax Error: Unexpected rlimit entry found in file: %(file)s line: %(line)s') % { 'file': file, 'line': lineno + 1 })
|
||||
|
||||
profile_data[profile][hat]['rlimit'].add(RlimitRule.parse(line))
|
||||
|
||||
elif BooleanRule.match(line):
|
||||
if profile and not do_include:
|
||||
raise AppArmorException(_('Syntax Error: Unexpected boolean definition found inside profile in file: %(file)s line: %(line)s') % {
|
||||
'file': file, 'line': lineno + 1 })
|
||||
else:
|
||||
active_profiles.add_boolean(file, BooleanRule.parse(line))
|
||||
|
||||
elif VariableRule.match(line):
|
||||
if profile and not do_include:
|
||||
raise AppArmorException(_('Syntax Error: Unexpected variable definition found inside profile in file: %(file)s line: %(line)s') % {
|
||||
'file': file, 'line': lineno + 1 })
|
||||
else:
|
||||
active_profiles.add_variable(file, VariableRule.parse(line))
|
||||
|
||||
elif RE_PROFILE_CONDITIONAL.search(line):
|
||||
# Conditional Boolean
|
||||
pass
|
||||
|
@ -1938,34 +1912,6 @@ def parse_profile_data(data, file, do_include):
|
|||
# Conditional Boolean defined
|
||||
pass
|
||||
|
||||
elif AbiRule.match(line):
|
||||
if profile:
|
||||
profile_data[profile][hat]['abi'].add(AbiRule.parse(line))
|
||||
else:
|
||||
active_profiles.add_abi(file, AbiRule.parse(line))
|
||||
|
||||
elif IncludeRule.match(line):
|
||||
rule_obj = IncludeRule.parse(line)
|
||||
if profile:
|
||||
profile_data[profile][hat]['inc_ie'].add(rule_obj)
|
||||
else:
|
||||
active_profiles.add_inc_ie(file, rule_obj)
|
||||
|
||||
for incname in rule_obj.get_full_paths(profile_dir):
|
||||
load_include(incname)
|
||||
|
||||
elif NetworkRule.match(line):
|
||||
if not profile:
|
||||
raise AppArmorException(_('Syntax Error: Unexpected network entry found in file: %(file)s line: %(line)s') % { 'file': file, 'line': lineno + 1 })
|
||||
|
||||
profile_data[profile][hat]['network'].add(NetworkRule.parse(line))
|
||||
|
||||
elif DbusRule.match(line):
|
||||
if not profile:
|
||||
raise AppArmorException(_('Syntax Error: Unexpected dbus entry found in file: %(file)s line: %(line)s') % {'file': file, 'line': lineno + 1 })
|
||||
|
||||
profile_data[profile][hat]['dbus'].add(DbusRule.parse(line))
|
||||
|
||||
elif RE_PROFILE_MOUNT.search(line):
|
||||
matches = RE_PROFILE_MOUNT.search(line).groups()
|
||||
|
||||
|
@ -1988,18 +1934,6 @@ def parse_profile_data(data, file, do_include):
|
|||
mount_rules.append(mount_rule)
|
||||
profile_data[profile][hat][allow]['mount'] = mount_rules
|
||||
|
||||
elif SignalRule.match(line):
|
||||
if not profile:
|
||||
raise AppArmorException(_('Syntax Error: Unexpected signal entry found in file: %(file)s line: %(line)s') % { 'file': file, 'line': lineno + 1 })
|
||||
|
||||
profile_data[profile][hat]['signal'].add(SignalRule.parse(line))
|
||||
|
||||
elif PtraceRule.match(line):
|
||||
if not profile:
|
||||
raise AppArmorException(_('Syntax Error: Unexpected ptrace entry found in file: %(file)s line: %(line)s') % { 'file': file, 'line': lineno + 1 })
|
||||
|
||||
profile_data[profile][hat]['ptrace'].add(PtraceRule.parse(line))
|
||||
|
||||
elif RE_PROFILE_PIVOT_ROOT.search(line):
|
||||
matches = RE_PROFILE_PIVOT_ROOT.search(line).groups()
|
||||
|
||||
|
@ -2097,13 +2031,6 @@ def parse_profile_data(data, file, do_include):
|
|||
# keep line as part of initial_comment (if we ever support writing abstractions, we should update serialize_profile())
|
||||
initial_comment = initial_comment + line + '\n'
|
||||
|
||||
elif FileRule.match(line):
|
||||
# leading permissions could look like a keyword, therefore handle file rules after everything else
|
||||
if not profile:
|
||||
raise AppArmorException(_('Syntax Error: Unexpected path entry found in file: %(file)s line: %(line)s') % { 'file': file, 'line': lineno + 1 })
|
||||
|
||||
profile_data[profile][hat]['file'].add(FileRule.parse(line))
|
||||
|
||||
elif not RE_RULE_HAS_COMMA.search(line):
|
||||
# Bah, line continues on to the next line
|
||||
if RE_HAS_COMMENT_SPLIT.search(line):
|
||||
|
@ -2134,6 +2061,42 @@ def parse_profile_data(data, file, do_include):
|
|||
|
||||
return profile_data
|
||||
|
||||
def match_line_against_rule_classes(line, profile, file, lineno, in_preamble):
|
||||
''' handle all lines handled by *Rule classes '''
|
||||
|
||||
for rule_name in [
|
||||
'abi',
|
||||
'alias',
|
||||
'boolean',
|
||||
'variable',
|
||||
'inc_ie',
|
||||
'capability',
|
||||
'change_profile',
|
||||
'dbus',
|
||||
'file', # file rules need to be parsed after variable rules
|
||||
'network',
|
||||
'ptrace',
|
||||
'rlimit',
|
||||
'signal',
|
||||
]:
|
||||
|
||||
if rule_name in ruletypes:
|
||||
rule_class = ruletypes[rule_name]['rule']
|
||||
else:
|
||||
rule_class = preamble_ruletypes[rule_name]['rule']
|
||||
|
||||
if rule_class.match(line):
|
||||
if not in_preamble and rule_name not in ruletypes:
|
||||
raise AppArmorException(_('Syntax Error: Unexpected %(rule)s definition found inside profile in file: %(file)s line: %(line)s') % { 'file': file, 'line': lineno + 1, 'rule': rule_name })
|
||||
|
||||
if in_preamble and rule_name not in preamble_ruletypes:
|
||||
raise AppArmorException(_('Syntax Error: Unexpected %(rule)s entry found in file: %(file)s line: %(line)s') % { 'file': file, 'line': lineno + 1, 'rule': rule_name })
|
||||
|
||||
rule_obj = rule_class.parse(line)
|
||||
return(rule_name, rule_obj)
|
||||
|
||||
return(None, None)
|
||||
|
||||
def parse_mount_rule(line):
|
||||
# XXX Do real parsing here
|
||||
return aarules.Raw_Mount_Rule(line)
|
||||
|
@ -2296,7 +2259,7 @@ def write_profile(profile, is_attachment=False):
|
|||
|
||||
original_aa[profile] = deepcopy(aa[profile])
|
||||
|
||||
def include_list_recursive(profile):
|
||||
def include_list_recursive(profile, in_preamble=False):
|
||||
''' get a list of all includes in a profile and its included files '''
|
||||
|
||||
includelist = profile['inc_ie'].get_all_full_paths(profile_dir)
|
||||
|
@ -2309,7 +2272,12 @@ def include_list_recursive(profile):
|
|||
continue
|
||||
full_list.append(incname)
|
||||
|
||||
for childinc in include[incname][incname]['inc_ie'].rules:
|
||||
if in_preamble:
|
||||
look_at = active_profiles.files[incname]
|
||||
else:
|
||||
look_at = include[incname][incname]
|
||||
|
||||
for childinc in look_at['inc_ie'].rules:
|
||||
for childinc_file in childinc.get_full_paths(profile_dir):
|
||||
if childinc_file not in full_list:
|
||||
includelist += [childinc_file]
|
||||
|
@ -2440,7 +2408,7 @@ def include_dir_filelist(include_name):
|
|||
|
||||
return files
|
||||
|
||||
def load_include(incname):
|
||||
def load_include(incname, in_preamble=False):
|
||||
load_includeslist = [incname]
|
||||
while load_includeslist:
|
||||
incfile = load_includeslist.pop(0)
|
||||
|
@ -2451,7 +2419,7 @@ def load_include(incname):
|
|||
pass # already read, do nothing
|
||||
elif os.path.isfile(incfile):
|
||||
data = get_include_data(incfile)
|
||||
incdata = parse_profile_data(data, incfile, True)
|
||||
incdata = parse_profile_data(data, incfile, True, in_preamble)
|
||||
attach_profile_data(include, incdata)
|
||||
#If the include is a directory means include all subfiles
|
||||
elif os.path.isdir(incfile):
|
||||
|
@ -2475,10 +2443,10 @@ def get_subdirectories(current_dir):
|
|||
return os.walk(current_dir).__next__()[1]
|
||||
|
||||
def loadincludes():
|
||||
loadincludes_dir('tunables')
|
||||
loadincludes_dir('abstractions')
|
||||
loadincludes_dir('tunables', True)
|
||||
loadincludes_dir('abstractions', False)
|
||||
|
||||
def loadincludes_dir(subdir):
|
||||
def loadincludes_dir(subdir, in_preamble):
|
||||
idir = os.path.join(profile_dir, subdir)
|
||||
|
||||
if os.path.isdir(idir): # if directory doesn't exist, silently skip loading it
|
||||
|
@ -2488,7 +2456,7 @@ def loadincludes_dir(subdir):
|
|||
continue
|
||||
else:
|
||||
fi = os.path.join(dirpath, fi)
|
||||
load_include(fi)
|
||||
load_include(fi, in_preamble)
|
||||
|
||||
def glob_common(path):
|
||||
globs = []
|
||||
|
|
|
@ -90,6 +90,13 @@ class ProfileList:
|
|||
else:
|
||||
self.files[filename]['profiles'].append(attachment)
|
||||
|
||||
def add_rule(self, filename, ruletype, rule):
|
||||
''' Store the given rule for the given profile filename preamble '''
|
||||
|
||||
self.init_file(filename)
|
||||
|
||||
self.files[filename][ruletype].add(rule)
|
||||
|
||||
def add_abi(self, filename, abi_rule):
|
||||
''' Store the given abi rule for the given profile filename preamble '''
|
||||
|
||||
|
@ -226,9 +233,6 @@ class ProfileList:
|
|||
inc_add[filename] = mainfile_variables['+='] # variable additions from main file
|
||||
|
||||
for incname in all_incfiles:
|
||||
if not self.files.get(incname):
|
||||
continue # tunables/* only end up in self.files if they contain variable or alias definitions
|
||||
|
||||
inc_vars = self.files[incname]['variable'].get_merged_variables()
|
||||
|
||||
for var in inc_vars['=']:
|
||||
|
|
|
@ -16,16 +16,16 @@
|
|||
|
||||
from apparmor.common import AppArmorBug, type_is_str
|
||||
|
||||
from apparmor.rule.abi import AbiRuleset
|
||||
from apparmor.rule.capability import CapabilityRuleset
|
||||
from apparmor.rule.change_profile import ChangeProfileRuleset
|
||||
from apparmor.rule.dbus import DbusRuleset
|
||||
from apparmor.rule.file import FileRuleset
|
||||
from apparmor.rule.include import IncludeRuleset
|
||||
from apparmor.rule.network import NetworkRuleset
|
||||
from apparmor.rule.ptrace import PtraceRuleset
|
||||
from apparmor.rule.rlimit import RlimitRuleset
|
||||
from apparmor.rule.signal import SignalRuleset
|
||||
from apparmor.rule.abi import AbiRule, AbiRuleset
|
||||
from apparmor.rule.capability import CapabilityRule, CapabilityRuleset
|
||||
from apparmor.rule.change_profile import ChangeProfileRule, ChangeProfileRuleset
|
||||
from apparmor.rule.dbus import DbusRule, DbusRuleset
|
||||
from apparmor.rule.file import FileRule, FileRuleset
|
||||
from apparmor.rule.include import IncludeRule, IncludeRuleset
|
||||
from apparmor.rule.network import NetworkRule, NetworkRuleset
|
||||
from apparmor.rule.ptrace import PtraceRule, PtraceRuleset
|
||||
from apparmor.rule.rlimit import RlimitRule, RlimitRuleset
|
||||
from apparmor.rule.signal import SignalRule, SignalRuleset
|
||||
|
||||
from apparmor.rule import quote_if_needed
|
||||
|
||||
|
@ -34,16 +34,16 @@ from apparmor.translations import init_translation
|
|||
_ = init_translation()
|
||||
|
||||
ruletypes = {
|
||||
'abi': {'ruleset': AbiRuleset},
|
||||
'inc_ie': {'ruleset': IncludeRuleset},
|
||||
'capability': {'ruleset': CapabilityRuleset},
|
||||
'change_profile': {'ruleset': ChangeProfileRuleset},
|
||||
'dbus': {'ruleset': DbusRuleset},
|
||||
'file': {'ruleset': FileRuleset},
|
||||
'network': {'ruleset': NetworkRuleset},
|
||||
'ptrace': {'ruleset': PtraceRuleset},
|
||||
'rlimit': {'ruleset': RlimitRuleset},
|
||||
'signal': {'ruleset': SignalRuleset},
|
||||
'abi': {'rule': AbiRule, 'ruleset': AbiRuleset, },
|
||||
'inc_ie': {'rule': IncludeRule, 'ruleset': IncludeRuleset, },
|
||||
'capability': {'rule': CapabilityRule, 'ruleset': CapabilityRuleset, },
|
||||
'change_profile': {'rule': ChangeProfileRule, 'ruleset': ChangeProfileRuleset, },
|
||||
'dbus': {'rule': DbusRule, 'ruleset': DbusRuleset, },
|
||||
'file': {'rule': FileRule, 'ruleset': FileRuleset, },
|
||||
'network': {'rule': NetworkRule, 'ruleset': NetworkRuleset, },
|
||||
'ptrace': {'rule': PtraceRule, 'ruleset': PtraceRuleset, },
|
||||
'rlimit': {'rule': RlimitRule, 'ruleset': RlimitRuleset, },
|
||||
'signal': {'rule': SignalRule, 'ruleset': SignalRuleset, },
|
||||
}
|
||||
|
||||
class ProfileStorage:
|
||||
|
|
|
@ -521,7 +521,7 @@ class AaTest_parse_profile_start_errors(AATest):
|
|||
|
||||
class AaTest_parse_profile_data(AATest):
|
||||
def test_parse_empty_profile_01(self):
|
||||
prof = parse_profile_data('/foo {\n}\n'.split(), 'somefile', False)
|
||||
prof = parse_profile_data('/foo {\n}\n'.split(), 'somefile', False, False)
|
||||
|
||||
self.assertEqual(list(prof.keys()), ['/foo'])
|
||||
self.assertEqual(list(prof['/foo'].keys()), ['/foo'])
|
||||
|
@ -532,20 +532,20 @@ class AaTest_parse_profile_data(AATest):
|
|||
def test_parse_duplicate_profile(self):
|
||||
with self.assertRaises(AppArmorException):
|
||||
# file contains two profiles with the same name
|
||||
parse_profile_data('profile /foo {\n}\nprofile /foo {\n}\n'.split(), 'somefile', False)
|
||||
parse_profile_data('profile /foo {\n}\nprofile /foo {\n}\n'.split(), 'somefile', False, False)
|
||||
|
||||
def test_parse_duplicate_child_profile(self):
|
||||
with self.assertRaises(AppArmorException):
|
||||
# file contains two child profiles with the same name
|
||||
parse_profile_data('profile /foo {\nprofile /bar {\n}\nprofile /bar {\n}\n}\n'.split(), 'somefile', False)
|
||||
parse_profile_data('profile /foo {\nprofile /bar {\n}\nprofile /bar {\n}\n}\n'.split(), 'somefile', False, False)
|
||||
|
||||
def test_parse_duplicate_hat(self):
|
||||
with self.assertRaises(AppArmorException):
|
||||
# file contains two hats with the same name
|
||||
parse_profile_data('profile /foo {\n^baz {\n}\n^baz {\n}\n}\n'.split(), 'somefile', False)
|
||||
parse_profile_data('profile /foo {\n^baz {\n}\n^baz {\n}\n}\n'.split(), 'somefile', False, False)
|
||||
|
||||
def test_parse_xattrs_01(self):
|
||||
prof = parse_profile_data('/foo xattrs=(user.bar=bar) {\n}\n'.split(), 'somefile', False)
|
||||
prof = parse_profile_data('/foo xattrs=(user.bar=bar) {\n}\n'.split(), 'somefile', False, False)
|
||||
|
||||
self.assertEqual(list(prof.keys()), ['/foo'])
|
||||
self.assertEqual(list(prof['/foo'].keys()), ['/foo'])
|
||||
|
@ -555,7 +555,7 @@ class AaTest_parse_profile_data(AATest):
|
|||
self.assertEqual(prof['/foo']['/foo']['xattrs'], 'user.bar=bar')
|
||||
|
||||
def test_parse_xattrs_02(self):
|
||||
prof = parse_profile_data('/foo xattrs=(user.bar=bar user.foo=*) {\n}\n'.split(), 'somefile', False)
|
||||
prof = parse_profile_data('/foo xattrs=(user.bar=bar user.foo=*) {\n}\n'.split(), 'somefile', False, False)
|
||||
|
||||
self.assertEqual(list(prof.keys()), ['/foo'])
|
||||
self.assertEqual(list(prof['/foo'].keys()), ['/foo'])
|
||||
|
@ -566,7 +566,7 @@ class AaTest_parse_profile_data(AATest):
|
|||
|
||||
def test_parse_xattrs_03(self):
|
||||
d = '/foo xattrs=(user.bar=bar) flags=(complain) {\n}\n'
|
||||
prof = parse_profile_data(d.split(), 'somefile', False)
|
||||
prof = parse_profile_data(d.split(), 'somefile', False, False)
|
||||
|
||||
self.assertEqual(list(prof.keys()), ['/foo'])
|
||||
self.assertEqual(list(prof['/foo'].keys()), ['/foo'])
|
||||
|
@ -579,7 +579,7 @@ class AaTest_parse_profile_data(AATest):
|
|||
with self.assertRaises(AppArmorException):
|
||||
# flags before xattrs
|
||||
d = '/foo flags=(complain) xattrs=(user.bar=bar) {\n}\n'
|
||||
parse_profile_data(d.split(), 'somefile', False)
|
||||
parse_profile_data(d.split(), 'somefile', False, False)
|
||||
|
||||
class AaTest_write_header(AATest):
|
||||
tests = [
|
||||
|
|
|
@ -430,12 +430,12 @@ class TestParseParserTests(AATest):
|
|||
apparmor.active_profiles.init_file(params['file'])
|
||||
|
||||
if expected:
|
||||
apparmor.parse_profile_data(data, params['file'], 0)
|
||||
apparmor.parse_profile_data(data, params['file'], 0, True)
|
||||
apparmor.active_profiles.get_all_merged_variables(params['file'], apparmor.include_list_recursive(apparmor.active_profiles.files[params['file']]))
|
||||
|
||||
else:
|
||||
with self.assertRaises(AppArmorException):
|
||||
apparmor.parse_profile_data(data, params['file'], 0)
|
||||
apparmor.parse_profile_data(data, params['file'], 0, True)
|
||||
apparmor.active_profiles.get_all_merged_variables(params['file'], apparmor.include_list_recursive(apparmor.active_profiles.files[params['file']]))
|
||||
|
||||
def parse_test_profiles(file_with_path):
|
||||
|
|
|
@ -344,7 +344,7 @@ class AaTest_get_all_merged_variables(AATest):
|
|||
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]))
|
||||
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], True))
|
||||
self.assertEqual(vars['@{TFTP_DIR}'], {'/var/tftp', '/srv/tftp', '/srv/tftpboot'})
|
||||
self.assertEqual(vars['@{HOME}'], {'@{HOMEDIRS}/*/', '/root/'})
|
||||
|
||||
|
@ -352,7 +352,7 @@ class AaTest_get_all_merged_variables(AATest):
|
|||
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]))
|
||||
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], True))
|
||||
self.assertEqual(vars['@{TFTP_DIR}'], {'/var/tftp', '/srv/tftp', '/srv/tftpboot'})
|
||||
self.assertEqual(vars['@{HOME}'], {'@{HOMEDIRS}/*/', '/root/', '/my/castle/'})
|
||||
|
||||
|
@ -361,7 +361,7 @@ class AaTest_get_all_merged_variables(AATest):
|
|||
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]))
|
||||
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], True))
|
||||
self.assertEqual(vars['@{TFTP_DIR}'], {'/var/tftp', '/srv/tftp', '/srv/tftpboot'})
|
||||
self.assertEqual(vars['@{HOME}'], {'@{HOMEDIRS}/*/', '/root/', '/my/castle/', '/on/the/road/'})
|
||||
|
||||
|
@ -370,7 +370,7 @@ class AaTest_get_all_merged_variables(AATest):
|
|||
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]))
|
||||
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], True))
|
||||
self.assertEqual(vars.get('@{TFTP_DIR}', None), None)
|
||||
self.assertEqual(vars['@{HOME}'], {'@{HOMEDIRS}/*/', '/root/', '/my/castle/', '/in/the/profile/'})
|
||||
|
||||
|
@ -379,14 +379,14 @@ class AaTest_get_all_merged_variables(AATest):
|
|||
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]))
|
||||
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], True))
|
||||
|
||||
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]))
|
||||
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], True))
|
||||
|
||||
def test_vars_from_nonexisting_profile(self):
|
||||
with self.assertRaises(AppArmorBug):
|
||||
|
|
Loading…
Add table
Reference in a new issue