forked from p15670423/monkey
UI: Remove Scoutsuite reporting
This commit is contained in:
parent
9dc0a6ed6f
commit
c0d1df6252
|
@ -71,7 +71,7 @@ class ReportPageComponent extends AuthComponent {
|
|||
}
|
||||
|
||||
getZeroTrustReportFromServer = async () => {
|
||||
let ztReport = {findings: {}, principles: {}, pillars: {}, scoutsuite_data: {}};
|
||||
let ztReport = {findings: {}, principles: {}, pillars: {}};
|
||||
await this.authFetch('/api/report/zero-trust/findings')
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
|
@ -87,11 +87,6 @@ class ReportPageComponent extends AuthComponent {
|
|||
.then(res => {
|
||||
ztReport.pillars = res;
|
||||
});
|
||||
await this.authFetch('/api/report/zero-trust/scoutsuite')
|
||||
.then(res => res.json())
|
||||
.then(res => {
|
||||
ztReport.scoutsuite_data = res;
|
||||
});
|
||||
return ztReport
|
||||
};
|
||||
|
||||
|
|
|
@ -30,8 +30,7 @@ class ZeroTrustReportPageComponent extends AuthComponent {
|
|||
<PrinciplesSection principles={this.state.principles}
|
||||
pillarsToStatuses={this.state.pillars.pillarsToStatuses}/>
|
||||
<FindingsSection pillarsToStatuses={this.state.pillars.pillarsToStatuses}
|
||||
findings={this.state.findings}
|
||||
scoutsuite_data={this.state.scoutsuite_data}/>
|
||||
findings={this.state.findings}/>
|
||||
</div>;
|
||||
}
|
||||
|
||||
|
@ -59,8 +58,7 @@ class ZeroTrustReportPageComponent extends AuthComponent {
|
|||
stillLoadingDataFromServer() {
|
||||
return typeof this.state.findings === 'undefined'
|
||||
|| typeof this.state.pillars === 'undefined'
|
||||
|| typeof this.state.principles === 'undefined'
|
||||
|| typeof this.state.scoutsuite_data === 'undefined';
|
||||
|| typeof this.state.principles === 'undefined';
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -33,13 +33,10 @@ class FindingsSection extends Component {
|
|||
</p>
|
||||
|
||||
<FindingsTable data={findingsByStatus[ZeroTrustStatuses.failed]}
|
||||
scoutsuite_data={this.props.scoutsuite_data}
|
||||
status={ZeroTrustStatuses.failed}/>
|
||||
<FindingsTable data={findingsByStatus[ZeroTrustStatuses.verify]}
|
||||
scoutsuite_data={this.props.scoutsuite_data}
|
||||
status={ZeroTrustStatuses.verify}/>
|
||||
<FindingsTable data={findingsByStatus[ZeroTrustStatuses.passed]}
|
||||
scoutsuite_data={this.props.scoutsuite_data}
|
||||
status={ZeroTrustStatuses.passed}/>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -4,7 +4,6 @@ import PaginatedTable from '../common/PaginatedTable';
|
|||
import * as PropTypes from 'prop-types';
|
||||
import PillarLabel from './PillarLabel';
|
||||
import EventsButton from './EventsButton';
|
||||
import ScoutSuiteRuleButton from './scoutsuite/ScoutSuiteRuleButton';
|
||||
|
||||
const EVENTS_COLUMN_MAX_WIDTH = 180;
|
||||
const PILLARS_COLUMN_MAX_WIDTH = 260;
|
||||
|
@ -36,16 +35,11 @@ export class FindingsTable extends Component {
|
|||
];
|
||||
|
||||
getFindingDetails(finding) {
|
||||
if ('scoutsuite_rules' in finding.details) {
|
||||
return <ScoutSuiteRuleButton scoutsuite_rules={finding.details.scoutsuite_rules}
|
||||
scoutsuite_data={this.props.scoutsuite_data}/>;
|
||||
} else {
|
||||
return <EventsButton finding_id={finding.finding_id}
|
||||
latest_events={finding.details.latest_events}
|
||||
oldest_events={finding.details.oldest_events}
|
||||
event_count={finding.details.event_count}
|
||||
exportFilename={'Events_' + finding.test_key}/>;
|
||||
}
|
||||
return <EventsButton finding_id={finding.finding_id}
|
||||
latest_events={finding.details.latest_events}
|
||||
oldest_events={finding.details.oldest_events}
|
||||
event_count={finding.details.event_count}
|
||||
exportFilename={'Events_' + finding.test_key}/>;
|
||||
}
|
||||
|
||||
getFindingPillars(finding) {
|
||||
|
|
|
@ -1,84 +0,0 @@
|
|||
import React, {useState} from 'react';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import '../../../../styles/components/scoutsuite/RuleDisplay.scss'
|
||||
import classNames from 'classnames';
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||
import {faChevronDown} from '@fortawesome/free-solid-svg-icons/faChevronDown';
|
||||
import {faChevronUp} from '@fortawesome/free-solid-svg-icons/faChevronUp';
|
||||
import ScoutSuiteDataParser from './ScoutSuiteDataParser';
|
||||
import Collapse from '@kunukn/react-collapse';
|
||||
import {faArrowRight} from '@fortawesome/free-solid-svg-icons';
|
||||
|
||||
export default function ResourceDropdown(props) {
|
||||
|
||||
const [isCollapseOpen, setIsCollapseOpen] = useState(false);
|
||||
let parser = new ScoutSuiteDataParser(props.scoutsuite_data.data.services);
|
||||
let resource_value = parser.getResourceValue(props.resource_path, props.template_path);
|
||||
|
||||
function getResourceDropdown() {
|
||||
return (
|
||||
<div key={props.resource_path} className={classNames('collapse-item',
|
||||
'resource-collapse', {'item--active': isCollapseOpen})}>
|
||||
<button className={'btn-collapse'}
|
||||
onClick={() => setIsCollapseOpen(!isCollapseOpen)}>
|
||||
<span>
|
||||
{Object.prototype.hasOwnProperty.call(resource_value, 'name') ?
|
||||
resource_value.name : props.resource_path}
|
||||
</span>
|
||||
<span>
|
||||
<FontAwesomeIcon icon={isCollapseOpen ? faChevronDown : faChevronUp}/>
|
||||
</span>
|
||||
</button>
|
||||
<Collapse
|
||||
className='collapse-comp'
|
||||
isOpen={isCollapseOpen}
|
||||
render={getResourceDropdownContents}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function replacePathDotsWithArrows(resourcePath) {
|
||||
let path_vars = resourcePath.split('.')
|
||||
let display_path = []
|
||||
for (let i = 0; i < path_vars.length; i++) {
|
||||
display_path.push(path_vars[i])
|
||||
if (i !== path_vars.length - 1) {
|
||||
display_path.push(<FontAwesomeIcon icon={faArrowRight} key={'arrow-' + i}/>)
|
||||
}
|
||||
}
|
||||
return display_path;
|
||||
}
|
||||
|
||||
function prettyPrintJson(data) {
|
||||
return JSON.stringify(data, null, 4);
|
||||
}
|
||||
|
||||
function getResourceValueDisplay() {
|
||||
return (
|
||||
<div>
|
||||
<p className={'resource-value-title'}>Value:</p>
|
||||
<pre className={'resource-value-json'}>{prettyPrintJson(resource_value)}</pre>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getResourceDropdownContents() {
|
||||
return (
|
||||
<div className={'resource-display'}>
|
||||
<div>
|
||||
<p className={'resource-path-title'}>Path:</p>
|
||||
<p className={'resource-path-contents'}>{replacePathDotsWithArrows(props.resource_path)}</p>
|
||||
</div>
|
||||
{getResourceValueDisplay()}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return getResourceDropdown();
|
||||
}
|
||||
|
||||
ResourceDropdown.propTypes = {
|
||||
template_path: PropTypes.string,
|
||||
resource_path: PropTypes.string,
|
||||
scoutsuite_data: PropTypes.object
|
||||
};
|
|
@ -1,70 +0,0 @@
|
|||
import React from 'react';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import '../../../../styles/components/scoutsuite/RuleDisplay.scss'
|
||||
import ResourceDropdown from './ResourceDropdown';
|
||||
|
||||
export default function RuleDisplay(props) {
|
||||
|
||||
return (
|
||||
<div className={'scoutsuite-rule-display'}>
|
||||
<div className={'description'}>
|
||||
<h3>{props.rule.description}({props.rule.service})</h3>
|
||||
</div>
|
||||
<div className={'rationale'}>
|
||||
<p dangerouslySetInnerHTML={{__html: props.rule.rationale}}/>
|
||||
</div>
|
||||
<div className={'checked-resources'}>
|
||||
<p className={'checked-resources-title'}>Resources checked: </p>
|
||||
<p>{props.rule.checked_items}</p>
|
||||
</div>
|
||||
{getReferences()}
|
||||
{getResources()}
|
||||
</div>);
|
||||
|
||||
function getReferences() {
|
||||
let references = []
|
||||
props.rule.references.forEach(reference => {
|
||||
references.push(<a href={reference}
|
||||
className={'reference-link'}
|
||||
target={'_blank'}
|
||||
rel="noopener noreferrer"
|
||||
key={reference}>{reference}</a>)
|
||||
})
|
||||
if (references.length) {
|
||||
return (
|
||||
<div className={'reference-list'}>
|
||||
<p className={'reference-list-title'}>References:</p>
|
||||
{references}
|
||||
</div>)
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function getResources() {
|
||||
let resources = []
|
||||
for (let i = 0; i < props.rule.items.length; i++) {
|
||||
let item = props.rule.items[i];
|
||||
let template_path = Object.prototype.hasOwnProperty.call(props.rule, 'display_path')
|
||||
? props.rule.display_path : props.rule.path;
|
||||
resources.push(<ResourceDropdown resource_path={item}
|
||||
template_path={template_path}
|
||||
scoutsuite_data={props.scoutsuite_data}
|
||||
key={template_path + i}/>)
|
||||
}
|
||||
if (resources.length) {
|
||||
return (
|
||||
<div className={'reference-list'}>
|
||||
<p className={'reference-list-title'}>Flagged resources (<b>{props.rule.flagged_items}</b>):</p>
|
||||
{resources}
|
||||
</div>)
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RuleDisplay.propTypes = {
|
||||
rule: PropTypes.object,
|
||||
scoutsuite_data: PropTypes.object
|
||||
};
|
|
@ -1,118 +0,0 @@
|
|||
export default class ScoutSuiteDataParser {
|
||||
constructor(runResults) {
|
||||
this.runResults = runResults
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets value of cloud resource based on path of specific checked field and more abstract template path,
|
||||
* which describes the scope of resource values.
|
||||
* @param itemPath contains path to a specific value e.g. s3.buckets.da1e7081077ce92.secure_transport_enabled
|
||||
* @param templatePath contains a template path for resource we would want to display e.g. s3.buckets.id
|
||||
* @returns {*[]|*} resource value e.g. {'bucket_id': 123, 'bucket_max_size': '123GB'}
|
||||
*/
|
||||
getResourceValue(itemPath, templatePath) {
|
||||
let resourcePath = this.fillTemplatePath(itemPath, templatePath);
|
||||
return this.getObjectValueByPath(resourcePath, this.runResults);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces id's in template path with id's from item path to form actual path to the object
|
||||
* @param itemPath e.g. s3.buckets.da1e7081077ce92.secure_transport_enabled
|
||||
* @param templatePath e.g. s3.buckets.id
|
||||
* @returns {*} e.g. s3.buckets.da1e7081077ce92
|
||||
*/
|
||||
fillTemplatePath(itemPath, templatePath) {
|
||||
let itemPathArray = itemPath.split('.');
|
||||
let templatePathArray = templatePath.split('.');
|
||||
let resourcePathArray = templatePathArray.map((val, i) => {
|
||||
return val === 'id' ? itemPathArray[i] : val
|
||||
})
|
||||
return resourcePathArray.join('.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves value from ScoutSuite data object based on path, provided in the rule
|
||||
* @param path E.g. a.id.c.id.e
|
||||
* @param source E.g. {a: {b: {c: {d: {e: [{result1: 'result1'}, {result2: 'result2'}]}}}}}
|
||||
* @returns {*[]|*} E.g. ['result1', 'result2']
|
||||
*/
|
||||
getObjectValueByPath(path, source) {
|
||||
let key;
|
||||
|
||||
while (path) {
|
||||
key = this.getNextKeyInPath(path);
|
||||
source = this.getValueForKey(key, path, source);
|
||||
path = this.trimFirstKey(path);
|
||||
}
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets next key from the path
|
||||
* @param path e.g. s3.buckets.id
|
||||
* @returns {string|*} s3
|
||||
*/
|
||||
getNextKeyInPath(path) {
|
||||
if (path.indexOf('.') !== -1) {
|
||||
return path.substr(0, path.indexOf('.'));
|
||||
} else {
|
||||
return path;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns value from object, based on path and current key
|
||||
* @param key E.g. "a"
|
||||
* @param path E.g. "a.b.c"
|
||||
* @param source E.g. {a: {b: {c: 'result'}}}
|
||||
* @returns {[]|*} E.g. {b: {c: 'result'}}
|
||||
*/
|
||||
getValueForKey(key, path, source) {
|
||||
if (key === 'id') {
|
||||
return this.getValueByReplacingUnknownKey(path, source);
|
||||
} else {
|
||||
return source[key];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets value from object if first key in path doesn't match source object
|
||||
* @param path unknown.b.c
|
||||
* @param source {a: {b: {c: [{result:'result'}]}}}
|
||||
* @returns {[]} 'result'
|
||||
*/
|
||||
getValueByReplacingUnknownKey(path, source) {
|
||||
let value = [];
|
||||
for (let key in source) {
|
||||
value = this.getObjectValueByPath(this.replaceFirstKey(path, key), source);
|
||||
value = value.concat(Object.values(value));
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces first key in path
|
||||
* @param path E.g. "one.two.three"
|
||||
* @param replacement E.g. "four"
|
||||
* @returns string E.g. "four.two.three"
|
||||
*/
|
||||
replaceFirstKey(path, replacement) {
|
||||
return replacement + path.substr(path.indexOf('.'), path.length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Trims the first key from dot separated path.
|
||||
* @param path E.g. "one.two.three"
|
||||
* @returns {string|boolean} E.g. "two.three"
|
||||
*/
|
||||
trimFirstKey(path) {
|
||||
if (path.indexOf('.') !== -1) {
|
||||
return path.substr(path.indexOf('.') + 1, path.length);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
import React, {Component} from 'react';
|
||||
import {Button} from 'react-bootstrap';
|
||||
import * as PropTypes from 'prop-types';
|
||||
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||
import {faList} from '@fortawesome/free-solid-svg-icons/faList';
|
||||
import ScoutSuiteRuleModal from './ScoutSuiteRuleModal';
|
||||
import CountBadge from '../../../ui-components/CountBadge';
|
||||
|
||||
export default class ScoutSuiteRuleButton extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
this.state = {
|
||||
isModalOpen: false
|
||||
}
|
||||
}
|
||||
|
||||
toggleModal = () => {
|
||||
this.setState({isModalOpen: !this.state.isModalOpen});
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<>
|
||||
<ScoutSuiteRuleModal scoutsuite_rules={this.props.scoutsuite_rules}
|
||||
scoutsuite_data={this.props.scoutsuite_data}
|
||||
isModalOpen={this.state.isModalOpen}
|
||||
hideCallback={this.toggleModal} />
|
||||
<div className="text-center" style={{'display': 'grid'}}>
|
||||
<Button variant={'monkey-info'} size={'lg'} onClick={this.toggleModal}>
|
||||
<FontAwesomeIcon icon={faList}/> Rules
|
||||
<CountBadge count={this.props.scoutsuite_rules.length}/>
|
||||
</Button>
|
||||
</div>
|
||||
</>);
|
||||
}
|
||||
|
||||
createRuleCountBadge() {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
ScoutSuiteRuleButton.propTypes = {
|
||||
scoutsuite_rules: PropTypes.array,
|
||||
scoutsuite_data: PropTypes.object
|
||||
};
|
|
@ -1,94 +0,0 @@
|
|||
import React, {useState} from 'react';
|
||||
import {Modal} from 'react-bootstrap';
|
||||
import * as PropTypes from 'prop-types';
|
||||
import Pluralize from 'pluralize';
|
||||
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) {
|
||||
const [openRuleId, setOpenRuleId] = useState(null)
|
||||
|
||||
function toggleRuleDropdown(ruleId) {
|
||||
let ruleIdToSet = (openRuleId === ruleId) ? null : ruleId;
|
||||
setOpenRuleId(ruleIdToSet);
|
||||
}
|
||||
|
||||
function renderRuleDropdowns() {
|
||||
let dropdowns = [];
|
||||
let rules = sortRules(props.scoutsuite_rules);
|
||||
rules.forEach(rule => {
|
||||
let dropdown = (<ScoutSuiteSingleRuleDropdown isCollapseOpen={openRuleId === rule.description}
|
||||
toggleCallback={() => toggleRuleDropdown(rule.description)}
|
||||
rule={rule}
|
||||
scoutsuite_data={props.scoutsuite_data}
|
||||
key={rule.description + rule.path}/>)
|
||||
dropdowns.push(dropdown)
|
||||
});
|
||||
return dropdowns;
|
||||
}
|
||||
|
||||
function getGeneralRuleOverview() {
|
||||
return <>
|
||||
There {Pluralize('is', props.scoutsuite_rules.length)}
|
||||
<span className={'badge badge-primary'}>{props.scoutsuite_rules.length}</span>
|
||||
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 <>
|
||||
<span className={'badge badge-danger'}>{failedRuleCnt}</span>
|
||||
failed security {Pluralize('rule', failedRuleCnt)}.
|
||||
</>
|
||||
}
|
||||
|
||||
function getPassedRuleOverview() {
|
||||
let passedRuleCnt = getRuleCountByStatus(props.scoutsuite_rules, STATUSES.STATUS_PASSED);
|
||||
return <>
|
||||
<span className={'badge badge-success'}>{passedRuleCnt}</span>
|
||||
passed security {Pluralize('rule', passedRuleCnt)}.
|
||||
</>
|
||||
}
|
||||
|
||||
function getUnexecutedRuleOverview() {
|
||||
let unexecutedRuleCnt = getRuleCountByStatus(props.scoutsuite_rules, STATUSES.STATUS_UNEXECUTED);
|
||||
return <>
|
||||
<span className={'badge badge-default'}>{unexecutedRuleCnt}</span>
|
||||
{Pluralize('rule', unexecutedRuleCnt)} {Pluralize('was', unexecutedRuleCnt)} not
|
||||
checked (no relevant resources for the rule).
|
||||
</>
|
||||
}
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Modal show={props.isModalOpen} onHide={() => props.hideCallback()} className={'scoutsuite-rule-modal'}>
|
||||
<Modal.Body>
|
||||
<h3>
|
||||
<div className="text-center">ScoutSuite rules</div>
|
||||
</h3>
|
||||
<hr/>
|
||||
<p>
|
||||
{getGeneralRuleOverview()}
|
||||
{getFailedRuleOverview()}
|
||||
{getPassedRuleOverview()}
|
||||
{getUnexecutedRuleOverview()}
|
||||
</p>
|
||||
{renderRuleDropdowns()}
|
||||
</Modal.Body>
|
||||
</Modal>
|
||||
</div>
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
ScoutSuiteRuleModal.propTypes = {
|
||||
isModalOpen: PropTypes.bool,
|
||||
scoutsuite_rules: PropTypes.array,
|
||||
scoutsuite_data: PropTypes.object,
|
||||
hideCallback: PropTypes.func
|
||||
};
|
|
@ -1,79 +0,0 @@
|
|||
import React from 'react';
|
||||
import Collapse from '@kunukn/react-collapse';
|
||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'
|
||||
import {faChevronUp} from '@fortawesome/free-solid-svg-icons/faChevronUp'
|
||||
import {faChevronDown} from '@fortawesome/free-solid-svg-icons/faChevronDown'
|
||||
|
||||
import classNames from 'classnames';
|
||||
import * as PropTypes from 'prop-types';
|
||||
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) {
|
||||
|
||||
function getRuleCollapse() {
|
||||
return (
|
||||
<div className={classNames('collapse-item',
|
||||
'rule-collapse', {'item--active': props.isCollapseOpen})}>
|
||||
<button className={classNames('btn-collapse', getDropdownClass())}
|
||||
onClick={props.toggleCallback}>
|
||||
<span>
|
||||
<FontAwesomeIcon icon={getRuleIcon()}/>
|
||||
{props.rule.description}
|
||||
</span>
|
||||
<span>
|
||||
<FontAwesomeIcon icon={props.isCollapseOpen ? faChevronDown : faChevronUp}/>
|
||||
</span>
|
||||
</button>
|
||||
<Collapse
|
||||
className='collapse-comp'
|
||||
isOpen={props.isCollapseOpen}
|
||||
render={renderRule}/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
function getRuleIcon() {
|
||||
let ruleStatus = getRuleStatus(props.rule);
|
||||
switch (ruleStatus) {
|
||||
case STATUSES.STATUS_PASSED:
|
||||
return faCheckCircle;
|
||||
case STATUSES.STATUS_VERIFY:
|
||||
return faExclamationCircle;
|
||||
case STATUSES.STATUS_FAILED:
|
||||
return faExclamationCircle;
|
||||
case STATUSES.STATUS_UNEXECUTED:
|
||||
return faCircle;
|
||||
}
|
||||
}
|
||||
|
||||
function getDropdownClass() {
|
||||
let ruleStatus = getRuleStatus(props.rule);
|
||||
switch (ruleStatus) {
|
||||
case STATUSES.STATUS_PASSED:
|
||||
return 'collapse-success';
|
||||
case STATUSES.STATUS_VERIFY:
|
||||
return 'collapse-danger';
|
||||
case STATUSES.STATUS_FAILED:
|
||||
return 'collapse-danger';
|
||||
case STATUSES.STATUS_UNEXECUTED:
|
||||
return 'collapse-default';
|
||||
}
|
||||
}
|
||||
|
||||
function renderRule() {
|
||||
return <RuleDisplay rule={props.rule} scoutsuite_data={props.scoutsuite_data}/>
|
||||
}
|
||||
|
||||
return getRuleCollapse();
|
||||
}
|
||||
|
||||
|
||||
ScoutSuiteSingleRuleDropdown.propTypes = {
|
||||
isCollapseOpen: PropTypes.bool,
|
||||
rule: PropTypes.object,
|
||||
scoutsuite_data: PropTypes.object,
|
||||
toggleCallback: PropTypes.func
|
||||
};
|
|
@ -1,40 +0,0 @@
|
|||
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) {
|
||||
const severity_order = {
|
||||
[STATUSES.STATUS_FAILED]: 1,
|
||||
[STATUSES.STATUS_VERIFY]: 2,
|
||||
[STATUSES.STATUS_PASSED]: 3,
|
||||
[STATUSES.STATUS_UNEXECUTED]: 4
|
||||
}
|
||||
|
||||
return severity_order[ruleStatusOne] - severity_order[ruleStatusTwo]
|
||||
}
|
|
@ -13,7 +13,6 @@
|
|||
@import 'components/PreviewPane';
|
||||
@import 'components/AdvancedMultiSelect';
|
||||
@import 'components/particle-component/ParticleBackground';
|
||||
@import 'components/scoutsuite/ResourceDropdown';
|
||||
@import 'components/ImageModal';
|
||||
@import 'components/Icons';
|
||||
@import 'components/inline-selection/InlineSelection';
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
.aws-scoutsuite-configuration a {
|
||||
display: inline-block;
|
||||
padding: 0 0 3px 0;
|
||||
}
|
||||
|
||||
.aws-scoutsuite-configuration ol {
|
||||
padding-left: 15px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.aws-scoutsuite-configuration ol.nested-ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.aws-scoutsuite-configuration li {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.aws-scoutsuite-configuration h2 {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.aws-scoutsuite-configuration p {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.aws-scoutsuite-configuration .cli-link {
|
||||
padding: 0 0 4px 0;
|
||||
}
|
||||
|
||||
.monkey-submit-button {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.aws-scoutsuite-key-configuration .collapse-item {
|
||||
padding: 0;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.aws-scoutsuite-key-configuration .collapse-item .btn-collapse .question-icon {
|
||||
display: inline-block;
|
||||
margin-right: 7px;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
.aws-scoutsuite-key-configuration .collapse-item .btn-collapse p {
|
||||
display: inline-block;
|
||||
margin-bottom: 0;
|
||||
font-size: 1.2em;
|
||||
margin-left: 5px
|
||||
}
|
||||
|
||||
.aws-scoutsuite-key-configuration .key-creation-tutorial {
|
||||
padding-bottom: 10px;
|
||||
}
|
||||
|
||||
.aws-scoutsuite-key-configuration .key-creation-tutorial p {
|
||||
margin-bottom: 2px;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.aws-scoutsuite-key-configuration .key-creation-tutorial h5 {
|
||||
margin-top: 15px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.aws-scoutsuite-key-configuration .key-creation-tutorial p:first-child {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.aws-scoutsuite-key-configuration .image-modal {
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.aws-scoutsuite-key-configuration .key-creation-tutorial img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
border: 1px solid black;
|
||||
}
|
||||
|
||||
.link-in-success-message {
|
||||
padding: 0 !important;
|
||||
vertical-align: initial !important;
|
||||
}
|
||||
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
.resource-display {
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.resource-display .resource-value-json {
|
||||
background-color: $gray-200;
|
||||
padding: 4px;
|
||||
}
|
||||
|
||||
.resource-display .resource-path-contents svg {
|
||||
margin-left: 5px;
|
||||
margin-right: 5px;
|
||||
width: 10px;
|
||||
}
|
||||
|
||||
.resource-display .resource-value-title,
|
||||
.resource-display .resource-path-title {
|
||||
margin-right:5px;
|
||||
font-weight: 500;
|
||||
margin-bottom: 0;
|
||||
}
|
|
@ -1,21 +0,0 @@
|
|||
.scoutsuite-rule-display .description h3{
|
||||
font-size: 1.2em;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.scoutsuite-rule-display p{
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.scoutsuite-rule-display .checked-resources-title,
|
||||
.scoutsuite-rule-display .flagged-resources-title,
|
||||
.scoutsuite-rule-display .reference-list-title{
|
||||
font-weight: 500;
|
||||
margin-right: 5px;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.scoutsuite-rule-display .reference-list a {
|
||||
display: block;
|
||||
margin-left: 10px;
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
.scoutsuite-rule-modal .modal-dialog {
|
||||
max-width: 1000px;
|
||||
top: 0;
|
||||
padding: 30px;
|
||||
}
|
||||
|
||||
.collapse-item.rule-collapse button > span:nth-child(2) {
|
||||
flex: 1
|
||||
}
|
Loading…
Reference in New Issue