예제 #1
0
    def wrapper(self, *args, **kwargs):
        if not has_admin_rights(self):
            LOGGER.warning('User %s tried to access admin REST service %s',
                           get_audit_name(self), self.request.path)
            raise tornado.web.HTTPError(403, 'Access denied')

        return func(self, *args, **kwargs)
예제 #2
0
    def start_script(self, config, values, user_id, all_audit_names):
        audit_name = audit_utils.get_audit_name(all_audit_names)

        executor = ScriptExecutor(config, values)
        execution_id = self._id_generator.next_id()

        audit_command = executor.get_secure_command()
        LOGGER.info('Calling script #%s: %s', execution_id, audit_command)

        executor.start()
        self._executors[execution_id] = executor
        self._execution_infos[execution_id] = _ExecutionInfo(
            execution_id=execution_id,
            owner=user_id,
            audit_name=audit_name,
            audit_command=audit_command,
            config=config,
            all_audit_names=all_audit_names)
        self._active_executor_ids.add(execution_id)

        self._add_post_finish_handling(execution_id, executor)

        self._fire_execution_started(execution_id)

        return execution_id
예제 #3
0
    def start_script(self, config, values, user_id, all_audit_names):
        audit_name = audit_utils.get_audit_name(all_audit_names)

        executor = ScriptExecutor(config, values)
        execution_id = self._id_generator.next_id()

        audit_command = executor.get_secure_command()
        LOGGER.info('Calling script #%s: %s', execution_id, audit_command)

        executor.start()
        self._executors[execution_id] = executor
        self._execution_infos[execution_id] = _ExecutionInfo(
            execution_id=execution_id,
            owner=user_id,
            audit_name=audit_name,
            audit_command=audit_command,
            config=config,
            all_audit_names=all_audit_names)
        self._active_executor_ids.add(execution_id)

        self._add_post_finish_handling(execution_id, executor)

        self._fire_execution_started(execution_id)

        return execution_id
예제 #4
0
    def create_filename(self, execution_id, all_audit_names, script_name, start_time):
        audit_name = get_audit_name(all_audit_names)
        audit_name = file_utils.to_filename(audit_name)

        date_string = ms_to_datetime(start_time).strftime(self._date_format)

        username = get_first_existing(all_audit_names, audit_utils.AUTH_USERNAME, audit_utils.PROXIED_USERNAME)

        mapping = {
            'ID': execution_id,
            'USERNAME': username,
            'HOSTNAME': get_first_existing(all_audit_names, audit_utils.PROXIED_HOSTNAME, audit_utils.HOSTNAME,
                                           default='unknown-host'),
            'IP': get_first_existing(all_audit_names, audit_utils.PROXIED_IP, audit_utils.IP),
            'DATE': date_string,
            'AUDIT_NAME': audit_name,
            'SCRIPT': script_name
        }

        filename = self._filename_template.safe_substitute(mapping)
        if not filename.lower().endswith('.log'):
            filename += '.log'

        filename = filename.replace(" ", "_")

        return filename
예제 #5
0
    def open(self, process_id):
        auth = self.application.auth
        if not auth.is_authenticated(self):
            return None

        logger = logging.getLogger("scriptServer")

        self.process_wrapper = running_scripts.get(int(process_id))

        if not self.process_wrapper:
            raise Exception("Couldn't find corresponding process")

        self.write_message(wrap_to_server_event("input", "your input >>"))

        self.write_message(wrap_script_output(" ---  OUTPUT  --- \n"))

        audit_name = get_audit_name(self, logger)

        output_logger = self.create_script_output_logger(audit_name, logger)
        output_logger.open()

        reading_thread = threading.Thread(target=pipe_process_to_http, args=(
            self.process_wrapper,
            output_logger,
            self.safe_write
        ))
        reading_thread.start()

        web_socket = self
        process_wrapper = self.process_wrapper

        class FinishListener(object):
            def finished(self):
                reading_thread.join()

                output_logger.close()

                try:
                    downloadable_files = file_download_feature.prepare_downloadable_files(
                        process_wrapper.get_config(),
                        process_wrapper.get_full_output(),
                        process_wrapper.execution_info.param_values,
                        audit_name,
                        get_tornado_secret(),
                        TEMP_FOLDER)

                    for file in downloadable_files:
                        filename = os.path.basename(file)
                        relative_path = file_utils.relative_path(file, TEMP_FOLDER)

                        web_socket.safe_write(wrap_to_server_event(
                            'file',
                            {'url': relative_path.replace(os.path.sep, '/'), 'filename': filename}))
                except:
                    logger.exception("Couldn't prepare downloadable files")

                tornado.ioloop.IOLoop.current().add_callback(web_socket.close)

        self.process_wrapper.add_finish_listener(FinishListener())
예제 #6
0
    def open(self, execution_id):
        auth = self.application.auth
        if not auth.is_authenticated(self):
            return None

        executor = self.application.execution_service.get_active_executor(
            execution_id)  # type: ScriptExecutor

        if not executor:
            raise Exception("Couldn't find corresponding process")

        self.executor = executor
        self.ioloop = tornado.ioloop.IOLoop.current()

        self.write_message(wrap_to_server_event("input", "your input >>"))

        self.write_message(wrap_script_output(" ---  OUTPUT  --- \n"))

        audit_name = get_audit_name(self)

        output_stream = executor.get_unsecure_output_stream()
        bash_formatting = executor.config.is_bash_formatting()
        pipe_output_to_http(output_stream, bash_formatting, self.safe_write)

        web_socket = self

        file_download_feature = self.application.file_download_feature

        class FinishListener(object):
            def finished(self):
                output_stream.wait_close()
                script_output = ''.join(output_stream.get_old_data())

                try:
                    downloadable_files = file_download_feature.prepare_downloadable_files(
                        executor.config, script_output,
                        executor.parameter_values, audit_name)

                    for file in downloadable_files:
                        filename = os.path.basename(file)
                        relative_path = file_utils.relative_path(
                            file, TEMP_FOLDER)

                        web_socket.safe_write(
                            wrap_to_server_event(
                                'file', {
                                    'url': relative_path.replace(
                                        os.path.sep, '/'),
                                    'filename': filename
                                }))
                except:
                    LOGGER.exception("Couldn't prepare downloadable files")

                web_socket.ioloop.add_callback(web_socket.close)

        executor.add_finish_listener(FinishListener())
예제 #7
0
    def validate_absolute_path(self, root, absolute_path):
        logger = logging.getLogger('scriptServer')

        audit_name = get_audit_name(self, logger)

        file_path = file_utils.relative_path(absolute_path, os.path.abspath(root))
        if not file_download_feature.allowed_to_download(file_path, audit_name, get_tornado_secret()):
            logger.warning('Access attempt from ' + audit_name + ' to ' + absolute_path)
            raise tornado.web.HTTPError(404)

        return super(AuthorizedStaticFileHandler, self).validate_absolute_path(root, absolute_path)
예제 #8
0
    def validate_absolute_path(self, root, absolute_path):
        if not self.application.auth.is_enabled() and (
                absolute_path.endswith("/login.html")):
            raise tornado.web.HTTPError(404)

        relative_path = file_utils.relative_path(absolute_path, root)
        if self.is_admin_file(relative_path):
            if not has_admin_rights(self):
                LOGGER.warning('User %s tried to access admin static file %s',
                               get_audit_name(self), relative_path)
                raise tornado.web.HTTPError(403)

        return super(AuthorizedStaticFileHandler,
                     self).validate_absolute_path(root, absolute_path)
예제 #9
0
    def validate_absolute_path(self, root, absolute_path):
        audit_name = get_audit_name(self)

        file_download_feature = self.application.file_download_feature

        file_path = file_utils.relative_path(absolute_path,
                                             os.path.abspath(root))
        if not file_download_feature.allowed_to_download(
                file_path, audit_name):
            LOGGER.warning('Access attempt from ' + audit_name + ' to ' +
                           absolute_path)
            raise tornado.web.HTTPError(404)

        return super(AuthorizedStaticFileHandler,
                     self).validate_absolute_path(root, absolute_path)
예제 #10
0
            def finished(self):
                return_code = request_handler_self.process_wrapper.get_return_code()

                if return_code != 0:
                    script = str(script_name)

                    audit_name = get_audit_name(request_handler_self, script_logger)

                    title = script + ' FAILED'
                    body = 'The script "' + script + '", started by ' + audit_name + \
                           ' exited with return code ' + str(return_code) + '.' + \
                           ' Usually this means an error, occurred during the execution.' + \
                           ' Please check the corresponding logs'

                    send_alerts(alerts_config, title, body)
예제 #11
0
    def _get_paths(self, execution_id, predicate):
        config = self.config
        if is_empty(config.output_files):
            return []

        paths = [_extract_path(f) for f in config.output_files if predicate(f)]
        paths = [p for p in paths if p]

        parameter_values = self.execution_service.get_user_parameter_values(
            execution_id)
        all_audit_names = self.execution_service.get_all_audit_names(
            execution_id)

        audit_name = audit_utils.get_audit_name(all_audit_names)
        username = audit_utils.get_audit_username(all_audit_names)

        return substitute_variable_values(config.parameters, paths,
                                          parameter_values, audit_name,
                                          username)
예제 #12
0
def get_audit_name(request_handler):
    logger = logging.getLogger('tests')
    return audit_utils.get_audit_name(request_handler, logger)
예제 #13
0
def get_audit_name(request_handler):
    return audit_utils.get_audit_name(request_handler)
예제 #14
0
    def post(self):
        script_name = None

        audit_name = get_audit_name(self)

        try:
            arguments = tornado_utils.get_form_arguments(self)
            execution_info = external_model.to_execution_info(arguments)

            script_name = execution_info.script

            config = load_config(script_name)

            if not config:
                message = 'Script with name "' + str(
                    script_name) + '" not found'
                LOGGER.error(message)
                respond_error(self, 400, message)
                return

            file_upload_feature = self.application.file_upload_feature
            if self.request.files:
                for key, value in self.request.files.items():
                    file_info = value[0]
                    file_path = file_upload_feature.save_file(
                        file_info.filename, file_info.body, audit_name)
                    execution_info.param_values[key] = file_path

            valid_parameters = model_helper.validate_parameters(
                execution_info.param_values, config)
            if not valid_parameters:
                message = 'Received invalid parameters'
                LOGGER.error(message)
                respond_error(self, 400, message)
                return

            executor = ScriptExecutor(config, execution_info.param_values,
                                      audit_name)

            audit_command = executor.get_secure_command()
            LOGGER.info('Calling script: ' + audit_command)
            LOGGER.info('User info: ' + str(get_all_audit_names(self)))

            process_id = executor.start()
            running_scripts[process_id] = executor

            self.write(str(process_id))

            secure_output_stream = executor.get_secure_output_stream()

            self.start_script_output_logger(audit_name, script_name,
                                            secure_output_stream)

            alerts_config = self.application.alerts_config
            if alerts_config:
                self.subscribe_fail_alerter(script_name, alerts_config,
                                            audit_name, executor,
                                            secure_output_stream)

        except Exception as e:
            LOGGER.exception("Error while calling the script")

            if hasattr(e, "strerror") and e.strerror:
                error_output = e.strerror
            else:
                error_output = "Unknown error occurred, contact the administrator"

            result = " ---  ERRORS  --- \n"
            result += error_output

            if script_name:
                script = str(script_name)
            else:
                script = "Some script"

            audit_name = audit_name
            send_alerts(
                self.application.alerts_config, script + ' NOT STARTED',
                "Couldn't start the script " + script + ' by ' + audit_name +
                '.\n\n' + result)

            respond_error(self, 500, result)
예제 #15
0
    def on_close(self):
        if self.executor.config.kill_on_disconnect:
            self.executor.kill()

        audit_name = get_audit_name(self)
        LOGGER.info(audit_name + ' disconnected')
예제 #16
0
def get_audit_name(request_handler):
    audit_name = audit_utils.get_audit_name(request_handler)
    return normalize_hostname(audit_name)
예제 #17
0
 def get_audit_name(self):
     return audit_utils.get_audit_name(self.audit_names)
예제 #18
0
    def post(self):
        script_name = None

        try:
            request_data = self.request.body

            execution_info = external_model.to_execution_info(request_data.decode("UTF-8"))

            script_name = execution_info.script

            config = load_config(script_name)

            if not config:
                respond_error(self, 400, "Script with name '" + str(script_name) + "' not found")
                return

            working_directory = config.get_working_directory()
            if working_directory is not None:
                working_directory = file_utils.normalize_path(working_directory)

            script_logger = logging.getLogger("scriptServer")

            valid_parameters = model_helper.validate_parameters(execution_info.param_values, config)
            if not valid_parameters:
                respond_error(self, 400, 'Received invalid parameters')
                return

            script_base_command = process_utils.split_command(config.get_script_command(), working_directory)

            script_args = build_command_args(execution_info.param_values, config)
            command = script_base_command + script_args

            audit_script_args = build_command_args(
                execution_info.param_values,
                config,
                model_helper.value_to_str)
            audit_command = script_base_command + audit_script_args

            script_logger.info('Calling script: ' + ' '.join(audit_command))
            script_logger.info('User info: ' + str(get_all_audit_names(self, script_logger)))

            run_pty = config.is_requires_terminal()
            if run_pty and not pty_supported:
                script_logger.warning(
                    "Requested PTY mode, but it's not supported for this OS (" + sys.platform + "). Falling back to POpen")
                run_pty = False

            if run_pty:
                self.process_wrapper = execution_pty.PtyProcessWrapper(command,
                                                                       config.get_name(),
                                                                       working_directory,
                                                                       config,
                                                                       execution_info)
            else:
                self.process_wrapper = execution_popen.POpenProcessWrapper(command,
                                                                           config.get_name(),
                                                                           working_directory,
                                                                           config,
                                                                           execution_info)
            self.process_wrapper.start()

            process_id = self.process_wrapper.get_process_id()

            running_scripts[process_id] = self.process_wrapper

            self.write(str(process_id))

            alerts_config = self.application.alerts_config
            if alerts_config:
                self.subscribe_fail_alerter(script_name, script_logger, alerts_config)


        except Exception as e:
            script_logger = logging.getLogger("scriptServer")
            script_logger.exception("Error while calling the script")

            if hasattr(e, "strerror") and e.strerror:
                error_output = e.strerror
            else:
                error_output = "Unknown error occurred, contact the administrator"

            result = " ---  ERRORS  --- \n"
            result += error_output

            if script_name:
                script = str(script_name)
            else:
                script = "Some script"

            audit_name = get_audit_name(self, script_logger)
            send_alerts(self.application.alerts_config, script + ' NOT STARTED',
                        "Couldn't start the script " + script + ' by ' + audit_name + '.\n\n' +
                        result)

            respond_error(self, 500, result)
예제 #19
0
def has_admin_rights(self):
    audit_name = get_audit_name(self)
    return self.application.authorizer.is_admin(audit_name)