diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteRuleModal.js b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteRuleModal.js index 926d52b9a..b7f212278 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteRuleModal.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteRuleModal.js @@ -2,9 +2,10 @@ import React, {useState} from 'react'; import {Modal} from 'react-bootstrap'; import * as PropTypes from 'prop-types'; import Pluralize from 'pluralize'; -import ScoutSuiteSingleRuleDropdown, {getRuleStatus} from './ScoutSuiteSingleRuleDropdown'; +import ScoutSuiteSingleRuleDropdown from './ScoutSuiteSingleRuleDropdown'; import '../../../../styles/components/scoutsuite/RuleModal.scss'; import STATUSES from '../../common/consts/StatusConsts'; +import {getRuleCountByStatus, sortRules} from './rule-parsing/ParsingUtils'; export default function ScoutSuiteRuleModal(props) { @@ -18,46 +19,54 @@ export default function ScoutSuiteRuleModal(props) { } } - function compareRules(firstRule, secondRule) { - let firstStatus = getRuleStatus(firstRule); - let secondStatus = getRuleStatus(secondRule); - return compareRuleStatuses(firstStatus, secondStatus); - } - - - function compareRuleStatuses(ruleStatusOne, ruleStatusTwo) { - if (ruleStatusOne === ruleStatusTwo) { - return 0; - } else if (ruleStatusOne === STATUSES.STATUS_FAILED) { - return -1; - } else if (ruleStatusTwo === STATUSES.STATUS_FAILED) { - return 1; - } else if (ruleStatusOne === STATUSES.STATUS_VERIFY) { - return -1; - } else if (ruleStatusTwo === STATUSES.STATUS_VERIFY) { - return 1; - } else if (ruleStatusOne === STATUSES.STATUS_PASSED) { - return -1; - } else if (ruleStatusTwo === STATUSES.STATUS_PASSED) { - return 1; - } - } - function renderRuleDropdowns() { let dropdowns = []; - let rules = props.scoutsuite_rules; - rules.sort(compareRules); + let rules = sortRules(props.scoutsuite_rules); rules.forEach(rule => { let dropdown = ( toggleRuleDropdown(rule.description)} rule={rule} scoutsuite_data={props.scoutsuite_data} - key={rule.description+rule.path}/>) + key={rule.description + rule.path}/>) dropdowns.push(dropdown) }); return dropdowns; } + function getGeneralRuleOverview() { + return <> + There {Pluralize('is', props.scoutsuite_rules.length)} +  {props.scoutsuite_rules.length} +  ScoutSuite {Pluralize('rule', props.scoutsuite_rules.length)} associated with this finding. + + } + + function getFailedRuleOverview() { + let failedRuleCnt = getRuleCountByStatus(props.scoutsuite_rules, STATUSES.STATUS_FAILED) + + + getRuleCountByStatus(props.scoutsuite_rules, STATUSES.STATUS_VERIFY); + return <> +  {failedRuleCnt} +  failed security {Pluralize('rule', failedRuleCnt)}. + + } + + function getPassedRuleOverview() { + let passedRuleCnt = getRuleCountByStatus(props.scoutsuite_rules, STATUSES.STATUS_PASSED); + return <> +  {passedRuleCnt} +  passed security {Pluralize('rule', passedRuleCnt)}. + + } + + function getUnexecutedRuleOverview() { + let unexecutedRuleCnt = getRuleCountByStatus(props.scoutsuite_rules, STATUSES.STATUS_UNEXECUTED); + return <> +  {unexecutedRuleCnt} +  {Pluralize('rule', unexecutedRuleCnt)} {Pluralize('was', unexecutedRuleCnt)} not + checked (no relevant resources for the rule). + + } + return (
props.hideCallback()} className={'scoutsuite-rule-modal'}> @@ -67,9 +76,10 @@ export default function ScoutSuiteRuleModal(props) {

- There {Pluralize('is', props.scoutsuite_rules.length)} { - {props.scoutsuite_rules.length} - } ScoutSuite {Pluralize('rule', props.scoutsuite_rules.length)} associated with this finding. + {getGeneralRuleOverview()} + {getFailedRuleOverview()} + {getPassedRuleOverview()} + {getUnexecutedRuleOverview()}

{renderRuleDropdowns()} diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteSingleRuleDropdown.js b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteSingleRuleDropdown.js index 72853a1e0..c396066b4 100644 --- a/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteSingleRuleDropdown.js +++ b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteSingleRuleDropdown.js @@ -6,10 +6,10 @@ import {faChevronDown} from '@fortawesome/free-solid-svg-icons/faChevronDown' import classNames from 'classnames'; import * as PropTypes from 'prop-types'; -import RULE_LEVELS from '../../common/consts/ScoutSuiteConsts/RuleLevels'; import STATUSES from '../../common/consts/StatusConsts'; import {faCheckCircle, faCircle, faExclamationCircle} from '@fortawesome/free-solid-svg-icons'; import RuleDisplay from './RuleDisplay'; +import {getRuleStatus} from './rule-parsing/ParsingUtils'; export default function ScoutSuiteSingleRuleDropdown(props) { @@ -70,18 +70,6 @@ export default function ScoutSuiteSingleRuleDropdown(props) { return getRuleCollapse(); } -export function getRuleStatus(rule) { - if (rule.checked_items === 0) { - return STATUSES.STATUS_UNEXECUTED - } else if (rule.items.length === 0) { - return STATUSES.STATUS_PASSED - } else if (rule.level === RULE_LEVELS.LEVEL_WARNING) { - return STATUSES.STATUS_VERIFY - } else { - return STATUSES.STATUS_FAILED - } -} - ScoutSuiteSingleRuleDropdown.propTypes = { isCollapseOpen: PropTypes.bool, diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/rule-parsing/ParsingUtils.js b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/rule-parsing/ParsingUtils.js new file mode 100644 index 000000000..5070797ab --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/rule-parsing/ParsingUtils.js @@ -0,0 +1,47 @@ +import STATUSES from '../../../common/consts/StatusConsts'; +import RULE_LEVELS from '../../../common/consts/ScoutSuiteConsts/RuleLevels'; + +export function getRuleStatus(rule) { + if (rule.checked_items === 0) { + return STATUSES.STATUS_UNEXECUTED + } else if (rule.items.length === 0) { + return STATUSES.STATUS_PASSED + } else if (rule.level === RULE_LEVELS.LEVEL_WARNING) { + return STATUSES.STATUS_VERIFY + } else { + return STATUSES.STATUS_FAILED + } +} + +export function getRuleCountByStatus(rules, status) { + return rules.filter(rule => getRuleStatus(rule) === status).length; +} + +export function sortRules(rules) { + rules.sort(compareRules); + return rules; +} + +function compareRules(firstRule, secondRule) { + let firstStatus = getRuleStatus(firstRule); + let secondStatus = getRuleStatus(secondRule); + return compareRuleStatuses(firstStatus, secondStatus); +} + +function compareRuleStatuses(ruleStatusOne, ruleStatusTwo) { + if (ruleStatusOne === ruleStatusTwo) { + return 0; + } else if (ruleStatusOne === STATUSES.STATUS_FAILED) { + return -1; + } else if (ruleStatusTwo === STATUSES.STATUS_FAILED) { + return 1; + } else if (ruleStatusOne === STATUSES.STATUS_VERIFY) { + return -1; + } else if (ruleStatusTwo === STATUSES.STATUS_VERIFY) { + return 1; + } else if (ruleStatusOne === STATUSES.STATUS_PASSED) { + return -1; + } else if (ruleStatusTwo === STATUSES.STATUS_PASSED) { + return 1; + } +}