def test_flow_repr_html_state(): # ICMP flows do not have ports flow_dict = { "dscp": 0, "dstIp": "2.1.1.1", "dstPort": 0, "ecn": 0, "fragmentOffset": 0, "icmpCode": 0, "icmpVar": 0, "ingressNode": "ingress", "ipProtocol": "TCP", "packetLength": 0, "srcIp": "5.5.1.1", "srcPort": 0, "state": "NEW", "tag": "BASE", "tcpFlagsAck": 0, "tcpFlagsCwr": 0, "tcpFlagsEce": 0, "tcpFlagsFin": 0, "tcpFlagsPsh": 0, "tcpFlagsRst": 0, "tcpFlagsSyn": 0, "tcpFlagsUrg": 0 } assert ("Firewall Classification" not in Flow.from_dict(flow_dict)._repr_html_()) # ESTABLISHED flow_dict['state'] = "ESTABLISHED" assert ("Firewall Classification: ESTABLISHED" in Flow.from_dict(flow_dict)._repr_html_())
def test_flow_str_ports(): # ICMP flows do not have ports flowDict = { "dscp": 0, "dstIp": "2.1.1.1", "dstPort": 1234, "ecn": 0, "fragmentOffset": 0, "icmpCode": 255, "icmpVar": 255, "ingressNode": "ingress", "ipProtocol": "ICMP", "packetLength": 0, "srcIp": "5.5.1.1", "srcPort": 2345, "state": "NEW", "tag": "BASE", "tcpFlagsAck": 0, "tcpFlagsCwr": 0, "tcpFlagsEce": 0, "tcpFlagsFin": 0, "tcpFlagsPsh": 0, "tcpFlagsRst": 0, "tcpFlagsSyn": 0, "tcpFlagsUrg": 0 } str = repr(Flow.from_dict(flowDict)) assert("2.1.1.1:1234" not in str) assert("5.5.1.1:2345" not in str) # UDP flowDict['ipProtocol'] = "UDP" str = repr(Flow.from_dict(flowDict)) assert("2.1.1.1:1234" not in str) assert("5.5.1.1:2345" not in str)
def test_get_ip_protocol_str(): flowDict = { "dscp": 0, "dstIp": "2.1.1.1", "dstPort": 0, "ecn": 0, "fragmentOffset": 0, "icmpCode": 255, "icmpVar": 255, "ingressNode": "ingress", "ipProtocol": "UNNAMED_243", "packetLength": 0, "srcIp": "5.5.1.1", "srcPort": 0, "state": "NEW", "tag": "BASE", "tcpFlagsAck": 0, "tcpFlagsCwr": 0, "tcpFlagsEce": 0, "tcpFlagsFin": 0, "tcpFlagsPsh": 0, "tcpFlagsRst": 0, "tcpFlagsSyn": 0, "tcpFlagsUrg": 0 } assert Flow.from_dict(flowDict).get_ip_protocol_str() == "ipProtocol=243" flowDict["ipProtocol"] = "TCP" assert Flow.from_dict(flowDict).get_ip_protocol_str() == "TCP"
def test_get_ip_protocol_str_tcp(): flow_dict = { "dscp": 0, "dstIp": "2.1.1.1", "dstPort": 80, "ecn": 0, "fragmentOffset": 0, "icmpCode": 255, "icmpVar": 255, "ingressNode": "ingress", "ipProtocol": "TCP", "packetLength": 0, "srcIp": "5.5.1.1", "srcPort": 80, "tcpFlagsAck": 0, "tcpFlagsCwr": 0, "tcpFlagsEce": 0, "tcpFlagsFin": 0, "tcpFlagsPsh": 0, "tcpFlagsRst": 0, "tcpFlagsSyn": 0, "tcpFlagsUrg": 0, } assert Flow.from_dict( flow_dict).get_ip_protocol_str() == "TCP (no flags set)" # with flags flow_dict["tcpFlagsAck"] = 1 assert Flow.from_dict(flow_dict).get_ip_protocol_str() == "TCP (ACK)"
def test_flow_repr_html_ports(): # ICMP flows do not have ports flow_dict = { "dscp": 0, "dstIp": "2.1.1.1", "dstPort": 0, "ecn": 0, "fragmentOffset": 0, "icmpCode": 255, "icmpVar": 255, "ingressNode": "ingress", "ipProtocol": "ICMP", "packetLength": 0, "srcIp": "5.5.1.1", "srcPort": 0, "state": "NEW", "tag": "BASE", "tcpFlagsAck": 0, "tcpFlagsCwr": 0, "tcpFlagsEce": 0, "tcpFlagsFin": 0, "tcpFlagsPsh": 0, "tcpFlagsRst": 0, "tcpFlagsSyn": 0, "tcpFlagsUrg": 0 } assert ("Port" not in Flow.from_dict(flow_dict)._repr_html_()) # UDP flow_dict['ipProtocol'] = "UDP" assert ("Port" in Flow.from_dict(flow_dict)._repr_html_())
def testFlowDeserializationOptionalMissing(): hopDict = { "dscp": 0, "dstIp": "2.1.1.1", "dstPort": 0, "ecn": 0, "fragmentOffset": 0, "icmpCode": 255, "icmpVar": 255, "ingressNode": "ingress", "ipProtocol": "IP", "packetLength": 0, "srcIp": "5.5.1.1", "srcPort": 0, "state": "NEW", "tag": "BASE", "tcpFlagsAck": 0, "tcpFlagsCwr": 0, "tcpFlagsEce": 0, "tcpFlagsFin": 0, "tcpFlagsPsh": 0, "tcpFlagsRst": 0, "tcpFlagsSyn": 0, "tcpFlagsUrg": 0 } # check deserialization flow = Flow.from_dict(hopDict) assert flow.srcIp == "5.5.1.1" # should convert to string without problems str(flow)
def test_get_ip_protocol_str_icmp(): flow_dict = { "dscp": 0, "dstIp": "2.1.1.1", "dstPort": 0, "ecn": 0, "fragmentOffset": 0, "icmpCode": 0, "icmpVar": 8, "ingressNode": "ingress", "ipProtocol": "ICMP", "packetLength": 0, "srcIp": "5.5.1.1", "srcPort": 0, "tcpFlagsAck": 0, "tcpFlagsCwr": 0, "tcpFlagsEce": 0, "tcpFlagsFin": 0, "tcpFlagsPsh": 0, "tcpFlagsRst": 0, "tcpFlagsSyn": 0, "tcpFlagsUrg": 0, } assert Flow.from_dict( flow_dict).get_ip_protocol_str() == "ICMP (type=8, code=0)"
def test_get_flag_str(): flow_dict = { "dscp": 0, "dstIp": "2.1.1.1", "dstPort": 0, "ecn": 0, "fragmentOffset": 0, "icmpCode": 0, "icmpVar": 8, "ingressNode": "ingress", "ipProtocol": "ICMP", "packetLength": 0, "srcIp": "5.5.1.1", "srcPort": 0, "tcpFlagsAck": 0, "tcpFlagsCwr": 0, "tcpFlagsEce": 0, "tcpFlagsFin": 0, "tcpFlagsPsh": 0, "tcpFlagsRst": 0, "tcpFlagsSyn": 0, "tcpFlagsUrg": 0, } assert Flow.from_dict(flow_dict).get_flag_str() == "no flags set" flow_dict["tcpFlagsAck"] = 1 assert Flow.from_dict(flow_dict).get_flag_str() == "ACK" flow_dict["tcpFlagsSyn"] = 1 assert Flow.from_dict(flow_dict).get_flag_str() == "SYN-ACK" flow_dict["tcpFlagsCwr"] = 1 assert Flow.from_dict(flow_dict).get_flag_str() == "SYN-ACK-CWR" flow_dict["tcpFlagsEce"] = 1 assert Flow.from_dict(flow_dict).get_flag_str() == "SYN-ACK-CWR-ECE" flow_dict["tcpFlagsFin"] = 1 assert Flow.from_dict(flow_dict).get_flag_str() == "SYN-FIN-ACK-CWR-ECE" flow_dict["tcpFlagsPsh"] = 1 assert Flow.from_dict( flow_dict).get_flag_str() == "SYN-FIN-ACK-CWR-ECE-PSH" flow_dict["tcpFlagsRst"] = 1 assert Flow.from_dict( flow_dict).get_flag_str() == "SYN-FIN-ACK-RST-CWR-ECE-PSH" flow_dict["tcpFlagsUrg"] = 1 assert Flow.from_dict( flow_dict).get_flag_str() == "SYN-FIN-ACK-RST-CWR-ECE-PSH-URG"
def test_flow_repr_html_start_location(): # ICMP flows do not have ports flow_dict = { "dscp": 0, "dstIp": "2.1.1.1", "dstPort": 0, "ecn": 0, "fragmentOffset": 0, "icmpCode": 255, "icmpVar": 255, "ingressNode": "ingressNode", "ingressVrf": "default", "ipProtocol": "ICMP", "packetLength": 0, "srcIp": "5.5.1.1", "srcPort": 0, "state": "NEW", "tag": "BASE", "tcpFlagsAck": 0, "tcpFlagsCwr": 0, "tcpFlagsEce": 0, "tcpFlagsFin": 0, "tcpFlagsPsh": 0, "tcpFlagsRst": 0, "tcpFlagsSyn": 0, "tcpFlagsUrg": 0, } assert "Start Location: ingressNode" in Flow.from_dict(flow_dict)._repr_html_lines() flow_dict["ingressVrf"] = "ingressVrf" assert ( "Start Location: ingressNode vrf=ingressVrf" in Flow.from_dict(flow_dict)._repr_html_lines() ) del flow_dict["ingressVrf"] flow_dict["ingressInterface"] = "ingressIface" flow = Flow.from_dict(flow_dict) assert ( "Start Location: ingressNode interface=ingressIface" in flow._repr_html_lines() )
def test_str(): flow_dict = { "dscp": 0, "dstIp": "2.1.1.1", "dstPort": 0, "ecn": 0, "fragmentOffset": 0, "icmpCode": 0, "icmpVar": 0, "ingressNode": "ingress", "ipProtocol": "UNNAMED_168", "packetLength": 512, "srcIp": "5.5.1.1", "srcPort": 0, "tcpFlagsAck": 0, "tcpFlagsCwr": 0, "tcpFlagsEce": 0, "tcpFlagsFin": 0, "tcpFlagsPsh": 0, "tcpFlagsRst": 0, "tcpFlagsSyn": 0, "tcpFlagsUrg": 0, } # no ports assert (str(Flow.from_dict(flow_dict)) == "start=ingress [5.5.1.1->2.1.1.1 ipProtocol=168]") # with ports flow_dict["ipProtocol"] = "TCP" flow_dict["dstPort"] = "80" flow_dict["srcPort"] = "800" assert (str(Flow.from_dict(flow_dict)) == "start=ingress [5.5.1.1:800->2.1.1.1:80 TCP (no flags set)]") # uncommon dscp flow_dict["dscp"] = "1" assert (str( Flow.from_dict(flow_dict) ) == "start=ingress [5.5.1.1:800->2.1.1.1:80 TCP (no flags set) dscp=1]") # uncommon ecn flow_dict["ecn"] = "1" assert ( str(Flow.from_dict(flow_dict)) == "start=ingress [5.5.1.1:800->2.1.1.1:80 TCP (no flags set) dscp=1 ecn=1]" ) # uncommon fragment offset flow_dict["fragmentOffset"] = "1501" assert ( str(Flow.from_dict(flow_dict)) == "start=ingress [5.5.1.1:800->2.1.1.1:80 TCP (no flags set) dscp=1 ecn=1 fragmentOffset=1501]" ) # uncommon packet length flow_dict["packetLength"] = "100" assert ( str(Flow.from_dict(flow_dict)) == "start=ingress [5.5.1.1:800->2.1.1.1:80 TCP (no flags set) dscp=1 ecn=1 fragmentOffset=1501 length=100]" )
def _parse_json_with_schema(schema, json_object): # type: (str, Any) -> Any """Process JSON object according to its schema.""" if json_object is None: # Honor null/None values return None # See if it's an iterable and we need to process it if _is_iterable_schema(schema): if not isinstance(json_object, list): raise ValueError( "Got non-list value for list/set schema {schema}. Value: {value}" .format(schema=schema, value=json_object)) base_schema = _get_base_schema(schema) return ListWrapper([ _parse_json_with_schema(base_schema, element) for element in json_object ]) # Handle "primitive" schemas if schema == "AclTrace": return AclTrace.from_dict(json_object) if schema == "FileLines": return FileLines.from_dict(json_object) if schema == "Flow": return Flow.from_dict(json_object) if schema == "FlowTrace": return FlowTrace.from_dict(json_object) if schema == "Integer" or schema == "Long": return int(json_object) if schema == "Interface": return Interface.from_dict(json_object) if schema == "Ip": return str(json_object) if schema == "Issue": return Issue.from_dict(json_object) if schema == "Node": return json_object["name"] if schema == "BgpRoute": return BgpRoute.from_dict(json_object) if schema == "BgpRouteDiffs": return BgpRouteDiffs.from_dict(json_object) if schema == "Prefix": return str(json_object) if schema == "SelfDescribing": return _parse_json_with_schema(json_object["schema"], json_object.get("value")) if schema == "String": return str(json_object) if schema == "Trace": return Trace.from_dict(json_object) return json_object
def _get_display_value(schema, json_object): # type (str, Any) -> Any if json_object is None: return None if _is_list_or_set_schema(schema): if not isinstance(json_object, list): raise ValueError("Got non-list value for list/set schema", schema, ":", json_object) output_list = [ str(_get_display_value(_get_base_schema(schema), element)) for element in json_object ] if _get_base_schema(schema) == "FlowTrace": return "\n".join(output_list) else: return output_list if schema == "AclTrace": return AclTrace(json_object) if schema == "Environment": return Environment(json_object) if schema == "FileLines": return FileLines(json_object) if schema == "Flow": return Flow(json_object) if schema == "FlowTrace": return FlowTrace(json_object) if schema == "Integer": return int(json_object) if schema == "Interface": return Interface(json_object) if schema == "Ip": return str(json_object) if schema == "Issue": return Issue(json_object) if schema == "Node": return json_object["name"] if schema == "Prefix": return str(json_object) if schema == "SelfDescribing": return _get_display_value(json_object["schema"], json_object.get("value")) if schema == "String": return str(json_object) return json_object
def testFlowDeserialization(): hopDict = { "dscp": 0, "dstIp": "2.1.1.1", "dstPort": 0, "ecn": 0, "fragmentOffset": 0, "icmpCode": 255, "icmpVar": 255, "ingressInterface": "intface", "ingressNode": "ingress", "ingressVrf": "vrfAbc", "ipProtocol": "IP", "packetLength": 0, "srcIp": "5.5.1.1", "srcPort": 0, "state": "NEW", "tag": "BASE", "tcpFlagsAck": 0, "tcpFlagsCwr": 0, "tcpFlagsEce": 0, "tcpFlagsFin": 0, "tcpFlagsPsh": 0, "tcpFlagsRst": 0, "tcpFlagsSyn": 0, "tcpFlagsUrg": 0 } # check deserialization flow = Flow.from_dict(hopDict) assert flow.srcIp == "5.5.1.1" assert flow.ingressInterface == "intface" assert flow.ingressVrf == "vrfAbc" # check the string representation has the essential elements (without forcing a strict format) flowStr = str(flow) assert "5.5.1.1" in flowStr assert "intface" in flowStr assert "vrfAbc" in flowStr
def __init__(self, dictionary): self.edge = Edge(dictionary["edge"]) self.routes = list(dictionary.get("routes", [])) transformed_flow = dictionary.get("transformedFlow") self.transformedFlow = Flow( transformed_flow) if transformed_flow else None
def test_header_constraints_of(): hc = HeaderConstraints.of( Flow( ipProtocol='ICMP', icmpCode=7, srcIp="1.1.1.1", dstIp="2.2.2.2", dscp=0, dstPort=0, srcPort=0, ecn=0, fragmentOffset=0, icmpVar=0, ingressInterface='', ingressNode='', ingressVrf='', packetLength=0, state='new', tag='tag', tcpFlagsAck=0, tcpFlagsCwr=0, tcpFlagsEce=0, tcpFlagsFin=0, tcpFlagsPsh=0, tcpFlagsRst=0, tcpFlagsSyn=0, tcpFlagsUrg=0, )) assert hc.srcIps == "1.1.1.1" assert hc.dstIps == "2.2.2.2" assert hc.ipProtocols == ['ICMP'] assert hc.icmpCodes == '7' assert hc.srcPorts is None assert hc.dstPorts is None assert hc.tcpFlags is None hc = HeaderConstraints.of( Flow( ipProtocol='TCP', srcPort=1000, dstPort=2000, tcpFlagsAck=True, srcIp="1.1.1.1", dstIp="2.2.2.2", dscp=0, ecn=0, fragmentOffset=0, icmpCode=0, icmpVar=0, ingressInterface='', ingressNode='', ingressVrf='', packetLength=0, state='new', tag='tag', tcpFlagsCwr=0, tcpFlagsEce=0, tcpFlagsFin=0, tcpFlagsPsh=0, tcpFlagsRst=0, tcpFlagsSyn=0, tcpFlagsUrg=0, )) assert hc.srcIps == "1.1.1.1" assert hc.dstIps == "2.2.2.2" assert hc.ipProtocols == ['TCP'] assert hc.icmpCodes is None assert hc.icmpTypes is None assert hc.srcPorts == '1000' assert hc.dstPorts == '2000' assert hc.tcpFlags == [ MatchTcpFlags( TcpFlags(ack=True), useAck=True, useCwr=True, useEce=True, useFin=True, usePsh=True, useRst=True, useSyn=True, useUrg=True, ) ]
def test_repr_html_lines(): flow_dict = { "dscp": 0, "dstIp": "2.1.1.1", "dstPort": 0, "ecn": 0, "fragmentOffset": 0, "icmpCode": 0, "icmpVar": 0, "ingressNode": "ingress", "ipProtocol": "UNNAMED_168", "packetLength": 512, "srcIp": "5.5.1.1", "srcPort": 0, "tcpFlagsAck": 0, "tcpFlagsCwr": 0, "tcpFlagsEce": 0, "tcpFlagsFin": 0, "tcpFlagsPsh": 0, "tcpFlagsRst": 0, "tcpFlagsSyn": 0, "tcpFlagsUrg": 0, } # no ports assert Flow.from_dict(flow_dict)._repr_html_lines() == [ "Start Location: ingress", "Src IP: 5.5.1.1", "Dst IP: 2.1.1.1", "IP Protocol: ipProtocol=168", ] # with ports flow_dict["ipProtocol"] = "TCP" flow_dict["dstPort"] = "80" flow_dict["srcPort"] = "800" assert Flow.from_dict(flow_dict)._repr_html_lines() == [ "Start Location: ingress", "Src IP: 5.5.1.1", "Src Port: 800", "Dst IP: 2.1.1.1", "Dst Port: 80", "IP Protocol: TCP (no flags set)", ] # uncommon dscp flow_dict["dscp"] = "1" assert Flow.from_dict(flow_dict)._repr_html_lines() == [ "Start Location: ingress", "Src IP: 5.5.1.1", "Src Port: 800", "Dst IP: 2.1.1.1", "Dst Port: 80", "IP Protocol: TCP (no flags set)", "DSCP: 1", ] # uncommon ecn flow_dict["ecn"] = "1" assert Flow.from_dict(flow_dict)._repr_html_lines() == [ "Start Location: ingress", "Src IP: 5.5.1.1", "Src Port: 800", "Dst IP: 2.1.1.1", "Dst Port: 80", "IP Protocol: TCP (no flags set)", "DSCP: 1", "ECN: 1", ] # uncommon fragment offset flow_dict["fragmentOffset"] = "1501" assert Flow.from_dict(flow_dict)._repr_html_lines() == [ "Start Location: ingress", "Src IP: 5.5.1.1", "Src Port: 800", "Dst IP: 2.1.1.1", "Dst Port: 80", "IP Protocol: TCP (no flags set)", "DSCP: 1", "ECN: 1", "Fragment Offset: 1501", ] # uncommon packet length flow_dict["packetLength"] = "100" assert Flow.from_dict(flow_dict)._repr_html_lines() == [ "Start Location: ingress", "Src IP: 5.5.1.1", "Src Port: 800", "Dst IP: 2.1.1.1", "Dst Port: 80", "IP Protocol: TCP (no flags set)", "DSCP: 1", "ECN: 1", "Fragment Offset: 1501", "Packet Length: 100", ]