def setUp(self): fn = os.path.join('schema', 'exp.jadn') # Load experimental OpenC2 schema schema = jadn_load(fn) sa = jadn_analyze(schema) if sa['undefined']: print('Warning - undefined:', sa['undefined']) self.tc = Codec(schema, verbose_rec=True, verbose_str=True)
def setUp(self): fn = os.path.join('schema', 'oc2ls-csdpr02-slpf_merged.jadn') schema = jadn_load(fn) sa = jadn_analyze(schema) if sa['undefined']: print('Warning - undefined:', sa['undefined']) self.tc = Codec(schema, verbose_rec=True, verbose_str=True)
class Relax2(unittest.TestCase): def setUp(self): schema = jadn_load(os.path.join("schema", "relax2.jadn")) self.tc = Codec(schema) def test1_attribute_syntax(self): msg_api = [{ "a": { "type": "name", "value": "John Smith" }, "b": { "type": "email", "value": "*****@*****.**" } }, { "a": { "type": "name", "value": "Fred Bloggs" }, "b": { "type": "email", "value": "*****@*****.**" } }] msg_min = [["John Smith", "*****@*****.**"], ["Fred Bloggs", "*****@*****.**"]] self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("addressBook", msg_api), msg_api) self.assertEqual(self.tc.decode("addressBook", msg_api), msg_api) self.tc.set_mode(False, False) # Minified (list/tag) self.assertEqual(self.tc.encode("addressBook", msg_api), msg_min) self.assertEqual(self.tc.decode("addressBook", msg_min), msg_api)
class BasicTypes(unittest.TestCase): def setUp(self): jadn_check(schema_person) jadn_analyze(schema_person) self.c = Codec(schema_person, "True", "True") # Verbose encoding mode (dict/name) def test_person(self): p1 = {"name": "Jon Public", "id": 196432} p2 = {"name": "Jon Public", "id": 196432, "email": "*****@*****.**"} p3 = { "name": "Jon Public", "id": 196432, "phone": [{ "number": "201-555-1234" }, { "number": "201-555-5678", "type": "WORK" }] } p4bad = { # Missing required id "name": "Jon Public" } p5bad = { # Bad phone type "name": "Jon Public", "id": 196432, "phone": [{ "number": "201-555-1234", "type": "CELL" }] } self.assertEqual(self.c.encode("Person", p1), p1) self.assertEqual(self.c.encode("Person", p2), p2) self.assertEqual(self.c.encode("Person", p3), p3) with self.assertRaises(ValueError): self.assertEqual(self.c.encode("Person", p4bad), p4bad) with self.assertRaises(ValueError): self.assertEqual(self.c.encode("Person", p5bad), p5bad)
class Experimental_IPv6_Net(unittest.TestCase): def setUp(self): fn = os.path.join('schema', 'exp.jadn') # Load experimental OpenC2 schema schema = jadn_load(fn) sa = jadn_analyze(schema) if sa['undefined']: print('Warning - undefined:', sa['undefined']) self.tc = Codec(schema, verbose_rec=True, verbose_str=True) ipv6_net_api = { # API IPv4 net. 'ipv6_net': [b' \x01\r\xb8\x85\xa3\x08\xd3\x13\x19\x8a.\x03psH', 64]} ipv6_net_api_bad1 = { # Negative 'ipv6_net': [b' \x01\r\xb8\x85\xa3\x08\xd3\x13\x19\x8a.\x03psH', -3]} ipv6_net_api_bad2 = { # Too large 'ipv6_net': [b' \x01\r\xb8\x85\xa3\x08\xd3\x13\x19\x8a.\x03psH', 142]} ipv6_net_ser = { # IPv4 net serialized in type-specific string (dotted decimal) format 'ipv6_net': '2001:db8:85a3:8d3:1319:8a2e:370:7348/64'} ipv6_net_ser_bad1 = { # Leading 0 'ipv6_net': '2001:db8:85a3:8d3:1319:8a2e:370:7348/064'} ipv6_net_ser_bad2 = { # Negative 'ipv6_net': '2001:db8:85a3:8d3:1319:8a2e:370:7348/-3'} ipv6_net_ser_bad3 = { # Too large 'ipv6_net': '2001:db8:85a3:8d3:1319:8a2e:370:7348/142'} def test_ipv6_net(self): self.assertEqual(self.tc.encode('Target', self.ipv6_net_api), self.ipv6_net_ser) self.assertEqual(self.tc.decode('Target', self.ipv6_net_ser), self.ipv6_net_api) with self.assertRaises(ValueError): self.tc.encode('Target', self.ipv6_net_api_bad1) with self.assertRaises(ValueError): self.tc.encode('Target', self.ipv6_net_api_bad2) # with self.assertRaises(ValueError): # self.tc.decode('Target', self.ipv6_net_ser_bad1) with self.assertRaises(ValueError): self.tc.decode('Target', self.ipv6_net_ser_bad2) with self.assertRaises(ValueError): self.tc.decode('Target', self.ipv6_net_ser_bad3)
class Experimental_IPv4_Net(unittest.TestCase): def setUp(self): fn = os.path.join('schema', 'exp.jadn') # Load experimental OpenC2 schema schema = jadn_load(fn) sa = jadn_analyze(schema) if sa['undefined']: print('Warning - undefined:', sa['undefined']) self.tc = Codec(schema, verbose_rec=True, verbose_str=True) ipv4_net_api = { # API IPv4 net. 'ipv4_net': [b'\xc0\xa8\x00\xfe', 24]} ipv4_net_api_bad1 = { # Negative 'ipv4_net': [b'\xc0\xa8\x00\xfe', -3]} ipv4_net_api_bad2 = { # Too large 'ipv4_net': [b'\xc0\xa8\x00\xfe', 42]} ipv4_net_ser = { # IPv4 net serialized in type-specific string (dotted decimal) format 'ipv4_net': '192.168.0.254/24'} ipv4_net_ser_bad1 = { # Leading 0 'ipv4_net': '192.168.0.254/024'} ipv4_net_ser_bad2 = { # Negative 'ipv4_net': '192.168.0.254/-3'} ipv4_net_ser_bad3 = { # Too large 'ipv4_net': '192.168.0.254/42'} def test_ipv4_net(self): self.assertEqual(self.tc.encode('Target', self.ipv4_net_api), self.ipv4_net_ser) self.assertEqual(self.tc.decode('Target', self.ipv4_net_ser), self.ipv4_net_api) with self.assertRaises(ValueError): self.tc.encode('Target', self.ipv4_net_api_bad1) with self.assertRaises(ValueError): self.tc.encode('Target', self.ipv4_net_api_bad2) # with self.assertRaises(ValueError): # self.tc.decode('Target', self.ipv4_net_ser_bad1) with self.assertRaises(ValueError): self.tc.decode('Target', self.ipv4_net_ser_bad2) with self.assertRaises(ValueError): self.tc.decode('Target', self.ipv4_net_ser_bad3)
class OpenC2(unittest.TestCase): def setUp(self): schema = jadn_load(os.path.join("schema", "openc2.jadn")) self.tc = Codec(schema, True, True) def test01_high_level(self): cmd_api = { "action": "deny", "target": { "ip_connection": { "src_addr": "1.2.3.4", "src_port": 21, "layer4_protocol": "tcp" } } } self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) print(json.dumps(cmd_api, indent=2))
class Compound( unittest.TestCase ): # TODO: arrayOf(rec,map,array,arrayof,choice), array(), map(), rec() def setUp(self): jadn_check(schema_compound) self.tc = Codec(schema_compound) C4a = {"rec": {"a": 1, "b": "c"}} C4m = {"10": [1, "c"]} def test_choice_rec_verbose(self): self.tc.set_mode(True, True) self.assertEqual(self.tc.decode("t_choice", self.C4a), self.C4a) self.assertEqual(self.tc.encode("t_choice", self.C4a), self.C4a) def test_choice_rec_min(self): self.tc.set_mode(False, False) self.assertEqual(self.tc.decode("t_choice", self.C4m), self.C4a) self.assertEqual(self.tc.encode("t_choice", self.C4a), self.C4m)
def setUp(self): schema = jadn_load(os.path.join("schema", "openc2.jadn")) self.tc = Codec(schema, True, True)
class SLPF(unittest.TestCase): def setUp(self): fn = os.path.join('schema', 'oc2ls-csdpr02-slpf_merged.jadn') schema = jadn_load(fn) sa = jadn_analyze(schema) if sa['undefined']: print('Warning - undefined:', sa['undefined']) self.tc = Codec(schema, verbose_rec=True, verbose_str=True) mdeny1c = { 'action': 'deny', 'target': { 'ip_connection': { 'protocol': 'tcp', 'src_addr': b'\x01\x02\x03\x04', 'src_port': 10996, 'dst_addr': b'\xc6\x02\x03\x04', 'dst_port': 80 } }, 'args': { 'start_time': 1534775460000, 'duration': 500, 'response_requested': 'ack', 'slpf': { 'drop_process': 'none' } }, 'actuator': { 'slpf': { 'asset_id': '30' } } } mdeny1c_s = { 'action': 'deny', 'target': { 'ip_connection': { 'protocol': 'tcp', 'src_addr': 'AQIDBA', 'src_port': 10996, 'dst_addr': 'xgIDBA', 'dst_port': 80 } }, 'args': { 'start_time': 1534775460000, 'duration': 500, 'response_requested': 'ack', 'slpf': { 'drop_process': 'none' } }, 'actuator': { 'slpf': { 'asset_id': '30' } } } mdeny1r = { 'status': 200 } mdeny2c = { 'action': 'deny', 'target': { 'ip_connection': { 'protocol': 'tcp', 'src_port': 21 } }, 'args': { 'slpf': { 'drop_process': 'false_ack' } }, 'actuator': { 'slpf': {} } } mdeny2r1 = {'status':200} mdeny2r2 = { 'status': 400, 'status_text': 'Validation Error: Target: ip_conection' } mdeny2r3 = { 'status': 501 } mdeny3c = { 'action': 'deny', 'target': { 'ip_addr': b'\x01\x02\x03\x04' }, 'args': { 'response_requested': 'none', 'slpf': { 'direction': 'ingress' } }, 'actuator': { 'slpf': { 'named_group': 'perimeter' } } } mdeny3c_s = { 'action': 'deny', 'target': { 'ip_addr': 'AQIDBA' }, 'args': { 'response_requested': 'none', 'slpf': { 'direction': 'ingress' } }, 'actuator': { 'slpf': { 'named_group': 'perimeter' } } } mdeny4c = { 'action': 'allow', 'target': { 'ip_connection': { 'protocol': 'tcp', 'dst_addr': b'\xc6\x33\x64\x11', 'src_port': 21 } }, 'actuator': { 'slpf': {} } } mdeny4c_s = { 'action': 'allow', 'target': { 'ip_connection': { 'protocol': 'tcp', 'dst_addr': 'xjNkEQ', 'src_port': 21 } }, 'actuator': { 'slpf': {} } } mdeny4r = { 'status': 200, 'slpf': { 'rule_number': 1234 } } mdelete1c = { 'action': 'delete', 'target': { 'slpf': { 'rule_number': 1234 } }, 'args': { 'response_requested': 'complete' }, 'actuator': { 'slpf': {} } } mupdate1c = { 'action': 'update', 'target': { 'file': { 'path': '\\\\someshared-drive\\somedirectory\\configurations', 'name': 'firewallconfiguration.txt' } }, 'actuator': { 'slpf': { 'named_group': 'network' } } } mupdate1r1 = {'status':200} mupdate1r2 = { 'status': 501, 'status_text': 'Update-File Not Implemented' } mupdate1r3 = { 'status': 500, 'status_text': 'Server error, Cannot access file' } mquery1c = { 'action': 'query', 'target': { 'features': [] } } mquery1r = {'status':200} mquery2c = { 'action': 'query', 'target': { 'features': ['versions'] } } mquery2r = { 'status': 200, 'versions': ['1.3'] } mquery3c = { 'action': 'query', 'target': { 'features': ['versions', 'profiles'] } } mquery3r = { 'status': 200, 'versions': ['1.3'], 'profiles': [ 'oasis-open.org/openc2/v1.0/ap-slpf', 'example.com/openc2/products/iot-toaster' ] } mquery4c = { 'action': 'query', 'target': { 'features': ['pairs'] } } mquery4r = { 'status': 200, 'schema': { 'meta': { 'module': 'oasis-open.org/openc2/v1.0/openc2-lang', 'patch': 'wd08-slpf-VendorX', 'title': 'OpenC2 Language Objects', 'description': 'OpenC2 Language supported by Vendor X SLPF.', 'exports': ['OpenC2-Command', 'OpenC2-Response'] }, 'types': [ ['OpenC2-Command', 'Record', [], '', [ [1, 'action', 'Action', [], ''], [2, 'target', 'Target', [], ''], [3, 'actuator', 'Actuator', ['[0'], ''], [4, 'args', 'Args', ['[0'], ''], [5, 'id', 'Command-ID', ['[0'], '']] ], ['Action', 'Enumerated', [], '', [ [3, 'query', ''], [6, 'deny', ''], [8, 'allow', ''], [16, 'update', ''], [20, 'delete', '']] ], ['Target', 'Choice', [], '', [ [10, 'file', 'File', [], ''], [11, 'ip_addr', 'IP-Addr', [], ''], [15, 'ip_connection', 'IP-Connection', [], ''], [16, 'openc2', 'OpenC2', [], ''], [1024, 'slpf', 'slpf:Target', [], '']] ], ['Actuator', 'Choice', [], '', [ [1024, 'slpf', 'slpf:Specifiers', [], '']] ], ['Args', 'Map', [], '', [ [1, 'start_time', 'Date-Time', ['[0'], ''], [2, 'stop_time', 'Date-Time', ['[0'], ''], [3, 'duration', 'Duration', ['[0'], ''], [4, 'response_requested', 'Response-Type', ['[0'], ''], [1024, 'slpf', 'slpf:Args', ['[0'], '']] ], ['OpenC2-Response', 'Record', [], '', [ [1, 'status', 'Status-Code', [], ''], [2, 'status_text', 'String', ['[0'], ''], [3, '*', 'Results', ['[0'], ''], [4, 'id', 'Command-ID', ['[0'], ''], [5, 'id_ref', 'Command-ID', ['[0'], ''], [6, 'actuator_id', 'String', ['[0'], '']] ], ['Status-Code', 'Enumerated', ['='], '', [ [102, 'Processing', ''], [200, 'OK', ''], [301, 'Moved Permanently', ''], [400, 'Bad Request', ''], [401, 'Unauthorized', ''], [403, 'Forbidden', ''], [500, 'Server Error', ''], [501, 'Not Implemented', '']] ], ['File', 'Map', [], '', [ [1, 'name', 'String', ['[0'], ''], [2, 'path', 'String', ['[0'], ''], [3, 'hashes', 'Hashes', ['[0'], '']] ], ['IP-Addr', 'Binary', [], ''], ['IP-Connection', 'Record', [], '', [ [1, 'src_addr', 'IP-Addr', ['[0'], ''], [2, 'src_port', 'Port', ['[0'], ''], [3, 'dst_addr', 'IP-Addr', ['[0'], ''], [4, 'dst_port', 'Port', ['[0'], ''], [5, 'protocol', 'L4-Protocol', ['[0'], '']] ], ['OpenC2', 'ArrayOf', ['*Query-Item', '[0', ']3'], ''], ['Command-ID', 'String', [], ''], ['Date-Time', 'Integer', [], ''], ['Duration', 'Integer', [], ''], ['Hashes', 'Map', [], '', [ [1, 'md5', 'Binary', ['[0'], ''], [4, 'sha1', 'Binary', ['[0'], ''], [6, 'sha256', 'Binary', ['[0'], '']] ], ['L4-Protocol', 'Enumerated', [], '', [ [1, 'icmp', ''], [6, 'tcp', ''], [17, 'udp', ''], [132, 'sctp', '']] ], ['Port', 'String', ['@port'], ''], ['Query-Item', 'Enumerated', [], '', [ [1, 'versions', ''], [2, 'profiles', ''], [3, 'schema', ''], [4, 'pairs', '']] ], ['Response-Type', 'Enumerated', [], '', [ [0, 'none', ''], [1, 'ack', ''], [2, 'status', ''], [3, 'complete', '']] ], ['Version', 'String', [], ''], ['Results', 'Map', [], '', [ [4, 'versions', 'Version', ['[0', ']0'], ''], [5, 'profiles', 'jadn:Uname', ['[0', ']0'], ''], [6, 'schema', 'jadn:Schema', ['[0', ']0'], ''], [7, 'pairs', 'ActionTargets', ['[0', ']0'], ''], [1024, 'slpf', 'slpf:Results', ['[0', ']0'], '']] ], ['ActionTargets', 'Array', [], '', [ [1, 'action', 'Action', [], ''], [2, 'targets', 'Target.*', [']0'], '']] ], ['slpf:Target', 'Choice', [], '', [ [1, 'rule_number', 'slpf:Rule-ID', [], '']] ], ['slpf:Args', 'Map', [], '', [ [1, 'drop_process', 'slpf:Drop-Process', ['[0'], ''], [2, 'running', 'Boolean', ['[0'], ''], [3, 'direction', 'slpf:Direction', ['[0'], ''], [4, 'insert_rule', 'slpf:Rule-ID', ['[0'], '']] ], ['slpf:Drop-Process', 'Enumerated', [], '', [ [1, 'none', ''], [2, 'reject', ''], [3, 'false_ack', '']] ], ['slpf:Direction', 'Enumerated', [], '', [ [1, 'ingress', ''], [2, 'egress', '']] ], ['slpf:Rule-ID', 'Integer', [], ''], ['slpf:Specifiers', 'Map', [], '', [ [1, 'hostname', 'String', ['[0'], ''], [2, 'named_group', 'String', ['[0'], ''], [3, 'asset_id', 'String', ['[0'], ''], [4, 'asset_tuple', 'String', ['[0', ']10'], '']] ], ['slpf:Results', 'Map', [], '', [ [1, 'rule_number', 'slpf:Rule-ID', ['[0'], '']] ], ['jadn:Schema', 'Record', [], '', [ [1, 'meta', 'jadn:Meta', [], ''], [2, 'types', 'jadn:Type', [']0'], '']] ], ['jadn:Meta', 'Map', [], '', [ [1, 'module', 'jadn:Uname', [], ''], [2, 'patch', 'String', ['[0'], ''], [3, 'title', 'String', ['[0'], ''], [4, 'description', 'String', ['[0'], ''], [5, 'imports', 'jadn:Import', ['[0', ']0'], ''], [6, 'exports', 'jadn:Identifier', ['[0', ']0'], ''], [7, 'bounds', 'jadn:Bounds', ['[0'], '']] ], ['jadn:Import', 'Array', [], '', [ [1, 'nsid', 'jadn:Nsid', [], ''], [2, 'uname', 'jadn:Uname', [], '']] ], ['jadn:Bounds', 'Array', [], '', [ [1, 'max_msg', 'Integer', [], ''], [2, 'max_str', 'Integer', [], ''], [3, 'max_bin', 'Integer', [], ''], [4, 'max_fields', 'Integer', [], '']] ], ['jadn:Type', 'Array', [], '', [ [1, 'tname', 'jadn:Identifier', [], ''], [2, 'btype', 'Enumerated', ['*jadn:JADN-Type'], ''], [3, 'opts', 'jadn:Options', [], ''], [4, 'desc', 'String', [], ''], [5, 'fields', 'jadn:JADN-Type', ['&2', '[0', ']0'], '']] ], ['jadn:JADN-Type', 'Choice', [], '', [ [1, 'Binary', 'Null', [], ''], [2, 'Boolean', 'Null', [], ''], [3, 'Integer', 'Null', [], ''], [4, 'Number', 'Null', [], ''], [5, 'Null', 'Null', [], ''], [6, 'String', 'Null', [], ''], [7, 'Array', 'jadn:FullField', [], ''], [8, 'ArrayOf', 'Null', [], ''], [9, 'Choice', 'jadn:FullField', [], ''], [10, 'Enumerated', 'jadn:EnumField', [], ''], [11, 'Map', 'jadn:FullField', [], ''], [12, 'Record', 'jadn:FullField', [], '']] ], ['jadn:EnumField', 'Array', [], '', [ [1, '', 'Integer', [], ''], [2, '', 'String', [], ''], [3, '', 'String', [], '']] ], ['jadn:FullField', 'Array', [], '', [ [1, '', 'Integer', [], ''], [2, '', 'jadn:Identifier', [], ''], [3, '', 'jadn:Identifier', [], ''], [4, '', 'jadn:Options', [], ''], [5, '', 'String', [], '']] ], ['jadn:Identifier', 'String', ['$^[a-zA-Z][\\w-]*$', '[0', ']32'], ''], ['jadn:Nsid', 'String', ['$^[a-zA-Z][\\w-]*$', '[1', ']8'], ''], ['jadn:Uname', 'String', ['[1', ']100'], ''], ['jadn:Options', 'ArrayOf', ['*jadn:Option', '[0', ']10'], ''], ['jadn:Option', 'String', ['[1', ']100'], ''] ] } } def test_deny1c(self): self.assertEqual(self.tc.encode('OpenC2-Command', self.mdeny1c), self.mdeny1c_s) self.assertEqual(self.tc.decode('OpenC2-Command', self.mdeny1c_s), self.mdeny1c) def test_deny1r(self): self.assertEqual(self.tc.encode('OpenC2-Response', self.mdeny1r), self.mdeny1r) self.assertEqual(self.tc.decode('OpenC2-Response', self.mdeny1r), self.mdeny1r) def test_deny2c(self): self.assertEqual(self.tc.encode('OpenC2-Command', self.mdeny2c), self.mdeny2c) self.assertEqual(self.tc.decode('OpenC2-Command', self.mdeny2c), self.mdeny2c) def test_deny2r(self): self.assertEqual(self.tc.encode('OpenC2-Response', self.mdeny2r1), self.mdeny2r1) self.assertEqual(self.tc.decode('OpenC2-Response', self.mdeny2r1), self.mdeny2r1) self.assertEqual(self.tc.encode('OpenC2-Response', self.mdeny2r2), self.mdeny2r2) self.assertEqual(self.tc.decode('OpenC2-Response', self.mdeny2r2), self.mdeny2r2) self.assertEqual(self.tc.encode('OpenC2-Response', self.mdeny2r3), self.mdeny2r3) self.assertEqual(self.tc.decode('OpenC2-Response', self.mdeny2r3), self.mdeny2r3) def test_deny3c(self): self.assertEqual(self.tc.encode('OpenC2-Command', self.mdeny3c), self.mdeny3c_s) self.assertEqual(self.tc.decode('OpenC2-Command', self.mdeny3c_s), self.mdeny3c) def test_deny4c(self): self.assertEqual(self.tc.encode('OpenC2-Command', self.mdeny4c), self.mdeny4c_s) self.assertEqual(self.tc.decode('OpenC2-Command', self.mdeny4c_s), self.mdeny4c) def test_deny4r(self): self.assertEqual(self.tc.encode('OpenC2-Response', self.mdeny4r), self.mdeny4r) self.assertEqual(self.tc.decode('OpenC2-Response', self.mdeny4r), self.mdeny4r) def test_delete1c(self): self.assertEqual(self.tc.encode('OpenC2-Command', self.mdelete1c), self.mdelete1c) self.assertEqual(self.tc.decode('OpenC2-Command', self.mdelete1c), self.mdelete1c) def test_update1c(self): self.assertEqual(self.tc.encode('OpenC2-Command', self.mupdate1c), self.mupdate1c) self.assertEqual(self.tc.decode('OpenC2-Command', self.mupdate1c), self.mupdate1c) def test_update1r(self): self.assertEqual(self.tc.encode('OpenC2-Response', self.mupdate1r1), self.mupdate1r1) self.assertEqual(self.tc.decode('OpenC2-Response', self.mupdate1r1), self.mupdate1r1) self.assertEqual(self.tc.encode('OpenC2-Response', self.mupdate1r2), self.mupdate1r2) self.assertEqual(self.tc.decode('OpenC2-Response', self.mupdate1r2), self.mupdate1r2) self.assertEqual(self.tc.encode('OpenC2-Response', self.mupdate1r3), self.mupdate1r3) self.assertEqual(self.tc.decode('OpenC2-Response', self.mupdate1r3), self.mupdate1r3) def test_query1c(self): self.assertEqual(self.tc.encode('OpenC2-Command', self.mquery1c), self.mquery1c) self.assertEqual(self.tc.decode('OpenC2-Command', self.mquery1c), self.mquery1c) def test_query1r(self): self.assertEqual(self.tc.encode('OpenC2-Response', self.mquery1r), self.mquery1r) self.assertEqual(self.tc.decode('OpenC2-Response', self.mquery1r), self.mquery1r) def test_query2c(self): self.assertEqual(self.tc.encode('OpenC2-Command', self.mquery2c), self.mquery2c) self.assertEqual(self.tc.decode('OpenC2-Command', self.mquery2c), self.mquery2c) def test_query2r(self): self.assertEqual(self.tc.encode('OpenC2-Response', self.mquery2r), self.mquery2r) self.assertEqual(self.tc.decode('OpenC2-Response', self.mquery2r), self.mquery2r) def test_query3c(self): self.assertEqual(self.tc.encode('OpenC2-Command', self.mquery3c), self.mquery3c) self.assertEqual(self.tc.decode('OpenC2-Command', self.mquery3c), self.mquery3c) def test_query3r(self): self.assertEqual(self.tc.encode('OpenC2-Response', self.mquery3r), self.mquery3r) self.assertEqual(self.tc.decode('OpenC2-Response', self.mquery3r), self.mquery3r) def test_query4c(self): self.assertEqual(self.tc.encode('OpenC2-Command', self.mquery4c), self.mquery4c) self.assertEqual(self.tc.decode('OpenC2-Command', self.mquery4c), self.mquery4c) def test_query4r(self): self.assertEqual(self.tc.encode('OpenC2-Response', self.mquery4r), self.mquery4r) self.assertEqual(self.tc.decode('OpenC2-Response', self.mquery4r), self.mquery4r)
class Language(unittest.TestCase): def setUp(self): fn = os.path.join('schema', 'oc2ls-csdpr02_merged.jadn') schema = jadn_load(fn) sa = jadn_analyze(schema) if sa['undefined']: print('Warning - undefined:', sa['undefined']) self.tc = Codec(schema, verbose_rec=True, verbose_str=True) mredirect = {'action': 'redirect', 'target': {'url': 'http://evil.com'}, 'args': {''}} mq1 = {'action': 'query', 'target': {'features': ['versions']}} mq2 = {'action': 'query', 'target': {'features': ['profiles']}} def test_query_oc2(self): self.assertEqual(self.tc.encode('OpenC2-Command', self.mq1), self.mq1) self.assertEqual(self.tc.decode('OpenC2-Command', self.mq1), self.mq1) self.assertEqual(self.tc.encode('OpenC2-Command', self.mq2), self.mq2) self.assertEqual(self.tc.decode('OpenC2-Command', self.mq2), self.mq2) # with self.assertRaises(TypeError): # self.tc.encode('OpenC2-Command', self.mq_bad1) # with self.assertRaises(TypeError): # self.tc.decode('OpenC2-Command', self.mq_bad1) mr1 = {'status': 200} mr2 = {'status': 200, 'status_text': 'The request has succeeded', 'versions': ['foo'] } def test_response_oc2(self): self.assertEqual(self.tc.encode('OpenC2-Response', self.mr1), self.mr1) self.assertEqual(self.tc.decode('OpenC2-Response', self.mr1), self.mr1) self.assertEqual(self.tc.encode('OpenC2-Response', self.mr2), self.mr2) self.assertEqual(self.tc.decode('OpenC2-Response', self.mr2), self.mr2) mex2c = { 'action': 'query', 'target': { 'properties': ['battery_percentage'] } } mex2r = { 'kvps': [['battery_percentage', '0.577216']] } def test_properties_cmd(self): self.assertEqual(self.tc.encode('OpenC2-Command', self.mex2c), self.mex2c) self.assertEqual(self.tc.decode('OpenC2-Command', self.mex2c), self.mex2c) def test_properties_rsp(self): self.assertEqual(self.tc.encode('OpenC2-Response', self.mex2r), self.mex2r) self.assertEqual(self.tc.decode('OpenC2-Response', self.mex2r), self.mex2r) mex3c = { 'action': 'query', 'target': { 'features': ['versions', 'profiles'] } } mex3r = { "status_text": 'ACME Corp Stateless Packet Filter Appliance', 'versions': ['1.0'], 'profiles': [ 'oasis-open.org/openc2/v1.0/ap-slpf' ] } def test_features_cmd(self): self.assertEqual(self.tc.encode('OpenC2-Command', self.mex3c), self.mex3c) self.assertEqual(self.tc.decode('OpenC2-Command', self.mex3c), self.mex3c) def test_features_rsp(self): self.assertEqual(self.tc.encode('OpenC2-Response', self.mex3r), self.mex3r) self.assertEqual(self.tc.decode('OpenC2-Response', self.mex3r), self.mex3r)
from libs.codec.codec import Codec from libs.codec.codec_utils import flatten from libs.codec.jadn import jadn_load # OpenC2 producer application: command1 = { # Python literals use either single or double quotes - no difference in API object "action": "mitigate", 'target': { "domain_name": 'cdn.badco.org' } } schema = jadn_load(os.path.join( "schema", "openc2.jadn")) # Load and validate the OpenC2 schema codec = Codec(schema, verbose_rec=True, verbose_str=True ) # Create an OpenC2 encoder/decoder (JSON-Verbose encoding) message1 = codec.encode("OpenC2Command", command1) # Validate and encode the command print("Command to be sent (API) =", command1) print("Sent Message (JSON-v string) =", json.dumps(message1)) # Single quotes are invalid in JSON # OpenC2 consumer application: message2 = '[32,{"7":"cdn.badco.org"}]' # Received OpenC2 command in JSON-minified format codec.set_mode(verbose_rec=False, verbose_str=False) # Tell codec to use JSON-minified encoding command2 = codec.decode( "OpenC2Command", json.loads(message2)) # Validate and decode the command print("Received Message (JSON-m string) =", message2) print("Decoded Command (API) =", command2)
class OpenC2(unittest.TestCase): def _write_examples(self, name, cmds): """ Create example JSON files as a side effect of running unit tests """ if True: # Set to False to not write example files for n, encoding in enumerate(["", "_flat", "_concise", "_min"]): if cmds[n] is not None: with open( os.path.join("examples", name + encoding + ".json"), "w") as f: f.write(json.dumps(cmds[n])) def setUp(self): schema = jadn_load(os.path.join("schema", "openc2.jadn")) self.tc = Codec(schema) def test01_mitigate_domain(self): cmd_api = { "action": "mitigate", "target": { "domain_name": "cdn.badco.org" } } cmd_flat = { "action": "mitigate", "target.domain_name": "cdn.badco.org" } cmd_noname = {"1": 32, "2": {"7": "cdn.badco.org"}} cmd_concise = ["mitigate", {"domain_name": "cdn.badco.org"}] cmd_min = [32, {"7": "cdn.badco.org"}] # Minified (list/tag) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_min) self.assertEqual(self.tc.decode("OpenC2Command", cmd_min), cmd_api) self.tc.set_mode(False, True) # Concise (list/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_concise) self.assertEqual(self.tc.decode("OpenC2Command", cmd_concise), cmd_api) self.tc.set_mode(True, False) # unused (dict/tag) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_noname) self.assertEqual(self.tc.decode("OpenC2Command", cmd_noname), cmd_api) self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(flatten(cmd_api), cmd_flat) self.assertEqual(fluff(cmd_flat), cmd_api) self._write_examples("t01_mitigate_domain", [cmd_api, cmd_flat, cmd_concise, cmd_min]) def test02_query_actions(self): cmd_api = {"action": "query", "target": {"openc2": {"actions": ""}}} rsp_api = { "status": "OK", "results": { "strings": [ "query", "report", "notify", "start", "stop", "set", "delete", "update", "investigate", "mitigate", "remediate" ] } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self._write_examples("t02_query_actions", [cmd_api, None, None, None]) self.assertEqual(self.tc.encode("OpenC2Response", rsp_api), rsp_api) self.assertEqual(self.tc.decode("OpenC2Response", rsp_api), rsp_api) self._write_examples("t02_query_actions_response", [rsp_api, None, None, None]) def test02_query_schema(self): cmd_api = {"action": "query", "target": {"openc2": {"schema": ""}}} schema = { # JSON does not allow line breaks within strings for readability. So encode struct into string. "meta": { "module": "openc2" }, "types": [[ "OpenC2Command", "Record", [], "", [[1, "action", "Action", [], ""], [2, "target", "Target", [], ""], [3, "actuator", "Actuator", ["?"], ""], [4, "modifiers", "Modifiers", ["?"], ""]] ]] } rsp_api = {"status": "OK", "results": {"string": json.dumps(schema)}} self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self._write_examples("t02_query_schema", [cmd_api, None, None, None]) self.assertEqual(self.tc.encode("OpenC2Response", rsp_api), rsp_api) self.assertEqual(self.tc.decode("OpenC2Response", rsp_api), rsp_api) self._write_examples("t02_query_schema_response", [rsp_api, None, None, None]) def test03_contain_user(self): cmd_api = { "action": "contain", "target": { "user_account": { "user_id": "21942", "account_login": "******", "is_disabled": True, "account_last_login": "******" } } } cmd_flat = { "action": "contain", "target.user_account.user_id": "21942", "target.user_account.account_login": "******", "target.user_account.is_disabled": True, "target.user_account.account_last_login": "******" } cmd_noname = { "1": 7, "2": { "19": { "1": "21942", "2": "jsmith", "8": True, "13": "2017-03-16T07:38:12-04:00" } } } cmd_concise = [ "contain", { "user_account": { "user_id": "21942", "account_login": "******", "is_disabled": True, "account_last_login": "******" } } ] cmd_min = [ 7, { "19": { "1": "21942", "2": "jsmith", "8": True, "13": "2017-03-16T07:38:12-04:00" } } ] # Minified (list/tag) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_min) self.assertEqual(self.tc.decode("OpenC2Command", cmd_min), cmd_api) self.tc.set_mode(False, True) # Concise (list/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_concise) self.assertEqual(self.tc.decode("OpenC2Command", cmd_concise), cmd_api) self.tc.set_mode(True, False) # unused (dict/tag) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_noname) self.assertEqual(self.tc.decode("OpenC2Command", cmd_noname), cmd_api) self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(flatten(cmd_api), cmd_flat) self.assertEqual(fluff(cmd_flat), cmd_api) self._write_examples("t03_contain_user", [cmd_api, cmd_flat, cmd_concise, cmd_min]) def test03_notify_email_addr(self): cmd_api = { "action": "notify", "target": { "email_addr": { "value": "*****@*****.**", "display_name": "Bruce Wayne" } } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self._write_examples("t03_notify_email_addr", [cmd_api, None, None, None]) def test04_deny_ip(self): cmd_api = { "action": "deny", "target": { "ip_connection": { "layer4_protocol": "TCP", "src_addr": { "ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334" }, "src_port": { "number": 10996 }, "dst_addr": { "ipv4": "1.2.3.5" }, "dst_port": { "protocol": "https" } } }, "actuator": { "network_firewall": { "asset_id": "30" } }, "modifiers": { "command_id": "pf17_8675309", "context": "91", "start_time": "2016-11-25T08:10:31-04:00", "duration": "PT2M30S" } } cmd_flat = { "action": "deny", "target.ip_connection.layer4_protocol": "TCP", "target.ip_connection.src_addr.ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334", "target.ip_connection.src_port.number": 10996, "target.ip_connection.dst_addr.ipv4": "1.2.3.5", "target.ip_connection.dst_port.protocol": "https", "actuator.network_firewall.asset_id": "30", "modifiers.command_id": "pf17_8675309", "modifiers.context": "91", "modifiers.start_time": "2016-11-25T08:10:31-04:00", "modifiers.duration": "PT2M30S" } cmd_noname = { "1": 6, "2": { "15": { "1": { "2": "2001:0db8:85a3:0000:0000:8a2e:0370:7334" }, "2": { "1": 10996 }, "3": { "1": "1.2.3.5" }, "4": { "2": 443 }, "5": 6 } }, "3": { "14": { "2": "30" } }, "4": { "1": "91", "2": "2016-11-25T08:10:31-04:00", "4": "PT2M30S", "6": "pf17_8675309" } } cmd_concise = [ "deny", { "ip_connection": [{ "ipv6": "2001:0db8:85a3:0000:0000:8a2e:0370:7334" }, { "number": 10996 }, { "ipv4": "1.2.3.5" }, { "protocol": "https" }, "TCP"] }, { "network_firewall": [None, "30"] }, { "context": "91", "start_time": "2016-11-25T08:10:31-04:00", "duration": "PT2M30S", "command_id": "pf17_8675309" } ] cmd_min = [ 6, { "15": [{ "2": "2001:0db8:85a3:0000:0000:8a2e:0370:7334" }, { "1": 10996 }, { "1": "1.2.3.5" }, { "2": 443 }, 6] }, { "14": [None, "30"] }, { "1": "91", "2": "2016-11-25T08:10:31-04:00", "4": "PT2M30S", "6": "pf17_8675309" } ] # Minified (list/tag) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_min) self.assertEqual(self.tc.decode("OpenC2Command", cmd_min), cmd_api) self.tc.set_mode(False, True) # Concise (list/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_concise) self.assertEqual(self.tc.decode("OpenC2Command", cmd_concise), cmd_api) self.tc.set_mode(True, False) # unused (dict/tag) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_noname) self.assertEqual(self.tc.decode("OpenC2Command", cmd_noname), cmd_api) self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(flatten(cmd_api), cmd_flat) self.assertEqual(fluff(cmd_flat), cmd_api) self._write_examples("t04_deny_ip", [cmd_api, cmd_flat, cmd_concise, cmd_min]) def test05_scan_domain(self): cmd_api = { # API / Verbose (dict/name) "action": "scan", "target": { "domain_name": "www.example.com" } } cmd_flat = {"action": "scan", "target.domain_name": "www.example.com"} cmd_noname = { # unused (dict/tag) "1": 1, "2": { "7": "www.example.com" } } cmd_concise = [ # Concise (list/name) "scan", { "domain_name": "www.example.com" } ] cmd_min = [1, {"7": "www.example.com"}] # Minified (list/tag) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_min) self.assertEqual(self.tc.decode("OpenC2Command", cmd_min), cmd_api) self.tc.set_mode(False, True) # Concise (list/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_concise) self.assertEqual(self.tc.decode("OpenC2Command", cmd_concise), cmd_api) self.tc.set_mode(True, False) # unused (dict/tag) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_noname) self.assertEqual(self.tc.decode("OpenC2Command", cmd_noname), cmd_api) self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(flatten(cmd_api), cmd_flat) self.assertEqual(dlist(fluff(cmd_flat)), cmd_api) # Convert numeric dict to list self._write_examples("t05_scan_domain", [cmd_api, cmd_flat, cmd_concise, cmd_min]) def test06_update_software(self): cmd_api = { # API / Verbose (dict/name) "action": "update", "target": { "software": { "name": "VirusBeGone", "vendor": "McAfmantec" } }, "actuator": { "process_remediation_service": { "actuator_id": "dns://host03274.example.org" } }, "modifiers": { "command_id": "474074afb389", "command_src": "dns://orch.example.org", "response": "ack", "source": "https://updates.example.org/win7_x64/patch_201704_0137.cab" } } cmd_flat = { "action": "update", "target.software.vendor": "McAfmantec", "target.software.name": "VirusBeGone", "actuator.process_remediation_service.actuator_id": "dns://host03274.example.org", "modifiers.command_id": "474074afb389", "modifiers.command_src": "dns://orch.example.org", "modifiers.response": "ack", "modifiers.source": "https://updates.example.org/win7_x64/patch_201704_0137.cab" } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(flatten(cmd_api), cmd_flat) self.assertEqual(dlist(fluff(cmd_flat)), cmd_api) # Convert numeric dict to list self._write_examples("t06_update_software", [cmd_api, cmd_flat, None, None]) # -- Response rsp_api = { "status": "Processing", "statusText": "Updating McAfmantec VirusBeGone ...", "response_src": "dns://orch.example.org", "command_ref": "474074afb389" } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Response", rsp_api), rsp_api) self.assertEqual(self.tc.decode("OpenC2Response", rsp_api), rsp_api) self._write_examples("t06_update_software_rsp", [rsp_api, None, None, None]) def test07_update_file(self): cmd_api = { "action": "update", "target": { "file": { "parent_directory": { "path": "\\\\someshared-drive\\somedirectory\\configurations" }, "name": "firewallconfiguration.txt" } }, "actuator": { "network_firewall": { "actuator_id": "dns://host03274.example.org" } } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self._write_examples("t07_update_file", [cmd_api, None, None, None]) def test08_negotiation(self): cmd_api = { "action": "query", "target": { "openc2": { "comm_supported": "" } }, "actuator": { "any": { "actuator_id": "https://router7319.example.org" } } } rsp_api = { "status": "OK", "results": { "comms": { "serialization": ["JSON", "JSON-min", "XML", "Protobuf"], "connection": [{ "DXL": { "channel": "c2-channel" } }] } } } cmd2_api = { "action": "set", "target": { "openc2": { "comm_selected": { "serialization": "Protobuf", "connection": { "REST": { "port": { "protocol": "https" } } } } } }, "actuator": { "any": { "actuator_id": "https://router7319.example.org" } } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.encode("OpenC2Response", rsp_api), rsp_api) self.assertEqual(self.tc.decode("OpenC2Response", rsp_api), rsp_api) self.assertEqual(self.tc.encode("OpenC2Command", cmd2_api), cmd2_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd2_api), cmd2_api) self._write_examples("t08_negotiation1", [cmd_api, None, None, None]) self._write_examples("t08_negotiation2", [rsp_api, None, None, None]) self._write_examples("t08_negotiation3", [cmd2_api, None, None, None]) def test09_cancel_command(self): cmd_api = { "action": "cancel", "target": { "openc2": { "command": "b33cd1d4-aeb4-43a3-bfe9-806f4a84ef79" } } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self._write_examples("t09_cancel_command", [cmd_api, None, None, None]) def test10_delete_email(self): cmd_api = { "action": "delete", "target": { "email_message": { "date": "2017-06-07T14:30:31-04:00", "from": { "value": "*****@*****.**" }, "subject": "Special Offer!" } } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self._write_examples("t10_delete_email", [cmd_api, None, None, None]) def test11_restart_process(self): # TODO: use a real actuator cmd_api = { "action": "restart", "target": { "process": { "pid": 17325, "name": "rm -rf /*.*" } }, "actuator": { "endpoint": { "actuator_id": "dns://i3494.hosts.example.com" } }, "modifiers": { "method": { "stop": "graceful" } } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self._write_examples("t11_restart_process", [cmd_api, None, None, None]) def test11_snapshot_process(self): # TODO: use a real actuator cmd_api = { "action": "snapshot", "target": { "process": { "creator_user": { "user_id": "jjadmin" } } }, "actuator": { "endpoint": { "actuator_id": "dns://i3494.hosts.example.com" } }, "modifiers": { "method": { "stop": "graceful" } } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self._write_examples("t11_snapshot_process", [cmd_api, None, None, None]) def test12_locate_ipaddr(self): cmd_api = { "action": "locate", "target": { "ipv4_addr": "209.59.128.0/18" } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self._write_examples("t12_locate_ipaddr", [cmd_api, None, None, None]) def test13_redirect_url(self): cmd_api = { "action": "redirect", "target": { "url": "https://www.shezuly.com/qqmusic.exe" } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self._write_examples("t13_redirect_url", [cmd_api, None, None, None]) def test14_stop_user_session(self): cmd_api = { "action": "stop", "target": { "user_session": { "effective-user": "******", "effective-user-id": "17239", "login-time": "2017-07-03T15:27:14-07:00" } } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self._write_examples("t14_stop_user_session", [cmd_api, None, None, None]) def test15_report_artifact(self): cmd_api = { "action": "report", "target": { "artifact": { "mime_type": "image/jpeg", "hashes": { "MD5": "79bdd30dca09def5b87c55a422382039", "SHA-256": "1cb611150cc54216470836003c503b77b6a6840afd695cb7528b1ca40b82d4e7" } } } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self._write_examples("t15_report_artifact", [cmd_api, None, None, None]) def test16_set_registry(self): cmd_api = { "action": "set", "target": { "windows_registry_key": { "key": "HKEY_LOCAL_MACHINE\\System\Foo\Bar", "values": [{ "name": "Foo", "data": "qwerty", "data_type": "REG_SZ" }] } } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self._write_examples("t16_set_registry", [cmd_api, None, None, None]) def test17_investigate_x509_certificate(self): cmd_api = { "action": "investigate", "target": { "x509_certificate": { "issuer": "C=ZA, ST=Western Cape, L=Cape Town, O=Thawte Consulting cc, " "OU=Certification Services Division, CN=Thawte Server CA/[email protected]", "subject": "C=US, ST=Maryland, L=Pasadena, O=Brent Baccala, OU=FreeSoft, " "CN=www.freesoft.org/[email protected]", "validity_not_before": "2016-03-12T12:00:00Z", "validity_not_after": "2016-08-21T12:00:00Z" } } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self._write_examples("t17_investigate_x509_certificate", [cmd_api, None, None, None]) def test18_allow_directory(self): cmd_api = { "action": "allow", "target": { "directory": { "path": "C:\\Windows\\System32" } } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self._write_examples("t18_allow_directory", [cmd_api, None, None, None]) def test19_start_device(self): cmd_api = { "action": "start", "target": { "device": { "manufacturer": "Dell", "model": "E3500", "serial_number": "12345CX678" } } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("OpenC2Command", cmd_api), cmd_api) self.assertEqual(self.tc.decode("OpenC2Command", cmd_api), cmd_api) self._write_examples("t19_start_device", [cmd_api, None, None, None]) def testb1_foo(self): # Unknown action cmd_api = {"action": "foo", "target": {"device": {"model": "bar"}}} self.tc.set_mode(True, True) # API / Verbose (dict/name) with self.assertRaises(ValueError): self.tc.encode("OpenC2Command", cmd_api) with self.assertRaises(ValueError): self.tc.decode("OpenC2Command", cmd_api) def testb2_scan(self): # Unknown target device property cmd_api = {"action": "scan", "target": {"device": {"dummy": "bar"}}} self.tc.set_mode(True, True) # API / Verbose (dict/name) with self.assertRaises(ValueError): self.tc.encode("OpenC2Command", cmd_api) with self.assertRaises(ValueError): self.tc.decode("OpenC2Command", cmd_api) def testb3_scan(self): # Extra targets cmd_api = { "action": "scan", "target": { "device": { "model": "bar" }, "author": "Charles Dickens", "title": "A Tale of Two Cities", "quote": "We had everything before us, we had nothing before us, we were all going direct to Heaven, " "we were all going direct the other way— in short, the period was so far like the present period, " "that some of its noisiest authorities insisted on its being received, for good or for evil, in the " "superlative degree of comparison only." } } self.tc.set_mode(True, True) # API / Verbose (dict/name) with self.assertRaises(ValueError): self.tc.encode("OpenC2Command", cmd_api) with self.assertRaises(ValueError): self.tc.decode("OpenC2Command", cmd_api)
def setUp(self): jadn_check(schema_bounds) self.tc = Codec(schema_bounds)
class Selectors(unittest.TestCase ): # TODO: bad schema - verify * field has only Choice type # TODO: add test cases to decode multiple values for Choice (bad) def setUp(self): jadn_check(schema_selectors) self.tc = Codec(schema_selectors) attr1_api = {"type": "Integer", "value": 17} attr2_api = {"type": "Primitive", "value": {"count": 17}} attr3_api = { "type": "Category", "value": { "animal": { "rat": { "length": 21, "weight": .342 } } } } attr4_bad_api = {"type": "Vegetable", "value": "turnip"} attr5_bad_api = {"type": "Category", "value": {"animal": {"fish": 10}}} def test_attribute_verbose(self): self.tc.set_mode(True, True) self.assertDictEqual(self.tc.encode("t_attribute", self.attr1_api), self.attr1_api) self.assertDictEqual(self.tc.decode("t_attribute", self.attr1_api), self.attr1_api) self.assertDictEqual(self.tc.encode("t_attribute", self.attr2_api), self.attr2_api) self.assertDictEqual(self.tc.decode("t_attribute", self.attr2_api), self.attr2_api) self.assertDictEqual(self.tc.encode("t_attribute", self.attr3_api), self.attr3_api) self.assertDictEqual(self.tc.decode("t_attribute", self.attr3_api), self.attr3_api) with self.assertRaises(ValueError): self.tc.encode("t_attribute", self.attr4_bad_api) with self.assertRaises(ValueError): self.tc.decode("t_attribute", self.attr4_bad_api) with self.assertRaises(ValueError): self.tc.encode("t_attribute", self.attr5_bad_api) with self.assertRaises(ValueError): self.tc.decode("t_attribute", self.attr5_bad_api) attr1_min = ["Integer", 17] attr2_min = ["Primitive", {"7": 17}] attr3_min = ["Category", {'2': {'5': [21, 0.342]}}] attr4_bad_min = ["Vegetable", {"7": 17}] attr5_bad_min = ["Category", {'2': {'9': 10}}] def test_attribute_min(self): self.tc.set_mode(False, False) self.assertListEqual(self.tc.encode("t_attribute", self.attr1_api), self.attr1_min) self.assertDictEqual(self.tc.decode("t_attribute", self.attr1_min), self.attr1_api) self.assertListEqual(self.tc.encode("t_attribute", self.attr2_api), self.attr2_min) self.assertDictEqual(self.tc.decode("t_attribute", self.attr2_min), self.attr2_api) self.assertListEqual(self.tc.encode("t_attribute", self.attr3_api), self.attr3_min) self.assertDictEqual(self.tc.decode("t_attribute", self.attr3_min), self.attr3_api) with self.assertRaises(ValueError): self.tc.encode("t_attribute", self.attr4_bad_api) with self.assertRaises(ValueError): self.tc.decode("t_attribute", self.attr4_bad_min) with self.assertRaises(ValueError): self.tc.encode("t_attribute", self.attr5_bad_api) with self.assertRaises(ValueError): self.tc.decode("t_attribute", self.attr5_bad_min) pep_api = {"foo": "bar", "data": {"count": 17}} pec_api = { "foo": "bar", "data": { "animal": { "rat": { "length": 21, "weight": .342 } } } } pep_bad_api = {"foo": "bar", "data": {"turnip": ""}} def test_property_explicit_verbose(self): self.tc.set_mode(True, True) self.assertDictEqual( self.tc.encode("t_property_explicit_primitive", self.pep_api), self.pep_api) self.assertDictEqual( self.tc.decode("t_property_explicit_primitive", self.pep_api), self.pep_api) self.assertDictEqual( self.tc.encode("t_property_explicit_category", self.pec_api), self.pec_api) self.assertDictEqual( self.tc.decode("t_property_explicit_category", self.pec_api), self.pec_api) with self.assertRaises(ValueError): self.tc.encode("t_property_explicit_primitive", self.pep_bad_api) with self.assertRaises(ValueError): self.tc.decode("t_property_explicit_primitive", self.pep_bad_api) pep_min = ['bar', {'7': 17}] pec_min = ['bar', {'2': {'5': [21, 0.342]}}] pep_bad_min = ['bar', {'6': 17}] def test_property_explicit_min(self): self.tc.set_mode(False, False) self.assertListEqual( self.tc.encode("t_property_explicit_primitive", self.pep_api), self.pep_min) self.assertDictEqual( self.tc.decode("t_property_explicit_primitive", self.pep_min), self.pep_api) self.assertListEqual( self.tc.encode("t_property_explicit_category", self.pec_api), self.pec_min) self.assertDictEqual( self.tc.decode("t_property_explicit_category", self.pec_min), self.pec_api) with self.assertRaises(ValueError): self.tc.encode("t_property_explicit_primitive", self.pep_bad_api) with self.assertRaises(ValueError): self.tc.decode("t_property_explicit_primitive", self.pep_bad_min) pip_api = {"foo": "bar", "count": 17} pic_api = {"foo": "bar", "animal": {"rat": {"length": 21, "weight": .342}}} pip_bad1_api = {"foo": "bar", "value": "turnip"} pip_bad2_api = {"foo": "bar", "value": {"turnip": ""}} def test_property_implicit_verbose(self): self.tc.set_mode(True, True) self.assertDictEqual( self.tc.encode("t_property_implicit_primitive", self.pip_api), self.pip_api) self.assertDictEqual( self.tc.decode("t_property_implicit_primitive", self.pip_api), self.pip_api) self.assertDictEqual( self.tc.encode("t_property_implicit_category", self.pic_api), self.pic_api) self.assertDictEqual( self.tc.decode("t_property_implicit_category", self.pic_api), self.pic_api) with self.assertRaises(ValueError): self.tc.encode("t_property_implicit_primitive", self.pip_bad1_api) with self.assertRaises(ValueError): self.tc.decode("t_property_implicit_primitive", self.pip_bad1_api) with self.assertRaises(ValueError): self.tc.encode("t_property_implicit_primitive", self.pip_bad2_api) with self.assertRaises(ValueError): self.tc.decode("t_property_implicit_primitive", self.pip_bad2_api) pip_min = ["bar", {"7": 17}] pic_min = ["bar", {"2": {"5": [21, .342]}}] pip_bad1_min = [] pip_bad2_min = [] def test_property_implicit_min(self): self.tc.set_mode(False, False) self.assertListEqual( self.tc.encode("t_property_implicit_primitive", self.pip_api), self.pip_min) self.assertDictEqual( self.tc.decode("t_property_implicit_primitive", self.pip_min), self.pip_api) self.assertListEqual( self.tc.encode("t_property_implicit_category", self.pic_api), self.pic_min) self.assertDictEqual( self.tc.decode("t_property_implicit_category", self.pic_min), self.pic_api) with self.assertRaises(ValueError): self.tc.encode("t_property_implicit_primitive", self.pip_bad1_api) with self.assertRaises(ValueError): self.tc.decode("t_property_implicit_primitive", self.pip_bad1_min) with self.assertRaises(ValueError): self.tc.encode("t_property_implicit_primitive", self.pip_bad2_api) with self.assertRaises(ValueError): self.tc.decode("t_property_implicit_primitive", self.pip_bad2_min)
def setUp(self): jadn_check(schema_compound) self.tc = Codec(schema_compound)
def setUp(self): jadn_check(schema_basic) self.tc = Codec(schema_basic)
class BasicTypes(unittest.TestCase): # TODO: Test Array def setUp(self): jadn_check(schema_basic) self.tc = Codec(schema_basic) def test_primitive(self): # Non-composed types (bool, int, num, str) self.assertEqual(self.tc.decode("t_bool", True), True) self.assertEqual(self.tc.decode("t_bool", False), False) self.assertEqual(self.tc.encode("t_bool", True), True) self.assertEqual(self.tc.encode("t_bool", False), False) with self.assertRaises(TypeError): self.tc.decode("t_bool", "True") with self.assertRaises(TypeError): self.tc.decode("t_bool", 1) with self.assertRaises(TypeError): self.tc.encode("t_bool", "True") with self.assertRaises(TypeError): self.tc.encode("t_bool", 1) self.assertEqual(self.tc.decode("t_int", 35), 35) self.assertEqual(self.tc.encode("t_int", 35), 35) with self.assertRaises(TypeError): self.tc.decode("t_int", 35.4) with self.assertRaises(TypeError): self.tc.decode("t_int", True) with self.assertRaises(TypeError): self.tc.decode("t_int", "hello") with self.assertRaises(TypeError): self.tc.encode("t_int", 35.4) with self.assertRaises(TypeError): self.tc.encode("t_int", True) with self.assertRaises(TypeError): self.tc.encode("t_int", "hello") self.assertEqual(self.tc.decode("t_num", 25.96), 25.96) self.assertEqual(self.tc.decode("t_num", 25), 25) self.assertEqual(self.tc.encode("t_num", 25.96), 25.96) self.assertEqual(self.tc.encode("t_num", 25), 25) with self.assertRaises(TypeError): self.tc.decode("t_num", True) with self.assertRaises(TypeError): self.tc.decode("t_num", "hello") with self.assertRaises(TypeError): self.tc.encode("t_num", True) with self.assertRaises(TypeError): self.tc.encode("t_num", "hello") self.assertEqual(self.tc.decode("t_str", "parrot"), "parrot") self.assertEqual(self.tc.encode("t_str", "parrot"), "parrot") with self.assertRaises(TypeError): self.tc.decode("t_str", True) with self.assertRaises(TypeError): self.tc.decode("t_str", 1) with self.assertRaises(TypeError): self.tc.encode("t_str", True) with self.assertRaises(TypeError): self.tc.encode("t_str", 1) def test_array_of(self): self.assertEqual(self.tc.decode("t_array_of", [1, 4, 9, 16]), [1, 4, 9, 16]) self.assertEqual(self.tc.encode("t_array_of", [1, 4, 9, 16]), [1, 4, 9, 16]) with self.assertRaises(TypeError): self.tc.decode("t_array_of", [1, "4", 9, 16]) with self.assertRaises(TypeError): self.tc.decode("t_array_of", 9) with self.assertRaises(TypeError): self.tc.encode("t_array_of", [1, "4", 9, 16]) with self.assertRaises(TypeError): self.tc.decode("t_array_of", 9) B1b = b"data to be encoded" B1s = "ZGF0YSB0byBiZSBlbmNvZGVk" B2b = "data\nto be ëncoded 旅程".encode(encoding="UTF-8") B2s = "ZGF0YQp0byBiZSDDq25jb2RlZCDml4XnqIs=" B3b = binascii.a2b_hex( "18e0c9987b8f32417ca6744f544b815ad2a6b4adca69d2c310bd033c57d363e3") B3s = "GODJmHuPMkF8pnRPVEuBWtKmtK3KadLDEL0DPFfTY+M=" B_bad1b = "string" B_bad2b = 394 B_bad3b = True B_bad1s = "ZgF%&0B++" def test_binary(self): self.assertEqual(self.tc.decode("t_bin", self.B1s), self.B1b) self.assertEqual(self.tc.decode("t_bin", self.B2s), self.B2b) self.assertEqual(self.tc.decode("t_bin", self.B3s), self.B3b) self.assertEqual(self.tc.encode("t_bin", self.B1b), self.B1s) self.assertEqual(self.tc.encode("t_bin", self.B2b), self.B2s) self.assertEqual(self.tc.encode("t_bin", self.B3b), self.B3s) with self.assertRaises((TypeError, binascii.Error)): self.tc.decode("t_bin", self.B_bad1s) with self.assertRaises(TypeError): self.tc.encode("t_bin", self.B_bad1b) with self.assertRaises(TypeError): self.tc.encode("t_bin", self.B_bad2b) with self.assertRaises(TypeError): self.tc.encode("t_bin", self.B_bad3b) C1a = {"type1": "foo"} C2a = {"type2": False} C3a = {"type3": 42} C1m = {"1": "foo"} C2m = {"4": False} C3m = {"7": 42} C1_bad1a = {"type1": 15} C1_bad2a = {"type5": "foo"} C1_bad3a = {"type1": "foo", "type2": False} C1_bad1m = {"1": 15} C1_bad2m = {"3": "foo"} C1_bad3m = {"1": "foo", "4": False} C1_bad4m = {1: "foo"} def test_choice_min(self): self.assertEqual(self.tc.decode("t_choice", self.C1m), self.C1a) self.assertEqual(self.tc.decode("t_choice", self.C2m), self.C2a) self.assertEqual(self.tc.decode("t_choice", self.C3m), self.C3a) self.assertEqual(self.tc.encode("t_choice", self.C1a), self.C1m) self.assertEqual(self.tc.encode("t_choice", self.C2a), self.C2m) self.assertEqual(self.tc.encode("t_choice", self.C3a), self.C3m) with self.assertRaises(TypeError): self.tc.decode("t_choice", self.C1_bad1m) with self.assertRaises(ValueError): self.tc.decode("t_choice", self.C1_bad2m) with self.assertRaises(ValueError): self.tc.decode("t_choice", self.C1_bad3m) with self.assertRaises(ValueError): self.tc.decode("t_choice", self.C1_bad4m) with self.assertRaises(TypeError): self.tc.encode("t_choice", self.C1_bad1a) with self.assertRaises(ValueError): self.tc.encode("t_choice", self.C1_bad2a) with self.assertRaises(ValueError): self.tc.encode("t_choice", self.C1_bad3a) def test_choice_verbose(self): self.tc.set_mode(True, True) self.assertEqual(self.tc.decode("t_choice", self.C1a), self.C1a) self.assertEqual(self.tc.decode("t_choice", self.C2a), self.C2a) self.assertEqual(self.tc.decode("t_choice", self.C3a), self.C3a) self.assertEqual(self.tc.encode("t_choice", self.C1a), self.C1a) self.assertEqual(self.tc.encode("t_choice", self.C2a), self.C2a) self.assertEqual(self.tc.encode("t_choice", self.C3a), self.C3a) with self.assertRaises(TypeError): self.tc.decode("t_choice", self.C1_bad1a) with self.assertRaises(ValueError): self.tc.decode("t_choice", self.C1_bad2a) with self.assertRaises(ValueError): self.tc.decode("t_choice", self.C1_bad3a) with self.assertRaises(TypeError): self.tc.encode("t_choice", self.C1_bad1a) with self.assertRaises(ValueError): self.tc.encode("t_choice", self.C1_bad2a) with self.assertRaises(ValueError): self.tc.encode("t_choice", self.C1_bad3a) def test_enumerated_min(self): self.assertEqual(self.tc.decode("t_enum", 15), "extra") self.assertEqual(self.tc.encode("t_enum", "extra"), 15) with self.assertRaises(ValueError): self.tc.decode("t_enum", 13) with self.assertRaises(TypeError): self.tc.decode("t_enum", "extra") with self.assertRaises(TypeError): self.tc.decode("t_enum", ["first"]) with self.assertRaises(ValueError): self.tc.encode("t_enum", "foo") with self.assertRaises(TypeError): self.tc.encode("t_enum", 15) with self.assertRaises(TypeError): self.tc.encode("t_enum", [1]) def test_enumerated_verbose(self): self.tc.set_mode(True, True) self.assertEqual(self.tc.decode("t_enum", "extra"), "extra") self.assertEqual(self.tc.encode("t_enum", "extra"), "extra") with self.assertRaises(ValueError): self.tc.decode("t_enum", "foo") with self.assertRaises(TypeError): self.tc.decode("t_enum", 42) with self.assertRaises(TypeError): self.tc.decode("t_enum", ["first"]) with self.assertRaises(ValueError): self.tc.encode("t_enum", "foo") with self.assertRaises(TypeError): self.tc.encode("t_enum", 42) with self.assertRaises(TypeError): self.tc.encode("t_enum", ["first"]) def test_enumerated_comp_min(self): self.assertEqual(self.tc.decode("t_enum_c", 15), 15) self.assertEqual(self.tc.encode("t_enum_c", 15), 15) with self.assertRaises(TypeError): self.tc.decode("t_enum_c", "extra") with self.assertRaises(TypeError): self.tc.encode("t_enum_c", "extra") def test_enumerated_comp_verbose(self): self.tc.set_mode(True, True) self.assertEqual(self.tc.decode("t_enum_c", 15), 15) self.assertEqual(self.tc.encode("t_enum_c", 15), 15) with self.assertRaises(TypeError): self.tc.decode("t_enum_c", "extra") with self.assertRaises(TypeError): self.tc.encode("t_enum_c", "extra") RGB1 = { "red": 24, "green": 120, "blue": 240 } # API (decoded) and verbose values Map and Record RGB2 = {"red": 50, "blue": 100} RGB3 = {"red": 9, "green": 80, "blue": 96, "alpha": 128} RGB_bad1a = {"red": 24, "green": 120} RGB_bad2a = {"red": 9, "green": 80, "blue": 96, "beta": 128} RGB_bad3a = {"red": 9, "green": 80, "blue": 96, "alpha": 128, "beta": 196} RGB_bad4a = {"red": "four", "green": 120, "blue": 240} RGB_bad5a = {"red": 24, "green": "120", "blue": 240} RGB_bad6a = {"red": 24, "green": 120, "bleu": 240} RGB_bad7a = {2: 24, "green": 120, "blue": 240} Map1m = { "2": 24, "4": 120, "6": 240 } # Encoded values Map (minimized and dict/tag mode) Map2m = {"2": 50, "6": 100} Map3m = {"2": 9, "4": 80, "6": 96, "9": 128} Map_bad1m = {"2": 24, "4": 120} Map_bad2m = {"2": 9, "4": 80, "6": 96, "9": 128, "12": 42} Map_bad3m = {"2": "four", "4": 120, "6": 240} Map_bad4m = {2: 24, 4: 120, 6: 240} Map_bad5m = [24, 120, 240] Rec1m = [24, 120, 240] # Encoded values Record (minimized) Rec2m = [50, None, 100] Rec3m = [9, 80, 96, 128] Rec_bad1m = [24, 120] Rec_bad2m = [9, 80, 96, 128, 42] Rec_bad3m = ["four", 120, 240] Rec1n = { "1": 24, "2": 120, "3": 240 } # Encoded values Record (unused dict/tag mode) Rec2n = {"1": 50, "3": 100} Rec3n = {"1": 9, "2": 80, "3": 96, "4": 128} Rec_bad1n = {"1": 24, "2": 120} Rec_bad2n = {"1": 9, "2": 80, "3": 96, "4": 128, "5": 42} Rec_bad3n = {"1": "four", "2": 120, "3": 240} Rec_bad4n = {1: 24, 2: 120, 3: 240} RGB1c = [24, 120, 240] # Encoded values Record (concise) RGB2c = [50, None, 100] RGB3c = [9, 80, 96, 128] RGB_bad1c = [24, 120] RGB_bad2c = [9, 80, 96, 128, 42] RGB_bad3c = ["four", 120, 240] def test_map_min(self): # dict structure, identifier tag self.assertDictEqual(self.tc.decode("t_map", self.Map1m), self.RGB1) self.assertDictEqual(self.tc.decode("t_map", self.Map2m), self.RGB2) self.assertDictEqual(self.tc.decode("t_map", self.Map3m), self.RGB3) self.assertDictEqual(self.tc.encode("t_map", self.RGB1), self.Map1m) self.assertDictEqual(self.tc.encode("t_map", self.RGB2), self.Map2m) self.assertDictEqual(self.tc.encode("t_map", self.RGB3), self.Map3m) with self.assertRaises(ValueError): self.tc.decode("t_map", self.Map_bad1m) with self.assertRaises(ValueError): self.tc.decode("t_map", self.Map_bad2m) with self.assertRaises(TypeError): self.tc.decode("t_map", self.Map_bad3m) with self.assertRaises(ValueError): self.tc.decode("t_map", self.Map_bad4m) with self.assertRaises(TypeError): self.tc.decode("t_map", self.Map_bad5m) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad1a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad2a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad3a) with self.assertRaises(TypeError): self.tc.encode("t_map", self.RGB_bad4a) with self.assertRaises(TypeError): self.tc.encode("t_map", self.RGB_bad5a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad6a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad7a) def test_map_unused(self): # dict structure, identifier tag self.tc.set_mode(True, False) self.assertDictEqual(self.tc.decode("t_map", self.Map1m), self.RGB1) self.assertDictEqual(self.tc.decode("t_map", self.Map2m), self.RGB2) self.assertDictEqual(self.tc.decode("t_map", self.Map3m), self.RGB3) self.assertDictEqual(self.tc.encode("t_map", self.RGB1), self.Map1m) self.assertDictEqual(self.tc.encode("t_map", self.RGB2), self.Map2m) self.assertDictEqual(self.tc.encode("t_map", self.RGB3), self.Map3m) with self.assertRaises(ValueError): self.tc.decode("t_map", self.Map_bad1m) with self.assertRaises(ValueError): self.tc.decode("t_map", self.Map_bad2m) with self.assertRaises(TypeError): self.tc.decode("t_map", self.Map_bad3m) with self.assertRaises(ValueError): self.tc.decode("t_map", self.Map_bad4m) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad1a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad2a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad3a) with self.assertRaises(TypeError): self.tc.encode("t_map", self.RGB_bad4a) with self.assertRaises(TypeError): self.tc.encode("t_map", self.RGB_bad5a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad6a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad7a) def test_map_concise(self): # dict structure, identifier name self.tc.set_mode(False, True) self.assertDictEqual(self.tc.decode("t_map", self.RGB1), self.RGB1) self.assertDictEqual(self.tc.decode("t_map", self.RGB2), self.RGB2) self.assertDictEqual(self.tc.decode("t_map", self.RGB3), self.RGB3) self.assertDictEqual(self.tc.encode("t_map", self.RGB1), self.RGB1) self.assertDictEqual(self.tc.encode("t_map", self.RGB2), self.RGB2) self.assertDictEqual(self.tc.encode("t_map", self.RGB3), self.RGB3) with self.assertRaises(ValueError): self.tc.decode("t_map", self.RGB_bad1a) with self.assertRaises(ValueError): self.tc.decode("t_map", self.RGB_bad2a) with self.assertRaises(ValueError): self.tc.decode("t_map", self.RGB_bad3a) with self.assertRaises(TypeError): self.tc.decode("t_map", self.RGB_bad4a) with self.assertRaises(TypeError): self.tc.decode("t_map", self.RGB_bad5a) with self.assertRaises(ValueError): self.tc.decode("t_map", self.RGB_bad6a) with self.assertRaises(ValueError): self.tc.decode("t_map", self.RGB_bad7a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad1a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad2a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad3a) with self.assertRaises(TypeError): self.tc.encode("t_map", self.RGB_bad4a) with self.assertRaises(TypeError): self.tc.encode("t_map", self.RGB_bad5a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad6a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad7a) def test_map_verbose(self): # dict structure, identifier name self.tc.set_mode(True, True) self.assertDictEqual(self.tc.decode("t_map", self.RGB1), self.RGB1) self.assertDictEqual(self.tc.decode("t_map", self.RGB2), self.RGB2) self.assertDictEqual(self.tc.decode("t_map", self.RGB3), self.RGB3) self.assertDictEqual(self.tc.encode("t_map", self.RGB1), self.RGB1) self.assertDictEqual(self.tc.encode("t_map", self.RGB2), self.RGB2) self.assertDictEqual(self.tc.encode("t_map", self.RGB3), self.RGB3) with self.assertRaises(ValueError): self.tc.decode("t_map", self.RGB_bad1a) with self.assertRaises(ValueError): self.tc.decode("t_map", self.RGB_bad2a) with self.assertRaises(ValueError): self.tc.decode("t_map", self.RGB_bad3a) with self.assertRaises(TypeError): self.tc.decode("t_map", self.RGB_bad4a) with self.assertRaises(TypeError): self.tc.decode("t_map", self.RGB_bad5a) with self.assertRaises(ValueError): self.tc.decode("t_map", self.RGB_bad6a) with self.assertRaises(ValueError): self.tc.decode("t_map", self.RGB_bad7a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad1a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad2a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad3a) with self.assertRaises(TypeError): self.tc.encode("t_map", self.RGB_bad4a) with self.assertRaises(TypeError): self.tc.encode("t_map", self.RGB_bad5a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad6a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad7a) def test_record_min(self): self.assertDictEqual(self.tc.decode("t_rec", self.Rec1m), self.RGB1) self.assertDictEqual(self.tc.decode("t_rec", self.Rec2m), self.RGB2) self.assertDictEqual(self.tc.decode("t_rec", self.Rec3m), self.RGB3) self.assertEqual(self.tc.encode("t_rec", self.RGB1), self.Rec1m) self.assertEqual(self.tc.encode("t_rec", self.RGB2), self.Rec2m) self.assertEqual(self.tc.encode("t_rec", self.RGB3), self.Rec3m) with self.assertRaises(ValueError): self.tc.decode("t_rec", self.Rec_bad1m) with self.assertRaises(ValueError): self.tc.decode("t_rec", self.Rec_bad2m) with self.assertRaises(TypeError): self.tc.decode("t_rec", self.Rec_bad3m) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad1a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad2a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad3a) with self.assertRaises(TypeError): self.tc.encode("t_map", self.RGB_bad4a) with self.assertRaises(TypeError): self.tc.encode("t_map", self.RGB_bad5a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad6a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad7a) def test_record_unused(self): self.tc.set_mode(True, False) self.assertDictEqual(self.tc.decode("t_rec", self.Rec1n), self.RGB1) self.assertDictEqual(self.tc.decode("t_rec", self.Rec2n), self.RGB2) self.assertDictEqual(self.tc.decode("t_rec", self.Rec3n), self.RGB3) self.assertEqual(self.tc.encode("t_rec", self.RGB1), self.Rec1n) self.assertEqual(self.tc.encode("t_rec", self.RGB2), self.Rec2n) self.assertEqual(self.tc.encode("t_rec", self.RGB3), self.Rec3n) with self.assertRaises(ValueError): self.tc.decode("t_rec", self.Rec_bad1n) with self.assertRaises(ValueError): self.tc.decode("t_rec", self.Rec_bad2n) with self.assertRaises(TypeError): self.tc.decode("t_rec", self.Rec_bad3n) with self.assertRaises(ValueError): self.tc.decode("t_rec", self.Rec_bad4n) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad1a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad2a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad3a) with self.assertRaises(TypeError): self.tc.encode("t_map", self.RGB_bad4a) with self.assertRaises(TypeError): self.tc.encode("t_map", self.RGB_bad5a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad6a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad7a) def test_record_concise(self): self.tc.set_mode(False, True) self.assertDictEqual(self.tc.decode("t_rec", self.RGB1c), self.RGB1) self.assertDictEqual(self.tc.decode("t_rec", self.RGB2c), self.RGB2) self.assertDictEqual(self.tc.decode("t_rec", self.RGB3c), self.RGB3) self.assertEqual(self.tc.encode("t_rec", self.RGB1), self.RGB1c) self.assertEqual(self.tc.encode("t_rec", self.RGB2), self.RGB2c) self.assertEqual(self.tc.encode("t_rec", self.RGB3), self.RGB3c) with self.assertRaises(ValueError): self.tc.decode("t_rec", self.RGB_bad1c) with self.assertRaises(ValueError): self.tc.decode("t_rec", self.RGB_bad2c) with self.assertRaises(TypeError): self.tc.decode("t_rec", self.RGB_bad3c) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad1a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad2a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad3a) with self.assertRaises(TypeError): self.tc.encode("t_map", self.RGB_bad4a) with self.assertRaises(TypeError): self.tc.encode("t_map", self.RGB_bad5a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad6a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad7a) def test_record_verbose(self): self.tc.set_mode(True, True) self.assertDictEqual(self.tc.decode("t_rec", self.RGB1), self.RGB1) self.assertDictEqual(self.tc.decode("t_rec", self.RGB2), self.RGB2) self.assertDictEqual(self.tc.decode("t_rec", self.RGB3), self.RGB3) self.assertDictEqual(self.tc.encode("t_rec", self.RGB1), self.RGB1) self.assertDictEqual(self.tc.encode("t_rec", self.RGB2), self.RGB2) self.assertDictEqual(self.tc.encode("t_rec", self.RGB3), self.RGB3) with self.assertRaises(ValueError): self.tc.decode("t_map", self.RGB_bad1a) with self.assertRaises(ValueError): self.tc.decode("t_map", self.RGB_bad2a) with self.assertRaises(ValueError): self.tc.decode("t_map", self.RGB_bad3a) with self.assertRaises(TypeError): self.tc.decode("t_map", self.RGB_bad4a) with self.assertRaises(TypeError): self.tc.decode("t_map", self.RGB_bad5a) with self.assertRaises(ValueError): self.tc.decode("t_map", self.RGB_bad6a) with self.assertRaises(ValueError): self.tc.decode("t_map", self.RGB_bad7a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad1a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad2a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad3a) with self.assertRaises(TypeError): self.tc.encode("t_map", self.RGB_bad4a) with self.assertRaises(TypeError): self.tc.encode("t_map", self.RGB_bad5a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad6a) with self.assertRaises(ValueError): self.tc.encode("t_map", self.RGB_bad7a) def test_array(self): # TODO: verbose and min, vector of unnamed fields pass
class Experimental_IPv6_Addr(unittest.TestCase): def setUp(self): fn = os.path.join('schema', 'exp.jadn') # Load experimental OpenC2 schema schema = jadn_load(fn) sa = jadn_analyze(schema) if sa['undefined']: print('Warning - undefined:', sa['undefined']) self.tc = Codec(schema, verbose_rec=True, verbose_str=True) ipv6_addr_b64_api = { # API IPv6 address. All API values are identical except for name. 'ipv6_addr_b64': b' \x01\r\xb8\x85\xa3\x08\xd3\x13\x19\x8a.\x03psH'} ipv6_addr_b64_ser = { # IPv6 address serialized in Base64url format 'ipv6_addr_b64': 'IAENuIWjCNMTGYouA3BzSA'} ipv6_addr_hex_api = { # API IPv6 address. All API values are identical except for name. 'ipv6_addr_x': b' \x01\r\xb8\x85\xa3\x08\xd3\x13\x19\x8a.\x03psH'} ipv6_addr_hex_ser = { # IPv6 address serialized in hex format 'ipv6_addr_x': '20010DB885A308D313198A2E03707348'} ipv6_addr_str_api = { # API IPv6 address. All API values are identical except for name. 'ipv6_addr_s': b' \x01\r\xb8\x85\xa3\x08\xd3\x13\x19\x8a.\x03psH'} ipv6_addr_str_ser = { # IPv6 address serialized in type-specific string (dotted decimal) format 'ipv6_addr_s': '2001:db8:85a3:8d3:1319:8a2e:370:7348'} ipv6_addr_b64_api_bad1 = { # Bad API IPv6 address - too short 'ipv6_addr_s': b' \x01\r\xb8\x85\xa3\x08\xd3\x13\x19\x8a.\x03ps'} ipv6_addr_b64_api_bad2 = { # Bad API IPv6 address - too long 'ipv6_addr_s': b' \x01\r\xb8\x85\xa3\x08\xd3\x13\x19\x8a.\x03psH\x01'} ipv6_addr_hex_ser_bad1 = { # Bad IPv6 address - too short 'ipv6_addr_x': '20010DB885A308D313198A2E037073'} ipv6_addr_hex_ser_bad2 = { # Bad IPv6 address - too long 'ipv6_addr_x': '20010DB885A308D313198A2E0370734801'} ipv6_addr_hex_ser_bad3 = { # Bad IPv6 address - punctuation 'ipv6_addr_x': '2001:0DB8:85A3:08D3:1319:8A2E:0370:7348'} ipv6_addr_hex_ser_bad4 = { # Bad IPv6 address - lower case 'ipv6_addr_x': '20010db885a308d313198a2e03707348'} ipv6_addr_hex_ser_bad5 = { # Bad IPv6 address - spaces 'ipv6_addr_x': '2001 0DB8 85A3 08D3 1319 8A2E 0370 7348'} ipv6_addr_str_ser_bad1 = { # Bad IPv6 address - too long 'ipv6_addr_s': '2001:db8:85a3:8d3:1319:8a2e:370:7348:0123'} ipv6_addr_str_ser_bad2 = { # Bad IPv6 address - leading zero 'ipv6_addr_s': '2001:0db8:85a3:08d3:1319:8a2e:0370:7348'} ipv6_addr_str_ser_bad3 = { # Bad IPv6 address - wrong punctuation 'ipv6_addr_s': '2001.db8.85a3.8d3.1319.8a2e.370.7348'} def test_ipv6_b64(self): self.assertEqual(self.tc.encode('Target', self.ipv6_addr_b64_api), self.ipv6_addr_b64_ser) self.assertEqual(self.tc.decode('Target', self.ipv6_addr_b64_ser), self.ipv6_addr_b64_api) with self.assertRaises(ValueError): self.tc.encode('Target', self.ipv6_addr_b64_api_bad1) with self.assertRaises(ValueError): self.tc.encode('Target', self.ipv6_addr_b64_api_bad2) def test_ipv6_hex(self): self.assertEqual(self.tc.encode('Target', self.ipv6_addr_hex_api), self.ipv6_addr_hex_ser) self.assertEqual(self.tc.decode('Target', self.ipv6_addr_hex_ser), self.ipv6_addr_hex_api) with self.assertRaises(ValueError): self.tc.decode('Target', self.ipv6_addr_hex_ser_bad1) with self.assertRaises(ValueError): self.tc.decode('Target', self.ipv6_addr_hex_ser_bad2) with self.assertRaises(TypeError): self.tc.decode('Target', self.ipv6_addr_hex_ser_bad3) with self.assertRaises(TypeError): self.tc.decode('Target', self.ipv6_addr_hex_ser_bad4) with self.assertRaises(TypeError): self.tc.decode('Target', self.ipv6_addr_hex_ser_bad5) def test_ipv6_str(self): self.assertEqual(self.tc.encode('Target', self.ipv6_addr_str_api), self.ipv6_addr_str_ser) self.assertEqual(self.tc.decode('Target', self.ipv6_addr_str_ser), self.ipv6_addr_str_api) with self.assertRaises(ValueError): self.tc.decode('Target', self.ipv6_addr_str_ser_bad1) # with self.assertRaises(ValueError): # https://tools.ietf.org/html/draft-main-ipaddr-text-rep-02#section-3 # self.tc.decode('Target', self.ipv6_addr_str_ser_bad2) # leading zeroes are not used with self.assertRaises(ValueError): self.tc.decode('Target', self.ipv6_addr_str_ser_bad3)
class Relax1(unittest.TestCase): def setUp(self): schema = jadn_load(os.path.join("schema", "relax1.jadn")) self.tc = Codec(schema) def test1_property_syntax(self): msg_api = [{ "name": "John Smith", "email": "*****@*****.**" }, { "name": "Fred Bloggs", "email": "*****@*****.**", "note": "Dr." }] msg_min = [["John Smith", "*****@*****.**"], ["Fred Bloggs", "*****@*****.**", "Dr."]] self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("addressBook", msg_api), msg_api) self.assertEqual(self.tc.decode("addressBook", msg_api), msg_api) self.tc.set_mode(False, False) # Minified (list/tag) self.assertEqual(self.tc.encode("addressBook", msg_api), msg_min) self.assertEqual(self.tc.decode("addressBook", msg_min), msg_api) def test2_card_explicit(self): msg_api = { "name": "John Smith", "email": "*****@*****.**", "info": { "phone": "555-1234" } } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("card2", msg_api), msg_api) self.assertEqual(self.tc.decode("card2", msg_api), msg_api) def test3_card_implicit(self): msg_api = { "name": "John Smith", "email": "*****@*****.**", "phone": "555-1234" } self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode("card2", msg_api), msg_api) self.assertEqual(self.tc.decode("card2", msg_api), msg_api)
class Experimental_IPv4_Addr(unittest.TestCase): def setUp(self): fn = os.path.join('schema', 'exp.jadn') # Load experimental OpenC2 schema schema = jadn_load(fn) sa = jadn_analyze(schema) if sa['undefined']: print('Warning - undefined:', sa['undefined']) self.tc = Codec(schema, verbose_rec=True, verbose_str=True) ipv4_addr_b64_api = { # API IPv4 address. All API values are identical except for name. 'ipv4_addr_b64': b'\xc0\xa8\x00\xfe'} ipv4_addr_b64_ser = { # IPv4 address serialized in Base64url format 'ipv4_addr_b64': 'wKgA_g'} ipv4_addr_hex_api = { # API IPv4 address. All API values are identical except for name. 'ipv4_addr_x': b'\xc0\xa8\x00\xfe'} ipv4_addr_hex_ser = { # IPv4 address serialized in hex format 'ipv4_addr_x': 'C0A800FE'} ipv4_addr_str_api = { # API IPv4 address. All API values are identical except for name. 'ipv4_addr_s': b'\xc0\xa8\x00\xfe'} ipv4_addr_str_ser = { # IPv4 address serialized in type-specific string (dotted decimal) format 'ipv4_addr_s': '192.168.0.254'} ipv4_addr_b64_api_bad1 = { # Bad API IPv4 address - too short 'ipv4_addr_s': b'\xc0\xa8\x00'} ipv4_addr_b64_api_bad2 = { # Bad API IPv4 address - too long 'ipv4_addr_s': b'\xc0\xa8\x00\xfe\x02'} ipv4_addr_hex_ser_bad1 = { # Bad IPv4 address - too short 'ipv4_addr_x': 'C0A800'} ipv4_addr_hex_ser_bad2 = { # Bad IPv4 address - too long 'ipv4_addr_x': 'C0A800FE02'} ipv4_addr_hex_ser_bad3 = { # Bad IPv4 address - punctuation 'ipv4_addr_x': 'C0A8:00FE'} ipv4_addr_hex_ser_bad4 = { # Bad IPv4 address - lower case 'ipv4_addr_x': 'C0a800fe'} ipv4_addr_hex_ser_bad5 = { # Bad IPv4 address - spaces 'ipv4_addr_x': 'C0 A8 00 FE'} ipv4_addr_str_ser_bad1 = { # Bad IPv4 address - too long 'ipv4_addr_s': '192.168.0.254.2'} ipv4_addr_str_ser_bad2 = { # Bad IPv4 address - leading zero 'ipv4_addr_s': '192.168.0.054'} ipv4_addr_str_ser_bad3 = { # Bad IPv4 address - wrong punctuation 'ipv4_addr_s': '192:168:0:54'} ipv4_addr_str_ser_bad4 = { # Bad IPv4 address - non-decimal 'ipv4_addr_s': '192.168.0.5a'} def test_ipv4_b64(self): self.assertEqual(self.tc.encode('Target', self.ipv4_addr_b64_api), self.ipv4_addr_b64_ser) self.assertEqual(self.tc.decode('Target', self.ipv4_addr_b64_ser), self.ipv4_addr_b64_api) with self.assertRaises(ValueError): self.tc.encode('Target', self.ipv4_addr_b64_api_bad1) with self.assertRaises(ValueError): self.tc.encode('Target', self.ipv4_addr_b64_api_bad2) def test_ipv4_hex(self): self.assertEqual(self.tc.encode('Target', self.ipv4_addr_hex_api), self.ipv4_addr_hex_ser) self.assertEqual(self.tc.decode('Target', self.ipv4_addr_hex_ser), self.ipv4_addr_hex_api) with self.assertRaises(ValueError): self.tc.decode('Target', self.ipv4_addr_hex_ser_bad1) with self.assertRaises(ValueError): self.tc.decode('Target', self.ipv4_addr_hex_ser_bad2) with self.assertRaises(TypeError): self.tc.decode('Target', self.ipv4_addr_hex_ser_bad3) with self.assertRaises(TypeError): self.tc.decode('Target', self.ipv4_addr_hex_ser_bad4) with self.assertRaises(TypeError): self.tc.decode('Target', self.ipv4_addr_hex_ser_bad5) def test_ipv4_str(self): self.assertEqual(self.tc.encode('Target', self.ipv4_addr_str_api), self.ipv4_addr_str_ser) self.assertEqual(self.tc.decode('Target', self.ipv4_addr_str_ser), self.ipv4_addr_str_api) with self.assertRaises(ValueError): self.tc.decode('Target', self.ipv4_addr_str_ser_bad1) # with self.assertRaises(ValueError): # https://tools.ietf.org/html/draft-main-ipaddr-text-rep-02#section-3 # self.tc.decode('Target', self.ipv4_addr_str_ser_bad2) # leading zeroes are not used with self.assertRaises(ValueError): self.tc.decode('Target', self.ipv4_addr_str_ser_bad3) with self.assertRaises(ValueError): self.tc.decode('Target', self.ipv4_addr_str_ser_bad4)
class Selectors(unittest.TestCase): def setUp(self): jadn_check(schema_selectors) self.tc = Codec(schema_selectors) attr1_api = {"type": "Integer", "value": 17} attr2_api = {"type": "Primitive", "value": {"count": 17}} attr3_api = {"type": "Category", "value": {"animal": {"rat": {"length": 21, "weight": .342}}}} attr4_bad_api = {"type": "vegetable", "value": "turnip"} attr5_bad_api = {"type": "vegetable", "value": {"turnip": ""}} def test_attribute(self): self.tc.set_mode(True, True) self.assertDictEqual(self.tc.encode("t_attribute", self.attr1_api), self.attr1_api) self.assertDictEqual(self.tc.decode("t_attribute", self.attr1_api), self.attr1_api) self.assertDictEqual(self.tc.encode("t_attribute", self.attr2_api), self.attr2_api) self.assertDictEqual(self.tc.decode("t_attribute", self.attr2_api), self.attr2_api) self.assertDictEqual(self.tc.encode("t_attribute", self.attr3_api), self.attr3_api) self.assertDictEqual(self.tc.decode("t_attribute", self.attr3_api), self.attr3_api) with self.assertRaises(ValueError): self.tc.encode("t_attribute", self.attr4_bad_api) with self.assertRaises(ValueError): self.tc.decode("t_attribute", self.attr4_bad_api) with self.assertRaises(ValueError): self.tc.encode("t_attribute", self.attr5_bad_api) with self.assertRaises(ValueError): self.tc.decode("t_attribute", self.attr5_bad_api) pep_api = {"foo": "bar", "data": {"count": 17}} pec_api = {"foo": "bar", "data": {"animal": {"rat": {"length": 21, "weight": .342}}}} pep_bad_api = {"foo": "bar", "data": {"turnip": ""}} def test_property_explicit(self): self.tc.set_mode(True, True) self.assertDictEqual(self.tc.encode("t_property_explicit_primitive", self.pep_api), self.pep_api) self.assertDictEqual(self.tc.decode("t_property_explicit_primitive", self.pep_api), self.pep_api) self.assertDictEqual(self.tc.encode("t_property_explicit_category", self.pec_api), self.pec_api) self.assertDictEqual(self.tc.decode("t_property_explicit_category", self.pec_api), self.pec_api) with self.assertRaises(ValueError): self.tc.encode("t_property_explicit_primitive", self.pep_bad_api) with self.assertRaises(ValueError): self.tc.decode("t_property_explicit_primitive", self.pep_bad_api) pip_api = {"foo": "bar", "count": 17} pic_api = {"foo": "bar", "animal": {"rat": {"length": 21, "weight": .342}}} pip_bad1_api = {"foo": "bar", "value": "turnip"} pip_bad2_api = {"foo": "bar", "value": {"turnip": ""}} def test_property_implicit(self): self.tc.set_mode(True, True) self.assertDictEqual(self.tc.encode("t_property_implicit_primitive", self.pip_api), self.pip_api) self.assertDictEqual(self.tc.decode("t_property_implicit_primitive", self.pip_api), self.pip_api) self.assertDictEqual(self.tc.encode("t_property_implicit_category", self.pic_api), self.pic_api) self.assertDictEqual(self.tc.decode("t_property_implicit_category", self.pic_api), self.pic_api) with self.assertRaises(TypeError): self.tc.encode("t_property_implicit_primitive", self.pip_bad1_api) with self.assertRaises(TypeError): self.tc.decode("t_property_implicit_primitive", self.pip_bad1_api) with self.assertRaises(ValueError): self.tc.encode("t_property_implicit_primitive", self.pip_bad2_api) with self.assertRaises(ValueError): self.tc.decode("t_property_implicit_primitive", self.pip_bad2_api)
def setUp(self): jadn_check(schema_selectors) self.tc = Codec(schema_selectors)
def setUp(self): jadn_check(schema_person) jadn_analyze(schema_person) self.c = Codec(schema_person, "True", "True") # Verbose encoding mode (dict/name)
class ListField( unittest.TestCase ): # TODO: arrayOf(rec,map,array,arrayof,choice), array(), map(), rec() def setUp(self): jadn_check(schema_listfield) self.tc = Codec(schema_listfield) Lna = { "string": "cat" } # Cardinality 0..n field doesn't omit empty list. Use ArrayOf type. Lsa = { "string": "cat", "list": "red" } # Always invalid, value is a string, not a list of one string. L0a = { "string": "cat", "list": [] } # List fields SHOULD have minimum cardinality 1 to prevent this ambiguity. L1a = {"string": "cat", "list": ["red"]} L2a = {"string": "cat", "list": ["red", "green"]} L3a = {"string": "cat", "list": ["red", "green", "blue"]} def test_opt_list_verbose(self): # n-P, s-F, 0-F, 1-P, 2-P, 3-F self.tc.set_mode(True, True) self.assertDictEqual(self.tc.encode("t_opt_list", self.Lna), self.Lna) self.assertDictEqual(self.tc.decode("t_opt_list", self.Lna), self.Lna) with self.assertRaises(TypeError): self.tc.encode("t_opt_list", self.Lsa) with self.assertRaises(TypeError): self.tc.decode("t_opt_list", self.Lsa) with self.assertRaises(ValueError): self.tc.encode("t_opt_list", self.L0a) with self.assertRaises(ValueError): self.tc.decode("t_opt_list", self.L0a) self.assertDictEqual(self.tc.encode("t_opt_list", self.L1a), self.L1a) self.assertDictEqual(self.tc.decode("t_opt_list", self.L1a), self.L1a) self.assertDictEqual(self.tc.encode("t_opt_list", self.L2a), self.L2a) self.assertDictEqual(self.tc.decode("t_opt_list", self.L2a), self.L2a) with self.assertRaises(ValueError): self.tc.encode("t_opt_list", self.L3a) with self.assertRaises(ValueError): self.tc.decode("t_opt_list", self.L3a) def test_list_1_2_verbose(self): # n-F, s-F, 0-F, 1-P, 2-P, 3-F self.tc.set_mode(True, True) with self.assertRaises(ValueError): self.tc.encode("t_list_1_2", self.Lna) with self.assertRaises(ValueError): self.tc.decode("t_list_1_2", self.Lna) with self.assertRaises(TypeError): self.tc.encode("t_list_1_2", self.Lsa) with self.assertRaises(TypeError): self.tc.decode("t_list_1_2", self.Lsa) with self.assertRaises(ValueError): self.tc.encode("t_list_1_2", self.L0a) with self.assertRaises(ValueError): self.tc.decode("t_list_1_2", self.L0a) self.assertDictEqual(self.tc.encode("t_list_1_2", self.L1a), self.L1a) self.assertDictEqual(self.tc.decode("t_list_1_2", self.L1a), self.L1a) self.assertDictEqual(self.tc.encode("t_list_1_2", self.L2a), self.L2a) self.assertDictEqual(self.tc.decode("t_list_1_2", self.L2a), self.L2a) with self.assertRaises(ValueError): self.tc.encode("t_list_1_2", self.L3a) with self.assertRaises(ValueError): self.tc.decode("t_list_1_2", self.L3a) def test_list_0_2_verbose(self): # n-P, s-F, 0-F, 1-P, 2-P, 3-F self.tc.set_mode(True, True) self.assertDictEqual(self.tc.encode("t_list_0_2", self.Lna), self.Lna) self.assertDictEqual(self.tc.decode("t_list_0_2", self.Lna), self.Lna) with self.assertRaises(TypeError): self.tc.encode("t_list_0_2", self.Lsa) with self.assertRaises(TypeError): self.tc.decode("t_list_0_2", self.Lsa) with self.assertRaises(ValueError): self.tc.encode("t_list_0_2", self.L0a) with self.assertRaises(ValueError): self.tc.decode("t_list_0_2", self.L0a) self.assertDictEqual(self.tc.encode("t_list_0_2", self.L1a), self.L1a) self.assertDictEqual(self.tc.decode("t_list_0_2", self.L1a), self.L1a) self.assertDictEqual(self.tc.encode("t_list_0_2", self.L2a), self.L2a) self.assertDictEqual(self.tc.decode("t_list_0_2", self.L2a), self.L2a) with self.assertRaises(ValueError): self.tc.encode("t_list_0_2", self.L3a) with self.assertRaises(ValueError): self.tc.decode("t_list_0_2", self.L3a) def test_list_2_3_verbose(self): # n-F, 0-F, 1-F, 2-P, 3-P self.tc.set_mode(True, True) with self.assertRaises(ValueError): self.tc.encode("t_list_2_3", self.Lna) with self.assertRaises(ValueError): self.tc.decode("t_list_2_3", self.Lna) with self.assertRaises(ValueError): self.tc.encode("t_list_2_3", self.L0a) with self.assertRaises(ValueError): self.tc.decode("t_list_2_3", self.L0a) with self.assertRaises(ValueError): self.tc.encode("t_list_2_3", self.L1a) with self.assertRaises(ValueError): self.tc.decode("t_list_2_3", self.L1a) self.assertDictEqual(self.tc.encode("t_list_2_3", self.L2a), self.L2a) self.assertDictEqual(self.tc.decode("t_list_2_3", self.L2a), self.L2a) self.assertDictEqual(self.tc.encode("t_list_2_3", self.L3a), self.L3a) self.assertDictEqual(self.tc.decode("t_list_2_3", self.L3a), self.L3a) def test_list_1_n_verbose(self): # n-F, 0-F, 1-P, 2-P, 3-P self.tc.set_mode(True, True) with self.assertRaises(ValueError): self.tc.encode("t_list_1_n", self.Lna) with self.assertRaises(ValueError): self.tc.decode("t_list_1_n", self.Lna) with self.assertRaises(ValueError): self.tc.encode("t_list_1_n", self.L0a) with self.assertRaises(ValueError): self.tc.decode("t_list_1_n", self.L0a) self.assertDictEqual(self.tc.encode("t_list_1_n", self.L1a), self.L1a) self.assertDictEqual(self.tc.decode("t_list_1_n", self.L1a), self.L1a) self.assertDictEqual(self.tc.encode("t_list_1_n", self.L2a), self.L2a) self.assertDictEqual(self.tc.decode("t_list_1_n", self.L2a), self.L2a) self.assertDictEqual(self.tc.encode("t_list_1_n", self.L3a), self.L3a) self.assertDictEqual(self.tc.decode("t_list_1_n", self.L3a), self.L3a)
def setUp(self): jadn_check(schema_listfield) self.tc = Codec(schema_listfield)
def setUp(self): schema = jadn_load(os.path.join("schema", "relax1.jadn")) self.tc = Codec(schema)
class OpenC2(unittest.TestCase): def setUp(self): schema = jadn_load(os.path.join("schema", "openc2.jadn")) self.tc = Codec(schema) def check(self, item, cmd_api, cmd_min, cmd_flat): self.tc.set_mode(False, False) # Minified (list/tag) self.assertEqual(self.tc.encode(item, cmd_api), cmd_min) self.assertEqual(self.tc.decode(item, cmd_min), cmd_api) self.tc.set_mode(True, True) # API / Verbose (dict/name) self.assertEqual(self.tc.encode(item, cmd_api), cmd_api) self.assertEqual(self.tc.decode(item, cmd_api), cmd_api) self.assertEqual(flatten(cmd_api), cmd_flat) self.assertEqual(fluff(cmd_flat), cmd_api) def test1_delete_cmd(self): cmd_api = { "action": "delete", "target": { "file": { "name": "otaku.exe", "hashes": { "SHA-256": "19ce084ab0599c1659e4ce12ae822bd3" "02e494608d796b8b8a233fdfc8456663" } } }, "actuator": { "endpoint_workstation": { "actuator_id": "dns://192.168.110.120", "asset_id": "B4920J" } }, "modifiers": { "command_id": "SEP1432_84295" } } cmd_flat = { "action": "delete", "target.file.name": "otaku.exe", "target.file.hashes.SHA-256": "19ce084ab0599c1659e4ce12ae822bd3" "02e494608d796b8b8a233fdfc8456663", "actuator.endpoint_workstation.actuator_id": "dns://192.168.110.120", "actuator.endpoint_workstation.asset_id": "B4920J", "modifiers.command_id": "SEP1432_84295" } cmd_min = [ 19, { "10": { "2": { "6": "19ce084ab0599c1659e4ce12ae822bd302e494608d796b8b8a233fdfc8456663" }, "4": "otaku.exe" } }, { "11": ["dns://192.168.110.120", "B4920J"] }, { "6": "SEP1432_84295" } ] self.check("OpenC2Command", cmd_api, cmd_min, cmd_flat) def test1_delete_response(self): cmd_api = {"status": "OK", "response_src": "dns://192.168.110.120"} cmd_flat = cmd_api cmd_min = [200, None, "dns://192.168.110.120"] self.check("OpenC2Response", cmd_api, cmd_min, cmd_flat) def test2_respond_cmd(self): cmd_api = { "action": "report", "target": { "url": "dummy" }, "actuator": { "endpoint_workstation": { "actuator_id": "dns://192.168.110.120" } }, "modifiers": { "respond_to": "dns://remote-server14.example.com", "command_ref": "SEP1432_84295" } } cmd_flat = { "action": "report", "target.url": "dummy", "actuator.endpoint_workstation.actuator_id": "dns://192.168.110.120", "modifiers.respond_to": "dns://remote-server14.example.com", "modifiers.command_ref": "SEP1432_84295" } cmd_min = [ 4, { "18": "dummy" }, { "11": ["dns://192.168.110.120"] }, { "9": "dns://remote-server14.example.com", "17": "SEP1432_84295" } ] self.check("OpenC2Command", cmd_api, cmd_min, cmd_flat)