diff --git a/cycode/cli/files_collector/sca/maven/base_restore_maven_dependencies.py b/cycode/cli/files_collector/sca/base_restore_dependencies.py similarity index 93% rename from cycode/cli/files_collector/sca/maven/base_restore_maven_dependencies.py rename to cycode/cli/files_collector/sca/base_restore_dependencies.py index bd4c3215..78ba3fd4 100644 --- a/cycode/cli/files_collector/sca/maven/base_restore_maven_dependencies.py +++ b/cycode/cli/files_collector/sca/base_restore_dependencies.py @@ -4,7 +4,7 @@ import click from cycode.cli.models import Document -from cycode.cli.utils.path_utils import get_file_content, get_file_dir, join_paths +from cycode.cli.utils.path_utils import get_file_content, get_file_dir, get_path_from_context, join_paths from cycode.cli.utils.shell_executor import shell from cycode.cyclient import logger @@ -23,7 +23,7 @@ def execute_command(command: List[str], file_name: str, command_timeout: int) -> return dependencies -class BaseRestoreMavenDependencies(ABC): +class BaseRestoreDependencies(ABC): def __init__(self, context: click.Context, is_git_diff: bool, command_timeout: int) -> None: self.context = context self.is_git_diff = is_git_diff @@ -34,7 +34,7 @@ def restore(self, document: Document) -> Optional[Document]: def get_manifest_file_path(self, document: Document) -> str: return ( - join_paths(self.context.params['paths'][0], document.path) + join_paths(get_path_from_context(self.context), document.path) if self.context.obj.get('monitor') else document.path ) diff --git a/cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py b/cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py index 21fdb7c3..d4896e95 100644 --- a/cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py +++ b/cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py @@ -3,7 +3,7 @@ import click -from cycode.cli.files_collector.sca.maven.base_restore_maven_dependencies import BaseRestoreMavenDependencies +from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies from cycode.cli.models import Document BUILD_GRADLE_FILE_NAME = 'build.gradle' @@ -11,7 +11,7 @@ BUILD_GRADLE_DEP_TREE_FILE_NAME = 'gradle-dependencies-generated.txt' -class RestoreGradleDependencies(BaseRestoreMavenDependencies): +class RestoreGradleDependencies(BaseRestoreDependencies): def __init__(self, context: click.Context, is_git_diff: bool, command_timeout: int) -> None: super().__init__(context, is_git_diff, command_timeout) diff --git a/cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py b/cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py index d9c117e6..084dec6c 100644 --- a/cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py +++ b/cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py @@ -3,8 +3,8 @@ import click -from cycode.cli.files_collector.sca.maven.base_restore_maven_dependencies import ( - BaseRestoreMavenDependencies, +from cycode.cli.files_collector.sca.base_restore_dependencies import ( + BaseRestoreDependencies, build_dep_tree_path, execute_command, ) @@ -16,7 +16,7 @@ MAVEN_DEP_TREE_FILE_NAME = 'bcde.mvndeps' -class RestoreMavenDependencies(BaseRestoreMavenDependencies): +class RestoreMavenDependencies(BaseRestoreDependencies): def __init__(self, context: click.Context, is_git_diff: bool, command_timeout: int) -> None: super().__init__(context, is_git_diff, command_timeout) diff --git a/cycode/cli/files_collector/sca/nuget/__init__.py b/cycode/cli/files_collector/sca/nuget/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/cycode/cli/files_collector/sca/nuget/restore_nuget_dependencies.py b/cycode/cli/files_collector/sca/nuget/restore_nuget_dependencies.py new file mode 100644 index 00000000..c54c3e5e --- /dev/null +++ b/cycode/cli/files_collector/sca/nuget/restore_nuget_dependencies.py @@ -0,0 +1,27 @@ +import os +from typing import List + +import click + +from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies +from cycode.cli.models import Document + +NUGET_PROJECT_FILE_EXTENSIONS = ['.csproj', '.vbproj'] +NUGET_LOCK_FILE_NAME = 'packages.lock.json' + + +class RestoreNugetDependencies(BaseRestoreDependencies): + def __init__(self, context: click.Context, is_git_diff: bool, command_timeout: int) -> None: + super().__init__(context, is_git_diff, command_timeout) + + def is_project(self, document: Document) -> bool: + return any(document.path.endswith(ext) for ext in NUGET_PROJECT_FILE_EXTENSIONS) + + def get_command(self, manifest_file_path: str) -> List[str]: + return ['dotnet', 'restore', manifest_file_path, '--use-lock-file', '--verbosity', 'quiet'] + + def get_lock_file_name(self) -> str: + return NUGET_LOCK_FILE_NAME + + def verify_restore_file_already_exist(self, restore_file_path: str) -> bool: + return os.path.isfile(restore_file_path) diff --git a/cycode/cli/files_collector/sca/sca_code_scanner.py b/cycode/cli/files_collector/sca/sca_code_scanner.py index 7366bcbe..d4cc0293 100644 --- a/cycode/cli/files_collector/sca/sca_code_scanner.py +++ b/cycode/cli/files_collector/sca/sca_code_scanner.py @@ -4,22 +4,20 @@ import click from cycode.cli import consts +from cycode.cli.files_collector.sca.base_restore_dependencies import BaseRestoreDependencies from cycode.cli.files_collector.sca.maven.restore_gradle_dependencies import RestoreGradleDependencies from cycode.cli.files_collector.sca.maven.restore_maven_dependencies import RestoreMavenDependencies +from cycode.cli.files_collector.sca.nuget.restore_nuget_dependencies import RestoreNugetDependencies from cycode.cli.models import Document from cycode.cli.utils.git_proxy import git_proxy -from cycode.cli.utils.path_utils import get_file_content, get_file_dir, join_paths +from cycode.cli.utils.path_utils import get_file_content, get_file_dir, get_path_from_context, join_paths from cycode.cyclient import logger if TYPE_CHECKING: from git import Repo - from cycode.cli.files_collector.sca.maven.base_restore_maven_dependencies import BaseRestoreMavenDependencies - -BUILD_GRADLE_FILE_NAME = 'build.gradle' -BUILD_GRADLE_KTS_FILE_NAME = 'build.gradle.kts' -BUILD_GRADLE_DEP_TREE_FILE_NAME = 'gradle-dependencies-generated.txt' BUILD_GRADLE_DEP_TREE_TIMEOUT = 180 +BUILD_NUGET_DEP_TREE_TIMEOUT = 180 def perform_pre_commit_range_scan_actions( @@ -90,7 +88,7 @@ def get_project_file_ecosystem(document: Document) -> Optional[str]: def try_restore_dependencies( context: click.Context, documents_to_add: Dict[str, Document], - restore_dependencies: 'BaseRestoreMavenDependencies', + restore_dependencies: 'BaseRestoreDependencies', document: Document, ) -> None: if restore_dependencies.is_project(document): @@ -104,7 +102,9 @@ def try_restore_dependencies( restore_dependencies_document.content = '' else: is_monitor_action = context.obj['monitor'] - project_path = context.params['paths'][0] + + project_path = get_path_from_context(context) + manifest_file_path = get_manifest_file_path(document, is_monitor_action, project_path) logger.debug('Succeeded to generate dependencies tree on path: %s', manifest_file_path) @@ -127,10 +127,11 @@ def add_dependencies_tree_document( documents_to_scan.extend(list(documents_to_add.values())) -def restore_handlers(context: click.Context, is_git_diff: bool) -> List[RestoreGradleDependencies]: +def restore_handlers(context: click.Context, is_git_diff: bool) -> List[BaseRestoreDependencies]: return [ RestoreGradleDependencies(context, is_git_diff, BUILD_GRADLE_DEP_TREE_TIMEOUT), RestoreMavenDependencies(context, is_git_diff, BUILD_GRADLE_DEP_TREE_TIMEOUT), + RestoreNugetDependencies(context, is_git_diff, BUILD_NUGET_DEP_TREE_TIMEOUT), ] diff --git a/cycode/cli/utils/path_utils.py b/cycode/cli/utils/path_utils.py index 02b0fcc6..4f8be3f1 100644 --- a/cycode/cli/utils/path_utils.py +++ b/cycode/cli/utils/path_utils.py @@ -3,6 +3,7 @@ from functools import lru_cache from typing import AnyStr, List, Optional +import click from binaryornot.helpers import is_binary_string from cycode.cyclient import logger @@ -100,3 +101,10 @@ def concat_unique_id(filename: str, unique_id: str) -> str: filename = filename[len(os.sep) :] return os.path.join(unique_id, filename) + + +def get_path_from_context(context: click.Context) -> Optional[str]: + path = context.params.get('path') + if path is None and 'paths' in context.params: + path = context.params['paths'][0] + return path