diff --git a/guarddog/cli.py b/guarddog/cli.py index cacdf371..106a22cd 100644 --- a/guarddog/cli.py +++ b/guarddog/cli.py @@ -10,7 +10,7 @@ import os import sys import tempfile -from typing import Optional, cast +from typing import Optional import click from prettytable import PrettyTable @@ -20,8 +20,7 @@ from guarddog.analyzer.sourcecode import get_sourcecode_rules from guarddog.ecosystems import ECOSYSTEM from guarddog.reporters.sarif import report_verify_sarif -from guarddog.scanners import get_scanner -from guarddog.scanners.scanner import PackageScanner +from guarddog.scanners import get_package_scanner, get_project_scanner from guarddog.utils.archives import safe_extract EXIT_CODE_ISSUES_FOUND = 1 @@ -158,7 +157,7 @@ def _verify( """ return_value = None rule_param = _get_rule_param(rules, exclude_rules, ecosystem) - scanner = get_scanner(ecosystem, True) + scanner = get_project_scanner(ecosystem) if scanner is None: sys.stderr.write(f"Command verify is not supported for ecosystem {ecosystem}") exit(1) @@ -210,7 +209,7 @@ def _scan( """ rule_param = _get_rule_param(rules, exclude_rules, ecosystem) - scanner = cast(Optional[PackageScanner], get_scanner(ecosystem, False)) + scanner = get_package_scanner(ecosystem) if scanner is None: sys.stderr.write(f"Command scan is not supported for ecosystem {ecosystem}") sys.exit(1) diff --git a/guarddog/scanners/__init__.py b/guarddog/scanners/__init__.py index c146285d..03060050 100644 --- a/guarddog/scanners/__init__.py +++ b/guarddog/scanners/__init__.py @@ -6,22 +6,49 @@ from .pypi_project_scanner import PypiRequirementsScanner from .go_package_scanner import GoModuleScanner from .go_project_scanner import GoDependenciesScanner -from .scanner import Scanner +from .scanner import PackageScanner, ProjectScanner from ..ecosystems import ECOSYSTEM -def get_scanner(ecosystem: ECOSYSTEM, project: bool) -> Optional[Scanner]: - match (ecosystem, project): - case (ECOSYSTEM.PYPI, False): +def get_package_scanner(ecosystem: ECOSYSTEM) -> Optional[PackageScanner]: + """ + Return a `PackageScanner` for the given ecosystem or `None` if it + is not yet supported. + + Args: + ecosystem (ECOSYSTEM): The ecosystem of the desired scanner + + Returns: + Optional[PackageScanner]: The result of the scanner request + + """ + match ecosystem: + case ECOSYSTEM.PYPI: return PypiPackageScanner() - case (ECOSYSTEM.PYPI, True): - return PypiRequirementsScanner() - case (ECOSYSTEM.NPM, False): + case ECOSYSTEM.NPM: return NPMPackageScanner() - case (ECOSYSTEM.NPM, True): - return NPMRequirementsScanner() - case (ECOSYSTEM.GO, False): + case ECOSYSTEM.GO: return GoModuleScanner() - case (ECOSYSTEM.GO, True): + return None + + +def get_project_scanner(ecosystem: ECOSYSTEM) -> Optional[ProjectScanner]: + """ + Return a `ProjectScanner` for the given ecosystem or `None` if + it is not yet supported. + + Args: + ecosystem (ECOSYSTEM): The ecosystem of the desired scanner + + Returns: + Optional[ProjectScanner]: The result of the scanner request + + """ + match ecosystem: + case ECOSYSTEM.PYPI: + return PypiRequirementsScanner() + case ECOSYSTEM.NPM: + return NPMRequirementsScanner() + case ECOSYSTEM.GO: return GoDependenciesScanner() return None diff --git a/guarddog/scanners/scanner.py b/guarddog/scanners/scanner.py index 610ad6b7..d27fb0c8 100644 --- a/guarddog/scanners/scanner.py +++ b/guarddog/scanners/scanner.py @@ -21,18 +21,7 @@ def noop(arg: typing.Any) -> None: pass -class Scanner: - def __init__(self) -> None: - pass - - @abstractmethod - def scan_local( - self, path, rules=None, callback: typing.Callable[[dict], None] = noop - ): - pass - - -class ProjectScanner(Scanner): +class ProjectScanner: def __init__(self, package_scanner): super().__init__() self.package_scanner = package_scanner @@ -212,7 +201,7 @@ def parse_requirements( pass -class PackageScanner(Scanner): +class PackageScanner: """ Scans package for attack vectors based on source code and metadata rules