From 7614722d4a0c600508504fac51c5ea78fd22c7c3 Mon Sep 17 00:00:00 2001 From: Ben Selwyn-Smith Date: Tue, 30 May 2023 14:48:16 +1000 Subject: [PATCH 1/5] feat: use database to store and retrieve found repos Signed-off-by: Ben Selwyn-Smith --- src/macaron/config/defaults.ini | 1 + src/macaron/database/database_manager.py | 23 +++++++++-- src/macaron/database/table_definitions.py | 2 + src/macaron/dependency_analyzer/cyclonedx.py | 19 ++++++++-- .../dependency_analyzer/cyclonedx_gradle.py | 2 +- .../dependency_analyzer/cyclonedx_mvn.py | 2 +- .../dependency_resolver.py | 28 +++++++++++--- src/macaron/slsa_analyzer/analyze_context.py | 15 +++++++- src/macaron/slsa_analyzer/analyzer.py | 21 +++++++--- .../cyclonedx/test_cyclonedx.py | 6 +-- .../java_repo_finder/test_java_repo_finder.py | 38 +++++++++++++++++++ 11 files changed, 133 insertions(+), 24 deletions(-) diff --git a/src/macaron/config/defaults.ini b/src/macaron/config/defaults.ini index 500d97c2f..2c55c885f 100644 --- a/src/macaron/config/defaults.ini +++ b/src/macaron/config/defaults.ini @@ -57,6 +57,7 @@ parent_limit = 10 # Disables repo finding for specific artifacts based on their group and artifact IDs. Format: {groupId}:{artifactId} # E.g. com.oracle.coherence.ce:coherence artifact_ignore_list = +ignore_database = False [git] # The list of allowed git hosts. diff --git a/src/macaron/database/database_manager.py b/src/macaron/database/database_manager.py index b375b512a..d5a4701d3 100644 --- a/src/macaron/database/database_manager.py +++ b/src/macaron/database/database_manager.py @@ -96,9 +96,9 @@ def insert(self, table: Table, values: dict) -> None: Parameters ---------- table: Table - The Table to insert to + The Table to insert to. values: dict - The mapping from column names to values to insert into the Table + The mapping from column names to values to insert into the Table. """ try: self.execute(insert(table).values(**values)) @@ -112,12 +112,29 @@ def execute(self, query: Any) -> None: Parameters ---------- query: Any - The SQLalchemy query to execute + The SQLAlchemy query to execute. """ with self.engine.connect() as conn: conn.execute(query) conn.commit() + def execute_and_return(self, query: Any) -> sqlalchemy.engine.cursor.CursorResult: + """ + Execute a SQLAlchemy core api query using a short-lived engine connection and returns the result. + + Parameters + ---------- + query: Any + The SQLAlchemy query to execute. + + Returns + ------- + Any : + The result of the query. + """ + with self.engine.connect() as conn: + return conn.execute(query) + def create_tables(self) -> None: """ Automatically create views for all tables known to _base.metadata. diff --git a/src/macaron/database/table_definitions.py b/src/macaron/database/table_definitions.py index d8b63d95c..fb4030879 100644 --- a/src/macaron/database/table_definitions.py +++ b/src/macaron/database/table_definitions.py @@ -77,6 +77,8 @@ class RepositoryTable(ORMBase): release_tag: Mapped[str] = mapped_column(String, nullable=True) commit_sha: Mapped[str] = mapped_column(String, nullable=False) commit_date: Mapped[str] = mapped_column(String, nullable=False) + namespace: Mapped[str] = mapped_column(String, nullable=True) + name: Mapped[str] = mapped_column(String, nullable=True) class SLSALevelTable(ORMBase): diff --git a/src/macaron/dependency_analyzer/cyclonedx.py b/src/macaron/dependency_analyzer/cyclonedx.py index 77a847717..604658a84 100644 --- a/src/macaron/dependency_analyzer/cyclonedx.py +++ b/src/macaron/dependency_analyzer/cyclonedx.py @@ -12,6 +12,7 @@ from macaron.config.defaults import defaults from macaron.config.global_config import global_config +from macaron.database.database_manager import DatabaseManager from macaron.dependency_analyzer.dependency_resolver import DependencyAnalyzer, DependencyInfo from macaron.errors import MacaronError from macaron.output_reporter.scm import SCMStatus @@ -139,12 +140,14 @@ def get_dep_components( def convert_components_to_artifacts( - components: Iterable[dict], root_component: Optional[dict | None] = None + db_man: DatabaseManager | None, components: Iterable[dict], root_component: Optional[dict | None] = None ) -> dict[str, DependencyInfo]: """Convert CycloneDX components using internal artifact representation. Parameters ---------- + db_man : DatabaseManager + The database manager for accessing the database (optional). components : list[dict] The dependency components. root_component: Optional[dict|None] @@ -196,7 +199,12 @@ def convert_components_to_artifacts( ) DependencyAnalyzer.add_latest_version( - item=item, key=key, all_versions=all_versions, latest_deps=latest_deps, url_to_artifact=url_to_artifact + db_man=db_man, + item=item, + key=key, + all_versions=all_versions, + latest_deps=latest_deps, + url_to_artifact=url_to_artifact, ) except KeyError as error: logger.debug(error) @@ -210,11 +218,13 @@ def convert_components_to_artifacts( return latest_deps -def get_deps_from_sbom(sbom_path: str | Path) -> dict[str, DependencyInfo]: +def get_deps_from_sbom(db_man: DatabaseManager | None, sbom_path: str | Path) -> dict[str, DependencyInfo]: """Get the dependencies from a provided SBOM. Parameters ---------- + db_man : DatabaseManager + The database manager for accessing the database (optional). sbom_path : str | Path The path to the SBOM file. @@ -223,6 +233,7 @@ def get_deps_from_sbom(sbom_path: str | Path) -> dict[str, DependencyInfo]: A dictionary where dependency artifacts are grouped based on "artifactId:groupId". """ return convert_components_to_artifacts( + db_man, get_dep_components( root_bom_path=Path(sbom_path), recursive=defaults.getboolean( @@ -230,5 +241,5 @@ def get_deps_from_sbom(sbom_path: str | Path) -> dict[str, DependencyInfo]: "recursive", fallback=False, ), - ) + ), ) diff --git a/src/macaron/dependency_analyzer/cyclonedx_gradle.py b/src/macaron/dependency_analyzer/cyclonedx_gradle.py index 76f9c0246..3a884cf0f 100644 --- a/src/macaron/dependency_analyzer/cyclonedx_gradle.py +++ b/src/macaron/dependency_analyzer/cyclonedx_gradle.py @@ -87,7 +87,7 @@ def collect_dependencies(self, dir_path: str) -> dict[str, DependencyInfo]: fallback=False, ), ) - return convert_components_to_artifacts(components, root_component) + return convert_components_to_artifacts(None, components, root_component) def remove_sboms(self, dir_path: str) -> bool: """Remove all the SBOM files in the provided directory recursively. diff --git a/src/macaron/dependency_analyzer/cyclonedx_mvn.py b/src/macaron/dependency_analyzer/cyclonedx_mvn.py index 73ca509d2..0732bc130 100644 --- a/src/macaron/dependency_analyzer/cyclonedx_mvn.py +++ b/src/macaron/dependency_analyzer/cyclonedx_mvn.py @@ -89,7 +89,7 @@ def collect_dependencies(self, dir_path: str) -> dict[str, DependencyInfo]: fallback=False, ), ) - return convert_components_to_artifacts(components, root_component) + return convert_components_to_artifacts(None, components, root_component) def remove_sboms(self, dir_path: str) -> bool: """Remove all the SBOM files in the provided directory recursively. diff --git a/src/macaron/dependency_analyzer/dependency_resolver.py b/src/macaron/dependency_analyzer/dependency_resolver.py index 9fa742eb0..c8f1775a4 100644 --- a/src/macaron/dependency_analyzer/dependency_resolver.py +++ b/src/macaron/dependency_analyzer/dependency_resolver.py @@ -9,10 +9,12 @@ from enum import Enum from typing import TypedDict +import sqlalchemy from packaging import version from macaron.config.defaults import defaults from macaron.config.target_config import Configuration +from macaron.database.database_manager import DatabaseManager from macaron.dependency_analyzer.java_repo_finder import find_java_repo from macaron.errors import MacaronError from macaron.output_reporter.scm import SCMStatus @@ -111,6 +113,7 @@ def get_cmd(self) -> list: @staticmethod def add_latest_version( + db_man: DatabaseManager | None, item: DependencyInfo, key: str, all_versions: dict[str, list[DependencyInfo]], @@ -121,6 +124,8 @@ def add_latest_version( Parameters ---------- + db_man : DatabaseManager | None + The database manager for accessing the database (optional). item : DependencyInfo The dictionary containing info about the dependency to be added. key : str @@ -133,7 +138,7 @@ def add_latest_version( Used to detect artifacts that have similar repos. """ if defaults.getboolean("repofinder.java", "find_repos"): - DependencyAnalyzer._find_repo(item) + DependencyAnalyzer._find_repo(db_man, item) # Check if the URL is already seen for a different artifact. if item["url"] != "": @@ -173,16 +178,29 @@ def add_latest_version( logger.error("Could not parse dependency version number: %s", error) @staticmethod - def _find_repo(item: DependencyInfo) -> None: + def _find_repo(db_man: DatabaseManager | None, item: DependencyInfo) -> None: """Find the repo for the current item, if the criteria are met.""" if item["url"] != "" or item["version"] == "unspecified" or not item["group"] or not item["name"]: logger.debug("Item URL already exists, or item is missing information: %s", item) return - gav = f"{item['group']}:{item['name']}:{item['version']}" + artifact = f"{item['group']}:{item['name']}" if f"{item['group']}:{item['name']}" in defaults.get_list("repofinder.java", "artifact_ignore_list"): - logger.debug("Skipping GAV: %s", gav) + logger.debug("Skipping artifact: %s", artifact) return + if db_man and not defaults.getboolean("repofinder.java", "ignore_database"): + # Perform database lookup + query = sqlalchemy.text( + "SELECT remote_path FROM _repository WHERE namespace = :group and name = :artifact" + ).bindparams(group=item["group"], artifact=item["name"]) + result: sqlalchemy.engine.cursor.CursorResult = db_man.execute_and_return(query) + row = result.first() + if row and row.remote_path: + logger.debug("Found database url: %s for artifact: %s", row.remote_path, artifact) + item["url"] = row.remote_path + return + logger.debug("No database url found for GAV: %s", artifact) + urls = find_java_repo( item["group"], item["name"], @@ -191,7 +209,7 @@ def _find_repo(item: DependencyInfo) -> None: ) item["url"] = DependencyAnalyzer.find_valid_url(list(urls)) if item["url"] == "": - logger.debug("Failed to find url for GAV: %s", gav) + logger.debug("Failed to find url for artifact: %s", artifact) @staticmethod def find_valid_url(urls: Iterable[str]) -> str: diff --git a/src/macaron/slsa_analyzer/analyze_context.py b/src/macaron/slsa_analyzer/analyze_context.py index 0274217dc..eb02f26cc 100644 --- a/src/macaron/slsa_analyzer/analyze_context.py +++ b/src/macaron/slsa_analyzer/analyze_context.py @@ -56,6 +56,8 @@ def __init__( output_dir: str = "", remote_path: str = "", current_date: str = "", + namespace: str = "", + name: str = "", ): """Initialize instance. @@ -74,11 +76,17 @@ def __init__( commit_date : str The commit date of the target repo. macaron_path : str - The Macaron's root path. + The Macaron root path. output_dir : str The output dir. remote_path : str The remote path for the target repo. + current_date: str + The current date. + namespace : str + The purl namespace element, a.k.a group id. + name : str + The purl name element, a.k.a artifact id. """ # / self.repo_full_name = full_name @@ -123,6 +131,9 @@ def __init__( policy=None, ) + self.namespace = namespace + self.name = name + self.repository_table = RepositoryTable(**self.get_repository_data()) @property @@ -208,6 +219,8 @@ def get_repository_data(self) -> dict: "branch_name": self.branch_name, "commit_sha": self.commit_sha, "remote_path": self.remote_path, + "namespace": self.namespace, + "name": self.name, } def get_analysis_result_data(self) -> dict: diff --git a/src/macaron/slsa_analyzer/analyzer.py b/src/macaron/slsa_analyzer/analyzer.py index 97c1ec431..1be073bff 100644 --- a/src/macaron/slsa_analyzer/analyzer.py +++ b/src/macaron/slsa_analyzer/analyzer.py @@ -36,7 +36,6 @@ from macaron.slsa_analyzer.build_tool.base_build_tool import NoneBuildTool # To load all checks into the registry -from macaron.slsa_analyzer.checks import * # pylint: disable=wildcard-import,unused-wildcard-import # noqa: F401,F403 from macaron.slsa_analyzer.checks.check_result import CheckResult, SkippedInfo from macaron.slsa_analyzer.ci_service import CI_SERVICES from macaron.slsa_analyzer.database_store import store_analysis_to_db, store_analyze_context_to_db @@ -140,7 +139,7 @@ def run(self, user_config: dict, sbom_path: str = "", skip_deps: bool = False) - if skip_deps: logger.info("Skipping automatic dependency analysis...") else: - deps_resolved = self.resolve_dependencies(main_record.context, sbom_path) + deps_resolved = self.resolve_dependencies(self.db_man, main_record.context, sbom_path) # Merge the automatically resolved dependencies with the manual configuration. deps_config = DependencyAnalyzer.merge_configs(deps_config, deps_resolved) @@ -240,11 +239,15 @@ def generate_reports(self, report: Report) -> None: for reporter in self.reporters: reporter.generate(output_target_path, report) - def resolve_dependencies(self, main_ctx: AnalyzeContext, sbom_path: str) -> dict[str, DependencyInfo]: + def resolve_dependencies( + self, db_man: DatabaseManager, main_ctx: AnalyzeContext, sbom_path: str + ) -> dict[str, DependencyInfo]: """Resolve the dependencies of the main target repo. Parameters ---------- + db_man : DatabaseManager + The database manager for accessing the database. main_ctx : AnalyzeContext The context of object of the target repository. sbom_path: str @@ -257,7 +260,7 @@ def resolve_dependencies(self, main_ctx: AnalyzeContext, sbom_path: str) -> dict """ if sbom_path: logger.info("Getting the dependencies from the SBOM defined at %s.", sbom_path) - return get_deps_from_sbom(sbom_path) + return get_deps_from_sbom(db_man, sbom_path) deps_resolved: dict[str, DependencyInfo] = {} @@ -392,7 +395,7 @@ def run_single(self, config: Configuration, existing_records: Optional[dict[str, policies_passed=[], ) - analyze_ctx = self.get_analyze_ctx(req_branch, git_obj) + analyze_ctx = self.get_analyze_ctx(req_branch, git_obj, repo_id) analyze_ctx.dynamic_data["policy"] = self.policies.get_policy_for_target(analyze_ctx.repo_full_name) analyze_ctx.check_results = self.perform_checks(analyze_ctx) @@ -406,7 +409,7 @@ def run_single(self, config: Configuration, existing_records: Optional[dict[str, context=analyze_ctx, ) - def get_analyze_ctx(self, branch_name: str, git_obj: Git) -> AnalyzeContext: + def get_analyze_ctx(self, branch_name: str, git_obj: Git, repo_id: str) -> AnalyzeContext: """Return the analyze context for a target repository. Parameters @@ -417,6 +420,8 @@ def get_analyze_ctx(self, branch_name: str, git_obj: Git) -> AnalyzeContext: the current branch name cannot be determined. git_obj : Git The pydriller Git object of the target repository. + repo_id : str + The id of the target repository. Returns ------- @@ -470,6 +475,8 @@ def get_analyze_ctx(self, branch_name: str, git_obj: Git) -> AnalyzeContext: commit_date_str, ) + artifact_id, group_id = repo_id.split(":") + # Initialize the analyzing context for this repository. analyze_ctx = AnalyzeContext( full_name, @@ -481,6 +488,8 @@ def get_analyze_ctx(self, branch_name: str, git_obj: Git) -> AnalyzeContext: global_config.macaron_path, self.output_path, origin_remote_path, + group_id, + artifact_id, ) self.db_man.add(analyze_ctx.repository_table) diff --git a/tests/dependency_analyzer/cyclonedx/test_cyclonedx.py b/tests/dependency_analyzer/cyclonedx/test_cyclonedx.py index d7baf180e..6758a7828 100644 --- a/tests/dependency_analyzer/cyclonedx/test_cyclonedx.py +++ b/tests/dependency_analyzer/cyclonedx/test_cyclonedx.py @@ -74,7 +74,7 @@ def test_convert_components_to_artifacts(snapshot: dict[str, DependencyInfo]) -> # Pass a root bom.json and two sub-project bom.json files in recursive mode. result = convert_components_to_artifacts( - get_dep_components(root_bom_path=root_bom_path, child_bom_paths=child_bom_paths, recursive=True) + None, get_dep_components(root_bom_path=root_bom_path, child_bom_paths=child_bom_paths, recursive=True) ) assert snapshot == result @@ -93,7 +93,7 @@ def test_low_quality_bom(snapshot: dict[str, DependencyInfo], name: str) -> None """ # Path to the BOM file. bom_path = Path(RESOURCES_DIR, name) - result = get_deps_from_sbom(bom_path) + result = get_deps_from_sbom(None, bom_path) assert snapshot == result @@ -104,5 +104,5 @@ def test_multiple_versions(snapshot: dict[str, DependencyInfo]) -> None: """ # Path to the BOM file. bom_path = Path(RESOURCES_DIR, "bom_multi_versions.json") - result = get_deps_from_sbom(bom_path) + result = get_deps_from_sbom(None, bom_path) assert snapshot == result diff --git a/tests/dependency_analyzer/java_repo_finder/test_java_repo_finder.py b/tests/dependency_analyzer/java_repo_finder/test_java_repo_finder.py index 49eb3065e..47d0aa484 100644 --- a/tests/dependency_analyzer/java_repo_finder/test_java_repo_finder.py +++ b/tests/dependency_analyzer/java_repo_finder/test_java_repo_finder.py @@ -7,7 +7,13 @@ import os from pathlib import Path +import pytest +import sqlalchemy + from macaron.config.defaults import defaults +from macaron.config.global_config import global_config +from macaron.database.database_manager import DatabaseManager +from macaron.database.table_definitions import RepositoryTable from macaron.dependency_analyzer.java_repo_finder import create_urls, find_parent, find_scm, parse_pom @@ -48,3 +54,35 @@ def test_java_repo_finder_hierarchical() -> None: assert group == "owner" assert artifact == "parent" assert version == "1" + + +@pytest.fixture() +def database_fixture() -> DatabaseManager: # type: ignore + """Set up and tear down a test database.""" + database_path = os.path.join(global_config.output_path, "test.db") + db_man = DatabaseManager(database_path) + db_man.create_tables() + yield db_man + db_man.terminate() + os.remove(database_path) + + +def test_java_repo_database(database_fixture: DatabaseManager) -> None: # pylint: disable=redefined-outer-name + """Test the database functionality used by the repo finder.""" + data = { + "full_name": "test_repo", + "commit_date": "02/02/02", + "branch_name": "branch_1", + "commit_sha": "shashasha", + "remote_path": "remote_path", + "namespace": "namespace", + "name": "name", + } + table = RepositoryTable(**data) + database_fixture.add(table) + database_fixture.session.commit() + query = sqlalchemy.text("SELECT remote_path FROM _repository WHERE namespace = namespace and name = name") + result = database_fixture.execute_and_return(query) + row = result.first() + assert row is not None + assert row.remote_path == "remote_path" From 357bef396ae25d76a0cfc2bfb4346258ed31ac7a Mon Sep 17 00:00:00 2001 From: Ben Selwyn-Smith Date: Tue, 30 May 2023 15:30:49 +1000 Subject: [PATCH 2/5] chore: restored checks import Signed-off-by: Ben Selwyn-Smith --- src/macaron/slsa_analyzer/analyzer.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/macaron/slsa_analyzer/analyzer.py b/src/macaron/slsa_analyzer/analyzer.py index 1be073bff..d8316cbb3 100644 --- a/src/macaron/slsa_analyzer/analyzer.py +++ b/src/macaron/slsa_analyzer/analyzer.py @@ -36,6 +36,7 @@ from macaron.slsa_analyzer.build_tool.base_build_tool import NoneBuildTool # To load all checks into the registry +from macaron.slsa_analyzer.checks import * # pylint: disable=wildcard-import,unused-wildcard-import # noqa: F401,F403 from macaron.slsa_analyzer.checks.check_result import CheckResult, SkippedInfo from macaron.slsa_analyzer.ci_service import CI_SERVICES from macaron.slsa_analyzer.database_store import store_analysis_to_db, store_analyze_context_to_db From b5123e0f6cdda6b5983065f31392e81c2bf7dbe7 Mon Sep 17 00:00:00 2001 From: Ben Selwyn-Smith Date: Thu, 1 Jun 2023 10:17:56 +1000 Subject: [PATCH 3/5] chore: updated policy checks; improved repo id database check Signed-off-by: Ben Selwyn-Smith --- src/macaron/config/defaults.ini | 2 +- .../dependency_resolver.py | 2 +- .../policy_engine/prelude/aggregate_rules.dl | 22 +++++++++---------- .../policy_engine/prelude/helper_rules.dl | 4 ++-- src/macaron/slsa_analyzer/analyzer.py | 5 ++++- 5 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/macaron/config/defaults.ini b/src/macaron/config/defaults.ini index 2c55c885f..cf53dd53e 100644 --- a/src/macaron/config/defaults.ini +++ b/src/macaron/config/defaults.ini @@ -57,7 +57,7 @@ parent_limit = 10 # Disables repo finding for specific artifacts based on their group and artifact IDs. Format: {groupId}:{artifactId} # E.g. com.oracle.coherence.ce:coherence artifact_ignore_list = -ignore_database = False +use_database = True [git] # The list of allowed git hosts. diff --git a/src/macaron/dependency_analyzer/dependency_resolver.py b/src/macaron/dependency_analyzer/dependency_resolver.py index c8f1775a4..769b71989 100644 --- a/src/macaron/dependency_analyzer/dependency_resolver.py +++ b/src/macaron/dependency_analyzer/dependency_resolver.py @@ -188,7 +188,7 @@ def _find_repo(db_man: DatabaseManager | None, item: DependencyInfo) -> None: logger.debug("Skipping artifact: %s", artifact) return - if db_man and not defaults.getboolean("repofinder.java", "ignore_database"): + if db_man and defaults.getboolean("repofinder.java", "use_database"): # Perform database lookup query = sqlalchemy.text( "SELECT remote_path FROM _repository WHERE namespace = :group and name = :artifact" diff --git a/src/macaron/policy_engine/prelude/aggregate_rules.dl b/src/macaron/policy_engine/prelude/aggregate_rules.dl index 64c1a074c..d7717af46 100644 --- a/src/macaron/policy_engine/prelude/aggregate_rules.dl +++ b/src/macaron/policy_engine/prelude/aggregate_rules.dl @@ -35,7 +35,7 @@ agg_levels(n+1) :- n <= 4, agg_levels(n). * Everything has a repository and uses a scripted build service. */ aggregate_level_requirement(1, repo) :- - repository(repo, _,_,_,_,_,_), + repository(repo, _,_,_,_,_,_,_,_), check_passed(repo, "mcn_build_service_1"), check_passed(repo, "mcn_version_control_system_1"). @@ -44,7 +44,7 @@ aggregate_level_requirement(1, repo) :- * The build is verifiably automated and deployable. */ aggregate_level_requirement(2, repo) :- - repository(repo, _,_,_,_,_,_), + repository(repo, _,_,_,_,_,_,_,_), aggregate_level_requirement(1, repo), check_passed(repo, "mcn_build_script_1"), check_passed(repo, "mcn_build_service_1"), @@ -55,7 +55,7 @@ aggregate_level_requirement(2, repo) :- * provenance information. */ aggregate_level_requirement(3, repo) :- - repository(repo, _,_,_,_,_,_), + repository(repo, _,_,_,_,_,_,_,_), check_passed(repo, "mcn_provenance_level_three_1"), aggregate_level_requirement(2, repo). @@ -63,7 +63,7 @@ aggregate_level_requirement(3, repo) :- * The release provenance passes verification. */ aggregate_level_requirement(4, repo) :- - repository(repo, _,_,_,_,_,_), + repository(repo, _,_,_,_,_,_,_,_), aggregate_level_requirement(3, repo), check_passed(repo, "mcn_provenance_level_three_1"), check_passed(repo, "mcn_trusted_builder_level_three_1"), @@ -94,9 +94,9 @@ aggregate_level_min_dependency_level(level, repo) <= aggregate_level_min_depende /** * The aggregate level for each repository that does not have any dependencies asserts the requirements are met. */ -aggregate_level(0, repo) :- repository(repo, _,_,_,_,_,_). +aggregate_level(0, repo) :- repository(repo, _,_,_,_,_,_,_,_). aggregate_level(level, repo) :- - repository(repo, name,_,_,_,_,_), + repository(repo, name,_,_,_,_,_,_,_), agg_levels(level), // this level's requirements aggregate_level_requirement(level, repo), @@ -108,7 +108,7 @@ aggregate_level(level, repo) :- * reach the required minimum level. */ aggregate_level(level, repo) :- - repository(repo, name,_,_,_,_,_), + repository(repo, name,_,_,_,_,_,_,_), agg_levels(level), // this level's requirements aggregate_level_requirement(level, repo), @@ -130,17 +130,17 @@ aggregate_level(level, repo) <= aggregate_level(higher_level, repo) :- meets_aggregate_level(level, repo) :- aggregate_level(real_level, repo), agg_levels(level), level <= real_level. Policy("aggregate_level_4", repo, reponame) :- - repository(repo, reponame,_,_,_,_,_), + repository(repo, reponame,_,_,_,_,_,_,_), meets_aggregate_level(4, repo). Policy("aggregate_level_3", repo, reponame) :- - repository(repo, reponame,_,_,_,_,_), + repository(repo, reponame,_,_,_,_,_,_,_), meets_aggregate_level(3, repo). Policy("aggregate_level_2", repo, reponame) :- - repository(repo, reponame,_,_,_,_,_), + repository(repo, reponame,_,_,_,_,_,_,_), meets_aggregate_level(2, repo). Policy("aggregate_level_1", repo, reponame) :- - repository(repo, reponame,_,_,_,_,_), + repository(repo, reponame,_,_,_,_,_,_,_), meets_aggregate_level(1, repo). diff --git a/src/macaron/policy_engine/prelude/helper_rules.dl b/src/macaron/policy_engine/prelude/helper_rules.dl index a8c922b54..7457f8f8c 100644 --- a/src/macaron/policy_engine/prelude/helper_rules.dl +++ b/src/macaron/policy_engine/prelude/helper_rules.dl @@ -25,7 +25,7 @@ is_check(check_name) :- check_result(_, check_name, _, _, _). * This fact exists iff a repository is hosted on a trusted public platform. */ .decl not_self_hosted_git(repo:number, message:symbol) -not_self_hosted_git(repo, message) :- repository(repo, name, remote, branch, release, commit_sha, commit_date), +not_self_hosted_git(repo, message) :- repository(repo, name, remote, branch, release, commit_sha, commit_date,_,_), match("^.*(github.com|gitlab.com).*$", remote), message=remote. /** @@ -40,7 +40,7 @@ transitive_dependency(repo, dependency) :- * Extract the id and full name from the repository relation. */ .decl is_repo(repo: number, repo_full_name: symbol) - is_repo(repo, name) :- repository(repo, name,_,_,_,_,_). + is_repo(repo, name) :- repository(repo, name,_,_,_,_,_,_,_). /** * ADT recursively describing a JSON object. diff --git a/src/macaron/slsa_analyzer/analyzer.py b/src/macaron/slsa_analyzer/analyzer.py index d8316cbb3..0104c2c0b 100644 --- a/src/macaron/slsa_analyzer/analyzer.py +++ b/src/macaron/slsa_analyzer/analyzer.py @@ -476,7 +476,10 @@ def get_analyze_ctx(self, branch_name: str, git_obj: Git, repo_id: str) -> Analy commit_date_str, ) - artifact_id, group_id = repo_id.split(":") + artifact_id = "" + group_id = "" + if defaults.getboolean("repofinder.java", "use_database") and not repo_id.startswith("http") and ":" in repo_id: + artifact_id, group_id = repo_id.split(":") # Initialize the analyzing context for this repository. analyze_ctx = AnalyzeContext( From 4668fc36ba524214d6988406f72f2936683a9615 Mon Sep 17 00:00:00 2001 From: Ben Selwyn-Smith Date: Thu, 1 Jun 2023 11:41:41 +1000 Subject: [PATCH 4/5] chore: updated test policy and database Signed-off-by: Ben Selwyn-Smith --- .../resources/facts/macaron.db.gz | Bin 7757 -> 7917 bytes .../resources/policies/testpolicy.dl | 12 ++++++------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/policy_engine/resources/facts/macaron.db.gz b/tests/policy_engine/resources/facts/macaron.db.gz index 92f4b6cec73e7a349a563e5618851127b371fc98..42426db3ad10fbacb2b6688dd340f06b8fa37fa5 100644 GIT binary patch literal 7917 zcmY*dWmFr=)}_UY7cE6wyhtd;{o)YZrML%ohv3o_C{UnyafcGzi%XCKg#f|biffR3 z?|nb+y>EWa?3puXowa86>^=057cVNWeXY^Zoh_^^JX~D>)|O~TIS5zkp@5(16wJw= zn2}7H)~rJ#@-Bdyal|=;mUt--<4nR!6B;e|1kY!pOfg$VFcVwfcONx#(x9GnM8BRt zVjGd|1+I{M=jNJFM#M;v1%sw2*gh55(<6TsIGc*3GYhvH1DmSeu#Vo~F`i5WU5t+j zu8ti6iXYiesw)N3vZ5EHnzGX-l)^&2RMVK1*ppEE-RL!6P!YZUe~Dx!lXV9;X40t0 zp;B^TQ?3Q5aiV8vf45r!|16YJu#ekXu~J z^%_;60>Uo4Z=yIpZ4lMQa?5&Wgoz__l6|>PyFLUSueS02j8N;!I6v(C9cJl4l!{0y zaGO}qt^WIO2bgz9c7Ie5V|t&xp%VMPfmR%IdUNU)ki9)wvxX^!V}z*_l|B&+$9n!x z{xw7-7=0N|oCAx{6r} z!G9NtCiM901hxJ|{|}-j`0xluF(ncG1EHM$zS6F6;=Qdj5~M2n zrR65iE^KHrGe00Q9ruCY#Io9UH*R|z-`}~q9GNa*x+2f5i)qcrEvuVv3@*+%2>v6p-b^)u*iksshjnX98FA{>r zC@v#&a2&RKF>|f}&CzrOc3!NB`9V&63~eProdVaa%Z~JTSVoPu<_A zD$3i50r8&HJvaF~gX(yT9Wz#z5v**QVgJ@tq1|?)B=v_T40u$sfy?s?eVT=3pMO6^ z;Jb}6!X~2VpdD-f%>uq*^KkUM&PVb>yE*^7z!Ko$TihBkTayTPl8=)Qc0oV1oXS4z z2T9a!L4{_=-bRkFk$+VY$kE5Wd;Xfm#!!j>V4Uet?2Oymk>C==^>unF0cN!+gKFA}cbs5tRH@ve@M!utC*6 z>seNMQln3w-4z#F98|S-NeyFog9EqYW>5>{uVC74)og$mw zYU2pIE+3^H;F_&RVC8-JcBxay1+#&UI6*a93i5N6R2<7`WxD4W;T3wutO9!ufoGbP zAZ09cMvCwI4WC_CBJx2_N9D`q>zQBzLEZZt)A7oCx|)Hq`wyK2vryff>d*v}mU{6x zZm%CU`4ltDIw!Tm4b_US!xd^0Y4LmnSsrz2cAXD9#a?fH@2noJ9^u=j%~H`@Rw>y@ zC=LhZq4;l8PJ<4C98mjbcdUTTCj7!;i^YZ2qFDqxC^TNgWD$+IoUM-RUiYJ%p%Mqj z!ZuOH%TA|V6G!VLt;u(|dLBUDIOx6#3w)TF_b$k@HCOsBT*RVO=nKc$qes9JdN1F9fYJ^2!4;n--a1337P#1HDv^()#4aB2rW?{^LD( zTI9}s^TG*OdM==~#0b+VPuRiwru`OXIdI&*9O+g{4|Fp-{yqF#JUXCstIP8=R8=-$ zccjy0GXUi3So-58-=i=lWX@U8#i6~iy*e-pE_m$f)I5DeQlif&SUcne8%KtK?9>^~0|bzIOt zWQQgctb$p>K#Y6>x1g~9#zVE0-&4lP?%kkXqW(pqYJzV69+uMoPt45Z(h^)t2dJoJ zX_|LmUr#@_ocCB+@3F<*hkA*;$jDPs$L!8*BeN%YJ0ZpL(x}7h-6@+zJtcY}{0(l5 zogS=s!$)Za(A8<09EE>3z7V_k1uoF6EU0Yb@9Fq)B?uh+SRqCYy5@`Tmn?{Qpv$FX9sA{5YT8-N@+0zB|mC0KVDi&(@%4~h5rcCbE#3kvC zg7%AlzUuD7p2WH7LB+Mj#In+D?5bHbt{(>UW_ieMibUYw-R=50?00w?+@(C z=3c3Mu^4=tvi0JGn)7h;@b)dF>sL$roP9tm8Id$enFK6X=!)=BlM7^5p7oOps; z&CN}7$^)u51&xJ1?WE^wV|uDU+GZ1IG4%eJp=Gzw{^q@?Cob%}Xa zt-Q4Mrp`p~{e>ECM>)b`PR=I?^+S84`j<7`b28sw%aC6Z+zh#g5>_zIP!8su>$-c8 zuFv6ji#WTZe^Gv|;)9-ZlvCLE1@WQ~-yymu!$iEmEc}3Vf#dPgEHyYaKBK4hC?6}M z=%>l}I?H&pEd?B)x@3cy`fi;m=+xtV!#70?y5koY6a9JDIw?_Oua&=DXGBO}TaC$T zF0N`SGzM}Oy9CAt$UXi{4|V<#k0Fci@!X%iJo|4%r0~ zeRn5ZA^YvCrzSVbOTWkWn_osIqaL_*{QZj>@wFQfIYXK7`gBRrzK#Mg$gOyw*WSP2a2_*V<)wg|Zuex__TdV~+x_C9$%{207et2j@}q;{z%g_qdlRAS6}Idr#+hIuNpydb;uA7WeziFUiJJswYmh#r zv-j%WyE_T9ON?ZqL#*?5n=L)9D5j<-t}4_QH)J9BObHzwk0GmglG(w41_L&XE;l-u zKYGl0W{|d-8)8C#=cC`K*C*`F?>A2N?%w>TdoyPsar_C99awHv)JVz_*D&1&1F!m< z#oW@T(A*hJa6d&NcTFsjA$ION32X0S@spb`v&_$qQL@L~?tq4GYS?t-CVf9;*xTi$ z6p=|MZ(clC_}ufZsgwy5yoqSNMn_vCn@Q)6qyU)W({mnI+^(z{uB@5ajdXVEA^)P2 zz~$820)jdl+Qb9IC`(uQKTjAZVhrG)y&hqky+?DqmiKqG`nqZ+L~rDGHR}dW6mY-9 z0C_P9X!{wk@_Buwx&e3Xu&#%=?KU`kT^NGoM;UNFy#EWa9elkZ{t6*9)3(Bykx z5B!!SdFZW9U^eO}{6XL#e57(k|y&?ih z&fjo$qs64;GBe#Lf%s36O*TJP+ti0{L>3#Db;L;3Jr>w2W(0!`BM<@WX-~hh?lNtE zle9{sZ)@YK&EjQvv8RqQR;}4emCvRf`U%J3-N^%Drl9J5*)h)=#I+xuP+;cse@XGR z1|HfMz%a!xt0+|A|M;>Xb${XaT%F_@4>y>nPye!2|1k~ssQMo6;tX(3EB_@yZ zWbWoxod+LJoj9WQl#FhCPn9KXV`;zM2=B%AwU6nCZq&^S>wEF!Lo7v3$~bIZjx1*#f0EuDT|Yx~mPh>hqsHCe z@zk3bG6TN+@Z;H=VG_xL|Z{IHO z5EB*~l-!?&w1%i&kI-QPEwOG=UQYkE$O^`|pX{25cc^=#)F%WjWYqssq?v8Vqd5IO zRW#adg6MHN5^XZ#g_2Ctq?y&TWF*K%!`IsOq!sZsmu&(d+IF!~V6tTRcoPzzxQF!- zYtX6-$<#{mB9Ey^7>#tq)Pp<=?7ZZabSQ$k70;Pd!_gDkddm}Ge6 zFJ7~-7S@)HStXBL`*hN6<9u#bAP+>XY}i>FobO(V9Hs4OCNpBA=u6b1Gdsi3&dKKO z@$Bd^c%&U>B&Q#6>_k#}h--@)j~%A1JdCXDr;7bn67R(x&|i26Br6oS!pS;FVKSQH z{#9Wvk>^BDf0aUY^Gn8y;BiJh`t@8hZnNB@?4asCnIsRrLReS}cf8B4| zUd-YjUkgZtx7hr@Dqt#}kqX$B%vLjXOPQ%y$L^pi(Y zt)WoUccX_#AJdsY^8-V%^r4)}&ij-f@8fc##<7+4x0#Vt($`0pAURW!5c}s0<16-x zIv<_;`Lh&jo6m6A=ulT9jI-~wHhi)&9~nRemRG%^ z)r-VU5vgDmaNTDR6YvEQu(;%Y38)yUM#xu_POI{_dW$-Ytf$oeakkctqlO1s&+vLF zyS+%`_39xZ55gA0_Z!$f6F1J7) zCHRazCQ|6{Z%uI8X$do@YubnFHu4za4+B{)(+rCajs(?L16<5ej}U!tt-~;FQhhm8s!}t$(r>mx&~YL$24a7u7*c zv(8JtPzazp#>zb*7(7QDoT9{d4 zA#&gi6~&pO`$&NylU^xWefaU@t3ZP_#BM>hDq;R`BCo3v;C=6E$lm(?4t1U2)9k!O z+3XA4npX?kK!$C6io*MScE^+fbyC9m9GyQWaAH0E_MMqWPuO>6BTI%9T*)n=XgoF{ z8jUS=qCMqH0;5Y>WU2Zu`ryQ4>~~3Isq@e^7!d&9V99V|;&@_g;s|?JnLrcX7ZZ_* z1zpCkS2Z%f^71Uof>BRZt$V3G^ZCddFKA@`APagkKcVtlZ!Ffx%#%N`>KzmOEGt5s zd9{Fv>jF2``>0NL6nt>Wkk3N4cN`@-GswSQ= z;^g=S9&hx?f%Mr6S4eyAbpssq$NPSWd(lq%&)QYk^ol{k*^*9h*vl_G(5n)c%OqBJ zah6^VQVTC0J~CdCVUQvtHwmp{OIt;wnvyHlPFRFIOrBgdY#vO`LzXrK!_y+QKpzsN zLvm|R(MW~zZ18qd#!>1K(r42pyQSQPy|C|BIe5E}7pBH!&oJ7)E1Z*LXJ}fRCYa%o zfzL*O<$nQ0S9yhLhEKa0uNL2@TBS)_N($|#kN@IoHb6Mkw=}n6&fGvCpq!MQzmu@L z+M=3o^v)KZrDTTr4fj=8-p0k^nbR=cTL@n7*q58rH|PvcS?Qm$sqFFQ>g8_w&Ejkzg2@sS9PZwJ>%VPyR7MHl-CIgjd;|l z8mC!yS{{D0XkAe}UVZS3t_`_VEZkHw{_{BB&&B*Wl6YxsH2<5e<FJw`bHq^xq;Gn_J643f6m@SZ-o?_1Jg z?O)AV)Y*&wgv+mRRGz)Ch5qXyeQK|HoroiH?5=l=I;5Df=C<<27`zZ_) z<5`rYW{^A5;7)#PTyit~*`w|#4|k9VhFQ5wAwtnr6ROTCcqT2K?@azpOnXEhx3(D= zWz{Du+)v(YBwNWC@3;W-bC@1~8uspg{M4X6{wAJtjlBQ4gV4dW^mGuNzt*gb(gUu? zr_nz$$BuRRW&EaEv(ojB{X68p=cpUPE=it}WU3d=vcl<25JCggfXip@+X?0EmpR7G z-qQoZt)*z=vT9E@10&RW<^elm@I3~WlE?V%jo7E9*HG_-wTxTL1`RU_vlUV~{}{A0 z(Le?c_j}O>N`G6*oxiI158Ps?q?dBbq{D)ZV;Xb3!}pu8HbkL|MeS5j2EJa;B47V{ z*QqGtE{fDx8q%X7Z*M;I!vvX?1CRlyiNnj=!^tv1e8h({5l2P+Tn5hpfnPFTe3fSF zoEtkz+?Qti?$&!_|A-?_b3z*(Ge0CI^O1K($?tVHVVIH7UE=^VML-%|&kvr%XWCjd z?C@oFiNkTjaM{c^()FFz8{T5b(DrUY?lu}`8>M;~ZF{vihdx3LA41*7` z+eO@~w-0N$MBT^|@V5MZF`UX}CyL5#!=Gt1=0NqAvg4K!Ye%v`mjtk%n1bC1 zQ0P}fakO){2X@1$A8D&bvis=^;Rcgq%a1LGJ0#}3W?_%jAPs#px zi9!oz;OARKwX=T?xQZiw6i5<44EL0!;kJNL*^%KAbLug=dDJB5gWqmg{bhG?Ed{Fa zn+y>MsGT|ewS=$uo$CL0y{JK_2s3Nwtp1bj8&+K0t5qH7+cz;jTMsGLZ?OI97p{y% zJU+FVtd`O_J5IW#xVfRESlZ|CXRt8k0@74;@E(U0X+lHh%bvsDFB@vr|M)tx!|;39 zQf6Z_Qfx8azzpy}Pmviz{kD4arpg4l!%3z3>XQ^lV%j_U}Ixvim5 zyH-U~`@qQkYp3#z?!1wj3JV7VrFBVJ;OR1A!H3`)CD}Q&Vu;+`=zawTpSbSX{Zq)y z{Y*+DKB4NGY#;mQ5N2%6pMmOxP{T~X?eqRkx`*xKSH9rRHjx{~lZ{OuCfr`?Wz@X; z<-V^(0A}7Cx+bNcP+q*e!5Sv!vDCiu`#jnZ2XvZs-Y(9OqUNR{Xhh(9TCTUR%r5ibpWOnIQfM5*i6|^R4n`&yf z(S2A6vF3+U(IgIvMzec(@Z!vAT$4f{n<@e|6hjBq3R%9E^~l5yO0W6Fw(qR{NLWnK zaIxQ055EJ91oq5lWa@;9fK$HrYX(cY99XEc7b;f0xxfWuxTmmE;1Rtn@X^oKc}W1M zoHK}u=V9HVBB||Hv=MgsEVYHTagIgRCB$W!vs-X-@`+^Y2IG`J==yyDiC!3nZ+@ga z(WnJE1|7rv!@-;8fSdZp#z0rez5}k)pAT=?>V|$4K*D;>$`Zr&Uaf3q^mslW9@+y> ziDS`v(M^A2dvzxCDx@{CN-2qpq@bQDbSOd{BQ)}q;u)KP{Wmni)+QWHwg)X&M-C>I ziJMi~ED>bt(vPj{{w!hwF|v_TO?!Dy=?_b@i<*Cx;mltpJdfZdb7y~WLl2oR*9=Kn h;?vrfPB>T?y#Hx^rNmsRzWI0uE_WNFL_>Ry_J1+aRVV-e literal 7757 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 Date: Thu, 15 Jun 2023 15:48:25 +1000 Subject: [PATCH 5/5] chore: switched to ORM queries Signed-off-by: Ben Selwyn-Smith --- src/macaron/dependency_analyzer/dependency_resolver.py | 7 ++++--- .../java_repo_finder/test_java_repo_finder.py | 4 +++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/macaron/dependency_analyzer/dependency_resolver.py b/src/macaron/dependency_analyzer/dependency_resolver.py index 769b71989..0c67b60ad 100644 --- a/src/macaron/dependency_analyzer/dependency_resolver.py +++ b/src/macaron/dependency_analyzer/dependency_resolver.py @@ -15,6 +15,7 @@ from macaron.config.defaults import defaults from macaron.config.target_config import Configuration from macaron.database.database_manager import DatabaseManager +from macaron.database.table_definitions import RepositoryTable from macaron.dependency_analyzer.java_repo_finder import find_java_repo from macaron.errors import MacaronError from macaron.output_reporter.scm import SCMStatus @@ -190,9 +191,9 @@ def _find_repo(db_man: DatabaseManager | None, item: DependencyInfo) -> None: if db_man and defaults.getboolean("repofinder.java", "use_database"): # Perform database lookup - query = sqlalchemy.text( - "SELECT remote_path FROM _repository WHERE namespace = :group and name = :artifact" - ).bindparams(group=item["group"], artifact=item["name"]) + query = sqlalchemy.select(RepositoryTable.remote_path).where( + RepositoryTable.namespace == item["group"], RepositoryTable.name == item["name"] + ) result: sqlalchemy.engine.cursor.CursorResult = db_man.execute_and_return(query) row = result.first() if row and row.remote_path: diff --git a/tests/dependency_analyzer/java_repo_finder/test_java_repo_finder.py b/tests/dependency_analyzer/java_repo_finder/test_java_repo_finder.py index 47d0aa484..a728dd73b 100644 --- a/tests/dependency_analyzer/java_repo_finder/test_java_repo_finder.py +++ b/tests/dependency_analyzer/java_repo_finder/test_java_repo_finder.py @@ -81,7 +81,9 @@ def test_java_repo_database(database_fixture: DatabaseManager) -> None: # pylin table = RepositoryTable(**data) database_fixture.add(table) database_fixture.session.commit() - query = sqlalchemy.text("SELECT remote_path FROM _repository WHERE namespace = namespace and name = name") + query = sqlalchemy.select(RepositoryTable).where( + RepositoryTable.namespace == "namespace", RepositoryTable.name == "name" + ) result = database_fixture.execute_and_return(query) row = result.first() assert row is not None