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
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { ReactElement } from 'react';
import { ActionsColumn } from '@patternfly/react-table';
import { DeferredCVEsToBeAssessed } from './types';
import { VulnerabilityWithRequest } from '../imageVulnerabilities.graphql';
import { Vulnerability } from '../imageVulnerabilities.graphql';

export type DeferredCVEActionsColumnProps = {
row: VulnerabilityWithRequest;
row: Vulnerability;
setVulnsToBeAssessed: React.Dispatch<React.SetStateAction<DeferredCVEsToBeAssessed>>;
canReobserveCVE: boolean;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { Bullseye, Spinner } from '@patternfly/react-core';
import usePagination from 'hooks/patternfly/usePagination';
import DeferredCVEsTable from './DeferredCVEsTable';
import useImageVulnerabilities from '../useImageVulnerabilities';
import { VulnerabilityWithRequest } from '../imageVulnerabilities.graphql';

type DeferredCVEsProps = {
imageId: string;
Expand All @@ -22,7 +21,7 @@ function DeferredCVEs({ imageId }: DeferredCVEsProps): ReactElement {
offset: (page - 1) * perPage,
sortOption: {
field: 'cve',
reversed: false,
reversed: true,
},
},
});
Expand All @@ -36,7 +35,7 @@ function DeferredCVEs({ imageId }: DeferredCVEsProps): ReactElement {
}

const itemCount = data?.image?.vulnCount || 0;
const rows = (data?.image?.vulns || []) as VulnerabilityWithRequest[];
const rows = data?.image?.vulns || [];

return (
<DeferredCVEsTable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { UsePaginationResult } from 'hooks/patternfly/usePagination';
import usePermissions from 'hooks/usePermissions';
import useAuthStatus from 'hooks/useAuthStatus';
import AffectedComponentsButton from '../AffectedComponents/AffectedComponentsButton';
import { VulnerabilityWithRequest } from '../imageVulnerabilities.graphql';
import { Vulnerability } from '../imageVulnerabilities.graphql';
import { DeferredCVEsToBeAssessed } from './types';
import DeferredCVEActionsColumn from './DeferredCVEActionsColumn';
import useRiskAcceptance from '../useRiskAcceptance';
Expand All @@ -26,7 +26,7 @@ import DeferralExpirationDate from '../DeferralExpirationDate';
import VulnerabilityRequestScope from '../PendingApprovals/VulnerabilityRequestScope';

export type DeferredCVEsTableProps = {
rows: VulnerabilityWithRequest[];
rows: Vulnerability[];
isLoading: boolean;
itemCount: number;
updateTable: () => void;
Expand All @@ -49,7 +49,7 @@ function DeferredCVEsTable({
onSelectAll,
onClearAll,
getSelectedIds,
} = useTableSelection<VulnerabilityWithRequest>(rows);
} = useTableSelection<Vulnerability>(rows);
const [vulnsToBeAssessed, setVulnsToBeAssessed] = useState<DeferredCVEsToBeAssessed>(null);
const { undoVulnRequests } = useRiskAcceptance({
requestIDs: vulnsToBeAssessed?.requestIDs || [],
Expand Down Expand Up @@ -161,9 +161,7 @@ function DeferredCVEsTable({
<DeferralExpirationDate
targetState={row.vulnerabilityRequest.targetState}
requestStatus={row.vulnerabilityRequest.status}
deferralReq={
row.vulnerabilityRequest.deferralReq.expiry
}
deferralReq={row.vulnerabilityRequest.deferralReq}
/>
) : (
'N/A'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import React, { ReactElement } from 'react';
import { ActionsColumn } from '@patternfly/react-table';
import { FalsePositiveCVEsToBeAssessed } from './types';
import { VulnerabilityWithRequest } from '../imageVulnerabilities.graphql';
import { Vulnerability } from '../imageVulnerabilities.graphql';

export type FalsePositiveCVEActionsColumnProps = {
row: VulnerabilityWithRequest;
row: Vulnerability;
setVulnsToBeAssessed: React.Dispatch<React.SetStateAction<FalsePositiveCVEsToBeAssessed>>;
canReobserveCVE: boolean;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import { Bullseye, Spinner } from '@patternfly/react-core';
import usePagination from 'hooks/patternfly/usePagination';
import FalsePositiveCVEsTable from './FalsePositiveCVEsTable';
import useImageVulnerabilities from '../useImageVulnerabilities';
import { VulnerabilityWithRequest } from '../imageVulnerabilities.graphql';

type FalsePositiveCVEsProps = {
imageId: string;
Expand All @@ -22,7 +21,7 @@ function FalsePositiveCVEs({ imageId }: FalsePositiveCVEsProps): ReactElement {
offset: (page - 1) * perPage,
sortOption: {
field: 'cve',
reversed: false,
reversed: true,
},
},
});
Expand All @@ -36,7 +35,7 @@ function FalsePositiveCVEs({ imageId }: FalsePositiveCVEsProps): ReactElement {
}

const itemCount = data?.image?.vulnCount || 0;
const rows = (data?.image?.vulns || []) as VulnerabilityWithRequest[];
const rows = data?.image?.vulns || [];

return (
<FalsePositiveCVEsTable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import { UsePaginationResult } from 'hooks/patternfly/usePagination';
import usePermissions from 'hooks/usePermissions';
import useAuthStatus from 'hooks/useAuthStatus';
import AffectedComponentsButton from '../AffectedComponents/AffectedComponentsButton';
import { VulnerabilityWithRequest } from '../imageVulnerabilities.graphql';
import { Vulnerability } from '../imageVulnerabilities.graphql';
import { FalsePositiveCVEsToBeAssessed } from './types';
import useRiskAcceptance from '../useRiskAcceptance';
import UndoVulnRequestModal from '../UndoVulnRequestModal';
Expand All @@ -25,7 +25,7 @@ import RequestCommentsButton from '../RequestComments/RequestCommentsButton';
import VulnerabilityRequestScope from '../PendingApprovals/VulnerabilityRequestScope';

export type FalsePositiveCVEsTableProps = {
rows: VulnerabilityWithRequest[];
rows: Vulnerability[];
isLoading: boolean;
itemCount: number;
updateTable: () => void;
Expand All @@ -48,7 +48,7 @@ function FalsePositiveCVEsTable({
onSelectAll,
onClearAll,
getSelectedIds,
} = useTableSelection<VulnerabilityWithRequest>(rows);
} = useTableSelection<Vulnerability>(rows);
const [vulnsToBeAssessed, setVulnsToBeAssessed] = useState<FalsePositiveCVEsToBeAssessed>(null);
const { undoVulnRequests } = useRiskAcceptance({
requestIDs: vulnsToBeAssessed?.requestIDs || [],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function ObservedCVEs({ imageId }: ObservedCVEsProps): ReactElement {
offset: (page - 1) * perPage,
sortOption: {
field: 'cve',
reversed: false,
reversed: true,
},
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ function ObservedCVEsTable({
<Td dataLabel="CVE">
<Flex alignItems={{ default: 'alignItemsCenter' }}>
<FlexItem>{row.cve}</FlexItem>
{row.vulnerabilityRequest && (
{row.vulnerabilityRequest?.id && (
<FlexItem>
<PendingApprovalPopover
vulnRequestId={row.vulnerabilityRequest.id}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ function useDeferVulnerability({ cveIDs, registry, remote, tag }: UseDeferVulner
};
if (expiresOn) {
request.expiresOn = expiresOn;
} else {
}
if (expiresWhenFixed) {
request.expiresWhenFixed = expiresWhenFixed;
}
const variables = { request };
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
import { gql } from '@apollo/client';

import { VulnerabilitySeverity } from 'types/cve.proto';
import { Scope, VulnerabilityRequest } from 'types/vuln_request.proto';
import { VulnerabilitySeverity, VulnerabilityState } from 'types/cve.proto';
import { SlimUser } from 'types/user.proto';
import { DeferralRequest, RequestComment, RequestStatus, Scope } from 'types/vuln_request.proto';

export type VulnerabilityRequest = {
id: string;
targetState: VulnerabilityState;
status: RequestStatus;
expired: boolean;
requestor: SlimUser;
approvers: SlimUser[];
comments: RequestComment[];
scope: Scope;
deferralReq: DeferralRequest;
updatedDeferralReq: DeferralRequest;
cves: {
ids: string[];
};
};

// This type is specific to the way we query using GraphQL
export type Vulnerability = {
Expand All @@ -13,10 +30,6 @@ export type Vulnerability = {
scoreVersion: string;
discoveredAtImage: string;
components: EmbeddedImageScanComponent[];
vulnerabilityRequest?: VulnerabilityRequest;
};

export type VulnerabilityWithRequest = Vulnerability & {
vulnerabilityRequest: VulnerabilityRequest;
};

Expand Down Expand Up @@ -77,6 +90,47 @@ export const GET_IMAGE_VULNERABILITIES = gql`
version
fixedIn
}
vulnerabilityRequest: effectiveVulnerabilityRequest {
id
targetState
status
expired
requestor {
id
name
}
approvers {
id
name
}
comments {
createdAt
id
message
user {
id
name
}
}
deferralReq {
expiresOn
expiresWhenFixed
}
updatedDeferralReq {
expiresOn
expiresWhenFixed
}
scope {
imageScope {
registry
remote
tag
}
}
cves {
ids
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
import { useApolloClient, useQuery } from '@apollo/client';
import { useEffect, useState } from 'react';
import { fetchVulnRequests } from 'services/VulnerabilityRequestsService';
import queryService from 'utils/queryService';
import {
GetImageVulnerabilitiesData,
GetImageVulnerabilitiesVars,
GET_IMAGE_VULNERABILITIES,
} from './imageVulnerabilities.graphql';
import { combineVulnsWithVulnRequests } from './utils/imageVulnerabilitiesUtils';

function useImageVulnerabilities({ imageId, vulnsQuery, pagination }) {
const [lastTimeRefetched, setLastTimeRefetched] = useState(() => new Date());
const [data, setData] = useState<GetImageVulnerabilitiesData>();

const client = useApolloClient();
const {
loading: isLoading,
data: vulnsData,
data,
error,
} = useQuery<GetImageVulnerabilitiesData, GetImageVulnerabilitiesVars>(
GET_IMAGE_VULNERABILITIES,
Expand All @@ -30,44 +23,10 @@ function useImageVulnerabilities({ imageId, vulnsQuery, pagination }) {
}
);

useEffect(() => {
if (vulnsData) {
const cves = vulnsData.image.vulns.map((vuln) => vuln.cve).join(',');
const queryObj = vulnsData.image.vulns.length
? {
CVE: cves,
'Expired Request': 'false',
}
: {};
const vulnRequestsQuery = queryService.objectToWhereClause(
queryObj,
encodeURIComponent('+')
);
fetchVulnRequests({ query: vulnRequestsQuery })
.then((vulnRequests) => {
const { vulns } = vulnsData.image;
const newVulns = combineVulnsWithVulnRequests(vulns, vulnRequests);
const newVulnsData: GetImageVulnerabilitiesData = {
image: {
name: vulnsData.image.name,
vulns: newVulns,
vulnCount: vulnsData.image.vulnCount,
},
};
setData(newVulnsData);
})
.catch(() => {
// @TODO: Handle error
});
}
// since sometimes when we refetch, the vulns data won't change, we need another indicator for refecthing
}, [vulnsData, lastTimeRefetched]);

async function refetchQuery() {
await client.refetchQueries({
include: [GET_IMAGE_VULNERABILITIES],
});
setLastTimeRefetched(new Date());
}

return { isLoading, data, error, refetchQuery };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,15 +89,9 @@ function useRiskAcceptance({ requestIDs }: UseRiskAcceptance) {

function updateVulnRequests(formValues) {
const { comment } = formValues;
let expiry = {};
const expiresWhenFixed = getExpiresWhenFixedValue(formValues.expiresOn);
const expiresOn = getExpiresOnValue(formValues.expiresOn);
if (expiresWhenFixed) {
expiry = { ...expiry, expiresWhenFixed };
}
if (expiresOn !== undefined) {
expiry = { ...expiry, expiresOn };
}
const expiry = { expiresOn, expiresWhenFixed };

const promises = requestIDs.map((requestID) => {
const variables: UpdateVulnerabilityRequest = {
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ export function getExpiresWhenFixedValue(expiresOn: string): boolean {

export type ExpiresOn = 'Until Fixable' | '2 weeks' | '30 days' | '90 days' | 'Indefinitely';

export function getExpiresOnValue(expiresOn: ExpiresOn): string | number | undefined {
let value: string | number | undefined;
export function getExpiresOnValue(expiresOn: ExpiresOn): string | number | null {
let value: string | number | null = null;
if (expiresOn === '2 weeks') {
value = addDaysToDate(new Date(), 14);
} else if (expiresOn === '30 days') {
value = addDaysToDate(new Date(), 30);
} else if (expiresOn === '90 days') {
value = addDaysToDate(new Date(), 90);
} else if (expiresOn === 'Indefinitely') {
value = 0;
value = null;
}
return value;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ export type UpdateVulnerabilityRequest = {
comment: string;
expiry: {
expiresWhenFixed?: boolean;
expiresOn?: string; // graphql.Time format (2021-12-03T18:25:39.397427643Z)
expiresOn?: string | number | null; // graphql.Time format (2021-12-03T18:25:39.397427643Z)
};
};

Expand Down