Exemplo n.º 1
0
    def find_unused_port(start_port,
                         end_port,
                         host="127.0.0.1",
                         socket_type="TCP",
                         ignore_ports=[]):
        """
        Finds an unused port in a range.

        :param start_port: first port in the range
        :param end_port: last port in the range
        :param host: host/address for bind()
        :param socket_type: TCP (default) or UDP
        :param ignore_ports: list of port to ignore within the range
        """

        if end_port < start_port:
            raise HTTPConflict(
                text="Invalid port range {}-{}".format(start_port, end_port))

        if socket_type == "UDP":
            socket_type = socket.SOCK_DGRAM
        else:
            socket_type = socket.SOCK_STREAM

        last_exception = None
        for port in range(start_port, end_port + 1):
            if port in ignore_ports:
                continue
            try:
                if ":" in host:
                    # IPv6 address support
                    with socket.socket(socket.AF_INET6, socket_type) as s:
                        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                        s.bind(
                            (host, port
                             ))  # the port is available if bind is a success
                else:
                    with socket.socket(socket.AF_INET, socket_type) as s:
                        s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                        s.bind(
                            (host, port
                             ))  # the port is available if bind is a success
                return port
            except OSError as e:
                last_exception = e
                if port + 1 == end_port:
                    break
                else:
                    continue

        raise HTTPConflict(
            text=
            "Could not find a free port between {} and {} on host {}, last exception: {}"
            .format(start_port, end_port, host, last_exception))
Exemplo n.º 2
0
    def statistics(request, response):

        try:
            memory_total = psutil.virtual_memory().total
            memory_free = psutil.virtual_memory().available
            memory_used = memory_total - memory_free  # actual memory usage in a cross platform fashion
            swap_total = psutil.swap_memory().total
            swap_free = psutil.swap_memory().free
            swap_used = psutil.swap_memory().used
            cpu_percent = int(CpuPercent.get())
            load_average_percent = [
                int(x / psutil.cpu_count() * 100) for x in psutil.getloadavg()
            ]
            memory_percent = int(psutil.virtual_memory().percent)
            swap_percent = int(psutil.swap_memory().percent)
            disk_usage_percent = int(psutil.disk_usage('/').percent)
        except psutil.Error as e:
            raise HTTPConflict(text="Psutil error detected: {}".format(e))
        response.json({
            "memory_total": memory_total,
            "memory_free": memory_free,
            "memory_used": memory_used,
            "swap_total": swap_total,
            "swap_free": swap_free,
            "swap_used": swap_used,
            "cpu_usage_percent": cpu_percent,
            "memory_usage_percent": memory_percent,
            "swap_usage_percent": swap_percent,
            "disk_usage_percent": disk_usage_percent,
            "load_average_percent": load_average_percent
        })
Exemplo n.º 3
0
async def users_post(request: Request) -> Response:
    session_maker = request.app['db_session_manager']
    session: Session = session_maker()
    try:
        data = await request.json()

        if data:
            user = session.query(Users).filter_by(login=data['login']).first()
            if user:
                return HTTPConflict()

            user = UsersSchema().load(data, session=session)

            session.add(user)
            session.commit()
            return HTTPCreated(headers={
                'Location': f"/users/{user.login}",
                'Content-Type': 'application/json'
            },
                               body=json.dumps({'id': user.id}))
        else:
            return HTTPBadRequest()
    except Exception:
        session.rollback()
        raise
    finally:
        session.close()
Exemplo n.º 4
0
    def reserve_udp_port(self, port, project):
        """
        Reserve a specific UDP port number

        :param port: UDP port number
        :param project: Project instance
        """

        if port in self._used_udp_ports:
            raise HTTPConflict(
                text="UDP port {} already in use on host {}".format(
                    port, self._console_host))
        if port < self._udp_port_range[0] or port > self._udp_port_range[1]:
            raise HTTPConflict(
                text="UDP port {} is outside the range {}-{}".format(
                    port, self._udp_port_range[0], self._udp_port_range[1]))
        self._used_udp_ports.add(port)
        project.record_udp_port(port)
        log.debug("UDP port {} has been reserved".format(port))
Exemplo n.º 5
0
 def create_nio(request, response):
     docker_manager = Docker.instance()
     container = docker_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
     nio_type = request.json["type"]
     if nio_type != "nio_udp":
         raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
     nio = docker_manager.create_nio(request.json)
     yield from container.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio)
     response.set_status(201)
     response.json(nio)
Exemplo n.º 6
0
    async def start(request, response):

        vmware_manager = VMware.instance()
        vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
        if vm.check_hw_virtualization():
            pm = ProjectManager.instance()
            if pm.check_hardware_virtualization(vm) is False:
                raise HTTPConflict(text="Cannot start VM because hardware virtualization (VT-x/AMD-V) is already used by another software like VirtualBox or KVM (on Linux)")
        await vm.start()
        response.set_status(204)
    def start(request, response):

        vbox_manager = VirtualBox.instance()
        vm = vbox_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
        if (yield from vm.check_hw_virtualization()):
            pm = ProjectManager.instance()
            if pm.check_hardware_virtualization(vm) is False:
                raise HTTPConflict(text="Cannot start VM because hardware virtualization (VT-x/AMD-V) is already used by another software like VMware or KVM (on Linux)")
        yield from vm.start()
        response.set_status(204)
Exemplo n.º 8
0
    def create_nio(request, response):

        vmware_manager = VMware.instance()
        vm = vmware_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
        nio_type = request.json["type"]
        if nio_type != "nio_udp":
            raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
        nio = vmware_manager.create_nio(None, request.json)
        yield from vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio)
        response.set_status(201)
        response.json(nio)
Exemplo n.º 9
0
    def create_nio(request, response):

        iou_manager = IOU.instance()
        vm = iou_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
        nio_type = request.json["type"]
        if nio_type not in ("nio_udp", "nio_tap", "nio_generic_ethernet"):
            raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
        nio = iou_manager.create_nio(vm.iouyap_path, request.json)
        vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), int(request.match_info["port_number"]), nio)
        response.set_status(201)
        response.json(nio)
Exemplo n.º 10
0
    def start(request, response):

        qemu_manager = Qemu.instance()
        vm = qemu_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
        if sys.platform.startswith("linux") and qemu_manager.config.get_section_config("Qemu").getboolean("enable_kvm", True) \
                and "-no-kvm" not in vm.options:
            pm = ProjectManager.instance()
            if pm.check_hardware_virtualization(vm) is False:
                raise HTTPConflict(text="Cannot start VM with KVM enabled because hardware virtualization (VT-x/AMD-V) is already used by another software like VMware or VirtualBox")
        yield from vm.start()
        response.json(vm)
Exemplo n.º 11
0
    async def create_nio(request, response):

        vmware_manager = VMware.instance()
        vm = vmware_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
        nio_type = request.json["type"]
        if nio_type not in ("nio_udp", "nio_vmnet", "nio_nat", "nio_tap"):
            raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
        nio = vmware_manager.create_nio(request.json)
        await vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio)
        response.set_status(201)
        response.json(nio)
Exemplo n.º 12
0
    def create_nio(request, response):

        qemu_manager = Qemu.instance()
        vm = qemu_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
        nio_type = request.json["type"]
        if nio_type not in ("nio_udp", "nio_tap", "nio_nat"):
            raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
        nio = qemu_manager.create_nio(vm.qemu_path, request.json)
        yield from vm.adapter_add_nio_binding(int(request.match_info["adapter_number"]), nio)
        response.set_status(201)
        response.json(nio)
Exemplo n.º 13
0
    def create_nio(request, response):

        vpcs_manager = VPCS.instance()
        vm = vpcs_manager.get_node(request.match_info["node_id"], project_id=request.match_info["project_id"])
        nio_type = request.json["type"]
        if nio_type not in ("nio_udp", "nio_tap"):
            raise HTTPConflict(text="NIO of type {} is not supported".format(nio_type))
        nio = vpcs_manager.create_nio(request.json)
        yield from vm.port_add_nio_binding(int(request.match_info["port_number"]), nio)
        response.set_status(201)
        response.json(nio)
Exemplo n.º 14
0
 def write_settings(request, response):
     controller = Controller.instance()
     if controller.settings is None:  # Server is not loaded ignore settings update to prevent buggy client sync issue
         return
     controller.settings = request.json
     try:
         controller.save()
     except (OSError, PermissionError) as e:
         raise HTTPConflict(
             text="Can't save the settings {}".format(str(e)))
     response.json(controller.settings)
     response.set_status(201)
Exemplo n.º 15
0
    def start_capture(request, response):

        iou_manager = IOU.instance()
        vm = iou_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])
        adapter_number = int(request.match_info["adapter_number"])
        port_number = int(request.match_info["port_number"])
        pcap_file_path = os.path.join(vm.project.capture_working_directory(), request.json["capture_file_name"])

        if not vm.is_running():
            raise HTTPConflict(text="Cannot capture traffic on a non started VM")
        yield from vm.start_capture(adapter_number, port_number, pcap_file_path, request.json["data_link_type"])
        response.json({"pcap_file_path": str(pcap_file_path)})
Exemplo n.º 16
0
    def stop_capture(request, response):

        iou_manager = IOU.instance()
        vm = iou_manager.get_vm(request.match_info["vm_id"], project_id=request.match_info["project_id"])

        if not vm.is_running():
            raise HTTPConflict(text="Cannot capture traffic on a non started VM")

        adapter_number = int(request.match_info["adapter_number"])
        port_number = int(request.match_info["port_number"])
        yield from vm.stop_capture(adapter_number, port_number)
        response.set_status(204)
Exemplo n.º 17
0
    def find_unused_port(start_port,
                         end_port,
                         host="127.0.0.1",
                         socket_type="TCP",
                         ignore_ports=None):
        """
        Finds an unused port in a range.

        :param start_port: first port in the range
        :param end_port: last port in the range
        :param host: host/address for bind()
        :param socket_type: TCP (default) or UDP
        :param ignore_ports: list of port to ignore within the range
        """

        if end_port < start_port:
            raise HTTPConflict(
                text="Invalid port range {}-{}".format(start_port, end_port))

        last_exception = None
        for port in range(start_port, end_port + 1):
            if ignore_ports and (port in ignore_ports or port in BANNED_PORTS):
                continue

            try:
                PortManager._check_port(host, port, socket_type)
                if host != "0.0.0.0":
                    PortManager._check_port("0.0.0.0", port, socket_type)
                return port
            except OSError as e:
                last_exception = e
                if port + 1 == end_port:
                    break
                else:
                    continue

        raise HTTPConflict(
            text=
            "Could not find a free port between {} and {} on host {}, last exception: {}"
            .format(start_port, end_port, host, last_exception))
Exemplo n.º 18
0
    def reserve_tcp_port(self, port, project):
        """
        Reserve a specific TCP port number

        :param port: TCP port number
        :param project: Project instance
        """

        if port in self._used_tcp_ports:
            raise HTTPConflict(text="TCP port {} already in use on host".format(port, self._console_host))
        self._used_tcp_ports.add(port)
        project.record_tcp_port(port)
        log.debug("TCP port {} has been reserved".format(port))
        return port
Exemplo n.º 19
0
    def update_nio(request, response):

        builtin_manager = Builtin.instance()
        node = builtin_manager.get_node(
            request.match_info["node_id"],
            project_id=request.match_info["project_id"])
        adapter_number = int(request.match_info["adapter_number"])

        try:
            nio = node.nios[adapter_number]
        except KeyError:
            raise HTTPConflict(
                text="NIO `{}` doesn't exist".format(adapter_number))

        if "filters" in request.json and nio:
            nio.filters = request.json["filters"]
        yield from node.update_nio(int(request.match_info["port_number"]), nio)
        response.set_status(201)
        response.json(request.json)
Exemplo n.º 20
0
    async def put(self, request: Request) -> Response:
        """
        ---
        summary: Create a new user
        description:
        security:
            - Bearer Authentication: [users_manage]
            - X-API-Key Authentication: [users_manage]
            - Session Authentication: [users_manage]
        tags:
            - users
        requestBody:
            description: JSON containing the changes to the user and/or their username to find them
            required: true
            content:
                application/json:
                    schema:
                        type: object
                        properties:
                            username:
                                type: string
                                description: username of the user you want to modify
                                required: true
                            password:
                                type: string
                                description: unhashed password that will be hashed before being added to the user
                            cards:
                                oneOf:
                                    - type: array
                                      description: list of all cards that will be assigned to the user
                                      items:
                                        type: string
                                        format: mifare uid
                                        pattern: '^([0-9a-fA-F]{8}|([0-9a-fA-F]{14}|[0-9a-fA-F]{20})$'
                                    - type: string
                                      description: a single card that will be assigned to the user
                                      format: mifare uid
                                      pattern: '^([0-9a-fA-F]{8}|([0-9a-fA-F]{14}|[0-9a-fA-F]{20})$'
                            permissions:
                                oneOf:
                                    - type: array
                                      description: list of all permissions that the user will have
                                      items:
                                        type: string
                                        enum:
                                            - admin
                                            - enter
                                            - logs
                                            - users_read
                                            - users_manage
                                            - cards
                                    - type: string
                                      description: a single permission you want to give the user
                                      enum:
                                        - admin
                                        - enter
                                        - logs
                                        - users_read
                                        - users_manage
                                        - cards
                        example:
                            username: example
                            password: hunter2
                            cards:
                                - ABABABAB
                                - 12345678
                            permissions: enter
        responses:
            "200":
                description: A JSON document indicating success along with some information about the user
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/User'

            "401":
                description: A JSON document indicating error in request (user not authenticated)
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/Error'
            "403":
                description: A JSON document indicating error in request (user doesn't have permission to preform this action)
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/Error'
            "409":
                description: A JSON document indicating error in request (user already exists)
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/Error'
        """

        data = await request.json()
        permissions = data.get("permissions", [])
        if not isinstance(permissions, list):
            permissions = [permissions]
        await check_api_permissions(request, ["users_manage", *permissions])
        username = data.get("username", False)
        if not username:
            raise HTTPBadRequest(
                reason="no username provided",
                body=json.dumps(
                    {"Ok": False, "Error": "no username provided", "status_code": 401}
                ),
                content_type="application/json",
            )
        user = await user_exists(request.app, username)
        if user:
            raise HTTPConflict(
                reason="User with this username already exists",
                body=json.dumps(
                    {
                        "Ok": False,
                        "Error": "User with this username already exists",
                        "status_code": 404,
                    }
                ),
                content_type="application/json",
            )
        cards = data.get("cards", [])
        if not isinstance(cards, list):
            cards = [cards]
        uid = register_user(
            request.app, username, data.get("password", None), permissions, cards
        )
        user = find_user_by_uid(request.app, uid, ["username", "cards", "permissions"])
        return respond_with_json(
            {"Ok": True, "Error": None, "status_code": 200, "user": user}
        )
Exemplo n.º 21
0
 def check_version(request, response):
     if request.json["version"] != __version__:
         raise HTTPConflict(
             text="Client version {} differs with server version {}".format(
                 request.json["version"], __version__))
     response.json({"version": __version__})
Exemplo n.º 22
0
    async def put(self, request: Request) -> Response:
        """
        ---
        summary: Create multiple new users
        description:
        security:
            - Bearer Authentication: [users_manage]
            - X-API-Key Authentication: [users_manage]
            - Session Authentication: [users_manage]
        tags:
            - users
        requestBody:
            description: JSON containing a list of new user objects
            required: true
            content:
                application/json:
                    schema:
                        type: object
                        properties:
                            users:
                                type: array
                                items:
                                    type: object
                                    properties:
                                        username:
                                            type: string
                                            description: username of the user you want to modify
                                            required: true
                                        password:
                                            type: string
                                            description: unhashed password that will be hashed before being added to the user
                                        cards:
                                            description: a single card or list of cards that will be assigned to the user
                                            oneOf:
                                                - type: array
                                                  description: list of all cards that will be assigned to the user
                                                  items:
                                                    type: string
                                                    format: mifare uid
                                                    pattern: '^([0-9a-fA-F]{8}|([0-9a-fA-F]{14}|[0-9a-fA-F]{20})$'
                                                - type: string
                                                  description: a single card that will be assigned to the user
                                                  format: mifare uid
                                                  pattern: '^([0-9a-fA-F]{8}|([0-9a-fA-F]{14}|[0-9a-fA-F]{20})$'
                                        permissions:
                                            description: a single permission or list of permissions that the user will have (you need to have a permission to assign it to others)
                                            oneOf:
                                                - type: array
                                                  description: list of all permissions that the user will have
                                                  items:
                                                    type: string
                                                    enum:
                                                        - admin
                                                        - enter
                                                        - logs
                                                        - users_read
                                                        - users_manage
                                                        - cards
                                                - type: string
                                                  description: a single permission you want to give the user
                                                  enum:
                                                    - admin
                                                    - enter
                                                    - logs
                                                    - users_read
                                                    - users_manage
                                                    - cards
                        example:
                            users:
                                - username: example
                                  password: hunter2
                                  cards:
                                    - ABABABAB
                                    - 12345678
                                  permissions: enter
                                - username: example2
                                  password: hunter4
                                  cards: FFFFFFFF
                                  permissions:
                                    - enter
                                    - cards
                                    - users_read
        responses:
            "200":
                description: A JSON document indicating success along with some information about the user
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/User'

            "401":
                description: A JSON document indicating error in request (user not authenticated)
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/Error'
            "403":
                description: A JSON document indicating error in request (user doesn't have permission to preform this action)
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/Error'
            "409":
                description: A JSON document indicating error in request (user already exists)
                content:
                    application/json:
                        schema:
                            $ref: '#/components/schemas/Error'
        """

        data = await request.json()
        if isinstance(data.get("users", None), list):
            users = data["users"]
        elif isinstance(data.get("users", ""), str):
            users = [data.get("users", "")]
        else:
            raise HTTPBadRequest(
                reason="no users provided",
                body=json.dumps({
                    "Ok": False,
                    "Error": "no users provided",
                    "status_code": 401
                }),
                content_type="application/json",
            )
        permissions = set()
        for user in users:
            user_permissions = user.get("permissions", [])
            if not isinstance(user_permissions, list):
                user_permission = [user_permissions]
            permissions.update(set(user_permissions))
        await check_api_permissions(request, ["users_manage", *permissions])
        result_users = []
        for user_data in users:
            username = user_data.get("username", False)
            if not username:
                raise HTTPBadRequest(
                    reason="no username provided for at least one user",
                    body=json.dumps({
                        "Ok": False,
                        "Error": "no username provided for at least one user",
                        "status_code": 401,
                    }),
                    content_type="application/json",
                )
            user = await user_exists(request.app, username)
            if user:
                raise HTTPConflict(
                    reason=
                    f"User with this username ({username}) already exists",
                    body=json.dumps({
                        "Ok": False,
                        "Error":
                        f"User with this username ({username}) already exists",
                        "status_code": 409,
                    }),
                    content_type="application/json",
                )
            cards = user_data.get("cards", [])
            if not isinstance(cards, list):
                user_data["cards"] = [cards]
        await register_users(request.app, users)
        users = [{
            "username": user.get("username"),
            "cards": user.get("cards", []),
            "permissions": user.get("permissions", []),
        } for user in users]
        return respond_with_json({
            "Ok": True,
            "Error": None,
            "status_code": 200,
            "users": users
        })