PolicyDifference: implement categories diff

Closes #35
This commit is contained in:
Chris PeBenito 2016-01-09 08:56:40 -05:00
parent 3bba5acf5e
commit 8b136a007c
6 changed files with 125 additions and 6 deletions

32
sediff
View File

@ -323,6 +323,38 @@ try:
print(" - {0}".format(mod.removed_range))
print()
if all_differences or args.category:
if diff.added_categories or diff.removed_categories or diff.modified_categories \
or args.category:
print("Categories ({0} Added, {1} Removed, {2} Modified)".format(
len(diff.added_categories), len(diff.removed_categories),
len(diff.modified_categories)))
if diff.added_categories and not args.stats:
print(" Added Categories: {0}".format(len(diff.added_categories)))
for c in sorted(diff.added_categories):
print(" + {0}".format(c))
if diff.removed_categories and not args.stats:
print(" Removed Categories: {0}".format(len(diff.removed_categories)))
for c in sorted(diff.removed_categories):
print(" - {0}".format(c))
if diff.modified_categories and not args.stats:
print(" Modified Categories: {0}".format(len(diff.modified_categories)))
for name, mod in sorted(diff.modified_categories.items()):
change = []
if mod.added_aliases:
change.append("{0} Added Aliases".format(len(mod.added_aliases)))
if mod.removed_aliases:
change.append("{0} Removed Aliases".format(len(mod.removed_aliases)))
print(" * {0} ({1})".format(name, ", ".join(change)))
print(" Aliases:")
for a in sorted(mod.added_aliases):
print(" + {0}".format(a))
for a in sorted(mod.removed_aliases):
print(" - {0}".format(a))
print()
if all_differences or args.allow:
if diff.added_allows or diff.removed_allows or diff.modified_allows or args.allow:
print("Allow Rules ({0} Added, {1} Removed, {2} Modified)".format(

View File

@ -18,6 +18,7 @@
#
from .bool import BooleansDifference
from .commons import CommonDifference
from .mls import CategoriesDifference
from .mlsrules import MLSRulesDifference
from .objclass import ObjClassDifference
from .rbacrules import RBACRulesDifference
@ -31,6 +32,7 @@ __all__ = ['PolicyDifference']
class PolicyDifference(BooleansDifference,
CategoriesDifference,
CommonDifference,
MLSRulesDifference,
ObjClassDifference,

View File

@ -16,7 +16,56 @@
# License along with SETools. If not, see
# <http://www.gnu.org/licenses/>.
#
from .difference import SymbolWrapper, Wrapper
from collections import namedtuple
from .descriptors import DiffResultDescriptor
from .difference import Difference, SymbolWrapper, Wrapper
modified_cat_record = namedtuple("modified_category", ["added_aliases",
"removed_aliases",
"matched_aliases"])
class CategoriesDifference(Difference):
"""Determine the difference in categories between two policies."""
added_categories = DiffResultDescriptor("diff_categories")
removed_categories = DiffResultDescriptor("diff_categories")
modified_categories = DiffResultDescriptor("diff_categories")
def diff_categories(self):
"""Generate the difference in categories between the policies."""
self.log.info(
"Generating category differences from {0.left_policy} to {0.right_policy}".format(self))
self.added_categories, self.removed_categories, matched_categories = self._set_diff(
(SymbolWrapper(c) for c in self.left_policy.categories()),
(SymbolWrapper(c) for c in self.right_policy.categories()))
self.modified_categories = dict()
for left_category, right_category in matched_categories:
# Criteria for modified categories
# 1. change to aliases
added_aliases, removed_aliases, matched_aliases = self._set_diff(
left_category.aliases(), right_category.aliases())
if added_aliases or removed_aliases:
self.modified_categories[left_category] = modified_cat_record(added_aliases,
removed_aliases,
matched_aliases)
#
# Internal functions
#
def _reset_diff(self):
"""Reset diff results on policy changes."""
self.log.debug("Resetting category differences")
self.added_categories = None
self.removed_categories = None
self.modified_categories = None
class LevelWrapper(Wrapper):

View File

@ -928,6 +928,29 @@ class PolicyDifferenceTest(ValidateRule, unittest.TestCase):
self.assertTrue(self.diff.modified_booleans["modified_bool"].added_state)
self.assertFalse(self.diff.modified_booleans["modified_bool"].removed_state)
#
# Categories
#
def test_added_category(self):
"""Diff: added category."""
self.assertSetEqual(set(["c6"]), self.diff.added_categories)
def test_removed_category(self):
"""Diff: removed category."""
self.assertSetEqual(set(["c5"]), self.diff.removed_categories)
def test_modified_category(self):
"""Diff: modified categories."""
self.assertEqual(2, len(self.diff.modified_categories))
# add alias
self.assertEqual(set(["foo"]), self.diff.modified_categories["c1"].added_aliases)
self.assertFalse(self.diff.modified_categories["c1"].removed_aliases)
# remove alias
self.assertFalse(self.diff.modified_categories["c0"].added_aliases)
self.assertEqual(set(["eggs"]), self.diff.modified_categories["c0"].removed_aliases)
class PolicyDifferenceTestNoDiff(unittest.TestCase):
@ -1140,3 +1163,15 @@ class PolicyDifferenceTestNoDiff(unittest.TestCase):
def test_modified_booleans(self):
"""NoDiff: no modified booleans."""
self.assertFalse(self.diff.modified_booleans)
def test_added_categories(self):
"""NoDiff: no added categories."""
self.assertFalse(self.diff.added_categories)
def test_removed_categories(self):
"""NoDiff: no removed categories."""
self.assertFalse(self.diff.removed_categories)
def test_modified_categories(self):
"""NoDiff: no modified categories."""
self.assertFalse(self.diff.modified_categories)

View File

@ -106,11 +106,12 @@ sensitivity s46;
dominance { s0 s1 s2 s3 s40 s41 s42 s43 s44 s45 s46 }
category c0;
category c1;
category c0 alias { spam eggs };
category c1 alias { bar };
category c2;
category c3;
category c4;
category c5;
#level decl
level s0:c0.c4;

View File

@ -106,12 +106,12 @@ sensitivity s46;
dominance { s0 s1 s2 s3 s40 s41 s42 s43 s44 s45 s46 }
category c0;
category c0a;
category c1;
category c0 alias { spam };
category c1 alias { foo bar };
category c2;
category c3;
category c4;
category c6;
#level decl
level s0:c0.c4;