Skip to content

Commit

Permalink
Merge pull request #2417 from anarkiwi/master
Browse files Browse the repository at this point in the history
Revert "Merge pull request #2377 from Bairdo/chewie-radius"
  • Loading branch information
anarkiwi committed Sep 3, 2018
2 parents 2a8bddf + f4c378b commit 6220b57
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 105 deletions.
19 changes: 12 additions & 7 deletions faucet/faucet_dot1x.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
class FaucetDot1x:
"""Wrapper for experimental Chewie 802.1x authenticator."""

# TODO: support other credentials.
CREDENTIALS = {
'gary': 'microphone',
}

def __init__(self, logger, metrics, send_flow_msgs):
self.logger = logger
self.metrics = metrics
Expand All @@ -39,10 +44,10 @@ def __init__(self, logger, metrics, send_flow_msgs):
self.dot1x_port = None

def _create_dot1x_speaker(self):
chewie = Chewie( # pylint: disable=too-many-function-args
self.dot1x_intf, self.logger,
self.auth_handler, self.failure_handler, self.logoff_handler,
'127.0.0.1')
chewie = Chewie(
self.dot1x_intf, self.CREDENTIALS,
self.logger, self.auth_handler,
MacAddress.from_string('00:00:00:00:00:01'))
hub.spawn(chewie.run)
return chewie

Expand All @@ -59,17 +64,17 @@ def auth_handler(self, address, _group_address):
if flowmods:
self._send_flow_msgs(self._valve, flowmods)

def logoff_handler(self, address, _):
def logoff_handler(self, address):
"""Callback for when an EAP logoff happens."""
self.logger.info('Logoff from MAC %s on %s',
str(address), self.dot1x_port)
self.metrics.inc_var('dp_dot1x_logoff', self._valve.base_prom_labels)
self.metrics.inc_var('port_dot1x_logoff', self._valve.port_labels(self.dot1x_port))
flowmods = self._valve.del_authed_mac(self.dot1x_port.number, str(address))
flowmods = self._valve.del_authed_mac(self.dot1x_port.number, address)
if flowmods:
self._send_flow_msgs(self._valve, flowmods)

def failure_handler(self, address, _):
def failure_handler(self, address):
"""Callback for when a EAP failure happens."""
self.logger.info('Failure from MAC %s on %s',
str(address), self.dot1x_port)
Expand Down
2 changes: 1 addition & 1 deletion faucet/valve.py
Original file line number Diff line number Diff line change
Expand Up @@ -1476,7 +1476,7 @@ def del_authed_mac(self, port_num, mac):
priority=self.dp.highest_priority,
strict=True
)
return ofmsg
return [ofmsg]

def add_route(self, vlan, ip_gw, ip_dst):
"""Add route to VLAN routing table."""
Expand Down
115 changes: 18 additions & 97 deletions tests/integration/mininet_tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import os
import random
import re
import shutil
import socket
import threading
import time
Expand Down Expand Up @@ -156,7 +155,7 @@ def test_untagged(self):
self.verify_events_log(event_log)


class FaucetSingle8021XSuccessTest(FaucetUntaggedTest):
class FaucetUntagged8021XSuccessTest(FaucetUntaggedTest):

SOFTWARE_ONLY = True

Expand Down Expand Up @@ -223,7 +222,7 @@ class FaucetSingle8021XSuccessTest(FaucetUntaggedTest):
network={
key_mgmt=IEEE8021X
eap=MD5
identity="user"
identity="user@example.com"
password="microphone"
}
"""
Expand All @@ -248,19 +247,11 @@ def _write_faucet_config(self):

self.CONFIG = self.CONFIG.replace('NFV_INTF', str(nfv_intf))
self.CONFIG_GLOBAL = self.CONFIG_GLOBAL.replace("NFV_MAC", nfv_intf.MAC())
super(FaucetSingle8021XSuccessTest, self)._write_faucet_config()
super(FaucetUntagged8021XSuccessTest, self)._write_faucet_config()

def setUp(self):
super(FaucetSingle8021XSuccessTest, self).setUp()
super(FaucetUntagged8021XSuccessTest, self).setUp()
self.host_drop_all_ips(self.nfv_host)
self.radius_port = 1812
# self.radius_port = mininet_test_util.find_free_port(
# self.ports_sock, self._test_name())
self.start_freeradius()

def tearDown(self):
self.nfv_host.cmd('kill %d' % self.freeradius_pid)
super(FaucetSingle8021XSuccessTest, self).tearDown()

def try_8021x(self, and_logff=False):
tcpdump_filter = 'ether proto 0x888e'
Expand All @@ -272,28 +263,22 @@ def try_8021x(self, and_logff=False):

def test_untagged(self):
tcpdump_txt = self.try_8021x(and_logff=True)

self.assertIn('Success', tcpdump_txt)
self.assertEqual(
1,
self.scrape_prometheus_var('dp_dot1x_success', default=0))
self.assertEqual(
1,
self.scrape_prometheus_var('port_dot1x_success', labels={'port': 1}, default=0))
self.scrape_prometheus_var('dp_dot1x_success', any_labels=True, default=0))
self.assertEqual(
0,
self.scrape_prometheus_var('dp_dot1x_failure', default=0))
self.assertEqual(
0,
self.scrape_prometheus_var('port_dot1x_failure', labels={'port': 1}, default=0))
self.scrape_prometheus_var('dp_dot1x_failure', any_labels=True, default=0))
self.assertEqual(
1,
self.scrape_prometheus_var('dp_dot1x_logoff', default=0))
self.scrape_prometheus_var('port_dot1x_success', any_labels=True, default=0))
self.assertEqual(
1,
self.scrape_prometheus_var('port_dot1x_logoff', labels={'port': 1}, default=0))
0,
self.scrape_prometheus_var('port_dot1x_failure', any_labels=True, default=0))
self.assertIn('Success', tcpdump_txt)
self.assertIn('logoff', tcpdump_txt)
# TODO check prometheus dp/port_dot1x_logoff once logoff_handler implemented on chewie side.

def wpa_supplicant_callback(self, and_logoff):
wpa_ctrl_path = os.path.join(
Expand All @@ -314,100 +299,36 @@ def wpa_supplicant_callback(self, and_logoff):
break
time.sleep(1)
self.assertEqual(eap_state, 'SUCCESS')
self.wait_until_matching_flow(
{'eth_src': self.eapol_host.MAC(), 'in_port': 1}, table_id=0)

self.eapol_host.cmd('wpa_cli -p %s logoff' % wpa_ctrl_path)

for i in range(10):
if not self.matching_flow_present(
{'eth_src': self.eapol_host.MAC(), 'in_port': 1}, table_id=0):
break
time.sleep(1)
else:
self.fail('authentication flow was not removed.')

def wait_for_radius(self, radius_log_path, timeout=10):
for i in range(timeout):
if os.path.exists(radius_log_path):
break
time.sleep(1)
else:
self.fail('could not open radius log after %d seconds' % timeout)

with open(radius_log_path, 'r') as log:
while True:
line = log.readline()
if not line:
time.sleep(1)
continue
if line.strip() == 'Ready to process requests.':
return

def start_freeradius(self):
with open('/etc/freeradius/users', 'w') as f:
f.write('user Cleartext-Password := "microphone"')

with open('/etc/freeradius/clients.conf', 'w') as f:
f.write('''client localhost {
ipaddr = 127.0.0.1
secret = SECRET
}''')

radius_log_path = '%s/radius.log' % self.tmpdir
shutil.copytree('/etc/freeradius/', '%s/freeradius' % self.tmpdir)
os.system('chmod o+rx %s' % self.root_tmpdir)
os.system('chown -R root:freerad %s/freeradius/*' % self.tmpdir)
os.system('chown root:freerad %s/freeradius' % self.tmpdir)

with open('%s/freeradius/radiusd.conf' % self.tmpdir, 'r+') as radiusd_file:
config = radiusd_file.read()
radiusd_file.seek(0)
radiusd_file.truncate()
new_config = config.replace('port = 0', 'port = %d' % self.radius_port, 2)
radiusd_file.write(new_config)

self.nfv_host.cmd('freeradius -sxx -l %s -d %s/freeradius &' % (radius_log_path, self.tmpdir))

self.freeradius_pid = self.nfv_host.lastPid
self.wait_for_radius(radius_log_path)
return radius_log_path


class FaucetSingle8021XFailureTest(FaucetSingle8021XSuccessTest):
class FaucetUntagged8021XFailureTest(FaucetUntagged8021XSuccessTest):
"""Failure due to incorrect identity/password"""

wpasupplicant_conf = """
ap_scan=0
network={
key_mgmt=IEEE8021X
eap=MD5
identity="user"
identity="user@example.com"
password="wrongpassword"
}
"""

def test_untagged(self):
tcpdump_txt = self.try_8021x(and_logff=False)
self.assertIn('Failure', tcpdump_txt)
faucet_log = self.env['faucet']['FAUCET_LOG']
with open(faucet_log, 'r') as log:
faucet_log_txt = log.read()
self.assertNotIn('Successful auth', faucet_log_txt)
self.assertEqual(
0,
self.scrape_prometheus_var('dp_dot1x_success', default=0))
self.scrape_prometheus_var('dp_dot1x_success', labels={'port': 1}, default=0))
self.assertEqual(
0,
self.scrape_prometheus_var('port_dot1x_success', labels={'port': 1}, default=0))
self.assertEqual(
0,
self.scrape_prometheus_var('dp_dot1x_logoff', default=0))
self.assertEqual(
0,
self.scrape_prometheus_var('port_dot1x_logoff', labels={'port': 1}, default=0))
self.assertEqual(
1,
self.scrape_prometheus_var('dp_dot1x_failure', default=0))
self.assertEqual(
1,
self.scrape_prometheus_var('port_dot1x_failure', labels={'port': 1}, default=0))
# TODO add prometheus dp/port_dot1x_failure check once failure handler is implemented on chewie side.


class FaucetUntaggedRandomVidTest(FaucetUntaggedTest):
Expand Down

0 comments on commit 6220b57

Please sign in to comment.