From c62928bd38daf65a9b0558b6af2c7509aa879733 Mon Sep 17 00:00:00 2001 From: Olga Lavtar Date: Fri, 21 Jun 2024 13:45:13 -0700 Subject: [PATCH] fix: fix for the component analysis to show gradle resolved version for the package in the dropdown Signed-off-by: Olga Lavtar --- .../exhort/providers/GradleProvider.java | 81 +++++++++++++++---- .../depTree.txt | 2 +- .../expected_component_sbom.json | 22 ++--- .../deps_with_ignore_named_params/depTree.txt | 2 +- .../expected_component_sbom.json | 22 ++--- 5 files changed, 90 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/redhat/exhort/providers/GradleProvider.java b/src/main/java/com/redhat/exhort/providers/GradleProvider.java index 3b4ae45..5579de4 100644 --- a/src/main/java/com/redhat/exhort/providers/GradleProvider.java +++ b/src/main/java/com/redhat/exhort/providers/GradleProvider.java @@ -251,27 +251,78 @@ private Sbom buildSbomFromTextFormat( List lines = extractLines(textFormatFile, configName); List arrayForSbom = new ArrayList<>(); - for (String line : lines) { - line = line.replaceAll("---", "-").replaceAll(" ", " "); - line = line.replaceAll(":(.*):(.*) -> (.*)$", ":$1:$3"); - line = line.replaceAll("(.*):(.*):(.*)$", "$1:$2:jar:$3"); - line = line.replaceAll(" \\(n\\)$", ""); - line = line.replaceAll(" \\(\\*\\)", ""); - line = line.replaceAll("$", ":compile"); - if (containsVersion(line)) { - arrayForSbom.add(line); + for (String line : lines) { + line = line.replaceAll("---", "-").replaceAll(" ", " "); + line = line.replaceAll(":(.*):(.*) -> (.*)$", ":$1:$3"); + line = line.replaceAll("(.*):(.*):(.*)$", "$1:$2:jar:$3"); + line = line.replaceAll(" \\(n\\)$", ""); + line = line.replaceAll(" \\(\\*\\)", ""); + line = line.replaceAll("$", ":compile"); + if (containsVersion(line)) { + arrayForSbom.add(line); + } + } + // remove duplicates for component analysis + if (List.of("api", "implementation", "compileOnly").contains(configName)) { + removeDuplicateIfExists(arrayForSbom, textFormatFile); + arrayForSbom = performManifestVersionsCheck(arrayForSbom, textFormatFile); } - } - // remove duplicates for component analysis - if (List.of("api", "implementation", "compile").contains(configName)) { - removeDuplicateIfExists(arrayForSbom, textFormatFile); - } String[] array = arrayForSbom.toArray(new String[0]); parseDependencyTree(root, 0, array, sbom); return sbom; } + private List performManifestVersionsCheck(List arrayForSbom, Path textFormatFile) throws IOException { + + List runtimeClasspathLines = extractLines(textFormatFile, "runtimeClasspath"); + Map runtimeClasspathVersions = parseDependencyVersions(runtimeClasspathLines); + List updatedLines = updateDependencies(arrayForSbom, runtimeClasspathVersions); + + return updatedLines; + } + + private Map parseDependencyVersions(List lines) { + Map dependencyVersions = new HashMap<>(); + + for (String line : lines) { + if (line.contains("->")) { + String[] splitLine = line.split("---"); + if (splitLine.length > 1) { + String dependencyPart = splitLine[1].trim(); + String[] parts = dependencyPart.split("-> "); + // Extract the dependency name (without the version) and the resolved version + String dependency = parts[0].substring(0, parts[0].lastIndexOf(':')).trim(); + String version = parts[1].split(" ")[0].trim(); + dependencyVersions.put(dependency, version); + } + } + } + + return dependencyVersions; + } + + private List updateDependencies(List lines, Map runtimeClasspathVersions) { + List updatedLines = new ArrayList<>(); + for (String line : lines) { + PackageURL packageURL = parseDep(line); + String[] parts = line.split(":"); + if (parts.length >= 4) { + String dependencyKey = packageURL.getNamespace() + ":" + packageURL.getName(); // Extract dependency key + if (runtimeClasspathVersions.containsKey(dependencyKey)) { + String newVersion = runtimeClasspathVersions.get(dependencyKey); + parts[3] = newVersion; // Replace version with the resolved version + updatedLines.add(String.join(":", parts)); + } else { + updatedLines.add(line); // Keep the original line if no update is needed + } + } else { + updatedLines.add(line); // Keep the original line if it doesn't match the expected pattern + } + } + return updatedLines; + } + private void removeDuplicateIfExists(List arrayForSbom, Path theContent) { Consumer removeDuplicateFunction = dependency -> { @@ -413,7 +464,7 @@ public Content provideComponent(Path manifestPath) throws IOException { Path tempFile = getDependencies(manifestPath); Map propertiesMap = extractProperties(manifestPath); - String[] configurationNames = {"api", "implementation", "compile"}; + String[] configurationNames = {"api", "implementation", "compileOnly", "runtimeOnly"}; String configName = null; for (String configurationName : configurationNames) { diff --git a/src/test/resources/tst_manifests/gradle/deps_with_ignore_full_specification/depTree.txt b/src/test/resources/tst_manifests/gradle/deps_with_ignore_full_specification/depTree.txt index ada09b9..5623cf2 100644 --- a/src/test/resources/tst_manifests/gradle/deps_with_ignore_full_specification/depTree.txt +++ b/src/test/resources/tst_manifests/gradle/deps_with_ignore_full_specification/depTree.txt @@ -2586,5 +2586,5 @@ No dependencies A web-based, searchable dependency report is available by adding the --scan option. -BUILD SUCCESSFUL in 714ms +BUILD SUCCESSFUL in 632ms 1 actionable task: 1 executed diff --git a/src/test/resources/tst_manifests/gradle/deps_with_ignore_full_specification/expected_component_sbom.json b/src/test/resources/tst_manifests/gradle/deps_with_ignore_full_specification/expected_component_sbom.json index 8c394ed..f9ce8f2 100644 --- a/src/test/resources/tst_manifests/gradle/deps_with_ignore_full_specification/expected_component_sbom.json +++ b/src/test/resources/tst_manifests/gradle/deps_with_ignore_full_specification/expected_component_sbom.json @@ -3,7 +3,7 @@ "specVersion" : "1.4", "version" : 1, "metadata" : { - "timestamp" : "2024-04-02T22:31:28Z", + "timestamp" : "2024-06-21T20:31:39Z", "component" : { "group" : "org.acme.dbaas", "name" : "postgresql-orm-quarkus", @@ -41,10 +41,10 @@ { "group" : "io.quarkus", "name" : "quarkus-resteasy", - "version" : "2.13.5.Final", - "purl" : "pkg:maven/io.quarkus/quarkus-resteasy@2.13.5.Final", + "version" : "2.13.7.Final", + "purl" : "pkg:maven/io.quarkus/quarkus-resteasy@2.13.7.Final", "type" : "library", - "bom-ref" : "pkg:maven/io.quarkus/quarkus-resteasy@2.13.5.Final" + "bom-ref" : "pkg:maven/io.quarkus/quarkus-resteasy@2.13.7.Final" }, { "group" : "io.quarkus", @@ -65,10 +65,10 @@ { "group" : "io.quarkus", "name" : "quarkus-vertx-http", - "version" : "2.13.5.Final", - "purl" : "pkg:maven/io.quarkus/quarkus-vertx-http@2.13.5.Final", + "version" : "2.13.7.Final", + "purl" : "pkg:maven/io.quarkus/quarkus-vertx-http@2.13.7.Final", "type" : "library", - "bom-ref" : "pkg:maven/io.quarkus/quarkus-vertx-http@2.13.5.Final" + "bom-ref" : "pkg:maven/io.quarkus/quarkus-vertx-http@2.13.7.Final" }, { "group" : "io.quarkus", @@ -117,10 +117,10 @@ "dependsOn" : [ "pkg:maven/io.quarkus/quarkus-hibernate-orm@2.13.5.Final", "pkg:maven/io.quarkus/quarkus-agroal@2.13.5.Final", - "pkg:maven/io.quarkus/quarkus-resteasy@2.13.5.Final", + "pkg:maven/io.quarkus/quarkus-resteasy@2.13.7.Final", "pkg:maven/io.quarkus/quarkus-resteasy-jackson@2.13.5.Final", "pkg:maven/io.quarkus/quarkus-jdbc-postgresql@2.13.5.Final", - "pkg:maven/io.quarkus/quarkus-vertx-http@2.13.5.Final", + "pkg:maven/io.quarkus/quarkus-vertx-http@2.13.7.Final", "pkg:maven/io.quarkus/quarkus-kubernetes-service-binding@2.13.5.Final", "pkg:maven/io.quarkus/quarkus-container-image-docker@2.13.5.Final", "pkg:maven/jakarta.validation/jakarta.validation-api@2.0.2", @@ -137,7 +137,7 @@ "dependsOn" : [ ] }, { - "ref" : "pkg:maven/io.quarkus/quarkus-resteasy@2.13.5.Final", + "ref" : "pkg:maven/io.quarkus/quarkus-resteasy@2.13.7.Final", "dependsOn" : [ ] }, { @@ -149,7 +149,7 @@ "dependsOn" : [ ] }, { - "ref" : "pkg:maven/io.quarkus/quarkus-vertx-http@2.13.5.Final", + "ref" : "pkg:maven/io.quarkus/quarkus-vertx-http@2.13.7.Final", "dependsOn" : [ ] }, { diff --git a/src/test/resources/tst_manifests/gradle/deps_with_ignore_named_params/depTree.txt b/src/test/resources/tst_manifests/gradle/deps_with_ignore_named_params/depTree.txt index 734869d..0b00d53 100644 --- a/src/test/resources/tst_manifests/gradle/deps_with_ignore_named_params/depTree.txt +++ b/src/test/resources/tst_manifests/gradle/deps_with_ignore_named_params/depTree.txt @@ -2586,5 +2586,5 @@ No dependencies A web-based, searchable dependency report is available by adding the --scan option. -BUILD SUCCESSFUL in 655ms +BUILD SUCCESSFUL in 594ms 1 actionable task: 1 executed diff --git a/src/test/resources/tst_manifests/gradle/deps_with_ignore_named_params/expected_component_sbom.json b/src/test/resources/tst_manifests/gradle/deps_with_ignore_named_params/expected_component_sbom.json index 392045e..f1c5b6d 100644 --- a/src/test/resources/tst_manifests/gradle/deps_with_ignore_named_params/expected_component_sbom.json +++ b/src/test/resources/tst_manifests/gradle/deps_with_ignore_named_params/expected_component_sbom.json @@ -3,7 +3,7 @@ "specVersion" : "1.4", "version" : 1, "metadata" : { - "timestamp" : "2024-04-02T22:35:27Z", + "timestamp" : "2024-06-21T20:33:14Z", "component" : { "group" : "org.acme.dbaas", "name" : "postgresql-orm-quarkus", @@ -41,10 +41,10 @@ { "group" : "io.quarkus", "name" : "quarkus-resteasy", - "version" : "2.13.5.Final", - "purl" : "pkg:maven/io.quarkus/quarkus-resteasy@2.13.5.Final", + "version" : "2.13.7.Final", + "purl" : "pkg:maven/io.quarkus/quarkus-resteasy@2.13.7.Final", "type" : "library", - "bom-ref" : "pkg:maven/io.quarkus/quarkus-resteasy@2.13.5.Final" + "bom-ref" : "pkg:maven/io.quarkus/quarkus-resteasy@2.13.7.Final" }, { "group" : "io.quarkus", @@ -65,10 +65,10 @@ { "group" : "io.quarkus", "name" : "quarkus-vertx-http", - "version" : "2.13.5.Final", - "purl" : "pkg:maven/io.quarkus/quarkus-vertx-http@2.13.5.Final", + "version" : "2.13.7.Final", + "purl" : "pkg:maven/io.quarkus/quarkus-vertx-http@2.13.7.Final", "type" : "library", - "bom-ref" : "pkg:maven/io.quarkus/quarkus-vertx-http@2.13.5.Final" + "bom-ref" : "pkg:maven/io.quarkus/quarkus-vertx-http@2.13.7.Final" }, { "group" : "io.quarkus", @@ -117,10 +117,10 @@ "dependsOn" : [ "pkg:maven/io.quarkus/quarkus-hibernate-orm@2.13.5.Final", "pkg:maven/io.quarkus/quarkus-agroal@2.13.5.Final", - "pkg:maven/io.quarkus/quarkus-resteasy@2.13.5.Final", + "pkg:maven/io.quarkus/quarkus-resteasy@2.13.7.Final", "pkg:maven/io.quarkus/quarkus-resteasy-jackson@2.13.5.Final", "pkg:maven/io.quarkus/quarkus-jdbc-postgresql@2.13.5.Final", - "pkg:maven/io.quarkus/quarkus-vertx-http@2.13.5.Final", + "pkg:maven/io.quarkus/quarkus-vertx-http@2.13.7.Final", "pkg:maven/io.quarkus/quarkus-kubernetes-service-binding@2.13.5.Final", "pkg:maven/io.quarkus/quarkus-container-image-docker@2.13.5.Final", "pkg:maven/jakarta.validation/jakarta.validation-api@2.0.2", @@ -137,7 +137,7 @@ "dependsOn" : [ ] }, { - "ref" : "pkg:maven/io.quarkus/quarkus-resteasy@2.13.5.Final", + "ref" : "pkg:maven/io.quarkus/quarkus-resteasy@2.13.7.Final", "dependsOn" : [ ] }, { @@ -149,7 +149,7 @@ "dependsOn" : [ ] }, { - "ref" : "pkg:maven/io.quarkus/quarkus-vertx-http@2.13.5.Final", + "ref" : "pkg:maven/io.quarkus/quarkus-vertx-http@2.13.7.Final", "dependsOn" : [ ] }, {