Пример #1
0
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)
Пример #2
0
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)
Пример #3
0
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)
Пример #4
0
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)
print("Decoded Command (API flat)       =", flatten(command2))
Пример #5
0
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)
Пример #6
0
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)
Пример #7
0
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)
Пример #8
0
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
Пример #9
0
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)
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)