"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.Vulnerabilities = void 0; var _eui = require("@elastic/eui"); var _css = require("@emotion/css"); var _react = _interopRequireWildcard(require("react")); var _i18n = require("@kbn/i18n"); var _sharedUxRouter = require("@kbn/shared-ux-router"); var _constants = require("../../common/constants"); var _use_cloud_posture_table = require("../../common/hooks/use_cloud_posture_table"); var _use_latest_vulnerabilities = require("./hooks/use_latest_vulnerabilities"); var _constants2 = require("../../../common/constants"); var _error_callout = require("../configurations/layout/error_callout"); var _findings_search_bar = require("../configurations/layout/findings_search_bar"); var _use_filtered_data_view = require("../../common/api/use_filtered_data_view"); var _vulnerability_badges = require("../../components/vulnerability_badges"); var _empty_state = require("../../components/empty_state"); var _vulnerability_finding_flyout = require("./vulnerabilities_finding_flyout/vulnerability_finding_flyout"); var _no_vulnerabilities_states = require("../../components/no_vulnerabilities_states"); var _use_setup_status_api = require("../../common/api/use_setup_status_api"); var _get_limit_properties = require("../../common/utils/get_limit_properties"); var _findings_layout = require("../configurations/layout/findings_layout"); var _vulnerabilities_table_columns = require("./vulnerabilities_table_columns"); var _cloud_posture_page = require("../../components/cloud_posture_page"); var _translations = require("./translations"); var _custom_sort_script = require("./utils/custom_sort_script"); var _use_styles = require("./hooks/use_styles"); var _findings_group_by_selector = require("../configurations/layout/findings_group_by_selector"); var _vulnerabilities_pathname_handler = require("./utils/vulnerabilities_pathname_handler"); var _constants3 = require("../../common/navigation/constants"); var _vulnerabilities_by_resource = require("./vulnerabilities_by_resource/vulnerabilities_by_resource"); var _resource_vulnerabilities = require("./vulnerabilities_by_resource/resource_vulnerabilities/resource_vulnerabilities"); var _get_vulnerabilities_grid_cell_actions = require("./utils/get_vulnerabilities_grid_cell_actions"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /* * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one * or more contributor license agreements. Licensed under the Elastic License * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ const getDefaultQuery = ({ query, filters }) => ({ query, filters, sort: [{ id: _vulnerabilities_table_columns.vulnerabilitiesColumns.severity, direction: 'desc' }, { id: _vulnerabilities_table_columns.vulnerabilitiesColumns.cvss, direction: 'desc' }], pageIndex: 0 }); const VulnerabilitiesDataGrid = ({ dataView, data, isFetching, onChangeItemsPerPage, onChangePage, onSort, urlQuery, onResetFilters, pageSize, setUrlQuery, pageIndex, sort }) => { const { euiTheme } = (0, _eui.useEuiTheme)(); const styles = (0, _use_styles.useStyles)(); const [showHighlight, setHighlight] = (0, _react.useState)(false); const invalidIndex = -1; const selectedVulnerability = (0, _react.useMemo)(() => { if (urlQuery.vulnerabilityIndex !== undefined) { return data === null || data === void 0 ? void 0 : data.page[urlQuery.vulnerabilityIndex]; } }, [data === null || data === void 0 ? void 0 : data.page, urlQuery.vulnerabilityIndex]); const onCloseFlyout = () => { setUrlQuery({ vulnerabilityIndex: invalidIndex }); }; const onSortHandler = (0, _react.useCallback)(newSort => { onSort(newSort); if (newSort.length !== sort.length) { setHighlight(true); setTimeout(() => { setHighlight(false); }, 2000); } }, [onSort, sort]); const { isLastLimitedPage, limitedTotalItemCount } = (0, _get_limit_properties.useLimitProperties)({ total: data === null || data === void 0 ? void 0 : data.total, pageIndex, pageSize }); const onOpenFlyout = (0, _react.useCallback)(vulnerabilityRow => { const vulnerabilityIndex = data === null || data === void 0 ? void 0 : data.page.findIndex(vulnerabilityRecord => { var _vulnerabilityRecord$, _vulnerabilityRow$vul, _vulnerabilityRecord$2, _vulnerabilityRow$res; return ((_vulnerabilityRecord$ = vulnerabilityRecord.vulnerability) === null || _vulnerabilityRecord$ === void 0 ? void 0 : _vulnerabilityRecord$.id) === ((_vulnerabilityRow$vul = vulnerabilityRow.vulnerability) === null || _vulnerabilityRow$vul === void 0 ? void 0 : _vulnerabilityRow$vul.id) && ((_vulnerabilityRecord$2 = vulnerabilityRecord.resource) === null || _vulnerabilityRecord$2 === void 0 ? void 0 : _vulnerabilityRecord$2.id) === ((_vulnerabilityRow$res = vulnerabilityRow.resource) === null || _vulnerabilityRow$res === void 0 ? void 0 : _vulnerabilityRow$res.id) && vulnerabilityRecord.vulnerability.package.name === vulnerabilityRow.vulnerability.package.name && vulnerabilityRecord.vulnerability.package.version === vulnerabilityRow.vulnerability.package.version; }); setUrlQuery({ vulnerabilityIndex }); }, [setUrlQuery, data === null || data === void 0 ? void 0 : data.page]); const columns = (0, _react.useMemo)(() => { if (!(data !== null && data !== void 0 && data.page)) { return []; } return (0, _get_vulnerabilities_grid_cell_actions.getVulnerabilitiesGridCellActions)({ columnGridFn: _vulnerabilities_table_columns.getVulnerabilitiesColumnsGrid, columns: _vulnerabilities_table_columns.vulnerabilitiesColumns, dataView, pageSize, data: data.page, setUrlQuery, filters: urlQuery.filters }); }, [data === null || data === void 0 ? void 0 : data.page, dataView, pageSize, setUrlQuery, urlQuery.filters]); const flyoutVulnerabilityIndex = urlQuery === null || urlQuery === void 0 ? void 0 : urlQuery.vulnerabilityIndex; const selectedVulnerabilityIndex = flyoutVulnerabilityIndex ? flyoutVulnerabilityIndex + pageIndex * pageSize : undefined; const renderCellValue = (0, _react.useMemo)(() => { const Cell = ({ columnId, rowIndex, setCellProps }) => { var _vulnerabilityRow$vul2; const rowIndexFromPage = rowIndex > pageSize - 1 ? rowIndex % pageSize : rowIndex; const vulnerabilityRow = data === null || data === void 0 ? void 0 : data.page[rowIndexFromPage]; (0, _react.useEffect)(() => { if (selectedVulnerabilityIndex === rowIndex) { setCellProps({ style: { backgroundColor: euiTheme.colors.highlight } }); } else { setCellProps({ style: { backgroundColor: 'inherit' } }); } }, [rowIndex, setCellProps]); if (isFetching) return null; if (!vulnerabilityRow) return null; if (!((_vulnerabilityRow$vul2 = vulnerabilityRow.vulnerability) !== null && _vulnerabilityRow$vul2 !== void 0 && _vulnerabilityRow$vul2.id)) return null; if (columnId === _vulnerabilities_table_columns.vulnerabilitiesColumns.actions) { return /*#__PURE__*/_react.default.createElement(_eui.EuiButtonIcon, { iconType: "expand", "aria-label": "View", onClick: () => { onOpenFlyout(vulnerabilityRow); } }); } if (columnId === _vulnerabilities_table_columns.vulnerabilitiesColumns.vulnerability) { var _vulnerabilityRow$vul3; return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (_vulnerabilityRow$vul3 = vulnerabilityRow.vulnerability) === null || _vulnerabilityRow$vul3 === void 0 ? void 0 : _vulnerabilityRow$vul3.id); } if (columnId === _vulnerabilities_table_columns.vulnerabilitiesColumns.cvss) { var _vulnerabilityRow$vul4, _vulnerabilityRow$vul5; if (!((_vulnerabilityRow$vul4 = vulnerabilityRow.vulnerability.score) !== null && _vulnerabilityRow$vul4 !== void 0 && _vulnerabilityRow$vul4.base) || !((_vulnerabilityRow$vul5 = vulnerabilityRow.vulnerability.score) !== null && _vulnerabilityRow$vul5 !== void 0 && _vulnerabilityRow$vul5.version)) { return null; } return /*#__PURE__*/_react.default.createElement(_vulnerability_badges.CVSScoreBadge, { score: vulnerabilityRow.vulnerability.score.base, version: vulnerabilityRow.vulnerability.score.version }); } if (columnId === _vulnerabilities_table_columns.vulnerabilitiesColumns.resourceName) { var _vulnerabilityRow$res2; return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (_vulnerabilityRow$res2 = vulnerabilityRow.resource) === null || _vulnerabilityRow$res2 === void 0 ? void 0 : _vulnerabilityRow$res2.name); } if (columnId === _vulnerabilities_table_columns.vulnerabilitiesColumns.resourceId) { var _vulnerabilityRow$res3; return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (_vulnerabilityRow$res3 = vulnerabilityRow.resource) === null || _vulnerabilityRow$res3 === void 0 ? void 0 : _vulnerabilityRow$res3.id); } if (columnId === _vulnerabilities_table_columns.vulnerabilitiesColumns.severity) { if (!vulnerabilityRow.vulnerability.severity) { return null; } return /*#__PURE__*/_react.default.createElement(_vulnerability_badges.SeverityStatusBadge, { severity: vulnerabilityRow.vulnerability.severity }); } if (columnId === _vulnerabilities_table_columns.vulnerabilitiesColumns.package) { var _vulnerabilityRow$vul6, _vulnerabilityRow$vul7; return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (_vulnerabilityRow$vul6 = vulnerabilityRow.vulnerability) === null || _vulnerabilityRow$vul6 === void 0 ? void 0 : (_vulnerabilityRow$vul7 = _vulnerabilityRow$vul6.package) === null || _vulnerabilityRow$vul7 === void 0 ? void 0 : _vulnerabilityRow$vul7.name); } if (columnId === _vulnerabilities_table_columns.vulnerabilitiesColumns.version) { var _vulnerabilityRow$vul8, _vulnerabilityRow$vul9; return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (_vulnerabilityRow$vul8 = vulnerabilityRow.vulnerability) === null || _vulnerabilityRow$vul8 === void 0 ? void 0 : (_vulnerabilityRow$vul9 = _vulnerabilityRow$vul8.package) === null || _vulnerabilityRow$vul9 === void 0 ? void 0 : _vulnerabilityRow$vul9.version); } if (columnId === _vulnerabilities_table_columns.vulnerabilitiesColumns.fixedVersion) { var _vulnerabilityRow$vul10, _vulnerabilityRow$vul11; return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, (_vulnerabilityRow$vul10 = vulnerabilityRow.vulnerability) === null || _vulnerabilityRow$vul10 === void 0 ? void 0 : (_vulnerabilityRow$vul11 = _vulnerabilityRow$vul10.package) === null || _vulnerabilityRow$vul11 === void 0 ? void 0 : _vulnerabilityRow$vul11.fixed_version); } return null; }; return Cell; }, [data === null || data === void 0 ? void 0 : data.page, euiTheme.colors.highlight, onOpenFlyout, pageSize, selectedVulnerabilityIndex, isFetching]); const onPaginateFlyout = (0, _react.useCallback)(nextVulnerabilityIndex => { // the index of the vulnerability in the current page const newVulnerabilityIndex = nextVulnerabilityIndex % pageSize; // if the vulnerability is not in the current page, we need to change the page const flyoutPageIndex = Math.floor(nextVulnerabilityIndex / pageSize); setUrlQuery({ pageIndex: flyoutPageIndex, vulnerabilityIndex: newVulnerabilityIndex }); }, [pageSize, setUrlQuery]); const showVulnerabilityFlyout = flyoutVulnerabilityIndex > invalidIndex; if ((data === null || data === void 0 ? void 0 : data.page.length) === 0) { return /*#__PURE__*/_react.default.createElement(_empty_state.EmptyState, { onResetFilters: onResetFilters }); } return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiProgress, { size: "xs", color: "accent", style: { opacity: isFetching ? 1 : 0 } }), /*#__PURE__*/_react.default.createElement(_eui.EuiDataGrid, { className: (0, _css.cx)({ [styles.gridStyle]: true }, { [styles.highlightStyle]: showHighlight }), "aria-label": _translations.VULNERABILITIES, columns: columns, columnVisibility: { visibleColumns: columns.map(({ id }) => id), setVisibleColumns: () => {} }, schemaDetectors: [_custom_sort_script.severitySchemaConfig], rowCount: limitedTotalItemCount, toolbarVisibility: { showColumnSelector: false, showDisplaySelector: false, showKeyboardShortcuts: false, showFullScreenSelector: false, additionalControls: { left: { prepend: /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiButtonEmpty, { size: "xs", color: "text" }, _i18n.i18n.translate('xpack.csp.vulnerabilities.totalVulnerabilities', { defaultMessage: '{total, plural, one {# Vulnerability} other {# Vulnerabilities}}', values: { total: data === null || data === void 0 ? void 0 : data.total } }))) }, right: /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false, className: styles.groupBySelector }, /*#__PURE__*/_react.default.createElement(_findings_group_by_selector.FindingsGroupBySelector, { type: "default", pathnameHandler: _vulnerabilities_pathname_handler.vulnerabilitiesPathnameHandler })) } }, gridStyle: { border: 'horizontal', cellPadding: 'l', stripes: false, rowHover: 'none', header: 'underline' }, renderCellValue: renderCellValue, inMemory: { level: 'enhancements' }, sorting: { columns: sort, onSort: onSortHandler }, pagination: { pageIndex, pageSize, pageSizeOptions: [10, 25, 100], onChangeItemsPerPage, onChangePage } }), isLastLimitedPage && /*#__PURE__*/_react.default.createElement(_findings_layout.LimitedResultsBar, null), showVulnerabilityFlyout && selectedVulnerability && /*#__PURE__*/_react.default.createElement(_vulnerability_finding_flyout.VulnerabilityFindingFlyout, { flyoutIndex: selectedVulnerabilityIndex, vulnerabilityRecord: selectedVulnerability, totalVulnerabilitiesCount: limitedTotalItemCount, onPaginate: onPaginateFlyout, closeFlyout: onCloseFlyout, isLoading: isFetching })); }; const VulnerabilitiesContent = ({ dataView }) => { const { sort, query, queryError, pageSize, pageIndex, onChangeItemsPerPage, onChangePage, onSort, urlQuery, setUrlQuery, onResetFilters } = (0, _use_cloud_posture_table.useCloudPostureTable)({ dataView, defaultQuery: getDefaultQuery, paginationLocalStorageKey: _constants.LOCAL_STORAGE_PAGE_SIZE_FINDINGS_KEY }); const multiFieldsSort = (0, _react.useMemo)(() => { return sort.map(({ id, direction }) => { if (id === _vulnerabilities_table_columns.vulnerabilitiesColumns.severity) { return (0, _custom_sort_script.severitySortScript)(direction); } if (id === _vulnerabilities_table_columns.vulnerabilitiesColumns.package) { return (0, _custom_sort_script.getCaseInsensitiveSortScript)(id, direction); } return { [id]: direction }; }); }, [sort]); const { data, isLoading, isFetching } = (0, _use_latest_vulnerabilities.useLatestVulnerabilities)({ query, sort: multiFieldsSort, enabled: !queryError, pageIndex, pageSize }); const error = queryError || null; if (isLoading && !error) { return (0, _cloud_posture_page.defaultLoadingRenderer)(); } if (!(data !== null && data !== void 0 && data.page) && !error) { return (0, _cloud_posture_page.defaultNoDataRenderer)(); } return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_findings_search_bar.FindingsSearchBar, { dataView: dataView, setQuery: newQuery => { setUrlQuery({ ...newQuery, pageIndex: 0 }); }, loading: isFetching, placeholder: _translations.SEARCH_BAR_PLACEHOLDER }), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: "m" }), error && /*#__PURE__*/_react.default.createElement(_error_callout.ErrorCallout, { error: error }), !error && /*#__PURE__*/_react.default.createElement(VulnerabilitiesDataGrid, { dataView: dataView, data: data, isFetching: isFetching, pageIndex: pageIndex, sort: sort, pageSize: pageSize, onChangeItemsPerPage: onChangeItemsPerPage, onChangePage: onChangePage, onSort: onSort, urlQuery: urlQuery, onResetFilters: onResetFilters, setUrlQuery: setUrlQuery })); }; const Vulnerabilities = () => { var _getSetupStatus$data, _getSetupStatus$data$; const { data, isLoading, error } = (0, _use_filtered_data_view.useFilteredDataView)(_constants2.LATEST_VULNERABILITIES_INDEX_PATTERN); const getSetupStatus = (0, _use_setup_status_api.useCspSetupStatusApi)(); if ((getSetupStatus === null || getSetupStatus === void 0 ? void 0 : (_getSetupStatus$data = getSetupStatus.data) === null || _getSetupStatus$data === void 0 ? void 0 : (_getSetupStatus$data$ = _getSetupStatus$data.vuln_mgmt) === null || _getSetupStatus$data$ === void 0 ? void 0 : _getSetupStatus$data$.status) !== 'indexed') return /*#__PURE__*/_react.default.createElement(_no_vulnerabilities_states.NoVulnerabilitiesStates, null); if (error) { return /*#__PURE__*/_react.default.createElement(_error_callout.ErrorCallout, { error: error }); } if (isLoading) { return (0, _cloud_posture_page.defaultLoadingRenderer)(); } if (!data) { return (0, _cloud_posture_page.defaultNoDataRenderer)(); } return /*#__PURE__*/_react.default.createElement(_sharedUxRouter.Routes, null, /*#__PURE__*/_react.default.createElement(_sharedUxRouter.Route, { exact: true, path: _constants3.findingsNavigation.resource_vulnerabilities.path, render: () => /*#__PURE__*/_react.default.createElement(_resource_vulnerabilities.ResourceVulnerabilities, { dataView: data }) }), /*#__PURE__*/_react.default.createElement(_sharedUxRouter.Route, { exact: true, path: _constants3.findingsNavigation.vulnerabilities_by_resource.path, render: () => /*#__PURE__*/_react.default.createElement(_vulnerabilities_by_resource.VulnerabilitiesByResource, { dataView: data }) }), /*#__PURE__*/_react.default.createElement(_sharedUxRouter.Route, { path: _constants3.findingsNavigation.vulnerabilities.path, render: () => /*#__PURE__*/_react.default.createElement(VulnerabilitiesContent, { dataView: data }) })); }; exports.Vulnerabilities = Vulnerabilities;