Skip to content

Commit

Permalink
feat: create mapping for ubi recommendation
Browse files Browse the repository at this point in the history
Signed-off-by: Olga Lavtar <olavtar@redhat.com>
  • Loading branch information
xieshenzh committed Mar 18, 2024
1 parent 026aec5 commit 3eb0606
Show file tree
Hide file tree
Showing 8 changed files with 441 additions and 165 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ protected DependencyTree buildTree(InputStream input) {
if (bom.getComponents() != null) {
componentPurls.putAll(
bom.getComponents().stream()
.filter(c -> c.getBomRef() != null)
.filter(c -> c.getBomRef() != null && c.getPurl() != null)
.collect(Collectors.toMap(Component::getBomRef, c -> new PackageRef(c.getPurl()))));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@
import org.apache.camel.Body;
import org.apache.camel.Exchange;
import org.apache.camel.ExchangeProperty;
import org.eclipse.microprofile.config.inject.ConfigProperty;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.redhat.exhort.api.PackageRef;
import com.redhat.exhort.api.v4.ProviderStatus;
import com.redhat.exhort.integration.Constants;
import com.redhat.exhort.integration.providers.ProviderResponseHandler;
import com.redhat.exhort.integration.trustedcontent.ubi.UBIRecommendation;
import com.redhat.exhort.model.DependencyTree;
import com.redhat.exhort.model.ProviderResponse;
import com.redhat.exhort.model.trustedcontent.IndexedRecommendation;
Expand All @@ -60,8 +60,7 @@ public class TcResponseHandler extends ProviderResponseHandler {

@Inject ObjectMapper mapper;

@ConfigProperty(name = "trustedcontent.recommended.ubi")
String recommendedUBIPurl;
@Inject UBIRecommendation ubiRecommendation;

public TrustedContentResponse parseResponse(
@Body byte[] tcResponse, @ExchangeProperty(Constants.SBOM_ID_PROPERTY) String sbomId)
Expand Down Expand Up @@ -116,14 +115,17 @@ private Map<PackageRef, IndexedRecommendation> getUBIRecommendation(String sbomI
return Collections.emptyMap();
}

PackageRef pkgRef = new PackageRef(sbomId);
var pkgRef = new PackageRef(sbomId);
if (!Constants.OCI_PURL_TYPE.equals(pkgRef.purl().getType())) {
return Collections.emptyMap();
}

IndexedRecommendation recommendation =
new IndexedRecommendation(new PackageRef(recommendedUBIPurl), null);
return Collections.singletonMap(pkgRef, recommendation);
var recommendedUBIPurl = ubiRecommendation.mapping().get(pkgRef.name());
if (recommendedUBIPurl != null) {
var recommendation = new IndexedRecommendation(new PackageRef(recommendedUBIPurl), null);
return Collections.singletonMap(pkgRef, recommendation);
}
return Collections.emptyMap();
}

@Override
Expand Down
6 changes: 3 additions & 3 deletions src/test/java/com/redhat/exhort/integration/AnalysisTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -668,9 +668,9 @@ public void testBatchSBOMAllWithToken(String sbom) {
.asPrettyString();

assertJson("reports/batch_report_all_token.json", body);
verifySnykRequest(OK_TOKEN, 2);
verifyOssRequest(OK_USER, OK_TOKEN, 2);
verifyOsvNvdRequest(2);
verifySnykRequest(OK_TOKEN, 3);
verifyOssRequest(OK_USER, OK_TOKEN, 3);
verifyOsvNvdRequest(3);
}

private void assertScanned(Scanned scanned) {
Expand Down
43 changes: 43 additions & 0 deletions src/test/java/com/redhat/exhort/integration/HtmlReportTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@
import com.gargoylesoftware.htmlunit.WebClient;
import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.DomNodeList;
import com.gargoylesoftware.htmlunit.html.HtmlAnchor;
import com.gargoylesoftware.htmlunit.html.HtmlButton;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlHeading2;
import com.gargoylesoftware.htmlunit.html.HtmlHeading4;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
Expand Down Expand Up @@ -317,6 +319,47 @@ public void testHtmlError() throws IOException {
verifyNoInteractionsWithOSS();
}

@Test
public void testBatchHtmlWithToken() throws IOException {
stubAllProviders();

String body =
given()
.header(CONTENT_TYPE, CycloneDxMediaType.APPLICATION_CYCLONEDX_JSON)
.body(loadBatchSBOMFile(CYCLONEDX))
.header("Accept", MediaType.TEXT_HTML)
.header(Constants.SNYK_TOKEN_HEADER, OK_TOKEN)
.header(Constants.OSS_INDEX_USER_HEADER, OK_USER)
.header(Constants.OSS_INDEX_TOKEN_HEADER, OK_TOKEN)
.when()
.post("/api/v4/batch-analysis")
.then()
.assertThat()
.statusCode(200)
.contentType(MediaType.TEXT_HTML)
.header(
Constants.EXHORT_REQUEST_ID_HEADER,
MatchesPattern.matchesPattern(REGEX_MATCHER_REQUEST_ID))
.extract()
.body()
.asString();

HtmlPage page = extractPage(body);
// Find the root div element with id "root"
HtmlElement rootElement = page.getFirstByXPath("//div[@id='root']");

// Verify multi tab layout
List<HtmlElement> sectionElements = rootElement.getByXPath("./section");
assertEquals(1, sectionElements.size());
List<HtmlAnchor> anchorElements =
page.getByXPath(
"//a[contains(@href, 'https://catalog.redhat.com/software/containers/ubi9/')]");
assertTrue(!anchorElements.isEmpty(), "At least one href contains the desired substring");

verifySnykRequest(OK_TOKEN, 3);
verifyOssRequest(OK_USER, OK_TOKEN, 3);
}

private HtmlTableBody getTableBodyForDependency(String depRef, DomElement table) {
List<HtmlTableBody> tbodies = table.getByXPath(".//tbody");
return tbodies.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,11 @@
import java.util.Map;
import java.util.Set;

import org.eclipse.microprofile.config.inject.ConfigProperty;
import org.junit.jupiter.api.Test;

import com.redhat.exhort.api.PackageRef;
import com.redhat.exhort.integration.Constants;
import com.redhat.exhort.integration.trustedcontent.ubi.UBIRecommendation;
import com.redhat.exhort.model.trustedcontent.IndexedRecommendation;

import io.quarkus.test.junit.QuarkusTest;
Expand All @@ -47,8 +47,7 @@ class TcResponseHandlerTest {

@Inject TcResponseHandler handler;

@ConfigProperty(name = "trustedcontent.recommended.ubi")
String recommendedUBIPurl;
@Inject UBIRecommendation mapping;

@Test
void testAggregation() throws IOException {
Expand Down Expand Up @@ -114,14 +113,15 @@ void testEmpty() throws IOException {

@Test
void testSbomId() throws IOException {
String sbomId = "pkg:oci/quay.io/test-app@0.0.1";
String sbomId = "pkg:oci/alpine@0.0.1";
handler.ubiRecommendation = mapping;
var response =
handler.parseResponse(
getClass()
.getClassLoader()
.getResourceAsStream("__files/trustedcontent/empty_report.json")
.readAllBytes(),
"pkg:oci/quay.io/test-app@0.0.1");
sbomId);
assertNotNull(response);
assertTrue(response.status().getOk());
assertEquals("OK", response.status().getMessage());
Expand All @@ -130,17 +130,19 @@ void testSbomId() throws IOException {

PackageRef sbomRef = new PackageRef(sbomId);
IndexedRecommendation recommendation =
new IndexedRecommendation(new PackageRef(recommendedUBIPurl), null);
new IndexedRecommendation(new PackageRef(expectedUBIRecommendation), null);
assertEquals(1, response.recommendations().size());
assertEquals(recommendation, response.recommendations().get(sbomRef));
}

private static final record ExpectedRecommendation(String version, Set<String> cves) {}

private static final String expectedUBIRecommendation = "pkg:oci/ubi@0.0.2";

public static class SbomIdTestProfile implements QuarkusTestProfile {
@Override
public Map<String, String> getConfigOverrides() {
return Map.of("trustedcontent.recommended.ubi", "pkg:oci/quay.io/test-app@0.0.2");
return Map.of("trustedcontent.recommendation.ubi.mapping.alpine", expectedUBIRecommendation);
}
}
}
76 changes: 70 additions & 6 deletions src/test/resources/__files/reports/batch_report_all_token.json
Original file line number Diff line number Diff line change
Expand Up @@ -839,7 +839,71 @@
}
}
},
"pkg:oci/quay.io/default-app@0.0.1": {
"pkg:oci/default-app@sha256:7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?repository_url=quay.io/default-app&tag=0.0.1": {
"scanned": {
"total": 2,
"direct": 2,
"transitive": 0
},
"providers": {
"oss-index": {
"status": {
"ok": false,
"name": "oss-index",
"code": 401,
"message": "Unauthorized: Verify the provided credentials are valid."
}
},
"trusted-content": {
"status": {
"ok": true,
"name": "trusted-content",
"code": 200,
"message": "OK"
}
},
"osv-nvd": {
"status": {
"ok": true,
"name": "osv-nvd",
"code": 200,
"message": "OK"
}
},
"snyk": {
"status": {
"ok": true,
"name": "snyk",
"code": 200,
"message": "OK"
},
"sources": {
"snyk": {
"summary": {
"direct": 0,
"transitive": 0,
"total": 0,
"dependencies": 0,
"critical": 0,
"high": 0,
"medium": 0,
"low": 0,
"remediations": 0,
"recommendations": 0,
"unscanned": 1
},
"unscanned": [
{
"ref": "pkg:oci/default-app@sha256%3A7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?repository_url=quay.io%2Fdefault-app&tag=0.0.1",
"reason": "unsupported-pkg-type"
}
]
}
}
}
}
},
"pkg:oci/debian@sha256:7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?tag=0.0.1": {
"scanned": {
"total": 2,
"direct": 2,
Expand Down Expand Up @@ -886,8 +950,8 @@
},
"dependencies": [
{
"ref": "pkg:oci/quay.io/default-app@0.0.1",
"recommendation": "pkg:oci/registry.access.redhat.com/ubi9/ubi@latest"
"ref": "pkg:oci/debian@sha256%3A7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?tag=0.0.1",
"recommendation": "pkg:oci/ubi@sha256%3Af5983f7c7878cc9b26a3962be7756e3c810e9831b0b9f9613e6f6b445f884e74?arch=amd64&repository_url=registry.access.redhat.com%2Fubi9%2Fubi&tag=9.3-1552"
}
]
}
Expand Down Expand Up @@ -917,13 +981,13 @@
},
"dependencies": [
{
"ref": "pkg:oci/quay.io/default-app@0.0.1",
"recommendation": "pkg:oci/registry.access.redhat.com/ubi9/ubi@latest"
"ref": "pkg:oci/debian@sha256%3A7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?tag=0.0.1",
"recommendation": "pkg:oci/ubi@sha256%3Af5983f7c7878cc9b26a3962be7756e3c810e9831b0b9f9613e6f6b445f884e74?arch=amd64&repository_url=registry.access.redhat.com%2Fubi9%2Fubi&tag=9.3-1552"
}
],
"unscanned": [
{
"ref": "pkg:oci/quay.io/default-app@0.0.1",
"ref": "pkg:oci/debian@sha256%3A7c288032ecf3319045d9fa538c3b0cc868a320d01d03bce15b99c2c336319994?tag=0.0.1",
"reason": "unsupported-pkg-type"
}
]
Expand Down
Loading

0 comments on commit 3eb0606

Please sign in to comment.