Esempio n. 1
0
 def test_auth_learn(self):
     """Test to validate MAC authentication status"""
     device_placement = DevicePlacement(switch='switch',
                                        port=1,
                                        connected=True)
     self._forchestrator._process_device_placement('00:11:22:33:44:55',
                                                   device_placement)
     self.assertEqual(self._get_auth_sm_state('00:11:22:33:44:55'),
                      'RADIUS Request')
     self._forchestrator._authenticator.process_radius_result(
         '00:11:22:33:44:55', 'ACCEPT', 'ACCEPT', None)
     self.assertEqual(self._get_auth_sm_state('00:11:22:33:44:55'),
                      'Authorized')
     device_placement = DevicePlacement(switch='switch',
                                        port=1,
                                        connected=False)
     self._forchestrator._process_device_placement('00:11:22:33:44:55',
                                                   device_placement,
                                                   expired_vlan=200)
     self.assertEqual(self._get_auth_sm_state('00:11:22:33:44:55'),
                      'Authorized')
     self._forchestrator._process_device_placement('00:11:22:33:44:55',
                                                   device_placement,
                                                   expired_vlan=100)
     self.assertEqual(self._get_auth_sm_state('00:11:22:33:44:55'), None)
Esempio n. 2
0
    def process_device_placement(self, eth_src, placement, static=False):
        """Process device placement"""
        if not placement.switch or not placement.port:
            raise Exception(f'Incomplete placement for {eth_src}: {placement}')

        devices_state = self._static_devices if static else self._dynamic_devices
        device_type = "static" if static else "dynamic"
        eth_src = eth_src.lower()

        with self._lock:
            device_placements = devices_state.device_mac_placements
            if placement.connected:
                device_placement = device_placements.setdefault(
                    eth_src, DevicePlacement())
                device_placement.CopyFrom(placement)
                self._logger.info('Received %s placement: %s, %s, %s',
                                  device_type, eth_src,
                                  device_placement.switch,
                                  device_placement.port)
            else:
                removed = device_placements.pop(eth_src, None)
                if removed:
                    self._logger.info('Removed %s placement: %s, %s, %s',
                                      device_type, eth_src, removed.switch,
                                      removed.port)

            self.flush_behavioral_config()
Esempio n. 3
0
    def _handle_learned_device(self, mac, device_placement, static=False):
        # if device is learned
        old_mac = self._placement_to_mac.get(
            (device_placement.switch, device_placement.port))
        stale_mac = old_mac if old_mac and old_mac != mac else None

        if stale_mac:
            switch = device_placement.switch
            port = device_placement.port
            self._logger.warning('Cleaning stale device placement: %s, %s, %s',
                                 old_mac, switch, port)
            stale_placement = DevicePlacement(switch=switch,
                                              port=port,
                                              connected=False)
            self._handle_disconnected_device(stale_placement)

        self._placement_to_mac[(device_placement.switch,
                                device_placement.port)] = mac
        self._process_device_placement(mac, device_placement, static=static)

        if mac not in self._state_machines:
            self._state_machines[mac] = PortStateMachine(
                mac, PortStateMachine.UNAUTHENTICATED,
                self._handle_unauthenticated_state, self._set_port_sequestered,
                self._set_port_operational, self._handle_infracted_state)

            device_behavior = (self._static_device_behaviors.get(mac)
                               or self._dynamic_device_behaviors.get(mac))
            if device_behavior:
                static = mac in self._static_device_behaviors
                self.handle_device_behavior(mac,
                                            device_behavior,
                                            static=static)

        return True, None, stale_mac
Esempio n. 4
0
    def _handle_learned_device(self, mac, device_placement, static=False):
        old_mac = self._placement_to_mac.get(
            (device_placement.switch, device_placement.port))
        stale_mac = old_mac if old_mac and old_mac != mac else None

        if stale_mac:
            switch = device_placement.switch
            port = device_placement.port
            self._logger.warning('Cleaning stale device placement: %s, %s, %s',
                                 old_mac, switch, port)
            stale_placement = DevicePlacement(switch=switch,
                                              port=port,
                                              connected=False)
            self._handle_disconnected_device(stale_placement)

        self._placement_to_mac[(device_placement.switch,
                                device_placement.port)] = mac
        self._process_device_placement(mac, device_placement, static=static)

        if mac not in self._state_machines:
            self._state_machines[mac] = PortStateMachine(
                mac,
                PortStateMachine.UNAUTHENTICATED,
                self._state_callbacks,
                state_overwrites=self._state_overwrites)

            device_behavior = (self._static_device_behaviors.get(mac)
                               or self._dynamic_device_behaviors.get(mac))
            if device_behavior:
                static_behavior = mac in self._static_device_behaviors
                self.handle_device_behavior(mac,
                                            device_behavior,
                                            static=static_behavior)

        return True, None, stale_mac
Esempio n. 5
0
    def _expire_devices(self, expired_device_placements, expected_device_placements):
        for expired_device_placement in expired_device_placements:
            mac = None
            switch = expired_device_placement[1][0]
            port = expired_device_placement[1][1]
            self._port_state_manager.handle_device_placement(
                mac, DevicePlacement(switch=switch, port=port), False)

        expected_device_placements.extend([
            # mac, device_placement.connected, static
            ('00:0X:00:00:00:01', False, False),
            ('00:0B:00:00:00:05', False, False)
        ])
        self._verify_received_device_placements(expected_device_placements)
Esempio n. 6
0
    def _process_device_placement(self,
                                  eth_src,
                                  device_placement,
                                  static=False):
        """Call device placement API for faucetizer/authenticator"""
        propagate_placement, mac, stale_mac = self._port_state_manager.handle_device_placement(
            eth_src, device_placement, static)

        src_mac = mac if mac else eth_src

        if self._authenticator and propagate_placement:
            if stale_mac:
                self._authenticator.process_device_placement(
                    stale_mac, DevicePlacement(connected=False))
            self._authenticator.process_device_placement(
                src_mac, device_placement)
        else:
            self._logger.info('Ignored deauthentication for %s on %s:%s',
                              src_mac, device_placement.switch,
                              device_placement.port)
Esempio n. 7
0
    def _update_device_placements(self):
        try:
            metrics = self._varz_state_collector.retry_get_faucet_metrics(
                [self._DEVICE_LEARNING_METRIC])
        except Exception as e:
            LOGGER.error('Could not get %s metric: %s',
                         self._DEVICE_LEARNING_METRIC, e)

        device_learning_metric = metrics.get(self._DEVICE_LEARNING_METRIC)
        if not device_learning_metric:
            LOGGER.info('No devices are learned')

        self._device_placements = {}
        for sample in device_learning_metric.samples:
            if sample.labels.get('dp_name') != self._SEC_SWITCH:
                continue

            mac = sample.labels.get('eth_src')
            if mac not in self._duts:
                continue

            port = int(sample.value)
            self._device_placements[mac] = DevicePlacement(
                switch=self._SEC_SWITCH, port=port)
Esempio n. 8
0
        {
            'radius_info': {
                'server_ip': ARGS.server_ip,
                'server_port': ARGS.server_port,
                'source_port': ARGS.source_port,
                'radius_secret_helper': f'echo {ARGS.radius_secret}'
            }
        }, OrchestrationConfig.AuthConfig)
    MOCK_RADIUS_QUERY = MockRadiusQuery()

    if ARGS.mab:
        AUTHENTICATOR = Authenticator(AUTH_CONFIG, mock_auth_callback)
        AUTHENTICATOR.do_mab_request(ARGS.src_mac, ARGS.port_id)
        input('Press any key to exit.')
    else:
        # test radius query call for device placement
        AUTHENTICATOR = Authenticator(AUTH_CONFIG, mock_auth_callback,
                                      MOCK_RADIUS_QUERY)
        TEST_MAC = '00:aa:bb:cc:dd:ee'
        DEV_PLACEMENT = DevicePlacement(switch='t2s2', port=1, connected=True)
        AUTHENTICATOR.process_device_placement(TEST_MAC, DEV_PLACEMENT)
        assert MOCK_RADIUS_QUERY.get_last_mac_queried() == TEST_MAC

        # test positive RADIUS response
        CODE = radius_query.ACCEPT
        SEGMENT = 'test'
        ROLE = 'test'
        EXPECTED_MAB_RESULT[TEST_MAC] = {'segment': SEGMENT, 'role': ROLE}
        AUTHENTICATOR.process_radius_result(TEST_MAC, CODE, SEGMENT, ROLE)
        EXPECTED_MAB_RESULT.pop(TEST_MAC)
Esempio n. 9
0
    def test_ports_states(self):
        """Test the port states with different signals"""
        static_device_behaviors = {
            '00:0X:00:00:00:01': {'segment': 'SEG_A', 'port_behavior': 'cleared'},
            '00:0Y:00:00:00:02': {'port_behavior': 'cleared'}
        }
        authentication_results = {
            '00:0X:00:00:00:01': {'segment': 'SEG_X'},
            '00:0Z:00:00:00:03': {'segment': 'SEG_C'},
            '00:0A:00:00:00:04': {'segment': 'SEG_D'},
            '00:0B:00:00:00:05': {'segment': 'SEG_E'}
        }
        testing_results = [
            ('00:0X:00:00:00:01', 'failed'),
            ('00:0Y:00:00:00:02', 'passed'),
            ('00:0Z:00:00:00:03', 'failed'),
            ('00:0A:00:00:00:04', 'passed')
        ]
        unauthenticated_devices = ['00:0X:00:00:00:01', '00:0A:00:00:00:04']
        expired_device_vlans = [
            ('00:0B:00:00:00:05', 600),
            ('00:0B:00:00:00:05', 500),
        ]

        # load static device behaviors
        for mac, device_behavior_map in static_device_behaviors.items():
            self._port_state_manager.handle_static_device_behavior(
                mac, dict_proto(device_behavior_map, DeviceBehavior))

        # devices are authenticated
        for mac, device_behavior_map in authentication_results.items():
            self._port_state_manager.handle_device_behavior(
                mac, dict_proto(device_behavior_map, DeviceBehavior))

        expected_states = {
            '00:0X:00:00:00:01': self.OPERATIONAL,
            '00:0Z:00:00:00:03': self.SEQUESTERED,
            '00:0A:00:00:00:04': self.SEQUESTERED,
            '00:0B:00:00:00:05': self.SEQUESTERED
        }
        self._verify_ports_states(expected_states)

        expected_received_device_behaviors = [
            ('00:0X:00:00:00:01', 'SEG_A', True),
            ('00:0X:00:00:00:01', 'SEG_A', True),
            ('00:0Z:00:00:00:03', 'TESTING', False),
            ('00:0A:00:00:00:04', 'TESTING', False),
            ('00:0B:00:00:00:05', 'TESTING', False)
        ]
        self._verify_received_device_behaviors(expected_received_device_behaviors)

        # received testing results for devices
        for testing_result in testing_results:
            self._port_state_manager.handle_testing_result(
                self._encapsulate_testing_result(*testing_result))

        expected_states = {
            '00:0X:00:00:00:01': self.OPERATIONAL,
            '00:0Z:00:00:00:03': self.INFRACTED,
            '00:0A:00:00:00:04': self.OPERATIONAL,
            '00:0B:00:00:00:05': self.SEQUESTERED
        }
        self._verify_ports_states(expected_states)

        expected_received_device_behaviors.extend([('00:0A:00:00:00:04', 'SEG_D', False)])
        self._verify_received_device_behaviors(expected_received_device_behaviors)

        # devices are unauthenticated
        for mac in unauthenticated_devices:
            self._port_state_manager.handle_device_behavior(mac, DeviceBehavior())

        expected_states = {
            '00:0X:00:00:00:01': self.OPERATIONAL,
            '00:0Z:00:00:00:03': self.INFRACTED,
            '00:0B:00:00:00:05': self.SEQUESTERED
        }
        self._verify_ports_states(expected_states)

        expected_received_device_behaviors.extend([('00:0A:00:00:00:04', '', False)])
        self._verify_received_device_behaviors(expected_received_device_behaviors)

        # devices are expired
        for expired_device_vlan in expired_device_vlans:
            mac = expired_device_vlan[0]
            expired_vlan = expired_device_vlan[1]
            self._port_state_manager.handle_device_placement(
                mac, DevicePlacement(switch='switch', port=1), False, expired_vlan)

        expired_received_device_placements = [('00:0B:00:00:00:05', False, False)]
        self._verify_received_device_placements(expired_received_device_placements)