Skip to content

Commit

Permalink
Host Details Page: Render vulnerable software warnings (#1220)
Browse files Browse the repository at this point in the history
* Conditionally renders vulnerability div and issue tooltip
* Refactors IconToolTip to include an Error icon
* Add vulnerabilities to type interface, small cleanup

Co-authored-by: Rachel Elysia Perkins <rachel@fleetdm.com>
  • Loading branch information
zwass and RachelElysia committed Jun 28, 2021
1 parent f1e42ee commit d6d5840
Show file tree
Hide file tree
Showing 9 changed files with 214 additions and 30 deletions.
Binary file added assets/images/icon-issue-fleet-black-50-16x16@2x.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
49 changes: 35 additions & 14 deletions frontend/components/IconToolTip/IconToolTip.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,48 @@ import ReactTooltip from "react-tooltip";
interface IIconToolTipProps {
text: string;
isHtml?: boolean;
issue?: boolean;
}

// TODO: handle html text better. possibly use 'children' prop for html
const IconToolTip = (props: IIconToolTipProps): JSX.Element => {
const { text, isHtml } = props;
const { text, isHtml, issue } = props;
let svgIcon = (
<svg
width="16"
height="17"
viewBox="0 0 16 17"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="8" cy="8.59961" r="8" fill="#6A67FE" />
<path
d="M7.49605 10.1893V9.70927C7.49605 9.33327 7.56405 8.98527 7.70005 8.66527C7.84405 8.34527 8.08405 7.99727 8.42005 7.62127C8.67605 7.34127 8.85205 7.10127 8.94805 6.90127C9.05205 6.70127 9.10405 6.48927 9.10405 6.26527C9.10405 6.00127 9.00805 5.79327 8.81605 5.64127C8.62405 5.48927 8.35205 5.41326 8.00005 5.41326C7.21605 5.41326 6.49205 5.70127 5.82805 6.27727L5.32405 5.12527C5.66005 4.82127 6.07605 4.57727 6.57205 4.39327C7.07605 4.20927 7.58405 4.11727 8.09605 4.11727C8.60005 4.11727 9.04005 4.20127 9.41605 4.36927C9.80005 4.53727 10.096 4.76927 10.304 5.06527C10.52 5.36127 10.628 5.70927 10.628 6.10927C10.628 6.47727 10.544 6.82127 10.376 7.14127C10.216 7.46127 9.92805 7.80927 9.51205 8.18527C9.13605 8.52927 8.87605 8.82927 8.73205 9.08527C8.58805 9.34127 8.49605 9.59727 8.45605 9.85327L8.40805 10.1893H7.49605ZM7.11205 12.6973V11.0293H8.79205V12.6973H7.11205Z"
fill="white"
/>
</svg>
);

if (issue) {
svgIcon = (
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<path
d="M0 8C0 12.4183 3.5817 16 8 16C12.4183 16 16 12.4183 16 8C16 3.5817 12.4183 0 8 0C3.5817 0 0 3.5817 0 8ZM14 8C14 11.3137 11.3137 14 8 14C4.6863 14 2 11.3137 2 8C2 4.6863 4.6863 2 8 2C11.3137 2 14 4.6863 14 8ZM7 12V10H9V12H7ZM7 4V9H9V4H7Z"
fill="#8B8FA2"
/>
</svg>
);
}
return (
<div className="icon-tooltip">
<span data-tip={text} data-html={isHtml}>
<svg
width="16"
height="17"
viewBox="0 0 16 17"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="8" cy="8.59961" r="8" fill="#6A67FE" />
<path
d="M7.49605 10.1893V9.70927C7.49605 9.33327 7.56405 8.98527 7.70005 8.66527C7.84405 8.34527 8.08405 7.99727 8.42005 7.62127C8.67605 7.34127 8.85205 7.10127 8.94805 6.90127C9.05205 6.70127 9.10405 6.48927 9.10405 6.26527C9.10405 6.00127 9.00805 5.79327 8.81605 5.64127C8.62405 5.48927 8.35205 5.41326 8.00005 5.41326C7.21605 5.41326 6.49205 5.70127 5.82805 6.27727L5.32405 5.12527C5.66005 4.82127 6.07605 4.57727 6.57205 4.39327C7.07605 4.20927 7.58405 4.11727 8.09605 4.11727C8.60005 4.11727 9.04005 4.20127 9.41605 4.36927C9.80005 4.53727 10.096 4.76927 10.304 5.06527C10.52 5.36127 10.628 5.70927 10.628 6.10927C10.628 6.47727 10.544 6.82127 10.376 7.14127C10.216 7.46127 9.92805 7.80927 9.51205 8.18527C9.13605 8.52927 8.87605 8.82927 8.73205 9.08527C8.58805 9.34127 8.49605 9.59727 8.45605 9.85327L8.40805 10.1893H7.49605ZM7.11205 12.6973V11.0293H8.79205V12.6973H7.11205Z"
fill="white"
/>
</svg>
{svgIcon}
</span>
{/* same colour as $core-fleet-blue */}
<ReactTooltip
Expand Down
9 changes: 9 additions & 0 deletions frontend/interfaces/software.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,13 @@ export default PropTypes.shape({
name: PropTypes.string,
version: PropTypes.string,
id: PropTypes.number,
vulnerabilities: PropTypes.arrayOf(
PropTypes.shape({
id: PropTypes.number,
uid: PropTypes.number,
username: PropTypes.string,
type: PropTypes.string,
groupname: PropTypes.string,
})
),
});
35 changes: 20 additions & 15 deletions frontend/pages/hosts/HostDetailsPage/HostDetailsPage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import Button from "components/buttons/Button";
import Modal from "components/modals/Modal";
import SoftwareListRow from "pages/hosts/HostDetailsPage/SoftwareListRow";
import PackQueriesListRow from "pages/hosts/HostDetailsPage/PackQueriesListRow";
import SoftwareVulnerabilities from "pages/hosts/HostDetailsPage/SoftwareVulnerabilities";
import HostUsersListRow from "pages/hosts/HostDetailsPage/HostUsersListRow";

import permissionUtils from "utilities/permissions";
Expand Down Expand Up @@ -377,6 +378,7 @@ export class HostDetailsPage extends Component {
return (
<div className="section section--software">
<p className="section__header">Software</p>

{host.software.length === 0 ? (
<div className="results">
<p className="results__header">
Expand All @@ -388,28 +390,31 @@ export class HostDetailsPage extends Component {
</p>
</div>
) : (
<div className={`${baseClass}__wrapper`}>
<table className={wrapperClassName}>
<thead>
<tr>
<th>Name</th>
<th>Type</th>
<th>Installed Version</th>
</tr>
</thead>
<tbody>
{!!host.software.length &&
host.software.map((software) => {
<>
<SoftwareVulnerabilities softwareList={host.software} />
<div className={`${baseClass}__wrapper`}>
<table className={wrapperClassName}>
<thead>
<tr>
<th />
<th>Name</th>
<th>Type</th>
<th>Installed Version</th>
</tr>
</thead>
<tbody>
{host.software.map((software) => {
return (
<SoftwareListRow
key={`software-row-${software.id}`}
software={software}
/>
);
})}
</tbody>
</table>
</div>
</tbody>
</table>
</div>
</>
)}
</div>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { Component } from "react";
import IconToolTip from "components/IconToolTip";

import softwareInterface from "interfaces/software";

Expand All @@ -11,7 +12,7 @@ class SoftwareListRow extends Component {

render() {
const { software } = this.props;
const { name, source, version } = software;
const { name, source, version, vulnerabilities } = software;

const TYPE_CONVERSION = {
apt_sources: "Package (APT)",
Expand All @@ -35,8 +36,26 @@ class SoftwareListRow extends Component {

const type = TYPE_CONVERSION[source] || "Unknown";

const vulnerabilitiesIcon = () => {
if (vulnerabilities.length === 0) {
return null;
}

const vulText =
vulnerabilities.length === 1 ? "vulnerability" : "vulnerabilities";

return (
<IconToolTip
text={`${vulnerabilities.length} ${vulText} detected`}
issue
isHtml
/>
);
};

return (
<tr>
<td className={`${baseClass}__name`}>{vulnerabilitiesIcon()}</td>
<td className={`${baseClass}__name`}>{name}</td>
<td className={`${baseClass}__type`}>{type}</td>
<td className={`${baseClass}__installed-version`}>{version}</td>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import React, { Component } from "react";
import PropTypes from "prop-types";

import FleetIcon from "components/icons/FleetIcon";
import softwareInterface from "interfaces/software";

const baseClass = "software-vulnerabilities";

class SoftwareVulnerabilities extends Component {
static propTypes = {
softwareList: PropTypes.arrayOf(softwareInterface),
};

render() {
const { softwareList } = this.props;

const vulsList = [];

const vulnerabilitiesListMaker = () => {
softwareList.forEach((software) => {
if (software.vulnerabilities) {
software.vulnerabilities.forEach((vulnerability) => {
vulsList.push({
name: software.name,
cve: vulnerability.cve,
details_link: vulnerability.details_link,
});
});
}
});
};

vulnerabilitiesListMaker();

const renderVulsCount = (list) => {
if (list.length === 1) {
return "1 vulnerability detected";
}
return `${list.length} vulnerabilities detected`;
};

const renderVul = (vul, index) => {
return (
<li key={index}>
Read more about{" "}
<a href={vul.details_link} target="_blank" rel="noopener noreferrer">
<em>{vul.name}</em> {vul.cve} vulnerability &nbsp;
<FleetIcon name="external-link" />
</a>
</li>
);
};

// No software vulnerabilities
if (vulsList.length === 0) {
return null;
}

// Software vulnerabilities
return (
<div className={`${baseClass}`}>
<div className={`${baseClass}__count`}>
<svg
xmlns="http://www.w3.org/2000/svg"
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
>
<path
d="M0 8C0 12.4183 3.5817 16 8 16C12.4183 16 16 12.4183 16 8C16 3.5817 12.4183 0 8 0C3.5817 0 0 3.5817 0 8ZM14 8C14 11.3137 11.3137 14 8 14C4.6863 14 2 11.3137 2 8C2 4.6863 4.6863 2 8 2C11.3137 2 14 4.6863 14 8ZM7 12V10H9V12H7ZM7 4V9H9V4H7Z"
fill="#8B8FA2"
/>
</svg>
&nbsp;
{renderVulsCount(vulsList)}
</div>
<div className={`${baseClass}__list`}>
<ul>{vulsList.map((vul, index) => renderVul(vul, index))}</ul>
</div>
</div>
);
}
}

export default SoftwareVulnerabilities;
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
.software-vulnerabilities {
font-size: $x-small;
background-color: $ui-off-white;
border: solid 1px $ui-fleet-black-50;
box-sizing: border-box;
border-radius: 10px;
overflow: scroll;
margin-bottom: $pad-large;
padding: $pad-large;
padding-bottom: $pad-small;

a {
color: $core-vibrant-blue;
font-weight: $bold;
text-decoration: none;
}

&__count {
font-size: $small;
font-weight: $bold;
}

svg {
padding-right: $pad-xxsmall;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { default } from "./SoftwareVulnerabilities";
17 changes: 17 additions & 0 deletions frontend/pages/hosts/HostDetailsPage/_styles.scss
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,23 @@
}
}

.section--software {
th {
&:first-child {
border-right: none;
width: 16px;
padding-right: 0px;
}
}
tr {
td {
&:first-child {
padding-right: 0px;
}
}
}
}

tbody {
td {
padding: 12px 27px;
Expand Down

0 comments on commit d6d5840

Please sign in to comment.