From 2bd871ae18a8b66d4ae192129299c809dd9af214 Mon Sep 17 00:00:00 2001 From: Chris PeBenito Date: Sat, 9 Jan 2016 09:01:52 -0500 Subject: [PATCH] PolicyDifference: implement sensitivities diff Closes #34 --- sediff | 32 +++++++++++++++++++++++++++ setools/diff/__init__.py | 3 ++- setools/diff/mls.py | 48 ++++++++++++++++++++++++++++++++++++++++ tests/diff.py | 35 +++++++++++++++++++++++++++++ tests/diff_left.conf | 12 +++++----- tests/diff_right.conf | 6 ++--- 6 files changed, 126 insertions(+), 10 deletions(-) diff --git a/sediff b/sediff index 4400008..684eaaa 100755 --- a/sediff +++ b/sediff @@ -355,6 +355,38 @@ try: print() + if all_differences or args.sensitivity: + if diff.added_sensitivities or diff.removed_sensitivities or diff.modified_sensitivities \ + or args.sensitivity: + print("Sensitivities ({0} Added, {1} Removed, {2} Modified)".format( + len(diff.added_sensitivities), len(diff.removed_sensitivities), + len(diff.modified_sensitivities))) + if diff.added_sensitivities and not args.stats: + print(" Added Sensitivites: {0}".format(len(diff.added_sensitivities))) + for s in sorted(diff.added_sensitivities): + print(" + {0}".format(s)) + if diff.removed_sensitivities and not args.stats: + print(" Removed Sensitivities: {0}".format(len(diff.removed_sensitivities))) + for s in sorted(diff.removed_sensitivities): + print(" - {0}".format(s)) + if diff.modified_sensitivities and not args.stats: + print(" Modified Sensitivities: {0}".format(len(diff.modified_sensitivities))) + for name, mod in sorted(diff.modified_sensitivities.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( diff --git a/setools/diff/__init__.py b/setools/diff/__init__.py index 11e928a..331b4d5 100644 --- a/setools/diff/__init__.py +++ b/setools/diff/__init__.py @@ -18,7 +18,7 @@ # from .bool import BooleansDifference from .commons import CommonDifference -from .mls import CategoriesDifference +from .mls import CategoriesDifference, SensitivitiesDifference from .mlsrules import MLSRulesDifference from .objclass import ObjClassDifference from .rbacrules import RBACRulesDifference @@ -38,6 +38,7 @@ class PolicyDifference(BooleansDifference, ObjClassDifference, RBACRulesDifference, RolesDifference, + SensitivitiesDifference, TERulesDifference, TypeAttributesDifference, TypesDifference, diff --git a/setools/diff/mls.py b/setools/diff/mls.py index a9fd57d..a440353 100644 --- a/setools/diff/mls.py +++ b/setools/diff/mls.py @@ -25,6 +25,10 @@ modified_cat_record = namedtuple("modified_category", ["added_aliases", "removed_aliases", "matched_aliases"]) +modified_sens_record = namedtuple("modified_sensitivity", ["added_aliases", + "removed_aliases", + "matched_aliases"]) + class CategoriesDifference(Difference): @@ -68,6 +72,50 @@ class CategoriesDifference(Difference): self.modified_categories = None +class SensitivitiesDifference(Difference): + + """Determine the difference in sensitivities between two policies.""" + + added_sensitivities = DiffResultDescriptor("diff_sensitivities") + removed_sensitivities = DiffResultDescriptor("diff_sensitivities") + modified_sensitivities = DiffResultDescriptor("diff_sensitivities") + + def diff_sensitivities(self): + """Generate the difference in sensitivities between the policies.""" + + self.log.info( + "Generating sensitivity differences from {0.left_policy} to {0.right_policy}". + format(self)) + + self.added_sensitivities, self.removed_sensitivities, matched_sensitivities = \ + self._set_diff( + (SymbolWrapper(s) for s in self.left_policy.sensitivities()), + (SymbolWrapper(s) for s in self.right_policy.sensitivities())) + + self.modified_sensitivities = dict() + + for left_category, right_category in matched_sensitivities: + # Criteria for modified sensitivities + # 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_sensitivities[left_category] = modified_sens_record(added_aliases, + removed_aliases, + matched_aliases) + + # + # Internal functions + # + def _reset_diff(self): + """Reset diff results on policy changes.""" + self.log.debug("Resetting sensitivity differences") + self.added_sensitivities = None + self.removed_sensitivities = None + self.modified_sensitivities = None + + class LevelWrapper(Wrapper): """Wrap levels to allow comparisons.""" diff --git a/tests/diff.py b/tests/diff.py index 6ecce76..dbcf147 100644 --- a/tests/diff.py +++ b/tests/diff.py @@ -951,6 +951,29 @@ class PolicyDifferenceTest(ValidateRule, unittest.TestCase): self.assertFalse(self.diff.modified_categories["c0"].added_aliases) self.assertEqual(set(["eggs"]), self.diff.modified_categories["c0"].removed_aliases) + # + # Sensitivity + # + def test_added_sensitivities(self): + """Diff: added sensitivities.""" + self.assertSetEqual(set(["s46"]), self.diff.added_sensitivities) + + def test_removed_sensitivities(self): + """Diff: removed sensitivities.""" + self.assertSetEqual(set(["s47"]), self.diff.removed_sensitivities) + + def test_modified_sensitivities(self): + """Diff: modified sensitivities.""" + self.assertEqual(2, len(self.diff.modified_sensitivities)) + + # add alias + self.assertEqual(set(["al4"]), self.diff.modified_sensitivities["s1"].added_aliases) + self.assertFalse(self.diff.modified_sensitivities["s1"].removed_aliases) + + # remove alias + self.assertFalse(self.diff.modified_sensitivities["s0"].added_aliases) + self.assertEqual(set(["al2"]), self.diff.modified_sensitivities["s0"].removed_aliases) + class PolicyDifferenceTestNoDiff(unittest.TestCase): @@ -1175,3 +1198,15 @@ class PolicyDifferenceTestNoDiff(unittest.TestCase): def test_modified_categories(self): """NoDiff: no modified categories.""" self.assertFalse(self.diff.modified_categories) + + def test_added_sensitivities(self): + """NoDiff: no added sensitivities.""" + self.assertFalse(self.diff.added_sensitivities) + + def test_removed_sensitivities(self): + """NoDiff: no removed sensitivities.""" + self.assertFalse(self.diff.removed_sensitivities) + + def test_modified_sensitivities(self): + """NoDiff: no modified sensitivities.""" + self.assertFalse(self.diff.modified_sensitivities) diff --git a/tests/diff_left.conf b/tests/diff_left.conf index 1a06786..0238767 100644 --- a/tests/diff_left.conf +++ b/tests/diff_left.conf @@ -92,8 +92,8 @@ class modified_remove_perm class modified_change_common inherits removed_common -sensitivity s0; -sensitivity s1; +sensitivity s0 alias { al1 al2 }; +sensitivity s1 alias { al3 }; sensitivity s2; sensitivity s3; sensitivity s40; @@ -102,9 +102,9 @@ sensitivity s42; sensitivity s43; sensitivity s44; sensitivity s45; -sensitivity s46; +sensitivity s47; -dominance { s0 s1 s2 s3 s40 s41 s42 s43 s44 s45 s46 } +dominance { s0 s1 s2 s3 s40 s41 s42 s43 s44 s45 s47 } category c0 alias { spam eggs }; category c1 alias { bar }; @@ -124,7 +124,7 @@ level s42:c0.c4; level s43:c0.c4; level s44:c0.c4; level s45:c0.c4; -level s46:c0.c4; +level s47:c0.c4; #some constraints mlsconstrain infoflow hi_r ((l1 dom l2) or (t1 == mls_exempt)); @@ -593,7 +593,7 @@ role_transition role_tr_matched_source role_tr_matched_target:infoflow3 role_tr_ ################################################################################ #users -user system roles system level s0 range s0 - s46:c1.c4; +user system roles system level s0 range s0; user removed_user roles system level s0 range s0; diff --git a/tests/diff_right.conf b/tests/diff_right.conf index f668ac4..b9bcd07 100644 --- a/tests/diff_right.conf +++ b/tests/diff_right.conf @@ -92,8 +92,8 @@ class modified_remove_perm class modified_change_common inherits added_common -sensitivity s0; -sensitivity s1; +sensitivity s0 alias { al1 }; +sensitivity s1 alias { al3 al4 }; sensitivity s2; sensitivity s3; sensitivity s40; @@ -593,7 +593,7 @@ role_transition role_tr_matched_source role_tr_matched_target:infoflow3 role_tr_ ################################################################################ #users -user system roles system level s0 range s0 - s46:c1.c4; +user system roles system level s0 range s0; user added_user roles system level s1 range s1;