Esempio n. 1
0
def admin_login(request):
    context = {}
    post_dict = request.POST.dict()

    if not is_registered():
        dendrite = Dendrite()
        try:
            dendrite.call('register', post_dict)
        except RequestTimeout:
            context.update(
                form_errors={'non_field_errors': [_('Request timeout')]})
        except RequestError as e:
            if e.errors:
                context.update(form_errors=e.errors)
            else:
                context.update(form_errors={'non_field_errors': [e.error_str]})
        else:
            # Registration succeeded -> redirect to same to avoid repost
            admin_session_login(request.session, post_dict['login'])
            return redirect('dashboard')
    else:
        # Authenticate admin
        login = post_dict.get('login', None)
        if login:
            admin = Administrator.get(login=login)
            if admin and admin.check_password(
                    request.POST.get('password', None)):
                admin_session_login(request.session, login)
                return redirect('dashboard')

        context['form_errors'] = [_('Invalid Credentials')]

    context.update(**post_dict)
    return dashboard(request, context)
Esempio n. 2
0
    async def poll(self, ip, timeout=10):
        ''' poll and cache result'''
        try:
            device_snmp = await asyncio.wait_for(self._poll(ip), timeout)
        except asyncio.TimeoutError:
            device_snmp = None

        if device_snmp is None:
            event = Event('runtime-failure', source='snmp', level='warning')
            event.add_data('ip', ip)
            event.notify()
            return

        # Try to find a cached device
        device_id = self.get_id_by_ip(ip)

        if not device_id and 'ports' in device_snmp:
            # Try to find cached device by mac
            for port in device_snmp['ports']:
                device_id = self.get_id_by_mac(port['mac'])
                if device_id:
                    break

        if device_id:
            cached_device = self.get_device_by_id(device_id)
        else:
            device_id = self.get_new_device_id()
            cached_device = None

        device_snmp['local_id'] = device_id

        # Update cached device if needed
        if cached_device != device_snmp:
            if cached_device is None or self.switch_has_changed(cached_device, device_snmp):
                # notify if has changed. Only send relevant keys
                Dendrite.publish_single('snmp', { k:v for k, v in device_snmp.items() if k not in IGNORE_SWITCH_KEYS })
            # cache the device, including dynamic fields like fw_mac
            with self.synapse.pipeline() as pipe:
                pipe.hset(self.DEVICE_SNMP_CACHE_PATH, device_id, device_snmp)
                pipe.hset(self.DEVICE_IP_SNMP_CACHE_PATH, ip, device_id)
                cached_macs = set()
                if cached_device:
                    for port in cached_device['ports']:
                        if port['mac']:
                            cached_macs.add(port['mac'])
                device_macs = set()
                for port in device_snmp['ports']:
                    if port['mac']:
                        device_macs.add(port['mac'])
                for mac in cached_macs - device_macs:  # macs not longer valid
                    pipe.hdel(self.DEVICE_MAC_SNMP_CACHE_PATH, mac)
                for mac in device_macs - cached_macs:  # new macs
                    pipe.hset(self.DEVICE_MAC_SNMP_CACHE_PATH, mac, device_id)
                pipe.execute()
        return device_snmp
Esempio n. 3
0
    def test_get(self):
        dummy = str(uuid4())
        self.dendrite.publish('test/get', dummy, retain=True)
        result = self.dendrite.get('test/get')

        self.assertEqual(result, dummy)

        Dendrite.publish_single('test/get', retain=True)

        time.sleep(1)

        with self.assertRaises(RequestTimeout):
            self.dendrite.get('test/get')
Esempio n. 4
0
    def test_notify_with_Dendrite(self):
        Dendrite = MagicMock()

        event = Event(event_type='test_event',
                      source='test',
                      dendrite=Dendrite())
        event.notify()

        self.assertEqual(event.dendrite.publish.call_count, 1)
Esempio n. 5
0
    def test_get_from_cb(self):
        get_result = []
        dummy = str(uuid4())

        def cb(data):
            self.dendrite.publish('test/get', dummy, retain=True)
            get_result.append(self.dendrite.get('test/get'))
            return 'Test OK: ' + data

        service = 'test/fct'
        self.dendrite.provide('test/fct', cb)

        params = str(uuid4())

        call_result = self.dendrite.call(service, params, timeout=5)

        self.assertEqual(call_result, 'Test OK: ' + params)
        self.assertEqual(get_result[0], dummy)

        Dendrite.publish_single('test/get', retain=True)
Esempio n. 6
0
    def __init__(self, dendrite=None):
        if dendrite is None:
            dendrite = Dendrite()
        self.dendrite = dendrite

        self.authentications = None
        self.provided_services = set()

        self.policy_template = Template(
            filename="/elan-agent/authentication/freeradius/policy")
        self.ldap_template = Template(
            filename="/elan-agent/authentication/freeradius/ldap-module")
        self.ad_template = Template(
            filename="/elan-agent/authentication/freeradius/ad-module")
        self.external_auth_template = Template('''
            update session-state {
                &ELAN-Auth-Provider := ${id}
            }
            external-auth {
                invalid = 1
                fail =  2
                reject = 3
                notfound = 4
                ok = return
                updated = return
            }
        ''')
        self.ldap_auth_template = Template('''
            update session-state {
                &ELAN-Auth-Provider := ${id}
            }
            ldap-auth-${id} {
                invalid = 1
                fail =  2
                reject = 3
                notfound = 4
                ok = return
                updated = return
            }
        ''')
        self.ad_auth_template = Template('''
            update session-state {
                &ELAN-Auth-Provider := ${id}
                &ELAN-AD-Auth-Provider := ${id}
            }
            ADldap {
                invalid = 1
                fail =  2
                reject = 3
                notfound = 4
                ok = return
                updated = return
            }
        ''')
Esempio n. 7
0
    def notify(self):
        data = {
                'type':        self.type,
                'source':      self.source,
                'level':       self.level,
                'timestamp':   datetime.datetime.utcfromtimestamp(self.timestamp).strftime('%Y-%m-%dT%H:%M:%SZ'),
                'data':        self.data,
        }

        if self.dendrite is None:
            return Dendrite.publish_single(self.EVENT_TOPIC, data)
        else:
            return self.dendrite.publish(self.EVENT_TOPIC, data)
Esempio n. 8
0
    def __init__(self, dendrite=None):
        if dendrite is None:
            self.dendrite = Dendrite()

        self.fw_mac_allowed_vlans = {}
        self.fw_mac_bridged_vlans = {}

        self.dendrite = dendrite
        self.synapse = Synapse()

        self.next_check = None
        self.check_authz_sema = threading.BoundedSemaphore()

        self.check_expired_authz()

        self.init_macs()
Esempio n. 9
0
    def __init__(self,
                 dendrite=None,
                 directory=DEFAULT_DIRECTORY,
                 prefix=DEFAULT_PREFIX,
                 delete_files=True,
                 loop=None):
        if dendrite is None:
            dendrite = Dendrite()
        if loop is None:
            loop = asyncio.get_event_loop()

        self.dendrite = dendrite
        self.directory = directory
        self.prefix = prefix
        self.delete_files = delete_files
        self.loop = loop
Esempio n. 10
0
class NetworkConfiguration:
    'Class to manipulate IP configuration and retrieve current status'
    dendrite = Dendrite()

    def get_current_ips(self, cidr=True):
        return self.get_current_ipv4(cidr=cidr)['ips'] + self.get_current_ipv6(
            cidr=cidr)['ips']

    def get_current_ipv4(self, cidr=True):
        current_ipv4 = self.dendrite.get_conf(IPv4_CURRENT_TOPIC) or {
            'ips': [],
            'gw': None,
            'dns': []
        }
        if not cidr:
            current_ipv4['ips'] = [
                ip.split('/')[0] for ip in current_ipv4['ips']
            ]

        return current_ipv4

    def get_ipv4_conf(self):
        return self.dendrite.get_conf(IPv4_CONF_TOPIC) or DEFAULT_IPv4_CONF

    def set_ipv4_conf(self, conf):
        self.dendrite.publish_conf(IPv4_CONF_TOPIC, conf)

    def get_current_ipv6(self, cidr=True):
        current_ipv6 = self.dendrite.get_conf(IPv6_CURRENT_TOPIC) or {
            'ips': [],
            'gw': None,
            'dns': []
        }
        if not cidr:
            current_ipv6['ips'] = [
                ip.split('/')[0] for ip in current_ipv6['ips']
            ]

        return current_ipv6

    def get_ipv6_conf(self):
        return self.dendrite.get_conf(IPv6_CONF_TOPIC) or DEFAULT_IPv6_CONF

    def set_ipv6_conf(self, conf):
        self.dendrite.publish_conf(IPv6_CONF_TOPIC, conf)
#!/usr/bin/env python3

from elan.authentication import AuthenticationProvider
from elan.neuron import Dendrite

if __name__ == "__main__":

    dendrite = Dendrite()
    provider = AuthenticationProvider(dendrite=dendrite)

    
    dendrite.subscribe_conf('authentication', cb=provider.new_authentication_conf)

    dendrite.wait_complete()
                    pipe.set(VLAN_LOCAL_INDEX_INDEX_PATH, index)
                    pipe.hset(VLAN_LOCAL_INDEX_PATH, nic, index)

            synapse.transaction(safe_index, VLAN_LOCAL_INDEX_INDEX_PATH)
            index = synapse.hget(VLAN_LOCAL_INDEX_PATH, nic)
        return index


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--default-conf-only",
                        help="just generate default configuration if needed",
                        action="store_true")
    args = parser.parse_args()

    dendrite = Dendrite()

    try:
        vlans = dendrite.get_conf('vlans', timeout=5)
    except ConnectionFailed:
        vlans = None

    if vlans is None:
        # Default vlan conf: first 2 interfaces bridged
        default_vlans = []
        count = 0
        for interface in physical_ifaces():
            count += 1
            default_vlans.append({'interface': interface})
            if count == 2:
                break
Esempio n. 13
0
class AxonMapper:
    def __init__(self):
        self.dendrite = Dendrite()

    def run(self):
        configure_axon()

        self.dendrite.provide('register', self.register)
        self.dendrite.provide('check-connectivity', self.check_connectivity)
        self.dendrite.provide('guest-request', self.guest_request)
        self.dendrite.subscribe('notify-knowledge', self.notify_knowledge)

        self.dendrite.wait_complete()

    def notify_knowledge(self, info):
        if 'sessions' in info:
            session.notify_current_sessions()
        if 'hostnames' in info:
            device.notify_known_hostnames()
        if 'fingerprints' in info:
            device.notify_known_fingerprints()

    def guest_request(self, request):
        response = self.dendrite.call('elan-center/guest-request', request)

        if response['sponsor_email'] or response['fixed_recipients']:
            # send mail
            lookup = TemplateLookup(['/elan-agent/elan-center', '.'])
            html_template = Template(
                filename='/elan-agent/elan-center/guest-request-email.html',
                lookup=lookup)
            text_template = Template(
                filename='/elan-agent/elan-center/guest-request-email.txt',
                lookup=lookup)
            html = html_template.render(**response)
            text = text_template.render(**response)

            if not response['sponsor_email']:
                recipients = response['fixed_recipients']
                bcc_recipients = []
            else:
                recipients = [response['sponsor_email']]
                bcc_recipients = response['fixed_recipients']

            send_mail(recipients=recipients,
                      bcc_recipients=bcc_recipients,
                      html=html,
                      text=text,
                      mail_subject='Guest Request for Network Access')

        return response

    def check_connectivity(self, data=None):
        # check elan-center connectivity
        try:
            connected = bool(
                int(
                    self.dendrite.get(
                        '$SYS/broker/connection/{uuid}/state'.format(
                            uuid=synapse.get(AGENT_UUID_PATH)))))
        except RequestTimeout:
            connected = False

        if connected:
            return {'status': 'connected'}
        raise RequestError('Connection to ELAN Center down')

    def register(self, data):
        # settings.configure must have been called before this imort
        from django.contrib.auth.hashers import make_password

        # check elan-center connectivity
        self.check_connectivity()

        if not data:
            return {'status': 'available'}

        data['interfaces'] = sorted(utils.physical_ifaces())

        result = self.dendrite.call(
            'elan-center/register',
            data)  # raises RequestError if registration fails

        # store this admin in conf (should be overridien once Axon correctly configured)
        self.dendrite.publish_conf('administrator', [
            dict(login=data['login'], password=make_password(data['password']))
        ])

        synapse.set(ACCOUNT_ID_PATH, result['account'])
        synapse.set(AGENT_ID_PATH, result['id'])
        synapse.set(AGENT_UUID_PATH, result['uuid'])

        # delay configuration so that caller has time to receive response...
        def delayed_action():
            configure_axon()
            # wait axon really started.
            time.sleep(5.0)
            session.notify_current_sessions()
            device.notify_known_hostnames()
            device.notify_known_fingerprints()

        t = threading.Timer(3.0, delayed_action)
        t.start()

        return {'status': 'registered'}
Esempio n. 14
0
 def __init__(self):
     self.dendrite = Dendrite()
#!/usr/bin/env python3

from elan.captive_portal import GuestAccessManager
from elan.neuron import Dendrite

if __name__ == "__main__":
    dendrite = Dendrite()
    manager = GuestAccessManager()
    dendrite.subscribe_conf('guest-access/active-authorizations', manager.new_authorizations)

    
    dendrite.wait_complete()
#!/usr/bin/env python3

import logging

from elan.network import NetworkConfigurator
from elan.neuron import Dendrite

logging.basicConfig()

if __name__ == "__main__":
    dendrite = Dendrite()
    configurator = NetworkConfigurator()
    dendrite.subscribe_conf('ipv4', configurator.set_ipv4)
    dendrite.subscribe_conf('ipv6', configurator.set_ipv6)

    dendrite.wait_complete()
Esempio n. 17
0
LAST_SEEN_PATH = 'device:macs:last_seen'

SESSION_IDS_PATH = 'device:mac:session-ids'
SESSION_IDS_SEQUENCE_PATH = 'device:mac:session-ids:sequence'

MAC_PORT_PATH = 'device:mac:port'
MAC_LAST_PORT_PATH = 'device:mac:last_port'
PORT_MACS_PATH = 'device:{local_id}:port:{interface}'

MAC_VLANS_PATH = 'device:mac:{mac}:vlans'
MAC_VLAN_IPS_PATH = 'device:mac:{mac}:vlan:{vlan}:ips'
MAC_AUTH_SESSION_PATH = 'device:mac:{mac}:authentication'

synapse = Synapse()
dendrite = Dendrite()


def format_date(date):
    if not date:
        return datetime.datetime.utcnow().strftime('%Y-%m-%dT%H:%M:%SZ')
    else:
        return datetime.datetime.utcfromtimestamp(date).strftime(
            '%Y-%m-%dT%H:%M:%SZ')


def is_online(mac, vlan=None, ip=None):
    ''' returns True if Mac (optionnaly, on VLAN, with IP) is connected '''

    data = dict(mac=mac)
    if vlan is not None:
Esempio n. 18
0
class DendriteTest(unittest.TestCase):
    'These tests require a MQTT broker'

    def setUp(self):
        self.dendrite = Dendrite()
        self.mqtt = client.Client()
        self.mqtt.connect(Dendrite.MQTT_HOST, Dendrite.MQTT_PORT)

    def tearDown(self):
        self.dendrite.finish()
        self.mqtt.disconnect()

    def test_publish(self):
        topic1 = 'test/topic1'
        topic2 = 'test/topic2'
        msg1 = dict(test='OK')

        self.mqtt.subscribe(topic1)
        self.mqtt.subscribe(topic2)

        future = concurrent.futures.Future()

        def on_message(client, userdata, message):
            future.set_result(message)

        self.mqtt.on_message = on_message
        self.mqtt.loop_start()

        time.sleep(1)
        self.dendrite.publish(topic1, msg1)

        msg = future.result(2)

        self.assertEqual(json.loads(msg.payload.decode()), msg1)
        self.assertEqual(msg.topic, topic1)

        msg2 = dict(test=dict(OK='ok'), OK='ok')

        results = []
        future = concurrent.futures.Future()

        def on_message2(client, userdata, message):
            results.append(message)
            if len(results) == 3:
                future.set_result(True)

        self.mqtt.on_message = on_message2

        self.dendrite.publish(topic2, msg1)
        self.dendrite.publish(topic2, msg2)
        self.dendrite.publish(topic1, msg2)

        future.result(2)

        self.assertEqual(json.loads(results[0].payload.decode()), msg1)
        self.assertEqual(results[0].topic, topic2)

        self.assertEqual(json.loads(results[1].payload.decode()), msg2)
        self.assertEqual(results[1].topic, topic2)

        self.assertEqual(json.loads(results[2].payload.decode()), msg2)
        self.assertEqual(results[2].topic, topic1)

    def test_subscribe(self):
        topic1 = 'test/topic1'
        msg1 = dict(test='OK', msg=1)

        future = concurrent.futures.Future()

        def get_msg(msg, topic):
            future.set_result({ 'msg': msg, 'topic': topic})

        self.dendrite.subscribe(topic1, get_msg)

        time.sleep(1)

        self.mqtt.publish(topic1, json.dumps(msg1))

        result = future.result(2)
        self.assertEqual(result, {'msg': msg1, 'topic': topic1})

    def test_subscribe_1arg(self):
        topic1 = 'test/topic1'
        msg1 = dict(test='OK', msg=1)

        future = concurrent.futures.Future()

        def get_msg(msg):
            future.set_result(msg)

        self.dendrite.subscribe(topic1, get_msg)

        time.sleep(1)

        self.mqtt.publish(topic1, json.dumps(msg1))

        result = future.result(2)

        self.assertEqual(result, msg1)

    def test_subscribe_1arg_method(self):
        topic1 = 'test/topic1'
        msg1 = dict(test='OK', msg=1)

        future = concurrent.futures.Future()

        class Dummy:

            def get_msg(self, msg):
                future.set_result(msg)

        d = Dummy()
        self.dendrite.subscribe(topic1, d.get_msg)

        time.sleep(1)

        self.mqtt.publish(topic1, json.dumps(msg1))

        result = future.result(2)

        self.assertEqual(result, msg1)

    def test_call_and_provide(self):

        def cb(data):
            return 'Test OK: ' + data

        service = 'test/fct'
        self.dendrite.provide('test/fct', cb)

        params = str(uuid4())

        result = self.dendrite.call(service, params)

        self.assertEqual(result, 'Test OK: ' + params)

    def test_call_and_provide_exception(self):

        def cb(data):
            raise RequestError({'something': 'happened'}, 'Error: Something Happened !')

        service = 'test/fct2'
        self.dendrite.provide('test/fct2', cb)

        with self.assertRaises(RequestError) as cm:
            self.dendrite.call(service, {})
        self.assertEqual(cm.exception.error_str, 'Error: Something Happened !')
        self.assertEqual(cm.exception.errors, {'something': 'happened'})

    def test_get(self):
        dummy = str(uuid4())
        self.dendrite.publish('test/get', dummy, retain=True)
        result = self.dendrite.get('test/get')

        self.assertEqual(result, dummy)

        Dendrite.publish_single('test/get', retain=True)

        time.sleep(1)

        with self.assertRaises(RequestTimeout):
            self.dendrite.get('test/get')

    def test_get_from_cb(self):
        get_result = []
        dummy = str(uuid4())

        def cb(data):
            self.dendrite.publish('test/get', dummy, retain=True)
            get_result.append(self.dendrite.get('test/get'))
            return 'Test OK: ' + data

        service = 'test/fct'
        self.dendrite.provide('test/fct', cb)

        params = str(uuid4())

        call_result = self.dendrite.call(service, params, timeout=5)

        self.assertEqual(call_result, 'Test OK: ' + params)
        self.assertEqual(get_result[0], dummy)

        Dendrite.publish_single('test/get', retain=True)

    def test_subscribe_cb_exception_catch(self):
        event_instance = Mock()
        with patch('elan.event.ExceptionEvent', return_value=event_instance) as ExceptionEventMock:
            topic1 = 'test/topic1'
            msg1 = dict(test='OK', msg=1)

            future = concurrent.futures.Future()

            def get_msg(msg, topic):
                future.set_result({ 'msg': msg, 'topic': topic})
                raise KeyError("foo")

            self.dendrite.subscribe(topic1, get_msg)

            time.sleep(1)

            self.mqtt.publish(topic1, json.dumps(msg1))

            result = future.result(2)

            time.sleep(1)
            ExceptionEventMock.assert_called_with(source='dendrite-subscribe-cb')

        event_instance.notify.assert_called_once_with()
Esempio n. 19
0
        self.synapse = Synapse()

    def agent_conf_updated(self, conf):
        conf_changed = False

        for key in self.KEYS:
            if self.conf.get(key, {}) != conf[key]:
                self.conf[key] = conf[key]
                conf_changed = True

                # save credentials for other program use...
                if key == 'credentials':
                    self.synapse.set(SNMP_DEFAULT_CREDENTIALS_PATH, conf[key])

        if conf_changed:
            # Grab template
            snmp_template = Template(filename="/elan-agent/nac/snmp/snmptrapd.conf")

            with open ("/etc/snmp/snmptrapd.conf", "w") as server_file:
                server_file.write(snmp_template.render(**self.conf))

            restart_service('elan-snmp-notification-receiver')


if __name__ == "__main__":
    dendrite = Dendrite()
    conf = SnmpConfigurator()
    dendrite.subscribe_conf('snmp', conf.agent_conf_updated)

    dendrite.wait_complete()
Esempio n. 20
0
#!/usr/bin/env python3

from elan.nac.manager import MacAuthorizationManager
from elan.nac import AUTHORIZATION_CHANGE_TOPIC, CHECK_AUTHZ_PATH
from elan.session import MAC_SESSION_TOPIC
from elan.neuron import Dendrite

if __name__ == "__main__":
    dendrite = Dendrite()
    manager = MacAuthorizationManager(dendrite=dendrite)

    def handle_disconnection(data):
        # we are only interested in deconnections
        if 'end' in data:
            manager.handle_disconnection(data['mac'])

    dendrite.subscribe(AUTHORIZATION_CHANGE_TOPIC,
                       manager.handle_authz_changed)
    dendrite.subscribe(MAC_SESSION_TOPIC, handle_disconnection)
    dendrite.subscribe(CHECK_AUTHZ_PATH, manager.check_authz)

    dendrite.wait_complete()
Esempio n. 21
0
#!/usr/bin/env python3

from elan.ids import generate_suricata_conf
from elan.neuron import Dendrite
from elan.utils import reload_service


def ip_conf_changed(*args, **kwargs):
    if generate_suricata_conf():
        reload_service('suricata')


if __name__ == "__main__":
    dendrite = Dendrite()
    dendrite.subscribe_conf('ipv4/current', ip_conf_changed)
    dendrite.subscribe_conf('ipv6/current', ip_conf_changed)

    dendrite.wait_complete()
Esempio n. 22
0
def dashboard(request, context=None):
    if context is None:
        context = {}

    dendrite = Dendrite()

    registered = is_registered()

    try:
        # will raise error if not connected
        dendrite.call('check-connectivity', timeout=2)
        is_connected = True
        connectivity_error = ''
    except RequestTimeout:
        is_connected = None  # Unknown
        connectivity_error = 'Connectivity check not implemented'
    except RequestError as e:
        is_connected = False
        connectivity_error = e.error_str

    registration_available = False
    registration_error = ''
    if not registered:
        try:
            dendrite.call('register', timeout=2)
            registration_available = True
        except RequestTimeout:
            registration_available = False
            registration_error = 'Registration service not implemented'
        except RequestError as e:
            registration_available = False
            registration_error = e.error_str

    current_ipv4 = netconf.get_current_ipv4(cidr=True)
    current_ipv4['ips'] = [
        *map(
            lambda x: dict(zip(['address', 'prefix_length'], x.split('/', 1))),
            current_ipv4['ips'])
    ]
    current_ipv6 = netconf.get_current_ipv6(cidr=True)
    current_ipv6['ips'] = [
        *map(
            lambda x: dict(zip(['address', 'prefix_length'], x.split('/', 1))),
            current_ipv6['ips'])
    ]

    context.update(
        registration_available=registration_available,
        registration_error=registration_error,
        is_admin=bool(request.session.get('admin', False)),
        is_connected=is_connected,
        connectivity_error=connectivity_error,
        is_registered=registered,
        interfaces={
            iface: {
                'up': is_iface_up(iface)
            }
            for iface in physical_ifaces()
        },
        ipv4=current_ipv4,
        ipv6=current_ipv6,
    )
    if not context.get('location', ''):
        # TODO:
        context['location'] = ''

    ip_conf = NetworkConfiguration()
    if not context.get('ipv4_form', None):
        context['ipv4_form'] = Ip4ConfigurationForm(
            initial=ip_conf.get_ipv4_conf())
    if not context.get('ipv6_form', None):
        context['ipv6_form'] = Ip6ConfigurationForm(
            initial=ip_conf.get_ipv6_conf())

    return render(request, 'captive-portal/dashboard.html', context)
Esempio n. 23
0
class NetworkConfigurator:
    'Class that does apply the network configuration. Use NetworkConfiguration class to manipulate Network Configuration'
    ip_conf_template = '/elan-agent/network/netplan-ip-conf.yaml'
    vlans_conf_template = '/elan-agent/network/netplan-vlans.yaml'
    ip_conf_file = '/etc/netplan/elan-ip-conf.yaml'
    vlans_conf_file = '/etc/netplan/elan-vlans.yaml'
    dendrite = Dendrite()

    def __init__(self):
        self.load_configuration()
        self.apply_ip_conf()

    def load_configuration(self):
        try:
            self.ipv4 = self.dendrite.get_conf(IPv4_CONF_TOPIC)
            if self.ipv4 is None:
                self.ipv4 = DEFAULT_IPv4_CONF

            self.ipv6 = self.dendrite.get_conf(IPv6_CONF_TOPIC)
            if self.ipv6 is None:
                self.ipv6 = DEFAULT_IPv6_CONF
        except ConnectionFailed:
            if os.path.exists(self.ip_conf_file):
                self.ipv4 = None
                self.ipv6 = None
            else:
                self.ipv4 = DEFAULT_IPv4_CONF
                self.ipv6 = DEFAULT_IPv6_CONF

    def set_ipv4(self, kwargs):
        self.ipv4 = kwargs
        self.apply_ip_conf()

    def set_ipv6(self, kwargs):
        self.ipv6 = kwargs
        self.apply_ip_conf()

    def apply_ip_conf(self):
        self.generate_ip_conf()
        self.reload()

    def generate_ip_conf(self):
        if self.ipv4 is not None and self.ipv6 is not None:
            self.generate_ip_conf_files(ipv4_conf=self.ipv4,
                                        ipv6_conf=self.ipv6)

    @classmethod
    def generate_ip_conf_files(cls, ipv4_conf, ipv6_conf):
        template = Template(filename=cls.ip_conf_template)

        with open(cls.ip_conf_file, 'w') as conf_file:
            conf_file.write(
                template.render(ipv4=ipv4_conf,
                                ipv6=ipv6_conf,
                                bridge_name=BRIDGE_NAME))

    @classmethod
    def vlans_conf_files_exists(cls):
        return os.path.exists(cls.vlans_conf_file)

    @classmethod
    def generate_vlans_conf_files(cls, vlans):
        template = Template(filename=cls.vlans_conf_template)

        with open(cls.vlans_conf_file, 'w') as conf_file:
            conf_file.write(
                template.render(vlans=vlans, bridge_name=BRIDGE_NAME))

    @staticmethod
    def reload():
        subprocess.run(['netplan', 'apply'])
Esempio n. 24
0
 def setUp(self):
     self.dendrite = Dendrite()
     self.mqtt = client.Client()
     self.mqtt.connect(Dendrite.MQTT_HOST, Dendrite.MQTT_PORT)
#!/usr/bin/env python3

from elan.neuron import Dendrite

if __name__ == "__main__":
    dendrite = Dendrite()
    dendrite.run_conf_cacher()
Esempio n. 26
0
class NetworkMonitor:
    '''
    class that will monitor and interface and publish current configuration (IPs, default gateway, and DNS)
    '''
    dendrite = Dendrite()

    def __init__(self,
                 interface=BRIDGE_NAME,
                 ipv4_topic=IPv4_CURRENT_TOPIC,
                 ipv6_topic=IPv6_CURRENT_TOPIC):
        self.interface = interface

        self.ipv4_topic = ipv4_topic
        self.ipv6_topic = ipv6_topic

        self.current_ipv4 = self.dendrite.get_conf(self.ipv4_topic) or {
            'ips': [],
            'gw': None,
            'dns': []
        }
        self.current_ipv6 = self.dendrite.get_conf(self.ipv6_topic) or {
            'ips': [],
            'gw': None,
            'dns': []
        }

    def run(self):

        with IPRoute() as ipr:
            # Bind before we get current values so that is they changed, we will be notified.
            ipr.bind(groups=rtnl.RTNLGRP_IPV4_IFADDR | rtnl.RTNLGRP_IPV6_IFADDR
                     | rtnl.RTNLGRP_IPV4_ROUTE | rtnl.RTNLGRP_IPV6_ROUTE)

            # all current values and publich after
            self.check_ips(publish=False)
            self.check_gw4(publish=False)
            self.check_gw6(publish=False)
            self.check_dns(publish=False)

            self.publish_current_ipv4()
            self.publish_current_ipv6()

            # set monitoring of DNS (executed in another thread)
            observer = watchdog.observers.Observer()
            observer.schedule(self.FileChangeHandler(
                file=RESOLV_FILE,
                moved_cb=self.check_dns,
                created_cb=self.check_dns),
                              path=os.path.dirname(RESOLV_FILE),
                              recursive=False)

            # monitor network Changes
            while True:
                events = ipr.get()
                for event in events:
                    if event['event'] in ['RTM_NEWROUTE', 'RTM_DELROUTE']:
                        if event['family'] == socket.AF_INET:
                            self.check_gw4()
                        elif event['family'] == socket.AF_INET6:
                            self.check_gw6()

                    elif event['event'] in [
                            'RTM_NEWADDR', 'RTM_DELADDR'
                    ] and event['index'] == ipr.link_lookup(
                            ifname=self.interface)[0]:
                        self.check_ips(ipr)

    def check_gw4(self, publish=True):
        gw4 = self.get_gw4()
        if self.current_ipv4['gw'] != gw4:
            self.current_ipv4['gw'] = gw4
            if publish:
                self.publish_current_ipv4()

    def check_gw6(self, publish=True):
        gw6 = self.get_gw6()
        if self.current_ipv6['gw'] != gw6:
            self.current_ipv6['gw'] = gw6
            if publish:
                self.publish_current_ipv6()

    def check_ips(self, publish=True):
        ips = self.get_ips(self.interface)

        ipv4s = [ip for ip in ips if '.' in ip]
        if set(self.current_ipv4['ips']) != set(ipv4s):
            self.current_ipv4['ips'] = ipv4s
            if publish:
                self.publish_current_ipv4()

        ipv6s = [ip for ip in ips if ':' in ip]
        if set(self.current_ipv6['ips']) != set(ipv6s):
            self.current_ipv6['ips'] = ipv6s
            if publish:
                self.publish_current_ipv6()

    def check_dns(self, publish=True):
        dns = self.parse_resolvconf(RESOLV_FILE)

        dns4 = [d for d in dns if '.' in d]
        if dns4 != self.current_ipv4['dns']:
            self.current_ipv4['dns'] = dns4
            if publish:
                self.publish_current_ipv4()

        dns6 = [d for d in dns if ':' in d]
        if dns6 != self.current_ipv6['dns']:
            self.current_ipv6['dns'] = dns6
            if publish:
                self.publish_current_ipv6()

    class FileChangeHandler(FileSystemEventHandler):
        def __init__(self, file, created_cb, moved_cb):
            self.file = file
            self.created_cb = created_cb
            self.moved_cb = moved_cb

        def on_moved(self, event):
            if event.dest_path == self.file:
                self.moved_cb()

        def on_created(self, event):
            if event.src_path == self.file:
                self.created_cb()

    def get_ips(self, interface):
        ipr = IPRoute()

        ips = set()
        index = ipr.link_lookup(ifname=interface)[0]
        for entry in ipr.get_addr(index=index):
            for key, value in entry['attrs']:
                if key == 'IFA_ADDRESS':
                    ip = '{ip}/{mask}'.format(ip=value,
                                              mask=entry['prefixlen'])
                    ips.add(ip)
                break

        return ips

    def get_gw4(self):
        try:
            return resolver.query('_gateway', 'A')[0].address
        except:
            return None

    def get_gw6(self):
        try:
            return resolver.query('_gateway', 'AAAA')[0].address
        except:
            return None

    def parse_resolvconf(self, file=RESOLV_FILE):
        dns = []
        try:
            with open(file) as resolvconf:
                for line in resolvconf:
                    if line.startswith('nameserver '):
                        line = line.rstrip()
                        dns += [n for n in line.split()[1:] if n]
        except FileNotFoundError:
            pass

        return dns

    def publish_current_ipv4(self):
        self.dendrite.publish_conf(self.ipv4_topic, self.current_ipv4)

    def publish_current_ipv6(self):
        self.dendrite.publish_conf(self.ipv6_topic, self.current_ipv6)