def _upload_report(self): try: self.cloud_api = CloudApi() except Exception as e: Logger().critical("CloudApi init failed!", exc_info=e) Logger().info("Init cloud_api success.") while True: time.sleep(10) try: self.cloud_api.upload_report() except Exception as e: Logger().warning("Upload report error.", exc_info=e)
class Monitor(base.BaseModule): """ 用于监控运行状态、启停其他模块的模块 """ def __init__(self): """ 初始化 """ self.preprocessor_proc = None self.crash_module = None self.cloud_thread = None self.web_console_thread = None def _upload_report(self): try: self.cloud_api = CloudApi() except Exception as e: Logger().critical("CloudApi init failed!", exc_info=e) Logger().info("Init cloud_api success.") while True: time.sleep(10) try: self.cloud_api.upload_report() except Exception as e: Logger().warning("Upload report error.", exc_info=e) def _check_alive(self): """ 判断其他模块是否正常运行 """ ppid = os.getppid() if ppid <= 1: Logger().warning("Detect main process stopped, Monitor exit!") self.crash_module = "main" return False # http server存活检测 # if not self.web_console_thread.isAlive(): # Logger().error("Detect monitor web console stopped, Monitor exit!") # self.crash_module = "Monitor_web_console" # return False if self.cloud_thread is not None and not self.cloud_thread.isAlive(): Logger().error( "Detect monitor cloud thread stopped, Monitor exit!") self.crash_module = "cloud_thread" return False if self.transaction_thread is not None and not self.transaction_thread.isAlive( ): Logger().error( "Detect monitor cloud transaction thread stopped, Monitor exit!" ) self.crash_module = "transaction_thread" return False if self.preprocessor_proc is None: pid = Communicator().get_value("pid", "Preprocessor") if pid != 0: try: self.preprocessor_proc = psutil.Process(pid) except Exception: Logger().error( "Init Preprocessor proc fail, Monitor exit!") self.crash_module = "preprocessor" return False return True elif not self.preprocessor_proc.is_running(): Logger().error("Detect preprocessor stopped, Monitor exit!") self.crash_module = "preprocessor" return False return True def _terminate_modules(self): """ 结束其他所有模块 """ all_procs = [] scanner_num = Config().get_config("scanner.max_module_instance") for i in range(scanner_num): pid = Communicator().get_value("pid", "Scanner_" + str(i)) if pid != 0: all_procs.append(pid) all_procs.append(Communicator().get_value("pid", "Preprocessor")) all_procs += Communicator().get_pre_http_pid() for pid in all_procs: if pid != 0: self._kill_proc_tree(pid) ppid = os.getppid() if ppid > 1: try: p = psutil.Process(ppid) p.kill() except Exception as e: Logger().error("Kill launcher failed", exc_info=e) def _kill_proc_tree(self, pid): """ 结束进程树, 递归结束目标和其子进程 Parameters: pid - 进程pid """ try: root_proc = psutil.Process(pid) procs = root_proc.children(recursive=True) procs.append(root_proc) for p in procs: p.send_signal(psutil.signal.SIGKILL) except Exception: pass def _get_self_ip(self): """ 获取本机ip """ info = psutil.net_if_addrs() for name, value in info.items(): for item in value: if (item[0] == 2 and item[1].find(".") > 0 and item[1] != '127.0.0.1' and item[2] is not None): return item[1] return "127.0.0.1" def _clean_mei(self): """ 清理pyinstaller运行时的临时文件 """ if hasattr(sys, "_MEIPASS"): try: shutil.rmtree(sys._MEIPASS) except Exception as e: Logger().error("Clean pyinstaller temp path {} failed".format( sys._MEIPASS), exc_info=e) def run(self): """ Monitor 主函数 """ # 多线程开始前初始化 RuntimeInfo() if Config().get_config("cloud_api.enable"): self.cloud_thread = threading.Thread(target=self._upload_report, name="upload_report_thread", daemon=True) self.cloud_thread.start() # 初始化调度类 scanner_schedulers = {} for module_name in RuntimeInfo().get_latest_info().keys(): if module_name.startswith("Scanner"): scanner_schedulers[module_name] = ScannerScheduler(module_name) ScannerManager().init_manager(scanner_schedulers) # 启动后台http server # web_console = WebConsole() # self.web_console_thread = threading.Thread( # target=web_console.run, # name="web_console_thread", # daemon=True # ) # self.web_console_thread.start() # 向云控后台发送心跳,用于建立ws连接 transaction = Transaction() self.transaction_thread = threading.Thread(target=transaction.run, name="transaction_thread", daemon=True) self.transaction_thread.start() time.sleep(1) if self._check_alive(): print("[-] OpenRASP-IAST init success!") print("[-] Visit web console in cloud server: {}".format( Config().get_config("cloud_api.backend_url"))) print( "[-] Before start scan task, set OpenRASP agent plugin algorithmConfig option 'fuzz_server' (edit iast.js or use cloud server web console) with url: 'http://{}:{}{}'" .format(self._get_self_ip(), Config().get_config("preprocessor.http_port"), Config().get_config("preprocessor.api_path"))) Logger().info("Monitor init success!") else: self._terminate_modules() sys.exit(1) while True: try: # 执行调度 RuntimeInfo().refresh_info() for module_name in scanner_schedulers: scanner_schedulers[module_name].do_schedule() time.sleep(Config().get_config("monitor.schedule_interval")) # 检测模块存活 if not self._check_alive(): self._terminate_modules() if self.crash_module == "main": Logger().info("OpenRASP-IAST exit!") print("[!] OpenRASP-IAST exit!") self._clean_mei() sys.exit(0) else: Logger().critical( "Detect Module {} down, exit!".format( self.crash_module)) self._clean_mei() sys.exit(1) except Exception as e: Logger().critical("Monitor module crash with unknow error!", exc_info=e) self._terminate_modules() self._clean_mei() sys.exit(2)