Example #1
0
    def prepare(self):
        """Prepare to handler reply."""

        self.set_header('Content-Type', 'application/json')

        # get requests do not require authentication
        if self.request.method == "GET":
            return

        accounts_manager = srv_or_die("accountsmanager")
        projects_manager = srv_or_die("projectsmanager")

        auth_header = self.request.headers.get('Authorization')

        if auth_header is None or not auth_header.startswith('Basic '):
            self.set_header('WWW-Authenticate', 'Basic realm=Restricted')
            self.send_error(401, message="Missing authorization header")
            return

        auth_bytes = bytes(auth_header[6:], 'utf-8')
        auth_decoded = base64.b64decode(auth_bytes).decode()
        username, password = auth_decoded.split(':', 2)

        # account does not exists
        if not accounts_manager.check_permission(username, password):
            self.send_error(401,
                            message="Invalid username/password combination")
            return

        account = accounts_manager.accounts[username]

        # root can do everything
        if account.username == "root":
            return

        # check if logged user is accessing his/her own account
        if self.request.uri.startswith("/api/v1/accounts"):

            pattern = re.compile("/api/v1/accounts/([a-zA-Z0-9:-]*)/?")
            match = pattern.match(self.request.uri)

            if match and match.group(1):
                username = match.group(1)
                if username == account.username:
                    return

        # check if logged user is accessing one of his/her projects
        if self.request.uri.startswith("/api/v1/projects"):

            pattern = re.compile("/api/v1/projects/([a-zA-Z0-9-]*)/?")
            match = pattern.match(self.request.uri)

            if match and match.group(1):
                project_id = UUID(match.group(1))
                if project_id in projects_manager.projects:
                    project = projects_manager.projects[project_id]
                    if account.username == project.owner:
                        return

        self.send_error(401, message="URI not authorized")
Example #2
0
    def start_service(self, service_id, name, params, storage=None):
        """Start a service."""

        # wait we are trying to start a service that already exists, abort
        if service_id in self.services:
            raise ValueError("Service %s is already running" % service_id)

        # this will look for the launch method and call it
        self.manager.log.info("Loading service: %s (%s)", name, service_id)
        self.manager.log.info("  - params: %s", params)

        service = self.load_service(service_id, name, params)

        # add to service list
        self.services[service.service_id] = service

        # set storage
        service.set_storage(storage)

        # register handlers
        for handler in service.HANDLERS:
            api_manager = srv_or_die("apimanager")
            api_manager.register_handler(handler)
            handler.service = service

        # start service
        self.manager.log.info("Starting service: %s (%s)", name, service_id)
        service.start()

        return service
    def update_vaps(self):
        """Update active VAPs."""

        for project in srv_or_die("projectsmanager").projects.values():

            # project does not have wifi_props
            if not project.wifi_props:
                continue

            # project does not use shared VAPs
            if project.wifi_props.bssid_type == T_BSSID_TYPE_UNIQUE:
                continue

            for block in self.device.blocks.values():

                bssid = project.generate_bssid(block.hwaddr)

                # vap has already been created
                if bssid in self.manager.vaps:
                    continue

                vap = VAP(bssid, block, project.wifi_props.ssid)

                self.send_add_vap(vap)

                self.manager.vaps[bssid] = vap
    def create(self, desc, project_id, owner, wifi_props=None, lte_props=None,
               lora_props=None):
        """Create new project."""

        if project_id in self.projects:
            raise ValueError("Project %s already defined" % project_id)

        accounts_manager = srv_or_die("accountsmanager")

        if owner not in accounts_manager.accounts:
            raise KeyError("Username %s not found" % owner)

        project = Project(project_id=project_id, desc=desc, owner=owner)

        if wifi_props:
            project.wifi_props = EmbeddedWiFiProps(**wifi_props)

        if lte_props:
            project.lte_props = EmbeddedLTEProps(**lte_props)

        if lora_props:
            project.lora_props = EmbeddedLoraProps(**lora_props)

        project.save()

        self.projects[project_id] = project

        project.upsert_wifi_slice(slice_id=0)

        project.upsert_lte_slice(slice_id=0)

        self.projects[project_id].start_services()

        return self.projects[project_id]
Example #5
0
    def __init__(self, *args, **kwargs):

        super().__init__(*args, **kwargs)

        # List of services in this Env/Project
        self.services = {}

        # Save pointer to EnvManager
        self.manager = srv_or_die("envmanager")
Example #6
0
    def blocks(self, blocks):
        """Assign a list of block to the LVAP.

        Assign a list of blocks to the LVAP. Accepts as input either a list or
        a ResourceBlock. If the list has more than one ResourceBlocks, then the
        first one is assigned to the downlink and the remaining are assigned
        to the uplink.

        Args:
            blocks: A list of ResourceBlocks or a ResourceBlock
        """

        if self.pending:
            raise ValueError("Handover in progress")

        if not blocks:
            return

        if isinstance(blocks, list):
            pool = blocks
        elif isinstance(blocks, ResourceBlock):
            pool = []
            pool.append(blocks)
        else:
            raise TypeError("Invalid type: %s" % type(blocks))

        for block in pool:
            if not isinstance(block, ResourceBlock):
                raise TypeError("Invalid type: %s" % type(block))

        # If LVAP is associated to a shared tenant, then reset LVAP
        project = srv_or_die("projectsmanager").load_project_by_ssid(self.ssid)

        if project and project.wifi_props and \
                project.wifi_props.bssid_type == prj.T_BSSID_TYPE_SHARED:

            # check if tenant is available at target block
            bssid = project.generate_bssid(pool[0].hwaddr)

            # if not ignore request
            if bssid not in project.vaps:
                return

            # otherwise reset lvap
            self.ssid = None
            self.association_state = False
            self.authentication_state = False

        # save target blocks
        self.target_blocks = pool

        if self.state is None:
            self.state = PROCESS_SPAWNING
        elif self.state == PROCESS_RUNNING:
            self.state = PROCESS_REMOVING
        else:
            IOError("Setting blocks on invalid state: %s" % self.state)
Example #7
0
    def ueqs(self):
        """Return the UEs."""

        if not self.lte_props:
            return {}

        ueqs = {
            k: v
            for k, v in srv_or_die("vbspmanager").ueqs.items()
            if v.plmnid == self.lte_props.plmnid
        }

        return ueqs
Example #8
0
    def vaps(self):
        """Return the VAPs."""

        if not self.wifi_props:
            return {}

        vaps = {
            k: v
            for k, v in srv_or_die("lvappmanager").vaps.items()
            if v.ssid == self.wifi_props.ssid
        }

        return vaps
    def update_slices(self):
        """Update active Slices."""

        # send slices configuration
        for project in srv_or_die("projectsmanager").projects.values():

            # project does not have wifi_props
            if not project.wifi_props:
                continue

            for slc in project.wifi_slices.values():
                for block in self.device.blocks.values():
                    self.device.connection.send_set_slice(project, slc, block)
Example #10
0
    def post(self):
        """Process login credentials."""

        username = self.get_argument("username", "")
        password = self.get_argument("password", "")

        accounts_manager = srv_or_die("accountsmanager")

        if accounts_manager.check_permission(username, password):
            self.set_secure_cookie("username", username)
            self.redirect("/index.html")
        else:
            self.clear_cookie("username")
            self.redirect("/auth/login?error=Wrong credentials!")
Example #11
0
    def get_project(self):
        """Get the current project or return None if not project is set."""

        # check if a project has been selected
        project_id = self.get_secure_cookie("project_id")

        if not project_id:
            return None

        project_id = UUID(project_id.decode('UTF-8'))
        projects_manager = srv_or_die("projectsmanager")

        if project_id not in projects_manager.projects:
            self.clear_cookie("project_id")
            return None

        return projects_manager.projects[project_id]
Example #12
0
    def start_service(self,
                      service_id,
                      name,
                      params,
                      configuration=None,
                      callbacks=None):
        """Start a service."""

        # wait we are trying to start a service that already exists, abort
        if service_id in self.services:
            raise ValueError("Service %s is already running" % service_id)

        # this will look for the launch method and call it
        self.manager.log.info("Loading service: %s (%s)", name, service_id)
        self.manager.log.info(" - params: %s", params)

        service = self.load_service(service_id, name, params)

        if not service:
            self.manager.log.error("Unable to start service id %s name %s",
                                   service_id, name)
            return

        # add to service list
        self.services[service.service_id] = service

        # set configuration
        if configuration:
            for entry in configuration:
                setattr(service, entry, configuration[entry])

        # set callbacks
        if callbacks:
            service.callbacks = callbacks

        # register handlers
        for handler in service.HANDLERS:
            api_manager = srv_or_die("apimanager")
            api_manager.register_handler(handler)
            handler.service = service

        # start service
        self.manager.log.info("Starting service: %s (%s)", name, service_id)
        service.start()

        return service
    def _handle_slice_status_response(self, status):
        """Handle an incoming SLICE_STATUS_RESPONSE message."""

        iface_id = status.iface_id
        slice_id = str(status.slice_id)
        ssid = SSID(status.ssid)

        project = srv_or_die("projectsmanager").load_project_by_ssid(ssid)
        block = self.device.blocks[iface_id]

        if not project:
            self.log.warning("Slice status from unknown SSID %s", ssid)
            return

        if slice_id not in project.wifi_slices:
            self.log.warning("Slice %s not found. Removing slice.", slice_id)
            self.send_del_slice(project, int(slice_id), block)
            return

        slc = project.wifi_slices[slice_id]

        if slc.properties['quantum'] != status.quantum:
            if self.device.addr not in slc.devices:
                slc.devices[self.device.addr] = dict()
            slc.devices[self.device.addr]['quantum'] = status.quantum

        amsdu_aggregation = bool(status.flags.amsdu_aggregation)
        if slc.properties['amsdu_aggregation'] != amsdu_aggregation:
            if self.device.addr not in slc.devices:
                slc.devices[self.device.addr] = dict()
            slc.devices[self.device.addr]['amsdu_aggregation'] = \
                amsdu_aggregation

        if slc.properties['sta_scheduler'] != status.sta_scheduler:
            if self.device.addr not in slc.devices:
                slc.devices[self.device.addr] = dict()
            slc.devices[self.device.addr]['sta_scheduler'] = \
                status.sta_scheduler

        project.save()
        project.refresh_from_db()

        self.log.info("Slice status: %s", slc)
Example #14
0
    def get(self):
        """Set the active project."""

        username = self.get_secure_cookie("username").decode('UTF-8')

        # if root deselect project
        if username == "root":
            self.clear_cookie("project_id")
            self.redirect('/')
            return

        # check if the project id is in the URL
        project_id = self.get_argument("project_id", None)

        # reset project selected
        if not project_id:
            self.clear_cookie("project_id")
            self.redirect('/')
            return

        try:

            # set project
            project_id = UUID(project_id)
            projects_manager = srv_or_die("projectsmanager")
            project = projects_manager.projects[project_id]

            if project.owner != username:
                self.clear_cookie("project_id")
                self.redirect('/')
                return

            self.set_secure_cookie("project_id", str(project.project_id))

        except KeyError:
            self.clear_cookie("project_id")

        except ValueError:
            self.clear_cookie("project_id")

        self.redirect('/')
Example #15
0
    def get(self, args=None):
        """Render index page."""

        try:

            username = self.get_secure_cookie("username").decode('UTF-8')
            accounts_manager = srv_or_die("accountsmanager")
            account = accounts_manager.accounts[username]

            page = "index.html" if not args else "%s.html" % args

            self.render(page,
                        username=account.username,
                        password=account.password,
                        name=account.name,
                        email=account.email,
                        project=self.get_project())

        except KeyError as ex:
            self.send_error(404, message=str(ex))

        except ValueError as ex:
            self.send_error(400, message=str(ex))
    def _handle_vap_status_response(self, status):
        """Handle an incoming STATUS_VAP message."""

        bssid = EtherAddress(status.bssid)
        ssid = SSID(status.ssid)

        project = srv_or_die("projectsmanager").load_project_by_ssid(ssid)

        if not project:
            self.log.warning("Unable to find SSID %s", ssid)
            self.send_del_vap(bssid)
            return

        # If the VAP does not exists, then create a new one
        if bssid not in self.manager.vaps:

            incoming = self.device.blocks[status.iface_id]

            self.manager.vaps[bssid] = VAP(bssid, incoming,
                                           project.wifi_props.ssid)

        vap = self.manager.vaps[bssid]

        self.log.info("VAP status: %s", vap)
    def _handle_auth_request(self, request):
        """Handle an incoming AUTH_REQUEST message."""

        sta = EtherAddress(request.sta)

        if sta not in self.manager.lvaps:
            self.log.info("Auth request from unknown LVAP %s", sta)
            return

        lvap = self.manager.lvaps[sta]

        incoming_bssid = EtherAddress(request.bssid)

        # The request bssid is the lvap current bssid, then just reply
        if lvap.bssid == incoming_bssid:
            lvap.bssid = incoming_bssid
            lvap.authentication_state = True
            lvap.association_state = False
            lvap.ssid = None
            lvap.commit()
            self.send_auth_response(lvap)
            return

        # Otherwise check if the requested BSSID belongs to a unique tenant
        for project in srv_or_die("projectsmanager").projects.values():

            if not project.wifi_props:
                continue

            if project.wifi_props.bssid_type == T_BSSID_TYPE_SHARED:
                continue

            bssid = project.generate_bssid(lvap.addr)

            if bssid == incoming_bssid:
                lvap.bssid = incoming_bssid
                lvap.authentication_state = True
                lvap.association_state = False
                lvap.ssid = None
                lvap.commit()
                self.send_auth_response(lvap)
                return

        # Finally check if this is a shared bssid
        for project in srv_or_die("projectsmanager").projects.values():

            if not project.wifi_props:
                continue

            if project.wifi_props.bssid_type == T_BSSID_TYPE_UNIQUE:
                continue

            if incoming_bssid in project.vaps:
                lvap.bssid = incoming_bssid
                lvap.authentication_state = True
                lvap.association_state = False
                lvap.ssid = None
                lvap.commit()
                self.send_auth_response(lvap)
                return

        self.log.info("Auth request from unknown BSSID %s", incoming_bssid)
Example #18
0
    def vaps(self):
        """Return the VAPs."""

        return srv_or_die("lvappmanager").vaps
Example #19
0
    def wtps(self):
        """Return the WTPs."""

        return srv_or_die("lvappmanager").devices
Example #20
0
    def __init__(self, *args, **kwargs):

        super().__init__(*args, **kwargs)

        # Save pointer to ProjectManager
        self.manager = srv_or_die("projectsmanager")
Example #21
0
 def lnss(self):
     """Return LNSs registered in this project context."""
     lnspd_manager = srv_or_die("lnspdmanager")
     return lnspd_manager.lnss
Example #22
0
 def lenddevs(self):
     """Return lEndDevs registered in this project context."""
     lnsp_manager = srv_or_die("lnspmanager")
     return lnsp_manager.lenddevs
Example #23
0
 def lgtws(self):
     """Return lGTWs registered in this project context."""
     lnsp_manager = srv_or_die("lnspmanager")
     return lnsp_manager.lgtws
Example #24
0
    def query(self, query):
        """Do a query to time-series manager."""

        ts_manager = srv_or_die("tsmanager")
        return ts_manager.query(query)
    def _handle_assoc_request(self, request):
        """Handle an incoming ASSOC_REQUEST message."""

        sta = EtherAddress(request.sta)

        ht_caps = request.flags.ht_caps
        ht_caps_info = dict(request.ht_caps_info)
        del ht_caps_info['_io']

        if sta not in self.manager.lvaps:
            self.log.info("Assoc request from unknown LVAP %s", sta)
            return

        lvap = self.manager.lvaps[sta]

        incoming_bssid = EtherAddress(request.bssid)

        if lvap.bssid != incoming_bssid:
            self.log.info("Assoc request for invalid BSSID %s", incoming_bssid)
            return

        incoming_ssid = SSID(request.ssid)

        # Check if the requested SSID is from a unique project
        for project in srv_or_die("projectsmanager").projects.values():

            if not project.wifi_props:
                continue

            if project.wifi_props.bssid_type == T_BSSID_TYPE_SHARED:
                continue

            bssid = project.generate_bssid(lvap.addr)

            if bssid != incoming_bssid:
                self.log.info("Invalid BSSID %s", incoming_bssid)
                continue

            if project.wifi_props.ssid == incoming_ssid:
                lvap.bssid = incoming_bssid
                lvap.authentication_state = True
                lvap.association_state = True
                lvap.ssid = incoming_ssid
                lvap.ht_caps = ht_caps
                lvap.ht_caps_info = ht_caps_info
                lvap.commit()
                self.send_assoc_response(lvap)
                return

        # Check if the requested SSID is from a unique project
        for project in srv_or_die("projectsmanager").projects.values():

            if not project.wifi_props:
                continue

            if project.wifi_props.bssid_type == T_BSSID_TYPE_UNIQUE:
                continue

            if incoming_bssid not in project.vaps:
                self.log.info("Invalid BSSID %s", incoming_bssid)
                continue

            if project.wifi_props.ssid == incoming_ssid:
                lvap.bssid = incoming_bssid
                lvap.authentication_state = True
                lvap.association_state = True
                lvap.ssid = incoming_ssid
                lvap.ht_caps = ht_caps
                lvap.ht_caps_info = ht_caps_info
                lvap.commit()
                self.send_assoc_response(lvap)
                return

        self.log.info("Unable to find SSID %s", incoming_ssid)
    def _handle_probe_request(self, request):
        """Handle an incoming PROBE_REQUEST message."""

        # Get station
        sta = EtherAddress(request.sta)

        # Incoming
        incoming_ssid = SSID(request.ssid)
        iface_id = request.iface_id
        ht_caps = request.flags.ht_caps
        ht_caps_info = dict(request.ht_caps_info)
        del ht_caps_info['_io']

        block = self.device.blocks[request.iface_id]

        msg = "Probe request from %s ssid %s iface_id %u ht_caps %u"

        if not incoming_ssid:
            self.log.debug(msg, sta, "Broadcast", iface_id, ht_caps)
        else:
            self.log.debug(msg, sta, incoming_ssid, iface_id, ht_caps)

        # Check is station is in ACL of any networks
        networks = \
            srv_or_die("projectsmanager").get_available_ssids(sta, block)

        if not networks:
            self.log.debug("No SSID available at this device")
            return

        # If lvap does not exist then create it. Otherwise just refresh the
        # list of available networks
        if sta not in self.manager.lvaps:

            # spawn new LVAP
            self.log.info("Spawning new LVAP %s on %s", sta, self.device.addr)

            assoc_id = randint(1, 2007)

            lvap = LVAP(sta, assoc_id=assoc_id)
            lvap.networks = networks
            lvap.ht_caps = ht_caps
            lvap.ht_caps_info = ht_caps_info

            # this will trigger an LVAP ADD message
            lvap.blocks = block

            # save LVAP in the runtime
            self.manager.lvaps[sta] = lvap

            # Send probe response
            self.send_probe_response(lvap, incoming_ssid)

            return

        lvap = self.manager.lvaps[sta]

        # If this probe request is not coming from the same interface on which
        # this LVAP is currenly running then ignore the probe
        if lvap.blocks[0].block_id != iface_id:
            return

        # If LVAP is not running then ignore
        if not lvap.is_running():
            return

        # Update list of available networks
        lvap.networks = networks
        lvap.commit()

        # Send probe response
        self.send_probe_response(lvap, incoming_ssid)
Example #27
0
    def write_points(self, points):
        """Write points to time-series manager."""

        ts_manager = srv_or_die("tsmanager")
        ts_manager.write_points(points)
Example #28
0
    def vbses(self):
        """Return the VBSes."""

        return srv_or_die("vbspmanager").devices