PolicyDifference: implement nodecon diff

Closes #38
This commit is contained in:
Chris PeBenito 2016-01-14 17:44:13 -05:00
parent 485c9746b4
commit dbad48a742
6 changed files with 224 additions and 0 deletions

22
sediff
View File

@ -880,6 +880,28 @@ try:
print()
if all_differences or args.nodecon:
if diff.added_nodecons or diff.removed_nodecons or diff.modified_nodecons \
or args.nodecon:
print("Nodecons ({0} Added, {1} Removed, {2} Modified)".format(
len(diff.added_nodecons), len(diff.removed_nodecons),
len(diff.modified_nodecons)))
if diff.added_nodecons and not args.stats:
print(" Added Nodecons: {0}".format(len(diff.added_nodecons)))
for n in sorted(diff.added_nodecons):
print(" + {0}".format(n))
if diff.removed_nodecons and not args.stats:
print(" Removed Nodecons: {0}".format(len(diff.removed_nodecons)))
for n in sorted(diff.removed_nodecons):
print(" - {0}".format(n))
if diff.modified_nodecons and not args.stats:
print(" Modified Nodecons: {0}".format(len(diff.modified_nodecons)))
for con, added_context, removed_context in sorted(diff.modified_nodecons):
print(" * nodecon {0.address} {0.netmask} +[{1}] -[{2}];".format(
con, added_context, removed_context))
print()
except Exception as err:
if args.debug:
import traceback

View File

@ -24,6 +24,7 @@ from .initsid import InitialSIDsDifference
from .mls import CategoriesDifference, LevelDeclsDifference, SensitivitiesDifference
from .mlsrules import MLSRulesDifference
from .netifcon import NetifconsDifference
from .nodecon import NodeconsDifference
from .objclass import ObjClassDifference
from .rbacrules import RBACRulesDifference
from .roles import RolesDifference
@ -44,6 +45,7 @@ class PolicyDifference(BooleansDifference,
LevelDeclsDifference,
MLSRulesDifference,
NetifconsDifference,
NodeconsDifference,
ObjClassDifference,
RBACRulesDifference,
RolesDifference,

90
setools/diff/nodecon.py Normal file
View File

@ -0,0 +1,90 @@
# 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 .context import ContextWrapper
from .descriptors import DiffResultDescriptor
from .difference import Difference, Wrapper
modified_nodecon_record = namedtuple("modified_nodecon", ["rule",
"added_context",
"removed_context"])
class NodeconsDifference(Difference):
"""Determine the difference in nodecons between two policies."""
added_nodecons = DiffResultDescriptor("diff_nodecons")
removed_nodecons = DiffResultDescriptor("diff_nodecons")
modified_nodecons = DiffResultDescriptor("diff_nodecons")
def diff_nodecons(self):
"""Generate the difference in nodecons between the policies."""
self.log.info("Generating nodecon differences from {0.left_policy} to {0.right_policy}".
format(self))
self.added_nodecons, self.removed_nodecons, matched_nodecons = self._set_diff(
(NodeconWraper(n) for n in self.left_policy.nodecons()),
(NodeconWraper(n) for n in self.right_policy.nodecons()))
self.modified_nodecons = []
for left_nodecon, right_nodecon in matched_nodecons:
# Criteria for modified nodecons
# 1. change to context
if ContextWrapper(left_nodecon.context) != ContextWrapper(right_nodecon.context):
self.modified_nodecons.append(modified_nodecon_record(left_nodecon,
right_nodecon.context,
left_nodecon.context))
#
# Internal functions
#
def _reset_diff(self):
"""Reset diff results on policy changes."""
self.log.debug("Resetting nodecon differences")
self.added_nodecons = None
self.removed_nodecons = None
self.modified_nodecons = None
class NodeconWraper(Wrapper):
"""Wrap nodecon statements for diff purposes."""
def __init__(self, ocon):
self.origin = ocon
self.ip_version = ocon.ip_version
self.address = ocon.address
self.netmask = ocon.netmask
self.key = hash(ocon)
def __hash__(self):
return self.key
def __lt__(self, other):
return self.origin < other.origin
def __eq__(self, other):
return self.ip_version == other.ip_version and \
self.address == other.address and \
self.netmask == other.netmask

View File

@ -1153,6 +1153,78 @@ class PolicyDifferenceTest(ValidateRule, unittest.TestCase):
self.assertEqual("added_user:object_r:system:s0", added_packet)
self.assertEqual("removed_user:object_r:system:s0", removed_packet)
#
# nodecons
#
def test_added_nodecons(self):
"""Diff: added nodecons."""
l = sorted(self.diff.added_nodecons)
self.assertEqual(4, len(l))
# new IPv4
nodecon = l[0]
self.assertEqual("127.0.0.4", nodecon.address)
self.assertEqual("255.255.255.255", nodecon.netmask)
# changed IPv4 netmask
nodecon = l[1]
self.assertEqual("127.0.0.5", nodecon.address)
self.assertEqual("255.255.255.0", nodecon.netmask)
# new IPv6
nodecon = l[2]
self.assertEqual("::4", nodecon.address)
self.assertEqual("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", nodecon.netmask)
# changed IPv6 netmask
nodecon = l[3]
self.assertEqual("::5", nodecon.address)
self.assertEqual("ffff:ffff:ffff:ffff:ffff:ffff:ffff:0", nodecon.netmask)
def test_removed_nodecons(self):
"""Diff: removed nodecons."""
l = sorted(self.diff.removed_nodecons)
self.assertEqual(4, len(l))
# new IPv4
nodecon = l[0]
self.assertEqual("127.0.0.2", nodecon.address)
self.assertEqual("255.255.255.255", nodecon.netmask)
# changed IPv4 netmask
nodecon = l[1]
self.assertEqual("127.0.0.5", nodecon.address)
self.assertEqual("255.255.255.255", nodecon.netmask)
# new IPv6
nodecon = l[2]
self.assertEqual("::2", nodecon.address)
self.assertEqual("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", nodecon.netmask)
# changed IPv6 netmask
nodecon = l[3]
self.assertEqual("::5", nodecon.address)
self.assertEqual("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", nodecon.netmask)
def test_modified_nodecons(self):
"""Diff: modified nodecons."""
l = sorted(self.diff.modified_nodecons)
self.assertEqual(2, len(l))
# changed IPv4
nodecon, added_context, removed_context = l[0]
self.assertEqual("127.0.0.3", nodecon.address)
self.assertEqual("255.255.255.255", nodecon.netmask)
self.assertEqual("modified_change_level:object_r:system:s2:c0", added_context)
self.assertEqual("modified_change_level:object_r:system:s2:c1", removed_context)
# changed IPv6
nodecon, added_context, removed_context = l[1]
self.assertEqual("::3", nodecon.address)
self.assertEqual("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", nodecon.netmask)
self.assertEqual("modified_change_level:object_r:system:s2:c1", added_context)
self.assertEqual("modified_change_level:object_r:system:s2:c0.c1", removed_context)
class PolicyDifferenceTestNoDiff(unittest.TestCase):
@ -1449,3 +1521,15 @@ class PolicyDifferenceTestNoDiff(unittest.TestCase):
def test_modified_netifcons(self):
"""NoDiff: no modified netifcons."""
self.assertFalse(self.diff.modified_netifcons)
def test_added_nodecons(self):
"""NoDiff: no added nodecons."""
self.assertFalse(self.diff.added_nodecons)
def test_removed_nodecons(self):
"""NoDiff: no removed nodecons."""
self.assertFalse(self.diff.removed_nodecons)
def test_modified_nodecons(self):
"""NoDiff: no modified nodecons."""
self.assertFalse(self.diff.modified_nodecons)

View File

@ -638,5 +638,18 @@ netifcon mod_ctx_netif removed_user:object_r:system:s0 system:object_r:system:s0
netifcon mod_pkt_netif system:object_r:system:s0 removed_user:object_r:system:s0
netifcon mod_both_netif removed_user:object_r:system:s0 removed_user:object_r:system:s0
# matched nodecons
nodecon 127.0.0.1 255.255.255.255 system:object_r:system:s0
nodecon ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff system:object_r:system:s0
# removed nodecons
nodecon 127.0.0.2 255.255.255.255 removed_user:object_r:system:s0
nodecon ::2 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff removed_user:object_r:system:s0
# modified nodecons
nodecon 127.0.0.3 255.255.255.255 modified_change_level:object_r:system:s2:c1
nodecon ::3 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff modified_change_level:object_r:system:s2:c0,c1
# change netmask (add/remove)
nodecon 127.0.0.5 255.255.255.255 system:object_r:system:s0
nodecon ::5 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff system:object_r:system:s0

View File

@ -638,5 +638,18 @@ netifcon mod_ctx_netif added_user:object_r:system:s0 system:object_r:system:s0
netifcon mod_pkt_netif system:object_r:system:s0 added_user:object_r:system:s0
netifcon mod_both_netif added_user:object_r:system:s0 added_user:object_r:system:s0
# matched nodecons
nodecon 127.0.0.1 255.255.255.255 system:object_r:system:s0
nodecon ::1 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff system:object_r:system:s0
# added nodecons
nodecon 127.0.0.4 255.255.255.255 added_user:object_r:system:s0
nodecon ::4 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff added_user:object_r:system:s0
# modified nodecons
nodecon 127.0.0.3 255.255.255.255 modified_change_level:object_r:system:s2:c0
nodecon ::3 ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff modified_change_level:object_r:system:s2:c1
# change netmask (add/remove)
nodecon 127.0.0.5 255.255.255.0 system:object_r:system:s0
nodecon ::5 ffff:ffff:ffff:ffff:ffff:ffff:ffff:: system:object_r:system:s0