Source code for src.checks

"""Module that allows to instantiate any selection of available checks
on a project"""

import json
import logging
from pathlib import Path
from typing import (
    Any,
    Callable,
    Dict,
    Iterable,
    List,
    Optional,
    Tuple,
    Type,
)

import jsonschema
from git import Repo
from gitlab import Gitlab
from gitlab.v4.objects import Project
from jsonschema import SchemaError, ValidationError

from src.checks.checked_in_binaries import CheckedInBinaries
from src.checks.comments_in_code import CommentsInCode
from src.checks.existence_of_documentation_infrastructure import (
    ExistenceOfDocumentationInfrastructure,
)
from src.checks.opencode_usage import OpencodeUsage
from src.checks.sast_usage_basic import SastUsageBasic
from src.checks.secrets import Secrets
from src.config import context
from src.exceptions import CheckConstructionException
from src.interfaces import CheckInterface

logger: logging.Logger = logging.getLogger(__name__)

available_checks: List[Type[CheckInterface]] = [
    CheckedInBinaries,
    CommentsInCode,
    ExistenceOfDocumentationInfrastructure,
    OpencodeUsage,
    SastUsageBasic,
    Secrets,
]


[docs] def results_valid(results: Dict[str, Any]) -> bool: """ Validates the results that a check instance's run method returned. """ schema_path: Path = Path( context.settings["local_repo_db_resources_dir"] ) / Path("schemas/check_common_output_format.json") logger.info(f"Loading check result schema from {schema_path}") with schema_path.open(mode="r") as f: schema = json.load(f) logger.info("Validating check results against schema") try: jsonschema.validate(results, schema) return True except ValidationError: logger.error("Check results do not conform to expected schema") except SchemaError: logger.error("Check results schema is not valid") return False
[docs] def validate_args(args_dict: Dict[str, Any]) -> bool: """Validates the set of arguments passed to the 'check' subcommand""" if args_dict.get("directory") and not args_dict.get("id"): logger.error( "Fatal: Illegal combination of parameters: " "The 'directory' option requires a project " "'id'" ) return False return True
[docs] def transform_args( args_dict: Dict[str, Any], ) -> Tuple[Optional[Path], Optional[int]]: """Transforms the set of arguments passed to the check subcommand""" if args_dict.get("verbose"): logging.getLogger().level = logging.DEBUG logger.debug("Prepare for lots out output") directory: str | Path | None = args_dict.get("directory") if directory: directory = Path(directory) _id: str | int | None = args_dict.get("id") if _id: _id = int(_id) return directory, _id
[docs] def iter_checks( proj: Project, repo: Repo, api: Gitlab, filter_func: Callable[[Type[CheckInterface]], bool] = lambda _: False, ) -> Iterable[CheckInterface]: """ This method is used to get instances of all checks in the set filter_func(availableChecks) for a single project. yields: check instances for the given project """ for check in available_checks: if filter_func(check): continue try: yield check(proj, repo, api) except CheckConstructionException as E: logger.error( f"Failed to instantiate {check.name} on {proj.name_with_namespace}, {repo}: {E}" ) continue