PolicyDifference: implement Booleans diff

This commit is contained in:
Chris PeBenito 2016-01-08 15:30:39 -05:00
parent 451e549001
commit d59444ef0e
6 changed files with 129 additions and 1 deletions

23
sediff
View File

@ -148,6 +148,29 @@ try:
print(" - {0}".format(p))
print()
if all_differences or args.bool_:
if diff.added_booleans or diff.removed_booleans or \
diff.modified_booleans or args.bool_:
print("Booleans ({0} Added, {1} Removed, {2} Modified)".format(
len(diff.added_booleans), len(diff.removed_booleans),
len(diff.modified_booleans)))
if diff.added_booleans and not args.stats:
print(" Added Booleans: {0}".format(len(diff.added_booleans)))
for a in sorted(diff.added_booleans):
print(" + {0}".format(a))
if diff.removed_booleans and not args.stats:
print(" Removed Booleans: {0}".format(len(diff.removed_booleans)))
for a in sorted(diff.removed_booleans):
print(" - {0}".format(a))
if diff.modified_booleans and not args.stats:
print(" Modified Booleans: {0}".format(len(diff.modified_booleans)))
for name, mod in sorted(diff.modified_booleans.items()):
print(" * {0} (Modified default state)".format(name))
print(" + {0}".format(mod.added_state))
print(" - {0}".format(mod.removed_state))
print()
if all_differences or args.role:
if diff.added_roles or diff.removed_roles or diff.modified_roles or args.role:
print("Roles ({0} Added, {1} Removed, {2} Modified)".format(len(diff.added_roles),

View File

@ -16,6 +16,7 @@
# License along with SETools. If not, see
# <http://www.gnu.org/licenses/>.
#
from .bool import BooleansDifference
from .commons import CommonDifference
from .mlsrules import MLSRulesDifference
from .objclass import ObjClassDifference
@ -29,7 +30,8 @@ from .users import UsersDifference
__all__ = ['PolicyDifference']
class PolicyDifference(CommonDifference,
class PolicyDifference(BooleansDifference,
CommonDifference,
MLSRulesDifference,
ObjClassDifference,
RBACRulesDifference,

64
setools/diff/bool.py Normal file
View File

@ -0,0 +1,64 @@
# Copyright 2016, Tresys Technology, LLC
#
# This file is part of SETools.
#
# SETools is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as
# published by the Free Software Foundation, either version 2.1 of
# the License, or (at your option) any later version.
#
# SETools is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with SETools. If not, see
# <http://www.gnu.org/licenses/>.
#
from collections import namedtuple
from .descriptors import DiffResultDescriptor
from .difference import Difference, SymbolWrapper
modified_bool_record = namedtuple("modified_boolean", ["added_state", "removed_state"])
class BooleansDifference(Difference):
"""Determine the difference in type attributes between two policies."""
added_booleans = DiffResultDescriptor("diff_booleans")
removed_booleans = DiffResultDescriptor("diff_booleans")
modified_booleans = DiffResultDescriptor("diff_booleans")
def diff_booleans(self):
"""Generate the difference in type attributes between the policies."""
self.log.info("Generating Boolean differences from {0.left_policy} to {0.right_policy}".
format(self))
self.added_booleans, self.removed_booleans, matched_booleans = \
self._set_diff(
(SymbolWrapper(b) for b in self.left_policy.bools()),
(SymbolWrapper(b) for b in self.right_policy.bools()))
self.modified_booleans = dict()
for left_boolean, right_boolean in matched_booleans:
# Criteria for modified booleans
# 1. change to default state
if left_boolean.state != right_boolean.state:
self.modified_booleans[left_boolean] = modified_bool_record(right_boolean.state,
left_boolean.state)
#
# Internal functions
#
def _reset_diff(self):
"""Reset diff results on policy changes."""
self.log.debug("Resetting Boolean differences")
self.added_booleans = None
self.removed_booleans = None
self.modified_booleans = None

View File

@ -910,6 +910,23 @@ class PolicyDifferenceTest(ValidateRule, unittest.TestCase):
self.assertSetEqual(set(["modified_remove_attr"]),
self.diff.modified_type_attributes["an_attr"].removed_types)
#
# Booleans
#
def test_added_boolean(self):
"""Diff: added boolean."""
self.assertSetEqual(set(["added_bool"]), self.diff.added_booleans)
def test_removed_boolean(self):
"""Diff: removed boolean."""
self.assertSetEqual(set(["removed_bool"]), self.diff.removed_booleans)
def test_modified_boolean(self):
"""Diff: modified boolean."""
self.assertEqual(1, len(self.diff.modified_booleans))
self.assertTrue(self.diff.modified_booleans["modified_bool"].added_state)
self.assertFalse(self.diff.modified_booleans["modified_bool"].removed_state)
class PolicyDifferenceTestNoDiff(unittest.TestCase):
@ -1110,3 +1127,15 @@ class PolicyDifferenceTestNoDiff(unittest.TestCase):
def test_modified_type_attributes(self):
"""NoDiff: no modified type attribute rules."""
self.assertFalse(self.diff.modified_type_attributes)
def test_added_booleans(self):
"""NoDiff: no added booleans."""
self.assertFalse(self.diff.added_booleans)
def test_removed_booleans(self):
"""NoDiff: no removed booleans."""
self.assertFalse(self.diff.removed_booleans)
def test_modified_booleans(self):
"""NoDiff: no modified booleans."""
self.assertFalse(self.diff.modified_booleans)

View File

@ -161,6 +161,11 @@ role modified_add_type;
role modified_remove_type;
role modified_remove_type types { system };
# booleans
bool same_bool true;
bool removed_bool true;
bool modified_bool false;
# Allow rule differences
type matched_source;
type matched_target;

View File

@ -162,6 +162,11 @@ role modified_add_type types { system };
role modified_remove_type;
# booleans
bool same_bool true;
bool added_bool true;
bool modified_bool true;
# Allow rule differences
type matched_source;
type matched_target;