diff --git a/cycode/cli/apps/scan/code_scanner.py b/cycode/cli/apps/scan/code_scanner.py index e7dff93f..21b5959e 100644 --- a/cycode/cli/apps/scan/code_scanner.py +++ b/cycode/cli/apps/scan/code_scanner.py @@ -15,7 +15,7 @@ from cycode.cli.console import console from cycode.cli.exceptions import custom_exceptions from cycode.cli.exceptions.handle_scan_errors import handle_scan_exception -from cycode.cli.files_collector.excluder import exclude_irrelevant_documents_to_scan +from cycode.cli.files_collector.excluder import excluder from cycode.cli.files_collector.models.in_memory_zip import InMemoryZip from cycode.cli.files_collector.path_documents import get_relevant_documents from cycode.cli.files_collector.repository_documents import ( @@ -56,8 +56,8 @@ def scan_sca_pre_commit(ctx: typer.Context, repo_path: str) -> None: progress_bar_section=ScanProgressBarSection.PREPARE_LOCAL_FILES, repo_path=repo_path, ) - git_head_documents = exclude_irrelevant_documents_to_scan(scan_type, git_head_documents) - pre_committed_documents = exclude_irrelevant_documents_to_scan(scan_type, pre_committed_documents) + git_head_documents = excluder.exclude_irrelevant_documents_to_scan(scan_type, git_head_documents) + pre_committed_documents = excluder.exclude_irrelevant_documents_to_scan(scan_type, pre_committed_documents) sca_code_scanner.perform_pre_hook_range_scan_actions(repo_path, git_head_documents, pre_committed_documents) scan_commit_range_documents( ctx, @@ -77,8 +77,8 @@ def scan_sca_commit_range(ctx: typer.Context, path: str, commit_range: str) -> N from_commit_documents, to_commit_documents = get_commit_range_modified_documents( progress_bar, ScanProgressBarSection.PREPARE_LOCAL_FILES, path, from_commit_rev, to_commit_rev ) - from_commit_documents = exclude_irrelevant_documents_to_scan(scan_type, from_commit_documents) - to_commit_documents = exclude_irrelevant_documents_to_scan(scan_type, to_commit_documents) + from_commit_documents = excluder.exclude_irrelevant_documents_to_scan(scan_type, from_commit_documents) + to_commit_documents = excluder.exclude_irrelevant_documents_to_scan(scan_type, to_commit_documents) sca_code_scanner.perform_pre_commit_range_scan_actions( path, from_commit_documents, from_commit_rev, to_commit_documents, to_commit_rev ) @@ -288,7 +288,7 @@ def scan_commit_range( {'path': path, 'commit_range': commit_range, 'commit_id': commit_id}, ) - documents_to_scan.extend(exclude_irrelevant_documents_to_scan(scan_type, commit_documents_to_scan)) + documents_to_scan.extend(excluder.exclude_irrelevant_documents_to_scan(scan_type, commit_documents_to_scan)) logger.debug('List of commit ids to scan, %s', {'commit_ids': commit_ids_to_scan}) logger.debug('Starting to scan commit range (it may take a few minutes)') diff --git a/cycode/cli/apps/scan/pre_commit/pre_commit_command.py b/cycode/cli/apps/scan/pre_commit/pre_commit_command.py index 40e6a8c1..9242b450 100644 --- a/cycode/cli/apps/scan/pre_commit/pre_commit_command.py +++ b/cycode/cli/apps/scan/pre_commit/pre_commit_command.py @@ -5,7 +5,7 @@ from cycode.cli import consts from cycode.cli.apps.scan.code_scanner import get_scan_parameters, scan_documents, scan_sca_pre_commit -from cycode.cli.files_collector.excluder import exclude_irrelevant_documents_to_scan +from cycode.cli.files_collector.excluder import excluder from cycode.cli.files_collector.repository_documents import ( get_diff_file_content, get_diff_file_path, @@ -45,5 +45,5 @@ def pre_commit_command( progress_bar.update(ScanProgressBarSection.PREPARE_LOCAL_FILES) documents_to_scan.append(Document(get_path_by_os(get_diff_file_path(file)), get_diff_file_content(file))) - documents_to_scan = exclude_irrelevant_documents_to_scan(scan_type, documents_to_scan) + documents_to_scan = excluder.exclude_irrelevant_documents_to_scan(scan_type, documents_to_scan) scan_documents(ctx, documents_to_scan, get_scan_parameters(ctx), is_git_diff=True) diff --git a/cycode/cli/apps/scan/repository/repository_command.py b/cycode/cli/apps/scan/repository/repository_command.py index c96ca577..e9a3f63d 100644 --- a/cycode/cli/apps/scan/repository/repository_command.py +++ b/cycode/cli/apps/scan/repository/repository_command.py @@ -7,7 +7,7 @@ from cycode.cli import consts from cycode.cli.apps.scan.code_scanner import get_scan_parameters, scan_documents from cycode.cli.exceptions.handle_scan_errors import handle_scan_exception -from cycode.cli.files_collector.excluder import exclude_irrelevant_documents_to_scan +from cycode.cli.files_collector.excluder import excluder from cycode.cli.files_collector.repository_documents import get_git_repository_tree_file_entries from cycode.cli.files_collector.sca.sca_code_scanner import perform_pre_scan_documents_actions from cycode.cli.logger import logger @@ -57,7 +57,7 @@ def repository_command( ) ) - documents_to_scan = exclude_irrelevant_documents_to_scan(scan_type, documents_to_scan) + documents_to_scan = excluder.exclude_irrelevant_documents_to_scan(scan_type, documents_to_scan) perform_pre_scan_documents_actions(ctx, scan_type, documents_to_scan) diff --git a/cycode/cli/apps/scan/scan_command.py b/cycode/cli/apps/scan/scan_command.py index a2ffb550..7c2de1a6 100644 --- a/cycode/cli/apps/scan/scan_command.py +++ b/cycode/cli/apps/scan/scan_command.py @@ -9,6 +9,7 @@ ISSUE_DETECTED_STATUS_CODE, NO_ISSUES_STATUS_CODE, ) +from cycode.cli.files_collector.excluder import excluder from cycode.cli.utils import scan_utils from cycode.cli.utils.get_api_client import get_scan_cycode_client from cycode.cli.utils.sentry import add_breadcrumb @@ -138,13 +139,19 @@ def scan_command( ctx.obj['show_secret'] = show_secret ctx.obj['soft_fail'] = soft_fail - ctx.obj['client'] = get_scan_cycode_client(ctx) ctx.obj['scan_type'] = scan_type ctx.obj['sync'] = sync ctx.obj['severity_threshold'] = severity_threshold ctx.obj['monitor'] = monitor ctx.obj['report'] = report + scan_client = get_scan_cycode_client(ctx) + ctx.obj['client'] = scan_client + + remote_scan_config = scan_client.get_scan_configuration_safe(scan_type) + if remote_scan_config: + excluder.apply_scan_config(str(scan_type), remote_scan_config) + if export_type and export_file: console_printer = ctx.obj['console_printer'] console_printer.enable_recording(export_type, export_file) diff --git a/cycode/cli/files_collector/excluder.py b/cycode/cli/files_collector/excluder.py index 9ef5e3d6..6abd8706 100644 --- a/cycode/cli/files_collector/excluder.py +++ b/cycode/cli/files_collector/excluder.py @@ -10,36 +10,12 @@ if TYPE_CHECKING: from cycode.cli.models import Document from cycode.cli.utils.progress_bar import BaseProgressBar, ProgressBarSection + from cycode.cyclient import models logger = get_logger('File Excluder') -def exclude_irrelevant_files( - progress_bar: 'BaseProgressBar', progress_bar_section: 'ProgressBarSection', scan_type: str, filenames: list[str] -) -> list[str]: - relevant_files = [] - for filename in filenames: - progress_bar.update(progress_bar_section) - if _is_relevant_file_to_scan(scan_type, filename): - relevant_files.append(filename) - - is_sub_path.cache_clear() # free up memory - - return relevant_files - - -def exclude_irrelevant_documents_to_scan(scan_type: str, documents_to_scan: list['Document']) -> list['Document']: - logger.debug('Excluding irrelevant documents to scan') - - relevant_documents = [] - for document in documents_to_scan: - if _is_relevant_document_to_scan(scan_type, document.path, document.content): - relevant_documents.append(document) - - return relevant_documents - - def _is_subpath_of_cycode_configuration_folder(filename: str) -> bool: return ( is_sub_path(configuration_manager.global_config_file_manager.get_config_directory_path(), filename) @@ -63,43 +39,6 @@ def _does_document_exceed_max_size_limit(content: str) -> bool: return get_content_size(content) > consts.FILE_MAX_SIZE_LIMIT_IN_BYTES -def _is_relevant_file_to_scan(scan_type: str, filename: str) -> bool: - if _is_subpath_of_cycode_configuration_folder(filename): - logger.debug( - 'The file is irrelevant because it is in the Cycode configuration directory, %s', - {'filename': filename, 'configuration_directory': consts.CYCODE_CONFIGURATION_DIRECTORY}, - ) - return False - - if _is_path_configured_in_exclusions(scan_type, filename): - logger.debug('The file is irrelevant because its path is in the ignore paths list, %s', {'filename': filename}) - return False - - if not _is_file_extension_supported(scan_type, filename): - logger.debug( - 'The file is irrelevant because its extension is not supported, %s', - {'scan_type': scan_type, 'filename': filename}, - ) - return False - - if is_binary_file(filename): - logger.debug('The file is irrelevant because it is a binary file, %s', {'filename': filename}) - return False - - if scan_type != consts.SCA_SCAN_TYPE and _does_file_exceed_max_size_limit(filename): - logger.debug( - 'The file is irrelevant because it has exceeded the maximum size limit, %s', - { - 'max_file_size': consts.FILE_MAX_SIZE_LIMIT_IN_BYTES, - 'file_size': get_file_size(filename), - 'filename': filename, - }, - ) - return False - - return not (scan_type == consts.SCA_SCAN_TYPE and not _is_file_relevant_for_sca_scan(filename)) - - def _is_file_relevant_for_sca_scan(filename: str) -> bool: if any(sca_excluded_path in filename for sca_excluded_path in consts.SCA_EXCLUDED_PATHS): logger.debug( @@ -110,52 +49,126 @@ def _is_file_relevant_for_sca_scan(filename: str) -> bool: return True -def _is_relevant_document_to_scan(scan_type: str, filename: str, content: str) -> bool: - if _is_subpath_of_cycode_configuration_folder(filename): - logger.debug( - 'The document is irrelevant because it is in the Cycode configuration directory, %s', - {'filename': filename, 'configuration_directory': consts.CYCODE_CONFIGURATION_DIRECTORY}, - ) - return False - - if _is_path_configured_in_exclusions(scan_type, filename): - logger.debug( - 'The document is irrelevant because its path is in the ignore paths list, %s', {'filename': filename} - ) - return False - - if not _is_file_extension_supported(scan_type, filename): - logger.debug( - 'The document is irrelevant because its extension is not supported, %s', - {'scan_type': scan_type, 'filename': filename}, - ) - return False - - if is_binary_content(content): - logger.debug('The document is irrelevant because it is a binary file, %s', {'filename': filename}) - return False - - if scan_type != consts.SCA_SCAN_TYPE and _does_document_exceed_max_size_limit(content): - logger.debug( - 'The document is irrelevant because it has exceeded the maximum size limit, %s', - { - 'max_document_size': consts.FILE_MAX_SIZE_LIMIT_IN_BYTES, - 'document_size': get_content_size(content), - 'filename': filename, - }, - ) - return False - - return True - - -def _is_file_extension_supported(scan_type: str, filename: str) -> bool: - filename = filename.lower() - - if scan_type == consts.IAC_SCAN_TYPE: - return filename.endswith(consts.IAC_SCAN_SUPPORTED_FILES) - - if scan_type == consts.SCA_SCAN_TYPE: - return filename.endswith(consts.SCA_CONFIGURATION_SCAN_SUPPORTED_FILES) - - return not filename.endswith(consts.SECRET_SCAN_FILE_EXTENSIONS_TO_IGNORE) +class Excluder: + def __init__(self) -> None: + self._scannable_extensions: dict[str, tuple[str, ...]] = { + consts.IAC_SCAN_TYPE: consts.IAC_SCAN_SUPPORTED_FILES, + consts.SCA_SCAN_TYPE: consts.SCA_CONFIGURATION_SCAN_SUPPORTED_FILES, + } + self._non_scannable_extensions: dict[str, tuple[str, ...]] = { + consts.SECRET_SCAN_TYPE: consts.SECRET_SCAN_FILE_EXTENSIONS_TO_IGNORE, + } + + def apply_scan_config(self, scan_type: str, scan_config: 'models.ScanConfiguration') -> None: + if scan_config.scannable_extensions: + self._scannable_extensions[scan_type] = tuple(scan_config.scannable_extensions) + + def _is_file_extension_supported(self, scan_type: str, filename: str) -> bool: + filename = filename.lower() + + scannable_extensions = self._scannable_extensions.get(scan_type) + if scannable_extensions: + return filename.endswith(scannable_extensions) + + non_scannable_extensions = self._non_scannable_extensions.get(scan_type) + if non_scannable_extensions: + return not filename.endswith(non_scannable_extensions) + + return True + + def _is_relevant_file_to_scan_common(self, scan_type: str, filename: str) -> bool: + if _is_subpath_of_cycode_configuration_folder(filename): + logger.debug( + 'The document is irrelevant because it is in the Cycode configuration directory, %s', + {'filename': filename, 'configuration_directory': consts.CYCODE_CONFIGURATION_DIRECTORY}, + ) + return False + + if _is_path_configured_in_exclusions(scan_type, filename): + logger.debug( + 'The document is irrelevant because its path is in the ignore paths list, %s', {'filename': filename} + ) + return False + + if not self._is_file_extension_supported(scan_type, filename): + logger.debug( + 'The document is irrelevant because its extension is not supported, %s', + {'scan_type': scan_type, 'filename': filename}, + ) + return False + + return True + + def _is_relevant_file_to_scan(self, scan_type: str, filename: str) -> bool: + if not self._is_relevant_file_to_scan_common(scan_type, filename): + return False + + if is_binary_file(filename): + logger.debug('The file is irrelevant because it is a binary file, %s', {'filename': filename}) + return False + + if scan_type != consts.SCA_SCAN_TYPE and _does_file_exceed_max_size_limit(filename): + logger.debug( + 'The file is irrelevant because it has exceeded the maximum size limit, %s', + { + 'max_file_size': consts.FILE_MAX_SIZE_LIMIT_IN_BYTES, + 'file_size': get_file_size(filename), + 'filename': filename, + }, + ) + return False + + return not (scan_type == consts.SCA_SCAN_TYPE and not _is_file_relevant_for_sca_scan(filename)) + + def _is_relevant_document_to_scan(self, scan_type: str, filename: str, content: str) -> bool: + if not self._is_relevant_file_to_scan_common(scan_type, filename): + return False + + if is_binary_content(content): + logger.debug('The document is irrelevant because it is a binary file, %s', {'filename': filename}) + return False + + if scan_type != consts.SCA_SCAN_TYPE and _does_document_exceed_max_size_limit(content): + logger.debug( + 'The document is irrelevant because it has exceeded the maximum size limit, %s', + { + 'max_document_size': consts.FILE_MAX_SIZE_LIMIT_IN_BYTES, + 'document_size': get_content_size(content), + 'filename': filename, + }, + ) + return False + + return True + + def exclude_irrelevant_files( + self, + progress_bar: 'BaseProgressBar', + progress_bar_section: 'ProgressBarSection', + scan_type: str, + filenames: list[str], + ) -> list[str]: + relevant_files = [] + for filename in filenames: + progress_bar.update(progress_bar_section) + if self._is_relevant_file_to_scan(scan_type, filename): + relevant_files.append(filename) + + is_sub_path.cache_clear() # free up memory + + return relevant_files + + def exclude_irrelevant_documents_to_scan( + self, scan_type: str, documents_to_scan: list['Document'] + ) -> list['Document']: + logger.debug('Excluding irrelevant documents to scan') + + relevant_documents = [] + for document in documents_to_scan: + if self._is_relevant_document_to_scan(scan_type, document.path, document.content): + relevant_documents.append(document) + + return relevant_documents + + +excluder = Excluder() diff --git a/cycode/cli/files_collector/models/in_memory_zip.py b/cycode/cli/files_collector/models/in_memory_zip.py index 8f58b12b..93ac4ac7 100644 --- a/cycode/cli/files_collector/models/in_memory_zip.py +++ b/cycode/cli/files_collector/models/in_memory_zip.py @@ -1,25 +1,28 @@ +from collections import defaultdict from io import BytesIO +from pathlib import Path from sys import getsizeof -from typing import TYPE_CHECKING, Optional +from typing import Optional from zipfile import ZIP_DEFLATED, ZipFile from cycode.cli.user_settings.configuration_manager import ConfigurationManager from cycode.cli.utils.path_utils import concat_unique_id -if TYPE_CHECKING: - from pathlib import Path - class InMemoryZip: def __init__(self) -> None: self.configuration_manager = ConfigurationManager() - # Create the in-memory file-like object self.in_memory_zip = BytesIO() - self.zip = ZipFile(self.in_memory_zip, 'a', ZIP_DEFLATED, False) + self.zip = ZipFile(self.in_memory_zip, mode='a', compression=ZIP_DEFLATED, allowZip64=False) + + self._files_count = 0 + self._extension_statistics = defaultdict(int) def append(self, filename: str, unique_id: Optional[str], content: str) -> None: - # Write the file to the in-memory zip + self._files_count += 1 + self._extension_statistics[Path(filename).suffix] += 1 + if unique_id: filename = concat_unique_id(filename, unique_id) @@ -28,7 +31,6 @@ def append(self, filename: str, unique_id: Optional[str], content: str) -> None: def close(self) -> None: self.zip.close() - # to bytes def read(self) -> bytes: self.in_memory_zip.seek(0) return self.in_memory_zip.read() @@ -40,3 +42,11 @@ def write_on_disk(self, path: 'Path') -> None: @property def size(self) -> int: return getsizeof(self.in_memory_zip) + + @property + def files_count(self) -> int: + return self._files_count + + @property + def extension_statistics(self) -> dict[str, int]: + return dict(self._extension_statistics) diff --git a/cycode/cli/files_collector/path_documents.py b/cycode/cli/files_collector/path_documents.py index e0f06312..556a8cf8 100644 --- a/cycode/cli/files_collector/path_documents.py +++ b/cycode/cli/files_collector/path_documents.py @@ -1,7 +1,7 @@ import os from typing import TYPE_CHECKING -from cycode.cli.files_collector.excluder import exclude_irrelevant_files +from cycode.cli.files_collector.excluder import excluder from cycode.cli.files_collector.iac.tf_content_generator import ( generate_tf_content_from_tfplan, generate_tfplan_document_name, @@ -54,7 +54,9 @@ def _get_relevant_files( progress_bar_section_len = len(all_files_to_scan) * 2 progress_bar.set_section_length(progress_bar_section, progress_bar_section_len) - relevant_files_to_scan = exclude_irrelevant_files(progress_bar, progress_bar_section, scan_type, all_files_to_scan) + relevant_files_to_scan = excluder.exclude_irrelevant_files( + progress_bar, progress_bar_section, scan_type, all_files_to_scan + ) # after finishing the first processing (excluding), # we must update the progress bar stage with respect of excluded files. diff --git a/cycode/cyclient/models.py b/cycode/cyclient/models.py index ed649644..fa952985 100644 --- a/cycode/cyclient/models.py +++ b/cycode/cyclient/models.py @@ -500,3 +500,19 @@ class Meta: @post_load def build_dto(self, data: dict[str, Any], **_) -> 'SupportedModulesPreferences': return SupportedModulesPreferences(**data) + + +@dataclass +class ScanConfiguration: + scannable_extensions: list[str] + + +class ScanConfigurationSchema(Schema): + class Meta: + unknown = EXCLUDE + + scannable_extensions = fields.List(fields.String(), allow_none=True) + + @post_load + def build_dto(self, data: dict[str, Any], **_) -> 'ScanConfiguration': + return ScanConfiguration(**data) diff --git a/cycode/cyclient/scan_client.py b/cycode/cyclient/scan_client.py index e0bf8131..b1c697c6 100644 --- a/cycode/cyclient/scan_client.py +++ b/cycode/cyclient/scan_client.py @@ -1,16 +1,17 @@ import json from copy import deepcopy -from typing import TYPE_CHECKING, Union +from typing import TYPE_CHECKING, Optional, Union from uuid import UUID from requests import Response from cycode.cli import consts from cycode.cli.config import configuration_manager -from cycode.cli.exceptions.custom_exceptions import CycodeError +from cycode.cli.exceptions.custom_exceptions import CycodeError, RequestHttpError from cycode.cli.files_collector.models.in_memory_zip import InMemoryZip from cycode.cyclient import models from cycode.cyclient.cycode_client_base import CycodeClientBase +from cycode.cyclient.logger import logger if TYPE_CHECKING: from cycode.cyclient.scan_config_base import ScanConfigBase @@ -100,12 +101,19 @@ def zipped_file_scan_async( is_commit_range: bool = False, ) -> models.ScanInitializationResponse: files = {'file': ('multiple_files_scan.zip', zip_file.read())} + + compression_manifest = { + 'file_count_by_extension': zip_file.extension_statistics, + 'file_count': zip_file.files_count, + } + response = self.scan_cycode_client.post( url_path=self.get_zipped_file_scan_async_url_path(scan_type), data={ 'is_git_diff': is_git_diff, 'scan_parameters': json.dumps(scan_parameters), 'is_commit_range': is_commit_range, + 'compression_manifest': json.dumps(compression_manifest), }, files=files, ) @@ -245,3 +253,25 @@ def report_scan_status(self, scan_type: str, scan_id: str, scan_status: dict) -> @staticmethod def parse_scan_response(response: Response) -> models.ScanResult: return models.ScanResultSchema().load(response.json()) + + def get_scan_configuration_path(self, scan_type: str) -> str: + correct_scan_type = self.scan_config.get_async_scan_type(scan_type) + return f'{self.get_scan_service_url_path(scan_type)}/{correct_scan_type}/configuration' + + def get_scan_configuration(self, scan_type: str) -> models.ScanConfiguration: + response = self.scan_cycode_client.get( + url_path=self.get_scan_configuration_path(scan_type), + hide_response_content_log=self._hide_response_log, + ) + return models.ScanConfigurationSchema().load(response.json()) + + def get_scan_configuration_safe(self, scan_type: str) -> Optional['models.ScanConfiguration']: + try: + return self.get_scan_configuration(scan_type) + except RequestHttpError as e: + if e.status_code == 404: + logger.debug( + 'Remote scan configuration is not supported for this scan type: %s', {'scan_type': scan_type} + ) + else: + logger.debug('Failed to get remote scan configuration: %s', {'scan_type': scan_type}, exc_info=e) diff --git a/tests/cli/commands/test_main_command.py b/tests/cli/commands/test_main_command.py index db8fe86b..2436adee 100644 --- a/tests/cli/commands/test_main_command.py +++ b/tests/cli/commands/test_main_command.py @@ -8,10 +8,10 @@ from cycode.cli import consts from cycode.cli.app import app -from cycode.cli.cli_types import OutputTypeOption +from cycode.cli.cli_types import OutputTypeOption, ScanTypeOption from cycode.cli.utils.git_proxy import git_proxy from tests.conftest import CLI_ENV_VARS, TEST_FILES_PATH, ZIP_CONTENT_PATH -from tests.cyclient.mocked_responses.scan_client import mock_scan_async_responses +from tests.cyclient.mocked_responses.scan_client import mock_remote_config_responses, mock_scan_async_responses _PATH_TO_SCAN = TEST_FILES_PATH.joinpath('zip_content').absolute() @@ -71,6 +71,7 @@ def test_optional_git_with_path_scan(scan_client: 'ScanClient', api_token_respon @responses.activate def test_required_git_with_path_repository(scan_client: 'ScanClient', api_token_response: responses.Response) -> None: + mock_remote_config_responses(responses, ScanTypeOption.SECRET, scan_client) responses.add(api_token_response) # fake env without Git executable diff --git a/tests/cyclient/mocked_responses/scan_client.py b/tests/cyclient/mocked_responses/scan_client.py index 1726e74c..c37c1d8a 100644 --- a/tests/cyclient/mocked_responses/scan_client.py +++ b/tests/cyclient/mocked_responses/scan_client.py @@ -114,9 +114,28 @@ def get_detection_rules_response(url: str) -> responses.Response: return responses.Response(method=responses.GET, url=url, json=json_response, status=200) +def get_scan_configuration_url(scan_type: str, scan_client: ScanClient) -> str: + api_url = scan_client.scan_cycode_client.api_url + service_url = scan_client.get_scan_configuration_path(scan_type) + return f'{api_url}/{service_url}' + + +def get_scan_configuration_response(url: str) -> responses.Response: + json_response = { + 'scannable_extensions': None, + } + + return responses.Response(method=responses.GET, url=url, json=json_response, status=200) + + +def mock_remote_config_responses(responses_module: responses, scan_type: str, scan_client: ScanClient) -> None: + responses_module.add(get_scan_configuration_response(get_scan_configuration_url(scan_type, scan_client))) + + def mock_scan_async_responses( responses_module: responses, scan_type: str, scan_client: ScanClient, scan_id: UUID, zip_content_path: Path ) -> None: + mock_remote_config_responses(responses_module, scan_type, scan_client) responses_module.add( get_zipped_file_scan_async_response(get_zipped_file_scan_async_url(scan_type, scan_client), scan_id) ) diff --git a/tests/test_code_scanner.py b/tests/test_code_scanner.py index 9ef09123..01234d1d 100644 --- a/tests/test_code_scanner.py +++ b/tests/test_code_scanner.py @@ -9,7 +9,7 @@ _try_get_aggregation_report_url_if_needed, ) from cycode.cli.cli_types import ScanTypeOption -from cycode.cli.files_collector.excluder import _is_relevant_file_to_scan +from cycode.cli.files_collector.excluder import excluder from cycode.cyclient.scan_client import ScanClient from tests.conftest import TEST_FILES_PATH from tests.cyclient.mocked_responses.scan_client import ( @@ -20,7 +20,7 @@ def test_is_relevant_file_to_scan_sca() -> None: path = os.path.join(TEST_FILES_PATH, 'package.json') - assert _is_relevant_file_to_scan(consts.SCA_SCAN_TYPE, path) is True + assert excluder._is_relevant_file_to_scan(consts.SCA_SCAN_TYPE, path) is True @pytest.mark.parametrize('scan_type', list(ScanTypeOption))