aboutsummaryrefslogtreecommitdiffstats
path: root/tests/unittests
diff options
context:
space:
mode:
authorJake Hunsaker <jhunsake@redhat.com>2022-11-03 10:51:40 -0400
committerJake Hunsaker <jhunsake@redhat.com>2022-11-30 13:25:53 -0500
commitd70f0a18d5dc632021e3aa5a84e60d4171772a48 (patch)
tree7dbbb82634e15141d029b01b575c1cab5586bbf3 /tests/unittests
parent54f3e7e0279029cfe980dd92baf64def7bb7cb36 (diff)
downloadsos-d70f0a18d5dc632021e3aa5a84e60d4171772a48.tar.gz
[cleaner,ipv6] Add support for IPv6 obfuscation
This commit adds a new parser and accompanying map for obfuscating IPv6 addresses. This new parser will attempt to capture valid IPv6 networks and addresses, and produce a mostly-randomized obfuscated pair. Due to the multiple formats an IPv6 address can take, some identifiers are necessary to preserve relevant information while still obfuscating actual addresses and networks. For example, global unicast addresses that have more than one defined hextet (greater than /16 prefix) will always generate an obfuscated address starting with `534f` (or 'so', continuing the style of our mac address handling that uses 'sos' as an identifier). Addresses with a /16 prefix or less, will start with simply '53'. Private addresses, which start with `fd` will generate an obfuscated address starting with `fd53`, so that the contextual understanding that it is a private network/address can remain. Link-local addresses which start with `fe80::` will remain that way, only having the device hextets obfuscated - again, keeping the contextual information that it is a link-local interface intact, as otherwise these obfuscations may confuse end users reviewing an sos report for problems. Note that the address `::1` and `::/0` are explicitly skipped and never obfuscated, for the same reasons given above. Additionally, this parser/map will write data to the default map (and any per-run private maps) differently than previous parsers. Rather than simply dumping the obfuscation pairs into the map, it is broken up via network, with hosts belonging to that network nested inside those network entries (still being json-formatted). Users will also note that the ipv6 entries in the map also have a `version` key, which is intended to be used for handling future updates to the parser/map when upgrading from an older sos version to a newer one. This may or may not be carried over to future updates to other parsers. Closes: #3008 Related: RHBZ#2134906 Signed-off-by: Jake Hunsaker <jhunsake@redhat.com>
Diffstat (limited to 'tests/unittests')
-rw-r--r--tests/unittests/cleaner_tests.py73
1 files changed, 73 insertions, 0 deletions
diff --git a/tests/unittests/cleaner_tests.py b/tests/unittests/cleaner_tests.py
index 9759b38a..8cf34341 100644
--- a/tests/unittests/cleaner_tests.py
+++ b/tests/unittests/cleaner_tests.py
@@ -13,10 +13,12 @@ from sos.cleaner.parsers.ip_parser import SoSIPParser
from sos.cleaner.parsers.mac_parser import SoSMacParser
from sos.cleaner.parsers.hostname_parser import SoSHostnameParser
from sos.cleaner.parsers.keyword_parser import SoSKeywordParser
+from sos.cleaner.parsers.ipv6_parser import SoSIPv6Parser
from sos.cleaner.mappings.ip_map import SoSIPMap
from sos.cleaner.mappings.mac_map import SoSMacMap
from sos.cleaner.mappings.hostname_map import SoSHostnameMap
from sos.cleaner.mappings.keyword_map import SoSKeywordMap
+from sos.cleaner.mappings.ipv6_map import SoSIPv6Map
class CleanerMapTests(unittest.TestCase):
@@ -27,6 +29,7 @@ class CleanerMapTests(unittest.TestCase):
self.host_map = SoSHostnameMap()
self.host_map.load_domains_from_options(['redhat.com'])
self.kw_map = SoSKeywordMap()
+ self.ipv6_map = SoSIPv6Map()
def test_mac_map_obfuscate_valid_v4(self):
_test = self.mac_map.get('12:34:56:78:90:ab')
@@ -96,11 +99,57 @@ class CleanerMapTests(unittest.TestCase):
_test = self.kw_map.get('foobar')
self.assertEqual(_test, 'obfuscatedword0')
+ def test_ipv6_obfuscate_global(self):
+ _net = '2022:1104:abcd::'
+ _ob_net = self.ipv6_map.get(_net)
+ self.assertNotEqual(_net, _ob_net, 'Address was unchanged')
+ self.assertTrue(_ob_net.startswith('534f'), 'Global address does not start with identifier')
+ _host = '2022:1104:abcd::1234'
+ _ob_host = self.ipv6_map.get(_host)
+ self.assertNotEqual(_host, _ob_host, 'Host address was unchanged')
+ self.assertTrue(_host.startswith(_net), 'Host address not in network')
+
+ def test_ipv6_link_local(self):
+ _test = 'fe80::1234'
+ _ob_test = self.ipv6_map.get(_test)
+ self.assertTrue(_ob_test.startswith('fe80'), 'Link-local identifier not maintained')
+ self.assertNotEqual(_test, _ob_test, 'Device address was unchanged')
+
+ def test_ipv6_private(self):
+ _net = 'fd00:abcd::'
+ _host = 'fd00:abcd::1234'
+ _ob_net = self.ipv6_map.get(_net).split('/')[0]
+ _ob_host = self.ipv6_map.get(_host)
+ self.assertTrue(_ob_net.startswith('fd53'), 'Private network does not start with identifier')
+ self.assertTrue(_ob_host.startswith(_ob_net), 'Private address not in same network')
+ self.assertNotEqual(_net, _ob_net, 'Private network was unchanged')
+
+ def test_ipv6_short_network(self):
+ _net = 'ff02::'
+ _ob_net = self.ipv6_map.get(_net)
+ self.assertTrue(_ob_net.startswith(('53', '54')), f'Short network does not start with identifier: {_ob_net}')
+
+ def test_ipv6_consistent_obfuscation(self):
+ _test = '2022:1104:abcd::ef09'
+ _new = self.ipv6_map.get(_test)
+ _second = self.ipv6_map.get(_test)
+ self.assertEqual(_new, _second, "Same address produced two different results")
+
+ def test_ipv6_global_no_collision(self):
+ """Tests that generating more than 256 global network obfuscations does
+ not produce any repeats"""
+ _nets = []
+ for i in range(1, 300):
+ _nets.append(self.ipv6_map.get(f"f{i:03}::abcd").split('::')[0])
+ # if there are any duplicates, then the length of the set will not match
+ self.assertTrue(len(set(_nets)) == len(_nets), "Duplicate global network obfuscations produced")
+ self.assertTrue(_nets[-1].startswith('54'), "First hextet of global network obfuscation over 256 not expected '54'")
class CleanerParserTests(unittest.TestCase):
def setUp(self):
self.ip_parser = SoSIPParser(config={})
+ self.ipv6_parser = SoSIPv6Parser(config={})
self.mac_parser = SoSMacParser(config={})
self.host_parser = SoSHostnameParser(config={},
opt_domains=['foobar.com'])
@@ -193,3 +242,27 @@ class CleanerParserTests(unittest.TestCase):
line = 'this is my foobar test line'
_test = self.kw_parser_none.parse_line(line)[0]
self.assertEqual(line, _test)
+
+ def test_ipv6_parser_strings(self):
+ t1 = 'testing abcd:ef01::1234 as a compressed address'
+ t2 = 'testing abcd:ef01::5678:1234 as a separate address'
+ t3 = 'testing 2607:c540:8c00:3318::34/64 as another address'
+ t4 = 'testing 2007:1234:5678:90ab:0987:6543:21fe:dcba as a full address'
+ t1_test = self.ipv6_parser.parse_line(t1)[0]
+ t2_test = self.ipv6_parser.parse_line(t2)[0]
+ t3_test = self.ipv6_parser.parse_line(t3)[0]
+ t4_test = self.ipv6_parser.parse_line(t4)[0]
+ self.assertNotEqual(t1, t1_test, f"Parser did not match and obfuscate '{t1}'")
+ self.assertNotEqual(t2, t2_test, f"Parser did not match and obfuscate '{t2}'")
+ self.assertNotEqual(t3, t3_test, f"Parser did not match and obfuscate '{t3}'")
+ self.assertNotEqual(t4, t4_test, f"Parser did not match and obfuscate '{t4}'")
+
+ def test_ipv6_no_match_signature(self):
+ modstr = '2D:4F:6E:55:4F:E8:5E:D2:D2:A3:73:62:AB:FD:F9:C5:A5:53:31:93'
+ mod_test = self.ipv6_parser.parse_line(modstr)[0]
+ self.assertEqual(modstr, mod_test, "Parser matched module signature, and should not")
+
+ def test_ipv6_no_match_log_false_positive(self):
+ logln = 'Automatically imported trusted_ca::ca from trusted_ca/ca into production'
+ log_test = self.ipv6_parser.parse_line(logln)[0]
+ self.assertEqual(logln, log_test, "IPv6 parser incorrectly matched a log line of 'trusted_ca::ca'")