mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-09-03 07:45:50 +00:00
IncludeRule: add get_full_paths()
This function returns a list of paths for an include rule. This can be - a single path if the include file is a file and exists - a single path if the include file doesn't exist, but doesn't have 'if exists' (this will cause a 'file not found' error when used) - a list of paths if the include is a directory - an empty list if the rule has 'if exists' and the file doesn't exist Also add some tests for get_full_paths()
This commit is contained in:
@@ -13,8 +13,9 @@
|
|||||||
# ----------------------------------------------------------------------
|
# ----------------------------------------------------------------------
|
||||||
|
|
||||||
from apparmor.regex import RE_INCLUDE, re_match_include_parse
|
from apparmor.regex import RE_INCLUDE, re_match_include_parse
|
||||||
from apparmor.common import AppArmorBug, AppArmorException, type_is_str
|
from apparmor.common import AppArmorBug, AppArmorException, is_skippable_file, type_is_str
|
||||||
from apparmor.rule import BaseRule, BaseRuleset, parse_comment
|
from apparmor.rule import BaseRule, BaseRuleset, parse_comment
|
||||||
|
import os
|
||||||
|
|
||||||
# setup module translations
|
# setup module translations
|
||||||
from apparmor.translations import init_translation
|
from apparmor.translations import init_translation
|
||||||
@@ -124,6 +125,34 @@ class IncludeRule(BaseRule):
|
|||||||
_('Include'), self.get_clean(),
|
_('Include'), self.get_clean(),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
def get_full_paths(self, profile_dir):
|
||||||
|
''' get list of full paths of an include (can contain multiple paths if self.path is a directory) '''
|
||||||
|
|
||||||
|
# currently this section is based on aa.py get_include_path() (with variable names changed)
|
||||||
|
# TODO: improve/fix logic to honor magic vs. quoted include paths
|
||||||
|
if self.path.startswith('/'):
|
||||||
|
full_path = self.path
|
||||||
|
else:
|
||||||
|
full_path = os.path.join(profile_dir, self.path)
|
||||||
|
|
||||||
|
files = []
|
||||||
|
|
||||||
|
if os.path.isdir(full_path):
|
||||||
|
for path in os.listdir(full_path):
|
||||||
|
if is_skippable_file(path):
|
||||||
|
continue
|
||||||
|
|
||||||
|
file_name = os.path.join(full_path, path)
|
||||||
|
if os.path.isfile(file_name): # only add files, but not subdirectories etc.
|
||||||
|
files.append(file_name)
|
||||||
|
|
||||||
|
elif os.path.exists(full_path):
|
||||||
|
files.append(full_path)
|
||||||
|
|
||||||
|
elif self.ifexists == False:
|
||||||
|
files.append(full_path) # add full_path even if it doesn't exist on disk. Might cause a 'file not found' error later.
|
||||||
|
|
||||||
|
return files
|
||||||
|
|
||||||
class IncludeRuleset(BaseRuleset):
|
class IncludeRuleset(BaseRuleset):
|
||||||
'''Class to handle and store a collection of include rules'''
|
'''Class to handle and store a collection of include rules'''
|
||||||
|
@@ -15,7 +15,10 @@
|
|||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
from common_test import AATest, setup_all_loops
|
from common_test import AATest, setup_all_loops, write_file
|
||||||
|
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
|
||||||
from apparmor.rule.include import IncludeRule, IncludeRuleset
|
from apparmor.rule.include import IncludeRule, IncludeRuleset
|
||||||
#from apparmor.rule import BaseRule
|
#from apparmor.rule import BaseRule
|
||||||
@@ -336,6 +339,45 @@ class IncludeLogprofHeaderTest(AATest):
|
|||||||
obj = IncludeRule._parse(params)
|
obj = IncludeRule._parse(params)
|
||||||
self.assertEqual(obj.logprof_header(), expected)
|
self.assertEqual(obj.logprof_header(), expected)
|
||||||
|
|
||||||
|
class IncludeFullPathsTest(AATest):
|
||||||
|
def AASetup(self):
|
||||||
|
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)
|
||||||
|
|
||||||
|
inc_dir = os.path.join(self.profile_dir, 'abstractions/inc.d')
|
||||||
|
os.mkdir(inc_dir, 0o755)
|
||||||
|
write_file(inc_dir, 'incfoo', '/incfoo r,')
|
||||||
|
write_file(inc_dir, 'incbar', '/incbar r,')
|
||||||
|
write_file(inc_dir, 'README', '# README') # gets skipped
|
||||||
|
|
||||||
|
sub_dir = os.path.join(self.profile_dir, 'abstractions/inc.d/subdir') # gets skipped
|
||||||
|
os.mkdir(sub_dir, 0o755)
|
||||||
|
|
||||||
|
empty_dir = os.path.join(self.profile_dir, 'abstractions/empty.d')
|
||||||
|
os.mkdir(empty_dir, 0o755)
|
||||||
|
|
||||||
|
tests = [
|
||||||
|
# @@ will be replaced with self.profile_dir
|
||||||
|
('include <abstractions/base>', ['@@/abstractions/base'] ),
|
||||||
|
# ('include "foo"', ['@@/foo'] ), # TODO: adjust logic to honor quoted vs. magic paths (and allow quoted relative paths in re_match_include_parse())
|
||||||
|
('include "/foo/bar"', ['/foo/bar'] ),
|
||||||
|
('include <abstractions/inc.d>', ['@@/abstractions/inc.d/incfoo', '@@/abstractions/inc.d/incbar'] ),
|
||||||
|
('include <abstractions/empty.d>', [] ),
|
||||||
|
('include <abstractions/not_found>', ['@@/abstractions/not_found'] ),
|
||||||
|
('include if exists <abstractions/not_found>', [] ),
|
||||||
|
]
|
||||||
|
|
||||||
|
def _run_test(self, params, expected):
|
||||||
|
exp2 = []
|
||||||
|
for path in expected:
|
||||||
|
exp2.append(path.replace('@@', self.profile_dir))
|
||||||
|
|
||||||
|
obj = IncludeRule._parse(params)
|
||||||
|
self.assertEqual(obj.get_full_paths(self.profile_dir), exp2)
|
||||||
|
|
||||||
## --- tests for IncludeRuleset --- #
|
## --- tests for IncludeRuleset --- #
|
||||||
|
|
||||||
class IncludeRulesTest(AATest):
|
class IncludeRulesTest(AATest):
|
||||||
|
Reference in New Issue
Block a user