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: 2 additions & 0 deletions ui/apps/platform/src/Components/EntityIcon.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ const imageMap = {
[entityTypes.SUBJECT]: group,
[entityTypes.IMAGE]: image,
[entityTypes.COMPONENT]: component,
[entityTypes.NODE_COMPONENT]: component,
[entityTypes.IMAGE_COMPONENT]: component,
[entityTypes.CVE]: cve,
[entityTypes.IMAGE_CVE]: cve,
[entityTypes.NODE_CVE]: cve,
Expand Down
1 change: 1 addition & 0 deletions ui/apps/platform/src/Components/TileLink/TileLink.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ const TileLink = ({
icon={icon}
subText={subText}
short={short}
textWrap
/>
);
let classes = '';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import RadioButtonGroup from 'Components/RadioButtonGroup';
import workflowStateContext from 'Containers/workflowStateContext';
import { DASHBOARD_LIMIT } from 'constants/workflowPages.constants';
import DashboardMenu from 'Components/DashboardMenu';
import useFeatureFlags from 'hooks/useFeatureFlags';
import PoliciesCountTile from '../Components/PoliciesCountTile';
import CvesCountTile from '../Components/CvesCountTile';
import ImagesCountTile from '../Components/ImagesCountTile';
Expand All @@ -23,16 +24,21 @@ import MostCommonVulnerabilities from '../widgets/MostCommonVulnerabilities';
import DeploymentsWithMostSeverePolicyViolations from '../widgets/DeploymentsWithMostSeverePolicyViolations';
import ClustersWithMostOrchestratorIstioVulnerabilities from '../widgets/ClustersWithMostOrchestratorIstioVulnerabilities';

const entityMenuTypes = [
entityTypes.CLUSTER,
entityTypes.NAMESPACE,
entityTypes.DEPLOYMENT,
entityTypes.COMPONENT,
];
const baseEntityMenuTypes = [entityTypes.CLUSTER, entityTypes.NAMESPACE, entityTypes.DEPLOYMENT];
const componentMenuType = [entityTypes.COMPONENT];
const splitComponentMenuTypes = [entityTypes.NODE_COMPONENT, entityTypes.IMAGE_COMPONENT];

const VulnDashboardPage = ({ history }) => {
const workflowState = useContext(workflowStateContext);
const searchState = workflowState.getCurrentSearchState();
const { isFeatureFlagEnabled } = useFeatureFlags();

let entityMenuTypes = [...baseEntityMenuTypes];
if (isFeatureFlagEnabled('ROX_FRONTEND_VM_UDPATES')) {
entityMenuTypes = [...baseEntityMenuTypes, ...splitComponentMenuTypes];
} else {
entityMenuTypes = [...baseEntityMenuTypes, ...componentMenuType];
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Feature flagged the entities we show in the VM dashboard menu dropdown

Screen Shot 2022-06-24 at 4 11 36 PM

Screen Shot 2022-06-24 at 4 11 53 PM


const cveFilterButtons = [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import TopCvssLabel from 'Components/TopCvssLabel';
import RiskScore from 'Components/RiskScore';
import Metadata from 'Components/Metadata';
import CvesByCvssScore from 'Containers/VulnMgmt/widgets/CvesByCvssScore';
import { entityGridContainerClassName } from 'Containers/Workflow/WorkflowEntityPage';
import { entityGridContainerBaseClassName } from 'Containers/Workflow/WorkflowEntityPage';

import RelatedEntitiesSideList from '../RelatedEntitiesSideList';
import TableWidgetFixableCves from '../TableWidgetFixableCves';
Expand All @@ -28,6 +28,8 @@ const emptyComponent = {
function VulnMgmtComponentOverview({ data, entityContext }) {
const workflowState = useContext(workflowStateContext);

const currentEntityType = workflowState.getCurrentEntityType();

// guard against incomplete GraphQL-cached data
const safeData = { ...emptyComponent, ...data };

Expand Down Expand Up @@ -73,9 +75,11 @@ function VulnMgmtComponentOverview({ data, entityContext }) {
);
}

const currentEntity = { [entityTypes.COMPONENT]: id };
const currentEntity = { [currentEntityType]: id };
const newEntityContext = { ...entityContext, ...currentEntity };

const entityGridContainerClassName = `${entityGridContainerBaseClassName} grid-columns-1 md:grid-columns-2 lg:grid-columns-2`;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why did you switch to the other exported class and re-concatenate?

Copy link
Copy Markdown
Contributor Author

@sachaudh sachaudh Jun 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is the before and after of this change

Before:
Screen Shot 2022-06-29 at 10 59 12 PM

After:
Screen Shot 2022-06-29 at 10 59 15 PM

I noticed that we were only showing two columns in the component overview so it differed from the class we were using in general, which was for 3 columns. So this change will instead use the base class and then append specific classes for this view

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

^ That's probably a side-effect of widening the tiles right sidebar.

I'm fine with your fix for it, but I'm afraid this may turn into whack-a-mole. Let's get UX suggestion on this. cc: @alanonthegit

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh no, that wasn't the issue. We're using grid columns for the overview and it was using a 3 column grid before. If you look at the first image you'll see it looks like you can add another third element to the right. It was on master as well. It's not really related to splitting the components but I just did it anyway.


return (
<div className="flex h-full">
<div className="flex flex-col flex-grow min-w-0">
Expand All @@ -102,15 +106,15 @@ function VulnMgmtComponentOverview({ data, entityContext }) {
<TableWidgetFixableCves
workflowState={workflowState}
entityContext={entityContext}
entityType={entityTypes.COMPONENT}
entityType={currentEntityType}
name={safeData?.name}
id={safeData?.id}
/>
</div>
</CollapsibleSection>
</div>
<RelatedEntitiesSideList
entityType={entityTypes.COMPONENT}
entityType={currentEntityType}
entityContext={newEntityContext}
data={safeData}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
getScopeQuery,
} from '../VulnMgmtPolicyQueryUtil';

const VulnMgmtComponent = ({
const VulnMgmtEntityComponent = ({
entityId,
entityListType,
search,
Expand Down Expand Up @@ -99,4 +99,4 @@ const VulnMgmtComponent = ({
);
};

export default VulnMgmtComponent;
export default VulnMgmtEntityComponent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React, { useContext } from 'react';
import { gql } from '@apollo/client';

import useCases from 'constants/useCaseTypes';
import entityTypes from 'constants/entityTypes';
import { defaultCountKeyMap } from 'constants/workflowPages.constants';
import workflowStateContext from 'Containers/workflowStateContext';
import WorkflowEntityPage from 'Containers/Workflow/WorkflowEntityPage';
import EntityList from '../../List/VulnMgmtList';
import VulnMgmtComponentOverview from './VulnMgmtComponentOverview';
import {
vulMgmtPolicyQuery,
tryUpdateQueryWithVulMgmtPolicyClause,
getScopeQuery,
} from '../VulnMgmtPolicyQueryUtil';

// We want to override some values because the imageComponent object has different field names
export const imageComponentCountKeyMap = {
...defaultCountKeyMap,
[entityTypes.CVE]: 'vulnCount: imageVulnerabilityCount',
};

const VulnMgmtImageComponent = ({
entityId,
entityListType,
search,
entityContext,
sort,
page,
refreshTrigger,
setRefreshTrigger,
}) => {
const workflowState = useContext(workflowStateContext);

const overviewQuery = gql`
query getComponent($id: ID!, $query: String, $scopeQuery: String) {
result: imageComponent(id: $id) {
id
name
version
fixedIn
location(query: $scopeQuery)
priority
vulnCount: imageVulnerabilityCount(query: $query, scopeQuery: $scopeQuery)
imageCount(query: $query)
topVuln: topImageVulnerability {
cvss
scoreVersion
}
}
}
`;

function getListQuery(listFieldName, fragmentName, fragment) {
return gql`
query getComponentSubEntity${entityListType}($id: ID!, $pagination: Pagination, $query: String, $policyQuery: String, $scopeQuery: String) {
result: imageComponent(id: $id) {
id
${imageComponentCountKeyMap[entityListType]}(query: $query, scopeQuery: $scopeQuery)
${listFieldName}(query: $query, scopeQuery: $scopeQuery, pagination: $pagination) { ...${fragmentName} }
unusedVarSink(query: $policyQuery)
unusedVarSink(query: $scopeQuery)
}
}
${fragment}
`;
}

const fullEntityContext = workflowState.getEntityContext();
const queryOptions = {
variables: {
id: entityId,
query: tryUpdateQueryWithVulMgmtPolicyClause(entityListType, search, entityContext),
...vulMgmtPolicyQuery,
cachebuster: refreshTrigger,
scopeQuery: getScopeQuery(fullEntityContext),
},
};

return (
<WorkflowEntityPage
entityId={entityId}
entityType={entityTypes.IMAGE_COMPONENT}
entityListType={entityListType}
useCase={useCases.VULN_MANAGEMENT}
ListComponent={EntityList}
OverviewComponent={VulnMgmtComponentOverview}
overviewQuery={overviewQuery}
getListQuery={getListQuery}
search={search}
sort={sort}
page={page}
queryOptions={queryOptions}
entityContext={entityContext}
setRefreshTrigger={setRefreshTrigger}
/>
);
};

export default VulnMgmtImageComponent;
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import React, { useContext } from 'react';
import { gql } from '@apollo/client';

import useCases from 'constants/useCaseTypes';
import entityTypes from 'constants/entityTypes';
import { defaultCountKeyMap } from 'constants/workflowPages.constants';
import workflowStateContext from 'Containers/workflowStateContext';
import WorkflowEntityPage from 'Containers/Workflow/WorkflowEntityPage';
import EntityList from '../../List/VulnMgmtList';
import VulnMgmtComponentOverview from './VulnMgmtComponentOverview';
import {
vulMgmtPolicyQuery,
tryUpdateQueryWithVulMgmtPolicyClause,
getScopeQuery,
} from '../VulnMgmtPolicyQueryUtil';

// We want to override some values because the nodeComponent object has different field names
export const nodeComponentCountKeyMap = {
...defaultCountKeyMap,
[entityTypes.CVE]: 'vulnCount: nodeVulnerabilityCount',
};

const VulnMgmtNodeComponent = ({
entityId,
entityListType,
search,
entityContext,
sort,
page,
refreshTrigger,
setRefreshTrigger,
}) => {
const workflowState = useContext(workflowStateContext);

const overviewQuery = gql`
query getComponent($id: ID!, $query: String, $scopeQuery: String) {
result: nodeComponent(id: $id) {
id
name
version
fixedIn
location(query: $scopeQuery)
priority
vulnCount: nodeVulnerabilityCount(query: $query, scopeQuery: $scopeQuery)
nodeCount(query: $query)
topVuln: topNodeVulnerability {
cvss
scoreVersion
}
}
}
`;

function getListQuery(listFieldName, fragmentName, fragment) {
return gql`
query getNodeComponentSubEntity${entityListType}($id: ID!, $pagination: Pagination, $query: String, $policyQuery: String, $scopeQuery: String) {
result: nodeComponent(id: $id) {
id
${nodeComponentCountKeyMap[entityListType]}(query: $query, scopeQuery: $scopeQuery)
${listFieldName}(query: $query, scopeQuery: $scopeQuery, pagination: $pagination) { ...${fragmentName} }
unusedVarSink(query: $policyQuery)
unusedVarSink(query: $scopeQuery)
}
}
${fragment}
`;
}

const fullEntityContext = workflowState.getEntityContext();
const queryOptions = {
variables: {
id: entityId,
query: tryUpdateQueryWithVulMgmtPolicyClause(entityListType, search, entityContext),
...vulMgmtPolicyQuery,
cachebuster: refreshTrigger,
scopeQuery: getScopeQuery(fullEntityContext),
},
};

return (
<WorkflowEntityPage
entityId={entityId}
entityType={entityTypes.NODE_COMPONENT}
entityListType={entityListType}
useCase={useCases.VULN_MANAGEMENT}
ListComponent={EntityList}
OverviewComponent={VulnMgmtComponentOverview}
overviewQuery={overviewQuery}
getListQuery={getListQuery}
search={search}
sort={sort}
page={page}
queryOptions={queryOptions}
entityContext={entityContext}
setRefreshTrigger={setRefreshTrigger}
/>
);
};

export default VulnMgmtNodeComponent;
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useContext } from 'react';
import PropTypes from 'prop-types';
import pluralize from 'pluralize';

import entityLabels from 'messages/entity';
import { useTheme } from 'Containers/ThemeProvider';
import workflowStateContext from 'Containers/workflowStateContext';
import { getEntityTypesByRelationship } from 'utils/entityRelationships';
Expand Down Expand Up @@ -33,9 +34,10 @@ const RelatedEntitiesSideList = ({ entityType, data, altCountKeyMap, entityConte
const contains = getEntityTypesByRelationship(entityType, relationshipTypes.CONTAINS, useCase)
.map((containEntity) => {
const count = data[countKeyMap[containEntity]];
const entityLabel = entityLabels[containEntity].toUpperCase();
return {
count,
label: pluralize(containEntity, count),
label: pluralize(entityLabel, count),
entity: containEntity,
url: workflowState.pushList(containEntity).setSearch('').toUrl(),
};
Expand All @@ -46,7 +48,7 @@ const RelatedEntitiesSideList = ({ entityType, data, altCountKeyMap, entityConte
}
return (
<div
className={` h-full relative border-base-100 border-l w-32 ${
className={`h-full relative border-base-100 border-l max-w-43 ${
!isDarkMode ? 'bg-primary-300' : 'bg-base-100'
}`}
>
Expand Down
Loading