Exemplo n.º 1
0
def test_check_tc_rule():
    #*** Instantiate classes:
    policy = policy_module.Policy(
        config,
        pol_dir_default="config/tests/regression",
        pol_dir_user="******",
        pol_filename="main_policy_regression_static.yaml")
    flow = flows_module.Flow(config)
    ident = identities.Identities(config, policy)

    #*** Test Flow 1 Packet 1 (Client TCP SYN):
    # 10.1.0.1 10.1.0.2 TCP 74 43297 > http [SYN]
    flow.ingest_packet(DPID1, INPORT1, pkts.RAW[0], datetime.datetime.now())
    #*** Set policy.pkt as work around for not calling parent method that sets it:
    policy.pkt = flow.packet

    #*** main_policy_regression_static.yaml shouldn't match HTTP (rule 0):
    tc_rules = policy_module.TCRules(policy)
    tc_rule = policy_module.TCRule(tc_rules, policy, 0)
    tc_rule_result = tc_rule.check_tc_rule(flow, ident)
    assert tc_rule_result.match == False
    assert tc_rule_result.continue_to_inspect == False
    assert tc_rule_result.classification_tag == ""
    assert tc_rule_result.actions == {}

    #*** main_policy_regression_static_3.yaml should match HTTP (rule 0):
    policy = policy_module.Policy(
        config,
        pol_dir_default="config/tests/regression",
        pol_dir_user="******",
        pol_filename="main_policy_regression_static_3.yaml")
    ident = identities.Identities(config, policy)
    tc_rules = policy_module.TCRules(policy)
    tc_rule = policy_module.TCRule(tc_rules, policy, 0)
    tc_rule_result = tc_rule.check_tc_rule(flow, ident)
    assert tc_rule_result.match == True
    assert tc_rule_result.continue_to_inspect == False
    assert tc_rule_result.classification_tag == "Constrained Bandwidth Traffic"
    assert tc_rule_result.actions == {
        'qos_treatment': 'constrained_bw',
        'set_desc': 'Constrained Bandwidth Traffic'
    }
Exemplo n.º 2
0
def test_harvest_DHCP():
    """
    Test harvesting identity metadata from an IPv4 DHCP request
    Note: this test is very basic and does not cover much...
    TBD: cover more scenarios and DHCP message types
    """
    #*** Instantiate flow, policy and identities objects:
    flow = flows_module.Flow(config)
    policy = policy_module.Policy(config)
    identities = identities_module.Identities(config, policy)

    #*** Client to Server DHCP Request:
    flow.ingest_packet(DPID1, INPORT1, pkts_dhcp.RAW[2],
                       datetime.datetime.now())
    identities.harvest(pkts_dhcp.RAW[2], flow.packet)
    flow_pkt = flow.packet

    assert identities.dhcp_msg.dpid == DPID1
    assert identities.dhcp_msg.in_port == INPORT1
    assert identities.dhcp_msg.eth_src == flow_pkt.eth_src
    assert identities.dhcp_msg.eth_dst == flow_pkt.eth_dst
    assert identities.dhcp_msg.ip_src == flow_pkt.ip_src
    assert identities.dhcp_msg.ip_dst == flow_pkt.ip_dst
    assert identities.dhcp_msg.tp_src == flow_pkt.tp_src
    assert identities.dhcp_msg.tp_dst == flow_pkt.tp_dst
    assert identities.dhcp_msg.transaction_id == '0xabc5667f'
    assert identities.dhcp_msg.host_name == 'pc1'
    assert identities.dhcp_msg.message_type == 'DHCPREQUEST'

    #*** Server to Client DHCP ACK:
    #*** Set ingest time so we can check validity based on lease
    ingest_time = datetime.datetime.now()
    flow.ingest_packet(DPID1, INPORT2, pkts_dhcp.RAW[3], ingest_time)
    identities.harvest(pkts_dhcp.RAW[3], flow.packet)
    flow_pkt = flow.packet

    assert identities.dhcp_msg.dpid == DPID1
    assert identities.dhcp_msg.in_port == INPORT2
    assert identities.dhcp_msg.eth_src == flow_pkt.eth_src
    assert identities.dhcp_msg.eth_dst == flow_pkt.eth_dst
    assert identities.dhcp_msg.ip_src == flow_pkt.ip_src
    assert identities.dhcp_msg.ip_dst == flow_pkt.ip_dst
    assert identities.dhcp_msg.tp_src == flow_pkt.tp_src
    assert identities.dhcp_msg.tp_dst == flow_pkt.tp_dst
    assert identities.dhcp_msg.transaction_id == '0xabc5667f'
    assert identities.dhcp_msg.host_name == ''
    assert identities.dhcp_msg.ip_assigned == '10.1.0.1'
    assert identities.dhcp_msg.message_type == 'DHCPACK'
    assert identities.dhcp_msg.lease_time == 300

    result_identity = identities.findbynode('pc1')
    logger.debug("result_identity=%s", result_identity)
    assert result_identity['mac_address'] == pkts_dhcp.ETH_SRC[2]
    assert result_identity['ip_address'] == '10.1.0.1'
Exemplo n.º 3
0
def test_check_policy():
    """
    Test that packet match against policy works correctly
    """
    #*** Instantiate tc, flows and identities classes, specifying
    #*** a particular main_policy file to use:
    policy = policy_module.Policy(
        config,
        pol_dir_default="config/tests/regression",
        pol_dir_user="******",
        pol_filename="main_policy_regression_static.yaml")
    flow = flows_module.Flow(config)
    ident = identities.Identities(config, policy)

    #*** Note: cannot query a classification until a packet has been
    #*** ingested - will throw error

    #*** Ingest a packet:
    #*** Test Flow 1 Packet 1 (Client TCP SYN):
    # 10.1.0.1 10.1.0.2 TCP 74 43297 > http [SYN]
    flow.ingest_packet(DPID1, INPORT1, pkts.RAW[0], datetime.datetime.now())
    #*** Check policy:
    policy.check_policy(flow, ident)
    #*** Should not match any rules in that policy:
    logger.debug("flow.classification.classified=%s",
                 flow.classification.classified)
    assert flow.classification.classified == 1
    assert flow.classification.classification_tag == ""
    assert flow.classification.actions == {}

    #*** Re-instantiate policy with different policy that should classify:
    policy = policy_module.Policy(
        config,
        pol_dir_default="config/tests/regression",
        pol_dir_user="******",
        pol_filename="main_policy_regression_static_3.yaml")

    #*** Re-ingest packet:
    #*** Test Flow 1 Packet 1 (Client TCP SYN):
    # 10.1.0.1 10.1.0.2 TCP 74 43297 > http [SYN]
    flow.ingest_packet(DPID1, INPORT1, pkts.RAW[0], datetime.datetime.now())
    #*** Check policy:
    policy.check_policy(flow, ident)
    #*** Should match policy:
    assert flow.classification.classified == 1
    assert flow.classification.classification_tag == "Constrained Bandwidth Traffic"
    logger.debug("flow.classification.actions=%s", flow.classification.actions)
    assert flow.classification.actions == {
        'set_desc': 'Constrained Bandwidth Traffic',
        'qos_treatment': 'constrained_bw'
    }
Exemplo n.º 4
0
def test_harvest_LLDP():
    """
    Test harvesting identity metadata from LLDP packets
    """
    #*** Instantiate flow, policy and identities objects:
    flow = flows_module.Flow(config)
    policy = policy_module.Policy(config)
    identities = identities_module.Identities(config, policy)

    #*** Test no result found by checking before LLDP ingestion:
    result_identity = identities.findbynode(pkts_lldp.LLDP_SYSTEM_NAME[0])
    assert result_identity == 0

    #*** LLDP packet 0:
    flow.ingest_packet(DPID1, INPORT1, pkts_lldp.RAW[0],
                       datetime.datetime.now())
    identities.harvest(pkts_lldp.RAW[0], flow.packet)
    result_identity = identities.findbynode(pkts_lldp.LLDP_SYSTEM_NAME[0])
    assert result_identity['host_name'] == pkts_lldp.LLDP_SYSTEM_NAME[0]
    assert result_identity['host_desc'] == pkts_lldp.LLDP_SYSTEM_DESC[0]
    assert result_identity['dpid'] == DPID1
    assert result_identity['in_port'] == INPORT1
    assert result_identity['mac_address'] == pkts_lldp.ETH_SRC[0]
    assert result_identity['harvest_type'] == 'LLDP'

    #*** LLDP packet 1:
    flow.ingest_packet(DPID1, INPORT1, pkts_lldp.RAW[1],
                       datetime.datetime.now())
    identities.harvest(pkts_lldp.RAW[1], flow.packet)
    result_identity = identities.findbynode(pkts_lldp.LLDP_SYSTEM_NAME[1])
    assert result_identity['host_name'] == pkts_lldp.LLDP_SYSTEM_NAME[1]
    assert result_identity['host_desc'] == pkts_lldp.LLDP_SYSTEM_DESC[1]
    assert result_identity['dpid'] == DPID1
    assert result_identity['in_port'] == INPORT1
    assert result_identity['mac_address'] == pkts_lldp.ETH_SRC[1]
    assert result_identity['harvest_type'] == 'LLDP'

    #*** LLDP packet 2:
    flow.ingest_packet(DPID1, INPORT1, pkts_lldp.RAW[2],
                       datetime.datetime.now())
    identities.harvest(pkts_lldp.RAW[2], flow.packet)
    result_identity = identities.findbynode(pkts_lldp.LLDP_SYSTEM_NAME[2])
    assert result_identity['host_name'] == pkts_lldp.LLDP_SYSTEM_NAME[2]
    assert result_identity['host_desc'] == pkts_lldp.LLDP_SYSTEM_DESC[2]
    assert result_identity['dpid'] == DPID1
    assert result_identity['in_port'] == INPORT1
    assert result_identity['mac_address'] == pkts_lldp.ETH_SRC[2]
    assert result_identity['harvest_type'] == 'LLDP'
Exemplo n.º 5
0
def test_harvest_ARP():
    """
    Test harvesting identity metadata from an IPv4 ARP reply.
    """
    #*** Instantiate flow, policy and identities objects:
    flow = flows_module.Flow(config)
    policy = policy_module.Policy(config)
    identities = identities_module.Identities(config, policy)

    #*** Server ARP Reply:
    flow.ingest_packet(DPID1, INPORT1, pkts_arp.RAW[1],
                       datetime.datetime.now())
    identities.harvest(pkts_arp.RAW[1], flow.packet)
    result_identity = identities.findbymac(pkts_arp.ETH_SRC[1])

    assert result_identity['mac_address'] == pkts_arp.ETH_SRC[1]
    assert result_identity['ip_address'] == '10.1.0.2'
Exemplo n.º 6
0
def test_get_dns_ip():
    """
    Test looking up a DNS CNAME to get an IP address
    """
    #*** Instantiate flow, policy and identities objects:
    flow = flows_module.Flow(config)
    policy = policy_module.Policy(config)
    identities = identities_module.Identities(config, policy)

    #*** DNS packet 1 (NAME to CNAME, then second answer with IP for CNAME):
    flow.ingest_packet(DPID1, INPORT1, pkts_dns.RAW[1],
                       datetime.datetime.now())
    identities.harvest(pkts_dns.RAW[1], flow.packet)

    logger.debug("Testing lookup of CNAME=%s", pkts_dns.DNS_CNAME[1])
    result_ip = api.get_dns_ip(pkts_dns.DNS_CNAME[1])
    assert result_ip == pkts_dns.DNS_IP[1]
Exemplo n.º 7
0
def test_get_host_by_ip():
    """
    Test get_host_by_ip
    """
    #*** Instantiate flow, policy and identities objects:
    flow = flows_module.Flow(config)
    policy = policy_module.Policy(config)
    identities = identities_module.Identities(config, policy)

    #*** Ingest ARP reply for MAC of pc1 so can ref later:
    flow.ingest_packet(DPID1, INPORT1, pkts_arp.RAW[3],
                       datetime.datetime.now())
    identities.harvest(pkts_arp.RAW[3], flow.packet)

    #*** Ingest LLDP from pc1
    flow.ingest_packet(DPID1, INPORT1, pkts_lldp.RAW[0],
                       datetime.datetime.now())
    identities.harvest(pkts_lldp.RAW[0], flow.packet)

    #*** Call the get_host_by_ip:
    get_host_by_ip_result = api.get_host_by_ip('10.1.0.1')

    logger.debug("get_host_by_ip_result=%s", get_host_by_ip_result)

    assert get_host_by_ip_result == 'pc1.example.com'

    #*** Test DHCP to host by IP

    #*** Client to Server DHCP Request:
    flow.ingest_packet(DPID1, INPORT1, pkts_dhcp.RAW[2],
                       datetime.datetime.now())
    identities.harvest(pkts_dhcp.RAW[2], flow.packet)

    #*** Server to Client DHCP ACK:
    flow.ingest_packet(DPID1, INPORT2, pkts_dhcp.RAW[3],
                       datetime.datetime.now())
    identities.harvest(pkts_dhcp.RAW[3], flow.packet)

    #*** Call the get_host_by_ip:
    get_host_by_ip_result = api.get_host_by_ip('10.1.0.1')

    logger.debug("get_host_by_ip_result=%s", get_host_by_ip_result)

    assert get_host_by_ip_result == 'pc1'
Exemplo n.º 8
0
def test_harvest_DNS():
    """
    Test harvesting identity metadata from DNS packets
    """
    #*** Instantiate flow, policy and identities objects:
    flow = flows_module.Flow(config)
    policy = policy_module.Policy(config)
    identities = identities_module.Identities(config, policy)

    #*** DNS packet 1 (NAME to CNAME, then second answer with IP for CNAME):
    flow.ingest_packet(DPID1, INPORT1, pkts_dns.RAW[1],
                       datetime.datetime.now())
    identities.harvest(pkts_dns.RAW[1], flow.packet)
    result_identity = identities.findbyservice(pkts_dns.DNS_NAME[1])
    assert result_identity['service_name'] == pkts_dns.DNS_NAME[1]
    assert result_identity['service_alias'] == pkts_dns.DNS_CNAME[1]
    result_identity = identities.findbyservice(pkts_dns.DNS_CNAME[1])
    assert result_identity['service_name'] == pkts_dns.DNS_CNAME[1]
    assert result_identity['ip_address'] == pkts_dns.DNS_IP[1]
Exemplo n.º 9
0
def test_get_service_by_ip():
    """
    Test ability of get_service_by_ip to resolve
    IPs to service names
    """
    #*** Instantiate flow, policy and identities objects:
    flow = flows_module.Flow(config)
    policy = policy_module.Policy(config)
    identities = identities_module.Identities(config, policy)

    tc_ident = tc_identity.IdentityInspect(config)
    #*** DNS packet 1 (NAME to CNAME, then second answer with IP for CNAME):
    # A www.facebook.com CNAME star-mini.c10r.facebook.com A 179.60.193.36
    flow.ingest_packet(DPID1, INPORT1, pkts_dns.RAW[1],
                       datetime.datetime.now())
    identities.harvest(pkts_dns.RAW[1], flow.packet)

    #*** Call the get_service_by_ip:
    get_service_by_ip_result = api.get_service_by_ip('179.60.193.36')
    logger.debug("get_service_by_ip_result=%s", get_service_by_ip_result)

    assert get_service_by_ip_result == 'www.facebook.com'
Exemplo n.º 10
0
def test_get_classification():
    """
    Test get_classification which takes a flow_hash
    and return a dictionary of a classification object
    for the flow_hash (if found), otherwise
    a dictionary of an empty classification object.
    """
    #*** Instantiate flow, policy and identities objects:
    flow = flows_module.Flow(config)
    policy = policy_module.Policy(config)
    ident = identities_module.Identities(config, policy)

    #*** Initial main_policy that matches tcp-80:
    policy = policy_module.Policy(
        config,
        pol_dir_default="config/tests/regression",
        pol_dir_user="******",
        pol_filename="main_policy_regression_static_3.yaml")

    #*** Ingest Flow 1 Packet 0 (Client TCP SYN):
    flow.ingest_packet(DPID1, INPORT1, pkts.RAW[0], datetime.datetime.now())
    #*** Classify the packet:
    policy.check_policy(flow, ident)

    logger.debug("pkt0 flow classification is %s",
                 flow.classification.dbdict())

    #*** Write classification result to classifications collection:
    flow.classification.commit()

    #*** Retrieve classification via get_classification and check results:
    clasfn_result = api.get_classification(flow.classification.flow_hash)
    assert clasfn_result['classified'] == 1
    assert clasfn_result[
        'classification_tag'] == "Constrained Bandwidth Traffic"
    assert clasfn_result['actions'][
        'set_desc'] == "Constrained Bandwidth Traffic"
    assert clasfn_result['actions']['qos_treatment'] == "constrained_bw"
Exemplo n.º 11
0
def test_classification_static():
    """
    Test that classification returns correct information for a static
    classification.
    Create a classification object, record it to DB then check
    that classification can be retrieved
    """
    #*** Initial main_policy won't match as looking for tcp-1234:
    policy = policy_module.Policy(
        config,
        pol_dir_default="config/tests/regression",
        pol_dir_user="******",
        pol_filename="main_policy_regression_static.yaml")

    #*** Instantiate flow and identities objects:
    flow = flows_module.Flow(config)
    ident = identities_module.Identities(config, policy)

    #*** Ingest Flow 2 Packet 0 (Client TCP SYN):
    flow.ingest_packet(DPID1, INPORT1, pkts2.RAW[0], datetime.datetime.now())

    #*** Base classification state:
    assert flow.classification.flow_hash == flow.packet.flow_hash
    assert flow.classification.classified == 0
    assert flow.classification.classification_tag == ""
    assert flow.classification.classification_time == 0
    assert flow.classification.actions == {}

    #*** Classify the packet:
    policy.check_policy(flow, ident)

    #*** Unmatched classification state:
    assert flow.classification.flow_hash == flow.packet.flow_hash
    assert flow.classification.classified == 1
    assert flow.classification.classification_tag == ""
    assert flow.classification.classification_time == 0
    assert flow.classification.actions == {}

    #*** Initial main_policy that matches tcp-80:
    policy = policy_module.Policy(
        config,
        pol_dir_default="config/tests/regression",
        pol_dir_user="******",
        pol_filename="main_policy_regression_static_3.yaml")

    #*** Classify the packet:
    policy.check_policy(flow, ident)

    #*** Matched classification state:
    assert flow.classification.flow_hash == flow.packet.flow_hash
    assert flow.classification.classified == 1
    assert flow.classification.classification_tag == "Constrained Bandwidth Traffic"
    assert flow.classification.actions == {
        'qos_treatment': 'constrained_bw',
        'set_desc': 'Constrained Bandwidth Traffic'
    }

    #*** Now test that classification remains after ingesting more packets
    #***  on same flow.
    #*** Load main_policy that matches dst tcp-80:
    policy = policy_module.Policy(
        config,
        pol_dir_default="config/tests/regression",
        pol_dir_user="******",
        pol_filename="main_policy_regression_static_4.yaml")

    #*** Ingest Flow 1 Packet 0 (Client TCP SYN):
    flow.ingest_packet(DPID1, INPORT1, pkts.RAW[0], datetime.datetime.now())
    #*** Classify the packet:
    policy.check_policy(flow, ident)

    logger.debug("pkt0 flow classification is %s",
                 flow.classification.dbdict())

    #*** Matched classification state:
    assert flow.classification.flow_hash == flow.packet.flow_hash
    assert flow.classification.classified == 1
    assert flow.classification.classification_tag == "Constrained Bandwidth Traffic"
    assert flow.classification.actions == {
        'qos_treatment': 'constrained_bw',
        'set_desc': 'Constrained Bandwidth Traffic'
    }

    #*** Write classification result to classifications collection:
    flow.classification.commit()

    #*** Ingest Flow 1 Packet 1 (Client TCP SYN+ACK):
    flow.ingest_packet(DPID1, INPORT1, pkts.RAW[1], datetime.datetime.now())

    logger.debug("pkt1a flow classification is %s",
                 flow.classification.dbdict())

    assert flow.classification.classified == 1

    #*** We would never run this as otherwise above test would have failed.
    #*** Left it in here to make the point that you shouldn't classify if
    #*** classified is set.
    if not flow.classification.classified:
        #*** Classify the packet:
        policy.check_policy(flow, ident)

    logger.debug("pkt1b flow classification is %s",
                 flow.classification.dbdict())

    #*** Matched classification state (shouldn't be changed by second packet):
    assert flow.classification.flow_hash == flow.packet.flow_hash
    assert flow.classification.classified == 1
    assert flow.classification.classification_tag == "Constrained Bandwidth Traffic"
    assert flow.classification.actions == {
        'qos_treatment': 'constrained_bw',
        'set_desc': 'Constrained Bandwidth Traffic'
    }
Exemplo n.º 12
0
def test_flow_mods():
    """
    Test flow_mods API
    """
    #*** Start api_external as separate process:
    logger.info("Starting api_external")
    api_ps = multiprocessing.Process(target=api.run, args=())
    api_ps.start()

    #*** Sleep to allow api_external to start fully:
    time.sleep(.5)

    #*** Instantiate flow, policy and identities objects:
    flow = flows_module.Flow(config)
    policy = policy_module.Policy(config)
    identities = identities_module.Identities(config, policy)

    #*** Create a sample result to use:
    ipv4_src = '10.1.0.1'
    ipv4_dst = '10.1.0.2'
    result = {
        'match_type': 'single',
        'forward_cookie': 1,
        'forward_match': {
            'eth_type': 0x0800,
            'ipv4_src': ipv4_src,
            'ipv4_dst': ipv4_dst,
            'ip_proto': 6
        },
        'reverse_cookie': 0,
        'reverse_match': {},
        'client_ip': ipv4_src
    }

    #*** Record flow mod:
    #*** Ingest a packet from pc1:
    # 10.1.0.1 10.1.0.2 TCP 74 43297 > http [SYN]
    flow.ingest_packet(DPID1, INPORT1, pkts.RAW[0], datetime.datetime.now())

    #*** Record suppressing this flow:
    flow.record_suppression(DPID1, 'suppress', result)

    #*** Call the external API:
    api_result = get_api_result(URL_FLOW_MODS)

    logger.debug("api_result=%s", api_result)

    #*** Check that API has returned expected results:
    assert api_result['_items'][0]['flow_hash'] == flow.packet.flow_hash
    assert api_result['_items'][0]['dpid'] == DPID1
    assert api_result['_items'][0]['suppress_type'] == 'suppress'
    assert api_result['_items'][0]['standdown'] == 0
    assert api_result['_items'][0]['match_type'] == 'single'
    assert api_result['_items'][0]['forward_cookie'] == 1
    assert api_result['_items'][0]['forward_match'] == {
        'eth_type': 0x0800,
        'ipv4_src': ipv4_src,
        'ipv4_dst': ipv4_dst,
        'ip_proto': 6
    }
    assert api_result['_items'][0]['reverse_cookie'] == 0
    assert api_result['_items'][0]['reverse_match'] == {}
    assert api_result['_items'][0]['client_ip'] == ipv4_src
    assert len(api_result['_items']) == 1

    #*** Record suppressing the same flow again, setting standdown:
    flow.record_suppression(DPID1, 'suppress', result, standdown=1)

    #*** Call the external API:
    api_result = get_api_result(URL_FLOW_MODS)

    logger.debug("api_result=%s", api_result)

    #*** Check that API has returned expected results for new record
    #***  (note that result items are defaulted due to standdown):
    assert api_result['_items'][1]['flow_hash'] == flow.packet.flow_hash
    assert api_result['_items'][1]['dpid'] == DPID1
    assert api_result['_items'][1]['suppress_type'] == 'suppress'
    assert api_result['_items'][1]['standdown'] == 1
    assert api_result['_items'][1]['match_type'] == ''
    assert api_result['_items'][1]['forward_cookie'] == 0
    assert api_result['_items'][1]['forward_match'] == {}
    assert api_result['_items'][1]['reverse_cookie'] == 0
    assert api_result['_items'][1]['reverse_match'] == {}
    assert len(api_result['_items']) == 2

    #*** Stop api_external sub-process:
    api_ps.terminate()
Exemplo n.º 13
0
def test_identities_ui():
    """
    Harvest identity data and test that the identities/ui API resource
    returns the correct information.
    The identities/ui resource does deduplication, so test that this
    works correctly
    """
    #*** Start api_external as separate process:
    logger.info("Starting api_external")
    api_ps = multiprocessing.Process(target=api.run, args=())
    api_ps.start()

    #*** Sleep to allow api_external to start fully:
    time.sleep(.5)

    #*** Instantiate flow, policy and identities objects:
    flow = flows_module.Flow(config)
    policy = policy_module.Policy(config)
    identities = identities_module.Identities(config, policy)

    #*** Ingest LLDP from pc1
    flow.ingest_packet(DPID1, INPORT1, pkts_lldp.RAW[0],
                       datetime.datetime.now())
    identities.harvest(pkts_lldp.RAW[0], flow.packet)

    #*** Call the external API:
    api_result = get_api_result(URL_TEST_IDENTITIES_UI)

    logger.debug("api_result=%s", api_result)

    #*** Test identity results for first LDAP packet:
    assert api_result['_items'][0]['host_name'] == 'pc1.example.com'
    assert api_result['_items'][0]['harvest_type'] == 'LLDP'
    assert api_result['_items'][0]['mac_address'] == '08:00:27:2a:d6:dd'
    assert len(api_result['_items']) == 1

    #*** Ingest LLDP from sw1:
    flow.ingest_packet(DPID1, INPORT1, pkts_lldp.RAW[1],
                       datetime.datetime.now())
    identities.harvest(pkts_lldp.RAW[1], flow.packet)

    #*** Call the external API:
    api_result = get_api_result(URL_TEST_IDENTITIES_UI)

    logger.debug("api_result=%s", api_result)

    #*** Test identity results for second LDAP packet:
    assert api_result['_items'][0]['host_name'] == 'sw1.example.com'
    assert api_result['_items'][0]['harvest_type'] == 'LLDP'
    assert api_result['_items'][0]['mac_address'] == '08:00:27:f7:25:13'
    assert len(api_result['_items']) == 2

    #*** Ingest LLDP from pc1 (again, to test deduplication):
    flow.ingest_packet(DPID1, INPORT1, pkts_lldp.RAW[0],
                       datetime.datetime.now())
    identities.harvest(pkts_lldp.RAW[0], flow.packet)

    #*** Call the external API:
    api_result = get_api_result(URL_TEST_IDENTITIES_UI)

    logger.debug("api_result=%s", api_result)

    #*** Test identity results for first LDAP packet:
    assert api_result['_items'][0]['host_name'] == 'pc1.example.com'
    assert api_result['_items'][0]['harvest_type'] == 'LLDP'
    assert api_result['_items'][0]['mac_address'] == '08:00:27:2a:d6:dd'
    #*** Should be 2, not 3, as has deduplicated the pc1 identities:
    assert len(api_result['_items']) == 2

    #*** Stop api_external sub-process:
    api_ps.terminate()
Exemplo n.º 14
0
def test_response_flows_removed_FLOWDIR_bytes_TXRX():
    """
    Test the flows_removed API various flavours of src/dst bytes
    sent/received by ingesting flow removal messages then checking
    that the API response correctly specifies appropriate
    stats for bytes sent, including identity enrichment
    """
    #*** Start api_external as separate process:
    logger.info("Starting api_external")
    api_ps = multiprocessing.Process(target=api.run, args=())
    api_ps.start()

    #*** Supports OpenFlow version 1.3:
    OFP_VERSION = ofproto_v1_3.OFP_VERSION

    #*** Instantiate supporting classes:
    flow = flows_module.Flow(config)
    policy = policy_module.Policy(config)
    identities = identities_module.Identities(config, policy)

    #*** Client to Server DHCP Request:
    flow.ingest_packet(DPID1, INPORT1, pkts_dhcp.RAW[2],
                       datetime.datetime.now())
    identities.harvest(pkts_dhcp.RAW[2], flow.packet)

    #*** Server to Client DHCP ACK:
    flow.ingest_packet(DPID1, INPORT2, pkts_dhcp.RAW[3],
                       datetime.datetime.now())
    identities.harvest(pkts_dhcp.RAW[3], flow.packet)

    #*** Load JSON representations of flow removed messages:
    with open('OFPMsgs/OFPFlowRemoved_1.json', 'r') as json_file:
        json_str_tx_1 = json_file.read()
        json_dict_tx_1 = json.loads(json_str_tx_1)
    with open('OFPMsgs/OFPFlowRemoved_2.json', 'r') as json_file:
        json_str_rx_1 = json_file.read()
        json_dict_rx_1 = json.loads(json_str_rx_1)
    with open('OFPMsgs/OFPFlowRemoved_3.json', 'r') as json_file:
        json_str_tx_2 = json_file.read()
        json_dict_tx_2 = json.loads(json_str_tx_2)
    with open('OFPMsgs/OFPFlowRemoved_4.json', 'r') as json_file:
        json_str_rx_2 = json_file.read()
        json_dict_rx_2 = json.loads(json_str_rx_2)
    with open('OFPMsgs/OFPFlowRemoved_5.json', 'r') as json_file:
        json_str_tx_3 = json_file.read()
        json_dict_tx_3 = json.loads(json_str_tx_3)
    with open('OFPMsgs/OFPFlowRemoved_6.json', 'r') as json_file:
        json_str_rx_3 = json_file.read()
        json_dict_rx_3 = json.loads(json_str_rx_3)

    #*** Switch 1:
    #*** Set up fake datapaths and synthesise messages:
    datapath1 = ofproto_protocol.ProtocolDesc(version=OFP_VERSION)
    datapath1.id = 1
    msg_tx_1_sw1 = ofproto_parser.ofp_msg_from_jsondict(
        datapath1, json_dict_tx_1)
    msg_rx_1_sw1 = ofproto_parser.ofp_msg_from_jsondict(
        datapath1, json_dict_rx_1)
    msg_tx_2_sw1 = ofproto_parser.ofp_msg_from_jsondict(
        datapath1, json_dict_tx_2)
    msg_rx_2_sw1 = ofproto_parser.ofp_msg_from_jsondict(
        datapath1, json_dict_rx_2)
    msg_tx_3_sw1 = ofproto_parser.ofp_msg_from_jsondict(
        datapath1, json_dict_tx_3)
    msg_rx_3_sw1 = ofproto_parser.ofp_msg_from_jsondict(
        datapath1, json_dict_rx_3)
    #*** Record flow removals to flow_rems database collection:
    flow.record_removal(msg_tx_1_sw1)
    flow.record_removal(msg_rx_1_sw1)
    flow.record_removal(msg_tx_2_sw1)
    flow.record_removal(msg_rx_2_sw1)
    flow.record_removal(msg_tx_3_sw1)
    flow.record_removal(msg_rx_3_sw1)

    #*** Switch 2 (same flows to check dedup for multiple switches works):
    #*** Set up fake datapaths and synthesise messages:
    datapath2 = ofproto_protocol.ProtocolDesc(version=OFP_VERSION)
    datapath2.id = 2
    msg_tx_1_sw2 = ofproto_parser.ofp_msg_from_jsondict(
        datapath2, json_dict_tx_1)
    msg_rx_1_sw2 = ofproto_parser.ofp_msg_from_jsondict(
        datapath2, json_dict_rx_1)
    msg_tx_2_sw2 = ofproto_parser.ofp_msg_from_jsondict(
        datapath2, json_dict_tx_2)
    msg_rx_2_sw2 = ofproto_parser.ofp_msg_from_jsondict(
        datapath2, json_dict_rx_2)
    msg_tx_3_sw2 = ofproto_parser.ofp_msg_from_jsondict(
        datapath1, json_dict_tx_3)
    msg_rx_3_sw2 = ofproto_parser.ofp_msg_from_jsondict(
        datapath1, json_dict_rx_3)
    #*** Record flow removals to flow_rems database collection:
    flow.record_removal(msg_tx_1_sw2)
    flow.record_removal(msg_rx_1_sw2)
    flow.record_removal(msg_tx_2_sw2)
    flow.record_removal(msg_rx_2_sw2)
    flow.record_removal(msg_tx_3_sw2)
    flow.record_removal(msg_rx_3_sw2)

    #*** Test flows_removed_src_bytes_sent API:
    #*** Call the external API:
    api_result = get_api_result(URL_TEST_FLOWS_REMOVED_SRC_BYTES_SENT)
    logger.debug("api_result=%s", api_result)

    #*** Validate API Response parameters:
    assert api_result['_items'][0]['_id'] == '10.1.0.2'
    assert api_result['_items'][0]['total_bytes_sent'] == 12345
    assert api_result['_items'][0]['identity'] == '10.1.0.2'
    assert api_result['_items'][1]['_id'] == '10.1.0.1'
    assert api_result['_items'][1]['total_bytes_sent'] == 5533
    assert api_result['_items'][1]['identity'] == 'pc1'

    #*** Test flows_removed_src_bytes_received API:
    #*** Call the external API:
    api_result = get_api_result(URL_TEST_FLOWS_REMOVED_SRC_BYTES_RECEIVED)
    logger.debug("api_result=%s", api_result)

    #*** Validate API Response parameters:
    assert api_result['_items'][0]['_id'] == '10.1.0.1'
    assert api_result['_items'][0]['total_bytes_received'] == 8628
    assert api_result['_items'][0]['identity'] == 'pc1'
    assert api_result['_items'][1]['_id'] == '10.1.0.2'
    assert api_result['_items'][1]['total_bytes_received'] == 543
    assert api_result['_items'][1]['identity'] == '10.1.0.2'

    #*** Test flows_removed_dst_bytes_sent API:
    #*** Call the external API:
    api_result = get_api_result(URL_TEST_FLOWS_REMOVED_DST_BYTES_SENT)
    logger.debug("api_result=%s", api_result)

    #*** Validate API Response parameters:
    assert api_result['_items'][0]['_id'] == '10.1.0.2'
    assert api_result['_items'][0]['total_bytes_sent'] == 8628
    assert api_result['_items'][0]['identity'] == '10.1.0.2'
    assert api_result['_items'][1]['_id'] == '10.1.0.1'
    assert api_result['_items'][1]['total_bytes_sent'] == 543
    assert api_result['_items'][1]['identity'] == 'pc1'

    #*** Test flows_removed_src_bytes_received API:
    #*** Call the external API:
    api_result = get_api_result(URL_TEST_FLOWS_REMOVED_DST_BYTES_RECEIVED)
    logger.debug("api_result=%s", api_result)

    #*** Validate API Response parameters:
    assert api_result['_items'][0]['_id'] == '10.1.0.1'
    assert api_result['_items'][0]['total_bytes_received'] == 12345
    assert api_result['_items'][0]['identity'] == 'pc1'
    assert api_result['_items'][1]['_id'] == '10.1.0.2'
    assert api_result['_items'][1]['total_bytes_received'] == 5533
    assert api_result['_items'][1]['identity'] == '10.1.0.2'

    #*** Stop api_external sub-process:
    api_ps.terminate()
Exemplo n.º 15
0
def test_classification_identity():
    """
    Test that classification returns correct information for an identity
    classification.
    Create a classification object, record it to DB then check
    that classification can be retrieved
    """
    #*** Load main_policy that matches identity pc1
    #*** and has action to constrain it's bandwidth:
    policy = policy_module.Policy(
        config,
        pol_dir_default="config/tests/regression",
        pol_dir_user="******",
        pol_filename="main_policy_regression_identity_2.yaml")

    #*** Instantiate flow and identities objects:
    flow = flows_module.Flow(config)
    ident = identities_module.Identities(config, policy)

    #*** Ingest and harvest LLDP Packet 2 (lg1) that shouldn't match:
    # 206 08:00:27:21:4f:ea 01:80:c2:00:00:0e LLDP NoS = 08:00:27:21:4f:ea
    # TTL = 120 System Name = lg1.example.com
    flow.ingest_packet(DPID1, INPORT1, pkts_lldp.RAW[2],
                       datetime.datetime.now())
    ident.harvest(pkts_lldp.RAW[2], flow.packet)

    #*** Ingest a packet from pc1:
    # 10.1.0.1 10.1.0.2 TCP 74 43297 > http [SYN]
    flow.ingest_packet(DPID1, INPORT1, pkts.RAW[0], datetime.datetime.now())

    #*** Classify the packet:
    policy.check_policy(flow, ident)

    #*** Unmatched classification state:
    assert flow.classification.flow_hash == flow.packet.flow_hash
    assert flow.classification.classified == 1
    assert flow.classification.classification_tag == ""
    assert flow.classification.actions == {}

    #*** Ingest ARP response for pc1 so we know MAC to IP mapping:
    flow.ingest_packet(DPID1, INPORT1, pkts_ARP_2.RAW[1],
                       datetime.datetime.now())
    ident.harvest(pkts_ARP_2.RAW[1], flow.packet)

    #*** Ingest and harvest LLDP Packet 0 (pc1) that should match:
    # 206 08:00:27:2a:d6:dd 01:80:c2:00:00:0e LLDP NoS = 08:00:27:2a:d6:dd
    # TTL = 120 System Name = pc1.example.com
    flow.ingest_packet(DPID1, INPORT1, pkts_lldp.RAW[0],
                       datetime.datetime.now())
    ident.harvest(pkts_lldp.RAW[0], flow.packet)

    #*** Ingest a packet from pc1:
    # 10.1.0.1 10.1.0.2 TCP 74 43297 > http [SYN]
    flow.ingest_packet(DPID1, INPORT1, pkts.RAW[0], datetime.datetime.now())

    #*** Classify the packet:
    policy.check_policy(flow, ident)

    #*** Matched classification state:
    assert flow.classification.flow_hash == flow.packet.flow_hash
    assert flow.classification.classified == 1
    assert flow.classification.classification_tag == "Constrained Bandwidth Traffic"
    assert flow.classification.actions == {
        'qos_treatment': 'constrained_bw',
        'set_desc': 'Constrained Bandwidth Traffic'
    }
Exemplo n.º 16
0
def test_indexing():
    """
    Test indexing of identities collection

    Ensure database indexing is working efficiently by harvesting
    various bits of identity metadata into identities collection
    then test how well queries perform against it to

    """
    #*** Instantiate flow, policy and identities objects:
    flow = flows_module.Flow(config)
    policy = policy_module.Policy(config)
    identities = identities_module.Identities(config, policy)

    flow.ingest_packet(DPID1, INPORT2, pkts_lldp.RAW[0],
                       datetime.datetime.now())
    identities.harvest(pkts_lldp.RAW[0], flow.packet)

    flow.ingest_packet(DPID1, INPORT1, pkts_lldp.RAW[1],
                       datetime.datetime.now())
    identities.harvest(pkts_lldp.RAW[1], flow.packet)

    flow.ingest_packet(DPID1, INPORT1, pkts_arp.RAW[1],
                       datetime.datetime.now())
    identities.harvest(pkts_arp.RAW[1], flow.packet)

    flow.ingest_packet(DPID1, INPORT1, pkts_arp.RAW[3],
                       datetime.datetime.now())
    identities.harvest(pkts_arp.RAW[3], flow.packet)

    flow.ingest_packet(DPID1, INPORT1, pkts_dhcp.RAW[2],
                       datetime.datetime.now())
    identities.harvest(pkts_dhcp.RAW[2], flow.packet)

    flow.ingest_packet(DPID1, INPORT1, pkts_dhcp.RAW[3],
                       datetime.datetime.now())
    identities.harvest(pkts_dhcp.RAW[3], flow.packet)

    flow.ingest_packet(DPID1, INPORT1, pkts_dns.RAW[1],
                       datetime.datetime.now())
    identities.harvest(pkts_dns.RAW[1], flow.packet)

    #*** Test identities collection indexing...
    #*** Check correct number of documents in packet_ins collection:
    assert identities.identities.count() == 7

    #*** Get findbymac query execution statistics:
    #*** Retrieve an explain of identities findbymac database query:
    explain = identities.findbymac(pkts2.ETH_SRC[1], test=1)
    #*** Check an index is used:
    assert explain['queryPlanner']['winningPlan']['inputStage'][
        'stage'] == 'FETCH'
    #*** Check how query ran:
    assert explain['executionStats']['executionSuccess'] == True
    assert explain['executionStats']['nReturned'] == 1
    assert explain['executionStats']['totalKeysExamined'] == 1
    assert explain['executionStats']['totalDocsExamined'] == 1

    #*** Get findbynode query execution statistics:
    #*** Retrieve an explain of identities findbynode database query:
    explain = identities.findbynode('pc1', test=1)
    #*** Check an index is used:
    assert explain['queryPlanner']['winningPlan']['inputStage'][
        'stage'] == 'FETCH'
    #*** Check how query ran:
    assert explain['executionStats']['executionSuccess'] == True
    assert explain['executionStats']['nReturned'] == 1
    assert explain['executionStats']['totalKeysExamined'] == 1
    assert explain['executionStats']['totalDocsExamined'] == 1

    #*** Retrieve an explain of identities findbynode database query with
    #*** harvest_type option set:
    explain = identities.findbynode('pc1', harvest_type='DHCP', test=1)
    #*** Check an index is used:
    assert explain['queryPlanner']['winningPlan']['inputStage'][
        'stage'] == 'FETCH'
    #*** Check how query ran:
    assert explain['executionStats']['executionSuccess'] == True
    assert explain['executionStats']['nReturned'] == 1
    assert explain['executionStats']['totalKeysExamined'] == 1
    assert explain['executionStats']['totalDocsExamined'] == 1

    #*** Get findbyservice query execution statistics:
    #*** Retrieve an explain of identities findbyservice database query:
    explain = identities.findbyservice(pkts_dns.DNS_NAME[1], test=1)
    #*** Check an index is used:
    assert explain['queryPlanner']['winningPlan']['inputStage'][
        'stage'] == 'FETCH'
    #*** Check how query ran:
    assert explain['executionStats']['executionSuccess'] == True
    assert explain['executionStats']['nReturned'] == 1
    assert explain['executionStats']['totalKeysExamined'] == 1
    assert explain['executionStats']['totalDocsExamined'] == 1
Exemplo n.º 17
0
def test_LLDP_identity():
    """
    Test harvesting identity metadata from LLDP packets and then
    using this to validate an identity
    """
    #*** Instantiate class objects:
    flow = flows_module.Flow(config)
    policy = policy_module.Policy(config)
    identities = identities_module.Identities(config, policy)
    tc_ident = tc_identity.IdentityInspect(config)

    #*** LLDP packet 0:
    flow.ingest_packet(DPID1, INPORT1, pkts_lldp.RAW[0],
                       datetime.datetime.now())
    identities.harvest(pkts_lldp.RAW[0], flow.packet)
    result_identity = identities.findbynode(pkts_lldp.LLDP_SYSTEM_NAME[0])
    assert result_identity['host_name'] == pkts_lldp.LLDP_SYSTEM_NAME[0]
    assert result_identity['host_desc'] == pkts_lldp.LLDP_SYSTEM_DESC[0]
    assert result_identity['dpid'] == DPID1
    assert result_identity['in_port'] == INPORT1
    assert result_identity['mac_address'] == pkts_lldp.ETH_SRC[0]
    assert result_identity['harvest_type'] == 'LLDP'

    #*** Test tc_identity (foo should fail)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_lldp_systemname'
    classifier_result.policy_value = 'foo'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == False

    #*** Test tc_identity (pc1.example.com should match)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_lldp_systemname'
    classifier_result.policy_value = 'pc1.example.com'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == True

    #*** Test tc_identity regular expression (*.example.com should match)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_lldp_systemname_re'
    classifier_result.policy_value = '^.*\.example\.com'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == True

    #*** Test tc_identity regular expression (pc1.* should match)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_lldp_systemname_re'
    classifier_result.policy_value = '^pc1\.*'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == True

    #*** Test tc_identity regular expression (*.example.org should fail)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_lldp_systemname_re'
    classifier_result.policy_value = '^.*\.example\.org'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == False

    #*** LLDP packet 1 - test time-based invalidity of stale data
    flow.ingest_packet(
        DPID1, INPORT1, pkts_lldp.RAW[1],
        datetime.datetime.now() - datetime.timedelta(seconds=125))
    identities.harvest(pkts_lldp.RAW[1], flow.packet)

    #*** Test tc_identity (sw1.example.com shouldn't match as data is stale as past LLDP TTL)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_lldp_systemname'
    classifier_result.policy_value = 'sw1.example.com'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == False

    #*** Reingest with current time to check it does work
    flow.ingest_packet(DPID1, INPORT1, pkts_lldp.RAW[1],
                       datetime.datetime.now())
    identities.harvest(pkts_lldp.RAW[1], flow.packet)

    #*** Test tc_identity (sw1.example.com should match as data is no longer stale)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_lldp_systemname'
    classifier_result.policy_value = 'sw1.example.com'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == True
Exemplo n.º 18
0
def test_DNS_identity():
    """
    Test harvesting identity metadata from DNS packets and then
    using this to validate an identity
    """
    #*** Instantiate class objects:
    flow = flows_module.Flow(config)
    policy = policy_module.Policy(config)
    identities = identities_module.Identities(config, policy)
    tc_ident = tc_identity.IdentityInspect(config)
    #*** DNS packet 1 (NAME to CNAME, then second answer with IP for CNAME):
    flow.ingest_packet(DPID1, INPORT1, pkts_dns.RAW[1],
                       datetime.datetime.now())
    identities.harvest(pkts_dns.RAW[1], flow.packet)
    result_identity = identities.findbyservice(pkts_dns.DNS_NAME[1])
    assert result_identity['service_name'] == pkts_dns.DNS_NAME[1]
    assert result_identity['service_alias'] == pkts_dns.DNS_CNAME[1]
    result_identity = identities.findbyservice(pkts_dns.DNS_CNAME[1])
    assert result_identity['service_name'] == pkts_dns.DNS_CNAME[1]
    assert result_identity['ip_address'] == pkts_dns.DNS_IP[1]

    #*** Ingest TCP SYN to www.facebook.com (CNAME star-mini.c10r.facebook.com,
    #*** IP 179.60.193.36)
    flow.ingest_packet(DPID1, INPORT1, pkts_facebook.RAW[0],
                       datetime.datetime.now())

    #*** Test tc_identity (foo should fail)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_service_dns'
    classifier_result.policy_value = 'foo'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == False

    #*** Test tc_identity (www.facebook.com should pass)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_service_dns'
    classifier_result.policy_value = 'www.facebook.com'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == True

    #*** Now, harvest another DNS packet with different A record for
    #*** www.facebook.com (CNAME star-mini.c10r.facebook.com A 31.13.95.36):
    flow.ingest_packet(DPID1, INPORT1, pkts_dns4.RAW[1],
                       datetime.datetime.now())
    identities.harvest(pkts_dns4.RAW[1], flow.packet)

    #*** Ingest TCP SYN to www.facebook.com (CNAME star-mini.c10r.facebook.com,
    #*** IP 179.60.193.36)
    flow.ingest_packet(DPID1, INPORT1, pkts_facebook.RAW[0],
                       datetime.datetime.now())

    #*** Test tc_identity (www.facebook.com, should pass even though there's
    #*** another A record against the CNAME, i.e. should handle one to many)
    #*** Test tc_identity (www.facebook.com should pass)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_service_dns'
    classifier_result.policy_value = 'www.facebook.com'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == True

    #*** Test regular expression match of previous test:
    #*** Test tc_identity (www.facebook.com should pass)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_service_dns_re'
    classifier_result.policy_value = '^.*\.facebook\.com'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == True

    #*** Test regular expression that shouldn't match:
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_service_dns_re'
    classifier_result.policy_value = '^.*\.facebook\.org'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == False

    #*** Ingest TCP SYN+ACK from www.facebook.com (CNAME star-mini.c10r.facebook.com,
    #*** IP 179.60.193.36) to test matching on source IP address:
    flow.ingest_packet(DPID1, INPORT1, pkts_facebook.RAW[1],
                       datetime.datetime.now())
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_service_dns'
    classifier_result.policy_value = 'www.facebook.com'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == True
Exemplo n.º 19
0
def test_DHCP_identity():
    """
    Test harvesting identity metadata from DHCP packets and then
    using this to validate an identities against the learnt DHCP hostname
    """
    #*** Instantiate class objects:
    flow = flows_module.Flow(config)
    policy = policy_module.Policy(config)
    identities = identities_module.Identities(config, policy)
    tc_ident = tc_identity.IdentityInspect(config)

    #*** Ingest packet from pc1:
    flow.ingest_packet(DPID1, INPORT1, pkts_http_pc1.RAW[0],
                       datetime.datetime.now())

    #*** Test tc_identity (pc1 should fail as haven't harvested DHCP yet)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_dhcp_hostname'
    classifier_result.policy_value = 'pc1'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == False

    #*** Harvesting DHCP host name for pc1 against IP 10.1.0.1
    #*** Client to Server DHCP Request (DHCP Option 12 host name is pc1):
    flow.ingest_packet(DPID1, INPORT1, pkts_dhcp.RAW[2],
                       datetime.datetime.now())
    identities.harvest(pkts_dhcp.RAW[2], flow.packet)
    #*** Server to Client DHCP ACK:
    flow.ingest_packet(DPID1, INPORT2, pkts_dhcp.RAW[3],
                       datetime.datetime.now())
    identities.harvest(pkts_dhcp.RAW[3], flow.packet)

    #*** Ingest packet from pc1:
    flow.ingest_packet(DPID1, INPORT1, pkts_http_pc1.RAW[0],
                       datetime.datetime.now())

    #*** Test tc_identity (pc1 should pass)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_dhcp_hostname'
    classifier_result.policy_value = 'pc1'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == True

    #*** Ingest packet *to* pc1:
    flow.ingest_packet(DPID1, INPORT2, pkts_http_pc1.RAW[1],
                       datetime.datetime.now())

    #*** Test tc_identity (pc1 should pass)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_dhcp_hostname'
    classifier_result.policy_value = 'pc1'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == True

    #*** Ingest packet from lg1:
    flow.ingest_packet(DPID1, INPORT1, pkts_http_lg1.RAW[0],
                       datetime.datetime.now())

    #*** Test tc_identity (pc1 should fail, as packet is from lg1)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_dhcp_hostname'
    classifier_result.policy_value = 'pc1'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == False

    #*** Ingest packet from pc1:
    flow.ingest_packet(DPID1, INPORT1, pkts_http_pc1.RAW[0],
                       datetime.datetime.now())

    #*** Test tc_identity (Regex pc.* should pass)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_dhcp_hostname_re'
    classifier_result.policy_value = 'pc.*'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == True

    #*** Test tc_identity (Regex ac.* should fail)
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'identity_dhcp_hostname_re'
    classifier_result.policy_value = 'ac.*'
    tc_ident.check_identity(classifier_result, flow.packet, identities)
    assert classifier_result.match == False
Exemplo n.º 20
0
def test_statistical_classifier():
    """
    Test instantiating custom classifiers and use of
    supplied sample statistical classifier
    """

    #*** Test DPIDs and in ports:
    DPID1 = 1
    INPORT1 = 1

    #*** Instantiate class object:
    flow = flows_module.Flow(config)  #*** Test DPIDs and in ports:
    DPID1 = 1
    INPORT1 = 1

    #*** Instantiate class objects:
    flow = flows_module.Flow(config)
    policy = policy_module.Policy(config)
    ident = identities_module.Identities(config, policy)

    #*** Instantiate custom classifiers
    tc_cust = tc_custom.CustomInspect(config)
    tc_cust.instantiate_classifiers(['statistical_qos_bandwidth_1'])

    #*** Instantiate match object:
    classifier_result = policy_module.TCClassifierResult("", "")

    #*** Ingest sufficient packets to complete statistical classification (7):

    #*** Ingest packet 10.1.0.1 10.1.0.2 TCP 38435 80 [SYN]
    flow.ingest_packet(DPID1, INPORT1, pkts2.RAW[0], datetime.datetime.now())

    classifier_result.policy_attr = 'custom'
    classifier_result.policy_value = 'statistical_qos_bandwidth_1'
    tc_cust.check_custom(classifier_result, flow, ident)
    assert classifier_result.match == True
    assert classifier_result.continue_to_inspect == True
    assert classifier_result.classification_tag == ""
    assert classifier_result.actions == {}

    #*** Ingest packet 10.1.0.2 10.1.0.1 TCP 80 38435 [SYN, ACK]
    flow.ingest_packet(DPID1, INPORT1, pkts2.RAW[1], datetime.datetime.now())
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'custom'
    classifier_result.policy_value = 'statistical_qos_bandwidth_1'
    tc_cust.check_custom(classifier_result, flow, ident)
    assert classifier_result.match == True
    assert classifier_result.continue_to_inspect == True
    assert classifier_result.classification_tag == ""
    assert classifier_result.actions == {}

    #*** Ingest packet
    flow.ingest_packet(DPID1, INPORT1, pkts2.RAW[2], datetime.datetime.now())
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'custom'
    classifier_result.policy_value = 'statistical_qos_bandwidth_1'
    tc_cust.check_custom(classifier_result, flow, ident)
    assert classifier_result.match == True
    assert classifier_result.continue_to_inspect == True
    assert classifier_result.classification_tag == ""
    assert classifier_result.actions == {}

    #*** Ingest packet
    flow.ingest_packet(DPID1, INPORT1, pkts2.RAW[3], datetime.datetime.now())
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'custom'
    classifier_result.policy_value = 'statistical_qos_bandwidth_1'
    tc_cust.check_custom(classifier_result, flow, ident)
    assert classifier_result.match == True
    assert classifier_result.continue_to_inspect == True
    assert classifier_result.classification_tag == ""
    assert classifier_result.actions == {}

    #*** Ingest packet
    flow.ingest_packet(DPID1, INPORT1, pkts2.RAW[4], datetime.datetime.now())
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'custom'
    classifier_result.policy_value = 'statistical_qos_bandwidth_1'
    tc_cust.check_custom(classifier_result, flow, ident)
    assert classifier_result.match == True
    assert classifier_result.continue_to_inspect == True
    assert classifier_result.classification_tag == ""
    assert classifier_result.actions == {}

    #*** Ingest packet
    flow.ingest_packet(DPID1, INPORT1, pkts2.RAW[5], datetime.datetime.now())
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'custom'
    classifier_result.policy_value = 'statistical_qos_bandwidth_1'
    tc_cust.check_custom(classifier_result, flow, ident)
    assert classifier_result.match == True
    assert classifier_result.continue_to_inspect == True
    assert classifier_result.classification_tag == ""
    assert classifier_result.actions == {}

    #*** Ingest packet
    #*** This should conclude the statistical classification for this flow
    #*** and conclude action is default priority
    flow.ingest_packet(DPID1, INPORT1, pkts2.RAW[6], datetime.datetime.now())
    classifier_result = policy_module.TCClassifierResult("", "")
    classifier_result.policy_attr = 'custom'
    classifier_result.policy_value = 'statistical_qos_bandwidth_1'
    tc_cust.check_custom(classifier_result, flow, ident)
    assert classifier_result.match == True
    assert classifier_result.continue_to_inspect == False
    assert classifier_result.classification_tag == "Normal flow"
    assert classifier_result.actions == {'qos_treatment': 'default_priority'}
Exemplo n.º 21
0
def test_indexing():
    """
    Test indexing of packet_ins and classification database collections

    Packets are ingested from 3 flows.

    Packets from one of the flows are too old to be significant

    The most recent packet is the one that the flow context is in
    and it only has one other packet ingested (i.e. packet_count == 2)
    """
    #*** Initial main_policy won't match as looking for tcp-1234:
    policy = policy_module.Policy(
        config,
        pol_dir_default="config/tests/regression",
        pol_dir_user="******",
        pol_filename="main_policy_regression_static.yaml")

    #*** Instantiate flow and identities objects:
    flow = flows_module.Flow(config)
    ident = identities_module.Identities(config, policy)

    #*** Ingest packets older than flow timeout:
    flow.ingest_packet(DPID1, INPORT1, pkts_ARP_2.RAW[0], datetime.datetime.now() - datetime.timedelta \
                                (seconds=config.get_value("flow_time_limit")+1))
    flow.ingest_packet(DPID1, INPORT1, pkts_ARP_2.RAW[1], datetime.datetime.now() - datetime.timedelta \
                                (seconds=config.get_value("flow_time_limit")+1))
    #*** Ingest current packets from two different flows:
    flow.ingest_packet(DPID1, INPORT1, pkts2.RAW[0], datetime.datetime.now())
    #*** Classify the packet:
    policy.check_policy(flow, ident)
    flow.classification.commit()
    flow.ingest_packet(DPID1, INPORT2, pkts2.RAW[1], datetime.datetime.now())
    flow.ingest_packet(DPID1, INPORT1, pkts2.RAW[2], datetime.datetime.now())
    flow.ingest_packet(DPID1, INPORT1, pkts.RAW[1], datetime.datetime.now())
    #*** Classify the packet:
    policy.check_policy(flow, ident)
    flow.classification.commit()
    flow.ingest_packet(DPID1, INPORT1, pkts2.RAW[3], datetime.datetime.now())
    flow.ingest_packet(DPID1, INPORT2, pkts2.RAW[4], datetime.datetime.now())
    flow.ingest_packet(DPID1, INPORT2, pkts2.RAW[5], datetime.datetime.now())
    flow.ingest_packet(DPID1, INPORT1, pkts2.RAW[6], datetime.datetime.now())
    #*** Classify the packet:
    policy.check_policy(flow, ident)
    flow.classification.commit()
    flow.ingest_packet(DPID1, INPORT2, pkts2.RAW[7], datetime.datetime.now())
    flow.ingest_packet(DPID1, INPORT1, pkts2.RAW[8], datetime.datetime.now())
    flow.ingest_packet(DPID1, INPORT2, pkts2.RAW[9], datetime.datetime.now())
    flow.ingest_packet(DPID1, INPORT1, pkts2.RAW[10], datetime.datetime.now())
    flow.ingest_packet(DPID1, INPORT2, pkts2.RAW[11], datetime.datetime.now())
    flow.ingest_packet(DPID1, INPORT1, pkts.RAW[2], datetime.datetime.now())
    #*** Classify the packet:
    policy.check_policy(flow, ident)
    flow.classification.commit()

    #*** Test packet_ins collection indexing...
    #*** Should be 16 documents in packet_ins collection:
    assert flow.packet_ins.count() == 16
    #*** Get query execution statistics:
    explain = flow.packet_count(test=1)
    #*** Check an index is used:
    assert explain['queryPlanner']['winningPlan']['inputStage'][
        'stage'] == 'IXSCAN'
    #*** Check how query ran:
    assert explain['executionStats']['executionSuccess'] == True
    assert explain['executionStats']['nReturned'] == 2
    #*** MongoDB returns 2 or 3 for this, not sure why...???:
    assert explain['executionStats']['totalKeysExamined'] > 1
    assert explain['executionStats']['totalKeysExamined'] < 4
    assert explain['executionStats']['totalDocsExamined'] == 2

    #*** Test classifications collection indexing...
    #*** Should be 4 documents in classifications collection:
    assert flow.classifications.count() == 4
    #*** Get query execution statistics:
    explain2 = flow.classification.test_query()
    #*** Check an index is used:
    assert explain2['queryPlanner']['winningPlan']['inputStage'][
        'stage'] == 'FETCH'
    #*** Check how query ran:
    assert explain2['executionStats']['executionSuccess'] == True
    assert explain2['executionStats']['nReturned'] == 1
    assert explain2['executionStats']['totalKeysExamined'] == 1
    assert explain2['executionStats']['totalDocsExamined'] == 1
Exemplo n.º 22
0
def test_check_tc_condition():
    """
    Check TC packet match against a TC condition (set of classifiers and
    match type)
    """
    #*** Instantiate classes:
    policy = policy_module.Policy(config)
    flow = flows_module.Flow(config)
    ident = identities.Identities(config, policy)

    #*** Test Flow 1 Packet 1 (Client TCP SYN):
    # 10.1.0.1 10.1.0.2 TCP 74 43297 > http [SYN]
    flow.ingest_packet(DPID1, INPORT1, pkts.RAW[0], datetime.datetime.now())
    #*** Set policy.pkt as work around for not calling parent method
    #***  that sets it:
    policy.pkt = flow.packet

    #*** HTTP is not OpenFlow so shouldn't match!
    logger.debug("condition_any_opf should not match")
    tc_rules = policy_module.TCRules(policy)
    tc_condition = policy_module.TCCondition(tc_rules, policy,
                                             condition_any_opf)
    condition_result = tc_condition.check_tc_condition(flow, ident)
    assert condition_result.match == False
    assert condition_result.continue_to_inspect == False
    assert condition_result.classification_tag == ""
    assert condition_result.actions == {}

    #*** HTTP is not OpenFlow so should match none rule!
    logger.debug("condition_any_opf should not match")
    tc_rules = policy_module.TCRules(policy)
    tc_condition = policy_module.TCCondition(tc_rules, policy,
                                             condition_none_opf)
    condition_result = tc_condition.check_tc_condition(flow, ident)
    assert condition_result.match == True
    assert condition_result.continue_to_inspect == False
    assert condition_result.classification_tag == ""
    assert condition_result.actions == {}

    #*** HTTP is HTTP so should match:
    logger.debug("condition_any_http should match")
    tc_condition = policy_module.TCCondition(tc_rules, policy,
                                             condition_any_http)
    condition_result = tc_condition.check_tc_condition(flow, ident)
    assert condition_result.match == True
    assert condition_result.continue_to_inspect == False
    assert condition_result.classification_tag == ""
    assert condition_result.actions == {}

    #*** Source AND Dest aren't both HTTP so should not match:
    logger.debug("condition_all_http should not match")
    tc_condition = policy_module.TCCondition(tc_rules, policy,
                                             condition_all_http)
    condition_result = tc_condition.check_tc_condition(flow, ident)
    assert condition_result.match == False
    assert condition_result.continue_to_inspect == False
    assert condition_result.classification_tag == ""
    assert condition_result.actions == {}

    #*** This should match (HTTP src and dst ports correct):
    logger.debug("condition_all_http2 should match")
    tc_condition = policy_module.TCCondition(tc_rules, policy,
                                             condition_all_http2)
    condition_result = tc_condition.check_tc_condition(flow, ident)
    assert condition_result.match == True
    assert condition_result.continue_to_inspect == False
    assert condition_result.classification_tag == ""
    assert condition_result.actions == {}

    #*** MAC should match:
    tc_condition = policy_module.TCCondition(tc_rules, policy,
                                             condition_any_mac)
    condition_result = tc_condition.check_tc_condition(flow, ident)
    assert condition_result.match == True
    assert condition_result.continue_to_inspect == False
    assert condition_result.classification_tag == ""
    assert condition_result.actions == {}

    tc_condition = policy_module.TCCondition(tc_rules, policy,
                                             condition_all_mac)
    condition_result = tc_condition.check_tc_condition(flow, ident)
    assert condition_result.match == True
    assert condition_result.continue_to_inspect == False
    assert condition_result.classification_tag == ""
    assert condition_result.actions == {}

    #*** Different MAC shouldn't match:
    tc_condition = policy_module.TCCondition(tc_rules, policy,
                                             condition_any_mac2)
    condition_result = tc_condition.check_tc_condition(flow, ident)
    assert condition_result.match == False
    assert condition_result.continue_to_inspect == False
    assert condition_result.classification_tag == ""
    assert condition_result.actions == {}