Exemple #1
0
    def test_startup(self):
        common.default_logging()
        context = stub_zmq.Context()
        agent = felix.FelixAgent(config_path, context)

        set_expected_global_rules()
        stub_fiptables.check_state(expected_iptables)
        stub_ipsets.check_state(expected_ipsets)

        self.assertEqual(agent.hostname, "test_hostname")
Exemple #2
0
    def test_no_work(self):
        """
        Test starting up, and sending no work at all.
        """
        common.default_logging()
        context = stub_zmq.Context()
        agent = felix.FelixAgent(config_path, context)
        context.add_poll_result(0)
        agent.run()

        set_expected_global_rules()
        stub_fiptables.check_state(expected_iptables)
        stub_ipsets.check_state(expected_ipsets)
Exemple #3
0
    def test_empty_ipsets(self):
        """
        Empty ipsets.
        """
        description = "Description : blah"
        suffix = "whatever"
        rule_list = []

        self.create_ipsets("inet")

        frules.update_ipsets(IPV4, description, suffix, rule_list,
                             "ipset_addr", "ipset_port", "ipset_icmp",
                             "tmp_ipset_addr", "tmp_ipset_port",
                             "tmp_ipset_icmp")

        stub_ipsets.check_state(expected_ipsets)
Exemple #4
0
    def test_exception(self):
        """
        Test exception when adding ipset value.
        """
        description = "description"
        suffix = "suffix"
        rule_list = [{'cidr': "1.2.3.4/24"}]

        self.create_ipsets("inet")

        with mock.patch('calico.felix.test.stub_ipsets.add',
                        side_effect=FailedSystemCall("oops", [], 1, "", "")):
            frules.update_ipsets(IPV4, description, suffix, rule_list,
                                 "ipset_addr", "ipset_port", "ipset_icmp",
                                 "tmp_ipset_addr", "tmp_ipset_port",
                                 "tmp_ipset_icmp")

        stub_ipsets.check_state(expected_ipsets)
Exemple #5
0
    def test_ipv6_ipsets(self):
        """
        IPv6 ipsets
        """
        description = "description"
        suffix = "suffix"
        rule_list = []
        default_cidr = "2001::1:2:3:4/24"

        self.create_ipsets("inet6")

        # Ignored rules
        rule_list.append({'blah': "junk"})  # no CIDR
        rule_list.append({'cidr': "junk"})  # junk CIDR
        rule_list.append({'cidr': "1.2.3.4/32"})  # IPv4, not v6
        rule_list.append({
            'cidr': default_cidr,
            'port': 123
        })  # port, no protocol
        rule_list.append({
            'cidr': default_cidr,
            'protocol': "tcp",
            'port': "blah"
        })  # bad port
        rule_list.append({
            'cidr': default_cidr,
            'protocol': "tcp",
            'port': ["blah", "bloop"]
        })  # bad port range
        rule_list.append({
            'cidr': default_cidr,
            'protocol': "tcp",
            'port': [0, 123]
        })  # bad port in range
        rule_list.append({
            'cidr': default_cidr,
            'protocol': "tcp",
            'port': [1, 2, 3]
        })  # not two in range
        rule_list.append({
            'cidr': default_cidr,
            'protocol': "tcp",
            'port': [1]
        })  # not two in range
        rule_list.append({
            'cidr': default_cidr,
            'protocol': "icmp",
            'port': "1"
        })  # port not allowed
        rule_list.append({
            'cidr': default_cidr,
            'protocol': "ipv6-icmp",
            'port': "1"
        })  # port not allowed
        rule_list.append({
            'cidr': default_cidr,
            'protocol': "icmp",
            'icmp_code': "1"
        })  # code without type
        rule_list.append({
            'cidr': default_cidr,
            'protocol': "blah",
            'port': "1"
        })  # port not allowed for protocol

        # Better rules
        rule_list.append({'cidr': "1:2:3::4/24"})
        expected_ipsets.add("ipset_addr", "1:2:3::4/24")

        rule_list.append({'cidr': "1:2:3::/0", 'protocol': "tcp"})
        expected_ipsets.add("ipset_port", "::/1,tcp:1-65535")
        expected_ipsets.add("ipset_port", "8000::/1,tcp:1-65535")

        rule_list.append({
            'cidr': "1::1/8",
            'protocol': "udp",
            'port': [2, 10]
        })
        expected_ipsets.add("ipset_port", "1::1/8,udp:2-10")

        rule_list.append({'cidr': "1::2/8", 'protocol': "sctp", 'port': "2"})
        expected_ipsets.add("ipset_port", "1::2/8,sctp:2")

        rule_list.append({
            'cidr': "1::3/8",
            'protocol': "udplite",
            'port': [2, 10]
        })
        expected_ipsets.add("ipset_port", "1::3/8,udplite:2-10")

        rule_list.append({'cidr': "1::4/8", 'protocol': "ipv6-icmp"})
        expected_ipsets.add("ipset_icmp", "1::4/8")

        rule_list.append({
            'cidr': "1::5/8",
            'protocol': "ipv6-icmp",
            'icmp_type': 123
        })
        expected_ipsets.add("ipset_port", "1::5/8,ipv6-icmp:123/0")

        rule_list.append({
            'cidr': "1::6/8",
            'protocol': "ipv6-icmp",
            'icmp_type': "type"
        })
        expected_ipsets.add("ipset_port", "1::6/8,ipv6-icmp:type")

        rule_list.append({
            'cidr': "1::7/8",
            'protocol': "ipv6-icmp",
            'icmp_type': 123,
            'icmp_code': "code"
        })
        expected_ipsets.add("ipset_port", "1::7/8,ipv6-icmp:123/code")

        rule_list.append({
            'cidr': "1::8/8",
            'protocol': "ipv6-icmp",
            'icmp_type': "type",
            'icmp_code': "code"
        })  # code ignored
        expected_ipsets.add("ipset_port", "1::8/8,ipv6-icmp:type")

        rule_list.append({'cidr': "1::9/8", 'protocol': "blah"})
        expected_ipsets.add("ipset_port", "1::9/8,blah:0")

        frules.update_ipsets(IPV6, description, suffix, rule_list,
                             "ipset_addr", "ipset_port", "ipset_icmp",
                             "tmp_ipset_addr", "tmp_ipset_port",
                             "tmp_ipset_icmp")

        stub_ipsets.check_state(expected_ipsets)
Exemple #6
0
    def test_main_flow(self):
        """
        Test starting up and going through some of the basic flow.
        """
        common.default_logging()
        context = stub_zmq.Context()
        agent = felix.FelixAgent(config_path, context)
        context.add_poll_result(0)
        agent.run()

        # Now we want to reply to the RESYNC request.
        resync_req = context.sent_data[TYPE_EP_REQ].pop()
        log.debug("Resync request : %s" % resync_req)
        self.assertFalse(context.sent_data_present())
        resync_id = resync_req['resync_id']
        resync_rsp = {
            'type': "RESYNCSTATE",
            'endpoint_count': 1,
            'rc': "SUCCESS",
            'message': "hello"
        }

        poll_result = context.add_poll_result(50)
        poll_result.add(TYPE_EP_REQ, resync_rsp)
        agent.run()

        # Felix expects one endpoint created message - give it what it wants
        endpoint_id = str(uuid.uuid4())
        log.debug("Build first endpoint created : %s" % endpoint_id)
        mac = stub_utils.get_mac()
        suffix = endpoint_id[:11]
        tap = "tap" + suffix
        addr = '1.2.3.4'
        endpoint_created_req = {
            'type': "ENDPOINTCREATED",
            'endpoint_id': endpoint_id,
            'resync_id': resync_id,
            'issued': futils.time_ms(),
            'mac': mac,
            'state': Endpoint.STATE_ENABLED,
            'addrs': [{
                'gateway': "1.2.3.1",
                'addr': addr
            }]
        }

        poll_result = context.add_poll_result(100)
        poll_result.add(TYPE_EP_REP, endpoint_created_req)
        agent.run()

        log.debug("Create tap interface %s" % tap)
        tap_obj = stub_devices.TapInterface(tap)
        stub_devices.add_tap(tap_obj)
        poll_result = context.add_poll_result(150)
        agent.run()

        #*********************************************************************#
        #* As soon as that endpoint has been made to exist, we should see an *#
        #* ACL request coming through, and a response to the endpoint        *#
        #* created.  We send a reply to that now.                            *#
        #*********************************************************************#
        endpoint_created_rsp = context.sent_data[TYPE_EP_REP].pop()
        self.assertEqual(endpoint_created_rsp['rc'], "SUCCESS")

        acl_req = context.sent_data[TYPE_ACL_REQ].pop()
        self.assertFalse(context.sent_data_present())
        self.assertEqual(acl_req['endpoint_id'], endpoint_id)

        acl_rsp = {'type': "GETACLSTATE", 'rc': "SUCCESS", 'message': ""}
        poll_result = context.add_poll_result(200)
        poll_result.add(TYPE_ACL_REQ, acl_rsp)

        # Check the rules are what we expect.
        set_expected_global_rules()
        add_endpoint_rules(suffix, tap, addr, None, mac)
        stub_fiptables.check_state(expected_iptables)
        add_endpoint_ipsets(suffix)
        stub_ipsets.check_state(expected_ipsets)

        # OK - now try giving it some ACLs, and see if they get applied correctly.
        acls = get_blank_acls()
        acls['v4']['outbound'].append({
            'cidr': "0.0.0.0/0",
            'protocol': "icmp"
        })
        acls['v4']['outbound'].append({
            'cidr': "1.2.3.0/24",
            'protocol': "tcp"
        })
        acls['v4']['outbound'].append({
            'cidr': "0.0.0.0/0",
            'protocol': "tcp",
            'port': "80"
        })
        acls['v4']['inbound'].append({
            'cidr': "1.2.2.0/24",
            'protocol': "icmp"
        })
        acls['v4']['inbound'].append({
            'cidr': "0.0.0.0/0",
            'protocol': "tcp",
            'port': "8080"
        })
        acls['v4']['inbound'].append({
            'cidr': "2.4.6.8/32",
            'protocol': "udp",
            'port': "8080"
        })
        acls['v4']['inbound'].append({'cidr': "1.2.3.3/32"})
        acls['v4']['inbound'].append({
            'cidr': "3.6.9.12/32",
            'protocol': "tcp",
            'port': ['10', '50']
        })

        acls['v4']['inbound'].append({
            'cidr': "5.4.3.2/32",
            'protocol': "icmp",
            'icmp_type': "3",
            'icmp_code': "2"
        })

        acls['v4']['inbound'].append({
            'cidr': "5.4.3.2/32",
            'protocol': "icmp",
            'icmp_type': "9"
        })

        acls['v4']['inbound'].append({
            'cidr': "5.4.3.2/32",
            'protocol': "icmp",
            'icmp_type': "blah"
        })

        # We include a couple of invalid rules that Felix will just ignore (and log).
        acls['v4']['inbound'].append({
            'cidr': "4.3.2.1/32",
            'protocol': "tcp",
            'port': ['blah', 'blah']
        })
        acls['v4']['inbound'].append({
            'cidr': "4.3.2.1/32",
            'protocol': "tcp",
            'port': ['1', '2', '3']
        })
        acls['v4']['inbound'].append({
            'cidr': "4.3.2.1/32",
            'protocol': "tcp",
            'port': 'flibble'
        })
        acls['v4']['inbound'].append({'protocol': "tcp"})
        acls['v4']['inbound'].append({'cidr': "4.3.2.1/32", 'port': "123"})
        acls['v4']['inbound'].append({
            'cidr': "4.3.2.1/32",
            'protocol': "icmp",
            'icmp_code': "blah"
        })
        acls['v4']['inbound'].append({
            'cidr': "4.3.2.1/32",
            'protocol': "icmp",
            'port': "1"
        })
        acls['v4']['inbound'].append({
            'cidr': "4.3.2.1/32",
            'protocol': "rsvp",
            'port': "1"
        })

        acl_req = {'type': "ACLUPDATE", 'acls': acls}

        poll_result.add(TYPE_ACL_SUB, acl_req, endpoint_id)
        agent.run()

        stub_fiptables.check_state(expected_iptables)
        expected_ipsets.add("felix-from-icmp-" + suffix, "0.0.0.0/1")
        expected_ipsets.add("felix-from-icmp-" + suffix, "128.0.0.0/1")
        expected_ipsets.add("felix-from-port-" + suffix, "1.2.3.0/24,tcp:0")
        expected_ipsets.add("felix-from-port-" + suffix, "0.0.0.0/1,tcp:80")
        expected_ipsets.add("felix-from-port-" + suffix, "128.0.0.0/1,tcp:80")

        expected_ipsets.add("felix-to-icmp-" + suffix, "1.2.2.0/24")
        expected_ipsets.add("felix-to-port-" + suffix, "0.0.0.0/1,tcp:8080")
        expected_ipsets.add("felix-to-port-" + suffix, "128.0.0.0/1,tcp:8080")
        expected_ipsets.add("felix-to-port-" + suffix, "2.4.6.8/32,udp:8080")
        expected_ipsets.add("felix-to-addr-" + suffix, "1.2.3.3/32")
        expected_ipsets.add("felix-to-port-" + suffix, "3.6.9.12/32,tcp:10-50")
        expected_ipsets.add("felix-to-port-" + suffix, "5.4.3.2/32,icmp:3/2")
        expected_ipsets.add("felix-to-port-" + suffix, "5.4.3.2/32,icmp:9/0")
        expected_ipsets.add("felix-to-port-" + suffix, "5.4.3.2/32,icmp:blah")

        stub_ipsets.check_state(expected_ipsets)

        # Add another endpoint, and check the state.
        endpoint_id2 = str(uuid.uuid4())
        log.debug("Build second endpoint created : %s" % endpoint_id2)
        mac2 = stub_utils.get_mac()
        suffix2 = endpoint_id2[:11]
        tap2 = "tap" + suffix2
        addr2 = '1.2.3.5'
        endpoint_created_req = {
            'type': "ENDPOINTCREATED",
            'endpoint_id': endpoint_id2,
            'issued': futils.time_ms(),
            'mac': mac2,
            'state': Endpoint.STATE_ENABLED,
            'addrs': [{
                'gateway': "1.2.3.1",
                'addr': addr2
            }]
        }

        poll_result = context.add_poll_result(250)
        poll_result.add(TYPE_EP_REP, endpoint_created_req)
        tap_obj2 = stub_devices.TapInterface(tap2)
        stub_devices.add_tap(tap_obj2)
        agent.run()

        # Check that we got what we expected - i.e. a success response, a GETACLSTATE,
        # and the rules in the right state.
        endpoint_created_rsp = context.sent_data[TYPE_EP_REP].pop()
        self.assertEqual(endpoint_created_rsp['rc'], "SUCCESS")

        acl_req = context.sent_data[TYPE_ACL_REQ].pop()
        self.assertEqual(acl_req['endpoint_id'], endpoint_id2)
        self.assertFalse(context.sent_data_present())

        add_endpoint_rules(suffix2, tap2, addr2, None, mac2)
        stub_fiptables.check_state(expected_iptables)
        add_endpoint_ipsets(suffix2)
        stub_ipsets.check_state(expected_ipsets)

        # OK, finally wind down with an ENDPOINTDESTROYED message for that second endpoint.
        endpoint_destroyed_req = {
            'type': "ENDPOINTDESTROYED",
            'endpoint_id': endpoint_id2,
            'issued': futils.time_ms()
        }

        poll_result = context.add_poll_result(300)
        poll_result.add(TYPE_EP_REP, endpoint_destroyed_req)
        stub_devices.del_tap(tap2)
        agent.run()

        # Rebuild and recheck the state.
        set_expected_global_rules()
        add_endpoint_rules(suffix, tap, addr, None, mac)
        stub_fiptables.check_state(expected_iptables)