Hello, this patch adds match() and _match() class methods to rule classes: - _match() returns a regex match object for the given raw_rule - match() converts the _match() result to True or False
The primary usage is to get an answer to the question "is this raw_rule your job?". (For a moment, I thought about naming the function *Rule.myjob() instead of *Rule.match() ;-) My next patch will change aa.py to use *Rule.match() instead of directly using RE_*, which will make the import list much shorter and hide another implementation detail inside the rule classes. Also change _parse() to use _match() instead of the regex, and add some tests for match() and _match(). Note: This patch depends on all my pending patches (well, except the .bzrignore patch ;-) [ 48-add-rule-match.diff ] === modified file utils/apparmor/rule/capability.py --- utils/apparmor/rule/capability.py 2015-04-17 22:44:58.568224878 +0200 +++ utils/apparmor/rule/capability.py 2015-04-21 23:22:21.695364126 +0200 @@ -61,10 +61,14 @@ raise AppArmorBug('Passed empty capability to CapabilityRule: %s' % str(cap_list)) @classmethod + def _match(cls, raw_rule): + return RE_PROFILE_CAP.search(raw_rule) + + @classmethod def _parse(cls, raw_rule): '''parse raw_rule and return CapabilityRule''' - matches = RE_PROFILE_CAP.search(raw_rule) + matches = cls._match(raw_rule) if not matches: raise AppArmorException(_("Invalid capability rule '%s'") % raw_rule) === modified file utils/apparmor/rule/__init__.py --- utils/apparmor/rule/__init__.py 2015-04-16 02:18:03.865500000 +0200 +++ utils/apparmor/rule/__init__.py 2015-04-21 23:24:53.741276189 +0200 @@ -26,6 +26,8 @@ # type specific rules should inherit from this class. # Methods that subclasses need to implement: # __init__ + # _match(cls, raw_rule) (as a class method) + # - parses a raw rule and returns a regex match object # _parse(cls, raw_rule) (as a class method) # - parses a raw rule and returns an object of the Rule subclass # get_clean(depth) @@ -49,7 +51,25 @@ self.raw_rule = None @classmethod + def match(cls, raw_rule): + '''return True if raw_rule matches the class (main) regex, False otherwise + Note: This function just provides an answer to "is this your job?". + It does not guarantee that the rule is completely valid.''' + + if cls._match(raw_rule): + return True + else: + return False + + # @abstractmethod FIXME - uncomment when python3 only + @classmethod + def _match(cls, raw_rule): + '''parse raw_rule and return regex match object''' + raise AppArmorBug("'%s' needs to implement _match(), but didn't" % (str(cls))) + + @classmethod def parse(cls, raw_rule): + '''parse raw_rule and return a rule object''' rule = cls._parse(raw_rule) rule.raw_rule = raw_rule.strip() return rule === modified file utils/apparmor/rule/network.py --- utils/apparmor/rule/network.py 2015-04-17 23:10:00.147204258 +0200 +++ utils/apparmor/rule/network.py 2015-04-21 23:22:12.494914387 +0200 @@ -98,10 +98,14 @@ raise AppArmorBug('Passed unknown object to NetworkRule: %s' % str(type_or_protocol)) @classmethod + def _match(cls, raw_rule): + return RE_PROFILE_NETWORK.search(raw_rule) + + @classmethod def _parse(cls, raw_rule): '''parse raw_rule and return NetworkRule''' - matches = RE_PROFILE_NETWORK.search(raw_rule) + matches = cls._match(raw_rule) if not matches: raise AppArmorException(_("Invalid network rule '%s'") % raw_rule) === modified file utils/test/test-baserule.py --- utils/test/test-baserule.py 2015-04-19 23:30:50.904564067 +0200 +++ utils/test/test-baserule.py 2015-04-21 23:21:41.578763715 +0200 @@ -22,6 +22,18 @@ with self.assertRaises(AppArmorBug): BaseRule._parse('foo') + def test_abstract__parse_2(self): + with self.assertRaises(AppArmorBug): + BaseRule.parse('foo') + + def test_abstract__match(self): + with self.assertRaises(AppArmorBug): + BaseRule._match('foo') + + def test_abstract__match2(self): + with self.assertRaises(AppArmorBug): + BaseRule.match('foo') + def test_is_equal_localvars(self): obj = BaseRule() with self.assertRaises(AppArmorBug): === modified file utils/test/test-capability.py --- utils/test/test-capability.py 2015-04-19 23:30:50.904564067 +0200 +++ utils/test/test-capability.py 2015-04-21 23:11:15.155343906 +0200 @@ -30,6 +30,7 @@ obj = CapabilityRule.parse(rawrule) + self.assertTrue(CapabilityRule.match(rawrule)) self.assertEqual(rawrule.strip(), obj.raw_rule) self._compare_obj(obj, expected) @@ -220,6 +221,7 @@ with self.assertRaises(AppArmorException): obj = CapabilityRule(CapabilityRule.parse(rawrule)) + self.assertFalse(CapabilityRule.match(rawrule)) self.assertIsNone(obj, 'CapbilityRule handed back an object unexpectedly') def test_invalid_cap_missing_comma(self): @@ -269,6 +271,7 @@ clean = obj.get_clean() raw = obj.get_raw() + self.assertTrue(CapabilityRule.match(rawrule)) self.assertEqual(cleanrule.strip(), clean, 'unexpected clean rule') self.assertEqual(rawrule.strip(), raw, 'unexpected raw rule') @@ -294,12 +297,15 @@ self.maxDiff = None def _is_covered(self, obj, rule_to_test): + self.assertTrue(CapabilityRule.match(rule_to_test)) return obj.is_covered(CapabilityRule.parse(rule_to_test)) def _is_covered_exact(self, obj, rule_to_test): + self.assertTrue(CapabilityRule.match(rule_to_test)) return obj.is_covered(CapabilityRule.parse(rule_to_test), True, True) def _is_equal(self, obj, rule_to_test, strict): + self.assertTrue(CapabilityRule.match(rule_to_test)) return obj.is_equal(CapabilityRule.parse(rule_to_test), strict) def test_covered_single(self): === modified file utils/test/test-network.py --- utils/test/test-network.py 2015-04-20 00:17:55.028303768 +0200 +++ utils/test/test-network.py 2015-04-21 23:04:14.672708712 +0200 @@ -49,6 +49,7 @@ ] def _run_test(self, rawrule, expected): + self.assertTrue(NetworkRule.match(rawrule)) obj = NetworkRule.parse(rawrule) self.assertEqual(rawrule.strip(), obj.raw_rule) self._compare_obj(obj, expected) @@ -63,6 +64,7 @@ ] def _run_test(self, rawrule, expected): + self.assertTrue(NetworkRule.match(rawrule)) # the above invalid rules still match the main regex! with self.assertRaises(expected): NetworkRule.parse(rawrule) @@ -152,6 +154,7 @@ class InvalidNetworkTest(AATest): def _check_invalid_rawrule(self, rawrule): obj = None + self.assertFalse(NetworkRule.match(rawrule)) with self.assertRaises(AppArmorException): obj = NetworkRule(NetworkRule.parse(rawrule)) @@ -180,6 +183,7 @@ class WriteNetworkTestAATest(AATest): def _run_test(self, rawrule, expected): + self.assertTrue(NetworkRule.match(rawrule)) obj = NetworkRule.parse(rawrule) clean = obj.get_clean() raw = obj.get_raw() @@ -210,6 +214,8 @@ obj = NetworkRule.parse(self.rule) check_obj = NetworkRule.parse(param) + self.assertTrue(NetworkRule.match(param)) + self.assertEqual(obj.is_equal(check_obj), expected[0], 'Mismatch in is_equal, expected %s' % expected[0]) self.assertEqual(obj.is_equal(check_obj, True), expected[1], 'Mismatch in is_equal/strict, expected %s' % expected[1]) Regards, Christian Boltz -- > Und nun rate mal, warum ausgerechnet v.a. Vielschreiber mutt > verwenden. Sicher nicht, weil KMail besser waere. Weil eine Handvoll muttschisten die alle dazu gezwungen hat? ;) [> David Haller und Manfred Misch in suse-linux] -- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor