PolicyDifference: add object class diff

Closes #28
This commit is contained in:
Chris PeBenito 2015-12-21 11:01:30 -05:00
parent b3dbe6a8b3
commit 92134725c1
5 changed files with 181 additions and 0 deletions

28
sediff
View File

@ -110,6 +110,34 @@ try:
print(" - {0}".format(p))
print()
if diff.added_classes or diff.removed_classes or diff.modified_classes:
print("Classes ({0} Added, {1} Removed, {2} Modified)".format(len(diff.added_classes),
len(diff.removed_classes),
len(diff.modified_classes)))
if diff.added_classes:
print(" Added Classes: {0}".format(len(diff.added_classes)))
for c in sorted(diff.added_classes):
print(" + {0}".format(c))
if diff.removed_classes:
print(" Removed Classes: {0}".format(len(diff.removed_classes)))
for c in sorted(diff.removed_classes):
print(" - {0}".format(c))
if diff.modified_classes:
print(" Modified Classes: {0}".format(len(diff.modified_classes)))
for name, mod in sorted(diff.modified_classes.items()):
change = []
if mod.added_perms:
change.append("{0} Added permissions".format(len(mod.added_perms)))
if mod.removed_perms:
change.append("{0} Removed permissions".format(len(mod.removed_perms)))
print(" * {0} ({1})".format(name, ", ".join(change)))
for p in sorted(mod.added_perms):
print(" + {0}".format(p))
for p in sorted(mod.removed_perms):
print(" - {0}".format(p))
print()
if diff.added_roles or diff.removed_roles or diff.modified_roles:
print("Roles ({0} Added, {1} Removed, {2} Modified)".format(len(diff.added_roles),
len(diff.removed_roles),

View File

@ -20,6 +20,8 @@ import logging
from collections import namedtuple
from weakref import WeakKeyDictionary
from .policyrep.exception import NoCommon
__all__ = ['PolicyDifference']
@ -27,6 +29,10 @@ modified_commons_record = namedtuple("modified_common", ["added_perms",
"removed_perms",
"matched_perms"])
modified_classes_record = namedtuple("modified_class", ["added_perms",
"removed_perms",
"matched_perms"])
modified_roles_record = namedtuple("modified_role", ["added_types",
"removed_types",
"matched_types"])
@ -142,6 +148,49 @@ class PolicyDifference(object):
removed_perms,
matched_perms)
#
# Object class differences
#
added_classes = DiffResultDescriptor("diff_classes")
removed_classes = DiffResultDescriptor("diff_classes")
modified_classes = DiffResultDescriptor("diff_classes")
def diff_classes(self):
"""Generate the difference in object classes between the policies."""
self.log.info(
"Generating class differences from {0.left_policy} to {0.right_policy}".format(self))
self.added_classes, self.removed_classes, matched_classes = self._set_diff(
self.left_policy.classes(), self.right_policy.classes())
self.modified_classes = dict()
for name in matched_classes:
# Criteria for modified classes
# 1. change to permissions (inherited common is expanded)
left_class = self.left_policy.lookup_class(name)
right_class = self.right_policy.lookup_class(name)
left_perms = left_class.perms
try:
left_perms |= left_class.common.perms
except NoCommon:
pass
right_perms = right_class.perms
try:
right_perms |= right_class.common.perms
except NoCommon:
pass
added_perms, removed_perms, matched_perms = self._set_diff(left_perms, right_perms)
if added_perms or removed_perms:
self.modified_classes[name] = modified_classes_record(added_perms,
removed_perms,
matched_perms)
#
# Role differences
#
@ -229,6 +278,9 @@ class PolicyDifference(object):
self.added_commons = None
self.removed_commons = None
self.modified_commons = None
self.added_classes = None
self.removed_classes = None
self.modified_classes = None
self.added_roles = None
self.removed_roles = None
self.modified_roles = None

View File

@ -28,6 +28,9 @@ class PolicyDifferenceTest(unittest.TestCase):
self.diff = PolicyDifference(SELinuxPolicy("tests/diff_left.conf"),
SELinuxPolicy("tests/diff_right.conf"))
#
# Types
#
def test_added_types(self):
"""Diff: added type"""
self.assertSetEqual(set(["added_type"]), self.diff.added_types)
@ -116,6 +119,9 @@ class PolicyDifferenceTest(unittest.TestCase):
self.assertFalse(self.diff.modified_types["modified_add_permissive"].removed_aliases)
self.assertFalse(self.diff.modified_types["modified_add_permissive"].matched_aliases)
#
# Roles
#
def test_added_role(self):
"""Diff: added role."""
self.assertSetEqual(set(["added_role"]), self.diff.added_roles)
@ -141,6 +147,9 @@ class PolicyDifferenceTest(unittest.TestCase):
self.diff.modified_roles["modified_remove_type"].removed_types)
self.assertFalse(self.diff.modified_roles["modified_remove_type"].added_types)
#
# Commons
#
def test_added_common(self):
"""Diff: added common."""
self.assertSetEqual(set(["added_common"]), self.diff.added_commons)
@ -165,6 +174,40 @@ class PolicyDifferenceTest(unittest.TestCase):
self.diff.modified_commons["modified_remove_perm"].removed_perms)
self.assertFalse(self.diff.modified_commons["modified_remove_perm"].added_perms)
#
# Classes
#
def test_added_class(self):
"""Diff: added class."""
self.assertSetEqual(set(["added_class"]), self.diff.added_classes)
def test_removed_class(self):
"""Diff: removed class."""
self.assertSetEqual(set(["removed_class"]), self.diff.removed_classes)
def test_modified_class_count(self):
"""Diff: modified class count."""
self.assertEqual(3, len(self.diff.modified_classes))
def test_modified_class_add_perm(self):
"""Diff: modified class with added perm."""
self.assertSetEqual(set(["added_perm"]),
self.diff.modified_classes["modified_add_perm"].added_perms)
self.assertFalse(self.diff.modified_classes["modified_add_perm"].removed_perms)
def test_modified_class_remove_perm(self):
"""Diff: modified class with removed perm."""
self.assertSetEqual(set(["removed_perm"]),
self.diff.modified_classes["modified_remove_perm"].removed_perms)
self.assertFalse(self.diff.modified_classes["modified_remove_perm"].added_perms)
def test_modified_class_change_common(self):
"""Diff: modified class due to modified common."""
self.assertSetEqual(set(["old_com"]),
self.diff.modified_classes["modified_change_common"].removed_perms)
self.assertSetEqual(set(["new_com"]),
self.diff.modified_classes["modified_change_common"].added_perms)
class PolicyDifferenceTestNoDiff(unittest.TestCase):
@ -209,3 +252,15 @@ class PolicyDifferenceTestNoDiff(unittest.TestCase):
def test_modified_commons(self):
"""NoDiff: no modified commons."""
self.assertFalse(self.diff.modified_commons)
def test_added_classes(self):
"""NoDiff: no added classes."""
self.assertFalse(self.diff.added_classes)
def test_removed_classes(self):
"""NoDiff: no removed classes."""
self.assertFalse(self.diff.removed_classes)
def test_modified_classes(self):
"""NoDiff: no modified classes."""
self.assertFalse(self.diff.modified_classes)

View File

@ -5,6 +5,10 @@ class infoflow4
class infoflow5
class infoflow6
class infoflow7
class removed_class
class modified_add_perm
class modified_remove_perm
class modified_change_common
sid kernel
sid security
@ -69,6 +73,25 @@ inherits infoflow
super_unmapped
}
class removed_class
{
null_perm
}
class modified_add_perm
{
same_perm
}
class modified_remove_perm
{
same_perm
removed_perm
}
class modified_change_common
inherits removed_common
sensitivity low_s;
sensitivity medium_s alias med;
sensitivity high_s;

View File

@ -5,6 +5,10 @@ class infoflow4
class infoflow5
class infoflow6
class infoflow7
class added_class
class modified_add_perm
class modified_remove_perm
class modified_change_common
sid kernel
sid security
@ -69,6 +73,25 @@ inherits infoflow
super_unmapped
}
class added_class
{
new_class_perm
}
class modified_add_perm
{
same_perm
added_perm
}
class modified_remove_perm
{
same_perm
}
class modified_change_common
inherits added_common
sensitivity low_s;
sensitivity medium_s alias med;
sensitivity high_s;