-
Notifications
You must be signed in to change notification settings - Fork 4
Remove the temp dir and exclude excel files #214
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
e790c73
70ff181
21f0365
5be9ba7
6f5750a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -28,13 +28,16 @@ | |
| import subprocess | ||
| import re | ||
| import shutil | ||
| import tempfile | ||
|
|
||
| PKG_NAME = "fosslight_binary" | ||
| logger = logging.getLogger(constant.LOGGER_NAME) | ||
|
|
||
| _REMOVE_FILE_EXTENSION = ['json', 'js'] | ||
| _REMOVE_FILE_EXTENSION = ['json', 'js', 'xlsx', 'xls', 'xlsm'] | ||
| _REMOVE_FILE_COMMAND_RESULT = ['timezone data', 'apple binary property list'] | ||
| INCLUDE_FILE_COMMAND_RESULT = ['current ar archive'] | ||
| _TEMP_DIR_PREFIX = '.fosslight_temp_' | ||
| _LOG_FILE_PREFIX = 'fosslight_log_bin_' | ||
|
|
||
| _error_logs = [] | ||
| _root_path = "" | ||
|
|
@@ -71,7 +74,67 @@ def get_checksum_and_tlsh(bin_with_path): | |
| return checksum_value, tlsh_value, error_msg | ||
|
|
||
|
|
||
| def init(path_to_find_bin, output_file_name, formats, path_to_exclude=[]): | ||
| def _prepare_temp_dir(output_dir, file_time): | ||
| """Create the temp directory that holds intermediate output. | ||
|
|
||
| Keep the timestamp in the directory name for traceability, but let the | ||
| OS add a unique suffix so concurrent scans targeting the same output path | ||
| never clobber each other's intermediate files. | ||
| """ | ||
| os.makedirs(output_dir, exist_ok=True) | ||
| return tempfile.mkdtemp(prefix=f'{_TEMP_DIR_PREFIX}{file_time}_', dir=output_dir) | ||
|
|
||
|
|
||
| def _cleanup_temp_dir(temp_path): | ||
| """Remove the temp directory if it is still there. | ||
|
|
||
| Called from the finally block of find_binaries so that only this | ||
| invocation's directory is removed, however the analysis ends. | ||
| """ | ||
| if not temp_path or not os.path.isdir(temp_path): | ||
| return | ||
|
|
||
| temp_path = os.path.abspath(temp_path) | ||
| logging_logger = logging.getLogger(constant.LOGGER_NAME) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 추가 확인 사항: _cleanup_temp_dir는 constant.LOGGER_NAME 로거에 직접 붙은 FileHandler만 닫음. 그런데 init 이후 모듈 전역 logger는 init_log의 반환 값으로 재할당되므로, init_log가 다른 이름의 로거에 FileHandler를 붙인다면 핸들러가 닫히지 않아 Windows에서 rmtree(ignore_errors=True)가 조용히 실패하고 temp가 남을 수 있음. init_log 구현에서 두 로거 이름이 일치하는지 확인 필요
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @coderabbit.ai, logger가 전역 변수로 있는데 logging_logger를 따로 받을 필요가 있나?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
You are interacting with an AI system.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bjk7119 , 기존 전역 logger를 사용하는 것을 권장드립니다. |
||
| for handler in logging_logger.handlers[:]: | ||
| if (isinstance(handler, logging.FileHandler) | ||
| and os.path.dirname(os.path.abspath(handler.baseFilename)) == temp_path): | ||
| handler.flush() | ||
| handler.close() | ||
| logging_logger.removeHandler(handler) | ||
|
|
||
| shutil.rmtree(temp_path, ignore_errors=True) | ||
|
|
||
|
|
||
| def _finalize_temp_output(temp_output_path, final_output_path, log_file, file_time, log=None): | ||
| """Publish analysis artifacts from the temp directory.""" | ||
| if not temp_output_path or not os.path.isdir(temp_output_path): | ||
| return True | ||
|
|
||
| publish_ok = True | ||
| try: | ||
| if os.path.isfile(log_file): | ||
| move_log_file(log_file, os.path.join( | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 추가 확인 사항: Windows에서는 FileHandler가 로그 파일을 열고 있는 상태에서 move_log_file이 호출되어 이동이 실패할 수 있음(열린 파일은 rename 불가). 이 경우 publish_ok=False가 되어 copytree가 실제로 결과를 게시하더라도 success_to_write=False로 반환됨. 로그 이동 전에 핸들러를 먼저 닫는 헬퍼를 호출하도록 순서 조정 권장
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @bjk7119 , windows에서 정상 동작하는지 테스트 결과 공유 부탁드립니다.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 문제: _finalize_temp_output가 로그 파일을 move할 시점에 해당 파일의 FileHandler가 아직 닫혀 있지 않을 수 있습니다. 핸들러를 닫는 로직은 그 이후 단계인 _cleanup_temp_dir에서만 수행되므로 move 시점에는 도움이 되지 않습니다. Windows에서는 열려 있는 파일의 이동이 PermissionError로 실패하기 쉬운데, 이번 변경부터 move 실패가 publish_ok=False → success_to_write=False로 승격되어 정상 완료된 스캔의 반환값(및 CLI exit code)이 실패로 바뀔 수 있습니다. 기존에는 debug 로그만 남기고 무시했고, 실제로는 copytree가 동일한 이름의 로그 파일을 최종 경로에 복사해주므로 move 실패는 publish 실패와 동등하지 않습니다. AS-IS: 로그 파일 move 실패 시 logger.debug로만 기록하고 무시했으며, 결과 파일은 copytree로 복사되어 정상 완료로 처리되었습니다. TO-BE: move를 시도하기 전에 로그 FileHandler를 close하도록 핸들러 정리 로직을 move 앞으로 이동하거나, move 실패를 publish 실패로 승격하지 않고 copytree에 의한 복사로 대체되도록 완화하세요. |
||
| final_output_path, f'{_LOG_FILE_PREFIX}{file_time}.txt')) | ||
| else: | ||
| if log: | ||
| log.debug("Moving binary analysis log file is skipped") | ||
| except Exception as ex: | ||
| publish_ok = False | ||
| if log: | ||
| log.error(f"Failed to move log file: {ex}") | ||
|
|
||
| try: | ||
| shutil.copytree(temp_output_path, final_output_path, dirs_exist_ok=True) | ||
| except Exception as ex: | ||
| publish_ok = False | ||
| if log: | ||
| log.error(f"Failed to publish scan artifacts: {ex}") | ||
|
|
||
| return publish_ok | ||
|
|
||
|
|
||
| def init(path_to_find_bin, output_file_name, formats, path_to_exclude=[], temp_path_holder=None): | ||
| global logger, _result_log | ||
|
|
||
| _json_ext = ".json" | ||
|
|
@@ -85,7 +148,9 @@ def init(path_to_find_bin, output_file_name, formats, path_to_exclude=[]): | |
| output_path = os.path.abspath(output_path) | ||
|
|
||
| original_output_path = output_path | ||
| output_path = os.path.join(output_path, '.fosslight_temp') | ||
| output_path = _prepare_temp_dir(output_path, file_time) | ||
| if temp_path_holder is not None: | ||
| temp_path_holder["path"] = output_path | ||
|
|
||
| while len(output_files) < len(output_extensions): | ||
| output_files.append(None) | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
@@ -125,7 +190,7 @@ def init(path_to_find_bin, output_file_name, formats, path_to_exclude=[]): | |
| logger.error(f"Format error - {msg}") | ||
| sys.exit(1) | ||
|
|
||
| log_file = os.path.join(output_path, f"fosslight_log_bin_{file_time}.txt") | ||
| log_file = os.path.join(output_path, f"{_LOG_FILE_PREFIX}{file_time}.txt") | ||
| logger, _result_log = init_log(log_file, True, logging.INFO, logging.DEBUG, | ||
| PKG_NAME, path_to_find_bin, path_to_exclude) | ||
|
|
||
|
|
@@ -172,6 +237,23 @@ def get_file_list(path_to_find, excluded_files): | |
| def find_binaries(path_to_find_bin, output_dir, formats, kb_url="", kb_token="", simple_mode=False, | ||
| correct_mode=True, correct_filepath="", path_to_exclude=[], | ||
| all_exclude_mode=()): | ||
| """Analyze binaries, leaving no temp directory behind however the run ends. | ||
|
|
||
| Ctrl+C (KeyboardInterrupt), an unexpected exception and the sys.exit raised | ||
| by error_occured all pass through the finally block. | ||
| """ | ||
| temp_path_holder = {} | ||
| try: | ||
| return _analyze_binaries(path_to_find_bin, output_dir, formats, kb_url, kb_token, | ||
| simple_mode, correct_mode, correct_filepath, path_to_exclude, | ||
| all_exclude_mode, temp_path_holder=temp_path_holder) | ||
| finally: | ||
| _cleanup_temp_dir(temp_path_holder.get("path")) | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
|
|
||
|
|
||
| def _analyze_binaries(path_to_find_bin, output_dir, formats, kb_url="", kb_token="", simple_mode=False, | ||
| correct_mode=True, correct_filepath="", path_to_exclude=[], | ||
| all_exclude_mode=(), temp_path_holder=None): | ||
| global start_time, finish_time, _root_path, _result_log | ||
|
|
||
| mode = "Normal Mode" | ||
|
|
@@ -186,7 +268,7 @@ def find_binaries(path_to_find_bin, output_dir, formats, kb_url="", kb_token="", | |
| _result_log, binary_yaml_file, compressed_yaml_file = init_simple(output_dir, PKG_NAME, start_time) | ||
| else: | ||
| _result_log, result_reports, output_extensions, formats, output_path, original_output_path, log_file = init( | ||
| path_to_find_bin, output_dir, formats, path_to_exclude) | ||
| path_to_find_bin, output_dir, formats, path_to_exclude, temp_path_holder) | ||
|
|
||
| total_bin_cnt = 0 | ||
| db_loaded_cnt = 0 | ||
|
|
@@ -289,23 +371,6 @@ def find_binaries(path_to_find_bin, output_dir, formats, kb_url="", kb_token="", | |
| else: | ||
| logger.error(f"Fail to generate result file.:{writing_msg}") | ||
|
|
||
| try: | ||
| if os.path.isfile(log_file): | ||
| move_log_file(log_file, os.path.join(original_output_path, f"fosslight_log_bin_{timestamp_for_filename(start_time)}.txt")) | ||
| else: | ||
| logger.debug("Moving binary analysis log file is skipped") | ||
| except Exception as ex: | ||
| logger.debug(f"Failed to move log file: {ex}") | ||
|
|
||
| try: | ||
| if os.path.isdir(output_path): | ||
| shutil.copytree(output_path, original_output_path, dirs_exist_ok=True) | ||
| shutil.rmtree(output_path) | ||
| else: | ||
| logger.debug(f"Temp directory not found, skip moving: {output_path}") | ||
| except Exception as ex: | ||
| logger.debug(f"Failed to move temp files: {ex}") | ||
|
|
||
| try: | ||
| print_result_log(mode=mode, success=True, result_log=_result_log, | ||
| file_cnt=str(cnt_file_except_skipped), | ||
|
|
@@ -314,6 +379,13 @@ def find_binaries(path_to_find_bin, output_dir, formats, kb_url="", kb_token="", | |
| except Exception as ex: | ||
| error_occured(error_msg=f"Print log : {ex}", exit=False) | ||
|
|
||
| if not simple_mode: | ||
| publish_ok = _finalize_temp_output( | ||
| output_path, original_output_path, log_file, | ||
| timestamp_for_filename(start_time), logger) | ||
| if not publish_ok: | ||
| success_to_write = False | ||
|
|
||
| return success_to_write, scan_item | ||
|
|
||
|
|
||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.