Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/resources/freemarker/templates/generated/main.js

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -87,13 +87,14 @@ public void testHtmlWithoutToken() throws IOException {
page = snykSourceBtn.click();

DomNodeList<DomElement> tables = page.getElementsByTagName("table");
assertEquals(2, tables.size());
System.out.println("tableSize: " + tables.size());
assertEquals(1, tables.size());
DomElement snykTable = tables.get(0);
HtmlTableBody tbody = getTableBodyForDependency("io.quarkus:quarkus-hibernate-orm", snykTable);
assertNotNull(tbody);
page = expandTransitiveTableDataCell(tbody);
tables = page.getElementsByTagName("table");
assertEquals(3, tables.size());
assertEquals(2, tables.size());
snykTable = tables.get(1);
List<HtmlTableBody> tbodies = snykTable.getByXPath(".//tbody");
HtmlTableBody privateIssueTbody =
Expand All @@ -117,8 +118,7 @@ public void testHtmlWithoutToken() throws IOException {
page = ossIndexSourceBtn.click();

List<HtmlHeading2> headings = page.getByXPath("//div[@class='pf-v5-c-empty-state__title']/h2");
assertEquals("Set up oss-index", headings.get(1).getTextContent());
assertEquals("No results found", headings.get(0).getTextContent());
assertEquals("Set up oss-index", headings.get(0).getTextContent());

verifySnykRequest(null);
}
Expand Down
20 changes: 12 additions & 8 deletions ui/src/api/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ export interface Dependency {
ref: string;
issues?: Vulnerability[];
transitive?: TransitiveDependency[];
highestVulnerability: Vulnerability | null;
recommendation?: string | null;
highestVulnerability?: Vulnerability | null;
}

export function getSources(report: Report): SourceItem[] {
Expand All @@ -77,11 +78,13 @@ export function getSources(report: Report): SourceItem[] {
} as SourceItem);
});
} else {
result.push({
provider: provider,
source: provider,
report: {} as SourceReport,
} as SourceItem);
if(provider !== 'trusted-content') {
result.push({
provider: provider,
source: provider,
report: {} as SourceReport,
} as SourceItem);
}
}
});
return result.sort((a, b) => {
Expand Down Expand Up @@ -134,8 +137,9 @@ export interface Vulnerability {
remediation?: {
fixedIn?: string[] | null;
trustedContent?: {
mavenPackage: string | null;
productStatus: string | null;
ref: string | '';
status: string | null;
justification: string | null;
};
};
}
Expand Down
55 changes: 9 additions & 46 deletions ui/src/components/RemediationLink.tsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,24 @@
import React, {useReducer} from 'react';
import {Button, ButtonVariant, Icon, Modal, ModalVariant} from '@patternfly/react-core';
import React from 'react';
import {Icon} from '@patternfly/react-core';

import {extractDependencyVersion} from '../utils/utils';
import {extractDependencyVersion, tcRemediationLink} from '../utils/utils';
import SecurityCheckIcon from '../images/security-check.svg';

interface RemediationLinkProps {
packageName: string;
packageName: string | '';
cves: string[];
}

export const RemediationLink: React.FC<RemediationLinkProps> = ({ packageName, cves }) => {
// const appContext = useAppContext();

const [isModalOpen, toggleModal] = useReducer((state) => !state, false);

return (
<>
<Button variant={ButtonVariant.link} onClick={toggleModal} style={{paddingLeft: "initial"}}>
<Icon isInline status="success">
<img src={SecurityCheckIcon} alt="Security Check Icon" />
</Icon>&nbsp;
<Icon isInline status="success">
<img src={SecurityCheckIcon} alt="Security Check Icon" />
</Icon>&nbsp;
<a href={tcRemediationLink(packageName)} target="_blank" rel="noreferrer">
{extractDependencyVersion(packageName)}
</Button>

<Modal
variant={ModalVariant.small}
title={extractDependencyVersion(packageName)}
isOpen={isModalOpen}
onClose={toggleModal}
actions={[
...cves.map((cve) => (
<Button
key="confirm"
component="a"
target="_blank"
rel="noreferrer"
variant={ButtonVariant.secondary}
// href={`${appContext.vexPath}${cve}-Quarkus.json`}
>
VEX
</Button>
)),
<Button
key="cancel"
component="a"
target="_blank"
rel="noreferrer"
variant={ButtonVariant.secondary}
// href={appContext.sbomPath}
>
SBOM
</Button>,
]}
>
Click either VEX or SBOM to download the corresponding file type. You can also click the
package name to view more information in Red Hat's Maven repository.
</Modal>
</a>
</>
);
};
39 changes: 28 additions & 11 deletions ui/src/components/SummaryCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export const SummaryCard = () => {
<ExclamationTriangleIcon style={{fill: "#f0ab00"}}/>
</Icon>&nbsp;Red Hat Overview of security Issues
</Title>
<Divider />
<Divider/>
<GridItem>
<Card isFlat isFullHeight>
<CardHeader>
Expand All @@ -52,7 +52,7 @@ export const SummaryCard = () => {
<DescriptionList isAutoFit style={{paddingTop: "10px"}}>
{
getSources(appContext.report).map((source, index) => {
if(Object.keys(source.report).length > 0){
if (Object.keys(source.report).length > 0) {
return (
<DescriptionListGroup key={index}>
<DescriptionListTerm style={{fontSize: "large"}}>{getSourceName(source)}</DescriptionListTerm>
Expand Down Expand Up @@ -84,19 +84,34 @@ export const SummaryCard = () => {
<CardBody>
<DescriptionListDescription>
<List isPlain>
<ListItem>
<Icon isInline status="success">
<img src={SecurityCheckIcon} alt="Security Check Icon"/>
</Icon>&nbsp;
There are no available Red Hat remediations for your SBOM at this time
</ListItem>
{getSources(appContext.report).map((source, index) => {
if (Object.keys(source.report).length > 0) {
return (
<ListItem>
<Icon isInline status="success">
<img src={SecurityCheckIcon} alt="Security Check Icon"/>
</Icon>&nbsp;{source.report.summary.remediations} remediations are available from Red Hat
for {source.provider}
</ListItem>
)
}
return (
<ListItem>
<Icon isInline status="success">
<img src={SecurityCheckIcon} alt="Security Check Icon"/>
</Icon>&nbsp;
There are no available Red Hat remediations for your SBOM at this time for {source.provider}
</ListItem>
)
})
}
</List>
</DescriptionListDescription>
</CardBody>
</DescriptionListGroup>
</Card>&nbsp;
</GridItem>
<GridItem md={6}>
<GridItem md={6}>
<Card isFlat>
<DescriptionListGroup>
<CardTitle component="h4">
Expand All @@ -108,10 +123,12 @@ export const SummaryCard = () => {
<DescriptionListDescription>
<List isPlain>
<ListItem>
Check out our new Trusted Profile Analyzer to get visibility and insight into your software risk profile, for instance by exploring vulnerabilites or analyzing SBOMs.
Check out our new Trusted Profile Analyzer to get visibility and insight into your software risk
profile, for instance by exploring vulnerabilites or analyzing SBOMs.
</ListItem>
<ListItem>
<a href="https://console.redhat.com/application-services/trusted-content" target="_blank" rel="noopener noreferrer">
<a href="https://console.redhat.com/application-services/trusted-content" target="_blank"
rel="noopener noreferrer">
<Button variant="primary" size="sm">
Take me there
</Button>
Expand Down
31 changes: 19 additions & 12 deletions ui/src/components/VulnerabilityRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,17 @@ import {VulnerabilityScore} from './VulnerabilityScore';
import {VulnerabilitySeverityLabel} from './VulnerabilitySeverityLabel';
import {usePrivateIssueHelper} from "../hooks/usePrivateDataHelper";
import {hasRemediations, VulnerabilityItem} from "../api/report";
import { useAppContext } from '../App';
import {useAppContext} from '../App';

interface VulnerabilityRowProps {
item: VulnerabilityItem;
providerName: string;
rowIndex: number;
}

export const VulnerabilityRow: React.FC<VulnerabilityRowProps> = ({ item, providerName, rowIndex }) => {
export const VulnerabilityRow: React.FC<VulnerabilityRowProps> = ({item, providerName, rowIndex}) => {
let ids;
if(item.vulnerability.cves && item.vulnerability.cves.length > 0) {
if (item.vulnerability.cves && item.vulnerability.cves.length > 0) {
ids = item.vulnerability.cves;
} else {
ids = [item.vulnerability.id];
Expand All @@ -43,24 +43,31 @@ export const VulnerabilityRow: React.FC<VulnerabilityRowProps> = ({ item, provid
</Td>
<Td>{item.vulnerability.title}</Td>
<Td noPadding>
<VulnerabilitySeverityLabel vulnerability={item.vulnerability} />
<VulnerabilitySeverityLabel vulnerability={item.vulnerability}/>
</Td>
</>
)}
<Td>
<VulnerabilityScore vulnerability={item.vulnerability} />
<VulnerabilityScore vulnerability={item.vulnerability}/>
</Td>
<Td>
<DependencyLink name={item.dependencyRef} showVersion={true}/>
</Td>
<Td>
{item.vulnerability.remediation?.trustedContent && (
<RemediationLink key={rowIndex} cves={item.vulnerability.cves || []} packageName={item.dependencyRef} />
)}
{item.vulnerability.remediation?.fixedIn && (
<VulnerabilityLink sourceName={providerName} vulnerability={item.vulnerability} />
)}
{!hasRemediations(item.vulnerability) && ""}
{
item.vulnerability.remediation?.trustedContent ? (
<RemediationLink
key={rowIndex}
cves={item.vulnerability.cves || []}
packageName={item.vulnerability.remediation?.trustedContent?.ref}
/>
) : item.vulnerability.remediation?.fixedIn ? (
<VulnerabilityLink sourceName={providerName} vulnerability={item.vulnerability}/>
) : !hasRemediations(item.vulnerability) ? (
// no remediations
<span></span>
) : null
}
</Td>
</Tr>
);
Expand Down
Loading