From c66cb11e79c14b89a73db49dc283feacbaa03792 Mon Sep 17 00:00:00 2001
From: VakarisZ
Date: Fri, 18 Sep 2020 10:26:25 +0300
Subject: [PATCH] Added ScoutSuite UI code
---
.../zero_trust/monkey_finding_details.py | 3 +-
.../cc/ui/src/components/pages/ReportPage.js | 7 +-
.../report-components/ZeroTrustReport.js | 9 +-
.../consts/ScoutSuiteConsts/RuleLevels.js | 6 ++
.../common/consts/StatusConsts.js | 8 ++
.../zerotrust/FindingsSection.js | 12 ++-
.../zerotrust/FindingsTable.js | 81 +++++++++--------
.../zerotrust/scoutsuite/ResourceDropdown.js | 75 ++++++++++++++++
.../zerotrust/scoutsuite/RuleDisplay.js | 56 ++++++++++++
.../scoutsuite/ScoutSuiteDataParser.js | 58 ++++++++++++
.../scoutsuite/ScoutSuiteRuleButton.js | 45 ++++++++++
.../scoutsuite/ScoutSuiteRuleModal.js | 58 ++++++++++++
.../ScoutSuiteSingleRuleDropdown.js | 90 +++++++++++++++++++
.../monkey_island/cc/ui/src/styles/Main.scss | 1 +
.../cc/ui/src/styles/components/Collapse.scss | 9 ++
.../scoutsuite/ResourceDropdown.scss | 20 +++++
.../components/scoutsuite/RuleDisplay.scss | 21 +++++
.../components/scoutsuite/RuleModal.scss | 5 ++
18 files changed, 519 insertions(+), 45 deletions(-)
create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/common/consts/ScoutSuiteConsts/RuleLevels.js
create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/common/consts/StatusConsts.js
create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ResourceDropdown.js
create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/RuleDisplay.js
create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteDataParser.js
create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteRuleButton.js
create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteRuleModal.js
create mode 100644 monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteSingleRuleDropdown.js
create mode 100644 monkey/monkey_island/cc/ui/src/styles/components/scoutsuite/ResourceDropdown.scss
create mode 100644 monkey/monkey_island/cc/ui/src/styles/components/scoutsuite/RuleDisplay.scss
create mode 100644 monkey/monkey_island/cc/ui/src/styles/components/scoutsuite/RuleModal.scss
diff --git a/monkey/monkey_island/cc/models/zero_trust/monkey_finding_details.py b/monkey/monkey_island/cc/models/zero_trust/monkey_finding_details.py
index 029136679..bcd19f593 100644
--- a/monkey/monkey_island/cc/models/zero_trust/monkey_finding_details.py
+++ b/monkey/monkey_island/cc/models/zero_trust/monkey_finding_details.py
@@ -1,9 +1,10 @@
from typing import List
-from mongoengine import DateTimeField, Document, StringField, EmbeddedDocumentListField
+from mongoengine import Document, EmbeddedDocumentListField
from monkey_island.cc.models.zero_trust.event import Event
+
class MonkeyFindingDetails(Document):
"""
This model represents additional information about monkey finding:
diff --git a/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js b/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js
index cb30ba117..e0b458c8b 100644
--- a/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js
+++ b/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.js
@@ -60,7 +60,7 @@ class ReportPageComponent extends AuthComponent {
}
getZeroTrustReportFromServer = async () => {
- let ztReport = {findings: {}, principles: {}, pillars: {}};
+ let ztReport = {findings: {}, principles: {}, pillars: {}, scoutsuite_data: {}};
await this.authFetch('/api/report/zero_trust/findings')
.then(res => res.json())
.then(res => {
@@ -76,6 +76,11 @@ 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
};
diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/ZeroTrustReport.js b/monkey/monkey_island/cc/ui/src/components/report-components/ZeroTrustReport.js
index 772802c9d..b400b3418 100644
--- a/monkey/monkey_island/cc/ui/src/components/report-components/ZeroTrustReport.js
+++ b/monkey/monkey_island/cc/ui/src/components/report-components/ZeroTrustReport.js
@@ -16,7 +16,7 @@ class ZeroTrustReportPageComponent extends AuthComponent {
componentDidUpdate(prevProps) {
if (this.props.report !== prevProps.report) {
- this.setState(this.props.report)
+ this.setState(this.props.report)
}
}
@@ -29,7 +29,9 @@ class ZeroTrustReportPageComponent extends AuthComponent {
-
+
;
}
@@ -57,7 +59,8 @@ class ZeroTrustReportPageComponent extends AuthComponent {
stillLoadingDataFromServer() {
return typeof this.state.findings === 'undefined'
|| typeof this.state.pillars === 'undefined'
- || typeof this.state.principles === 'undefined';
+ || typeof this.state.principles === 'undefined'
+ || typeof this.state.scoutsuite_data === 'undefined';
}
diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/common/consts/ScoutSuiteConsts/RuleLevels.js b/monkey/monkey_island/cc/ui/src/components/report-components/common/consts/ScoutSuiteConsts/RuleLevels.js
new file mode 100644
index 000000000..20b92a3eb
--- /dev/null
+++ b/monkey/monkey_island/cc/ui/src/components/report-components/common/consts/ScoutSuiteConsts/RuleLevels.js
@@ -0,0 +1,6 @@
+const RULE_LEVELS = {
+ LEVEL_WARNING: 'warning',
+ LEVEL_DANGER: 'danger'
+}
+
+export default RULE_LEVELS
diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/common/consts/StatusConsts.js b/monkey/monkey_island/cc/ui/src/components/report-components/common/consts/StatusConsts.js
new file mode 100644
index 000000000..472b045ae
--- /dev/null
+++ b/monkey/monkey_island/cc/ui/src/components/report-components/common/consts/StatusConsts.js
@@ -0,0 +1,8 @@
+const STATUSES = {
+ STATUS_UNEXECUTED: 'Unexecuted',
+ STATUS_PASSED: 'Passed',
+ STATUS_VERIFY: 'Verify',
+ STATUS_FAILED: 'Failed'
+}
+
+export default STATUSES
diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/FindingsSection.js b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/FindingsSection.js
index 5fa3a4a80..eb8231441 100644
--- a/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/FindingsSection.js
+++ b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/FindingsSection.js
@@ -32,9 +32,15 @@ class FindingsSection extends Component {
insight as to what exactly happened during this test.
-
-
-
+
+
+
);
}
diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/FindingsTable.js b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/FindingsTable.js
index f83921dae..10e546767 100644
--- a/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/FindingsTable.js
+++ b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/FindingsTable.js
@@ -4,52 +4,59 @@ 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 = 170;
+const EVENTS_COLUMN_MAX_WIDTH = 250;
const PILLARS_COLUMN_MAX_WIDTH = 200;
-const columns = [
- {
- columns: [
- {
- Header: 'Finding', accessor: 'test',
- style: {'whiteSpace': 'unset'} // This enables word wrap
- },
-
- {
- Header: 'Events', id: 'events',
- accessor: x => {
- return ;
- },
- maxWidth: EVENTS_COLUMN_MAX_WIDTH
- },
-
- {
- Header: 'Pillars', id: 'pillars',
- accessor: x => {
- const pillars = x.pillars;
- const pillarLabels = pillars.map((pillar) =>
-
- );
- return {pillarLabels}
;
- },
- maxWidth: PILLARS_COLUMN_MAX_WIDTH,
- style: {'whiteSpace': 'unset'}
- }
- ]
- }
-];
export class FindingsTable extends Component {
+ columns = [
+ {
+ columns: [
+ {
+ Header: 'Finding', accessor: 'test',
+ style: {'whiteSpace': 'unset'} // This enables word wrap
+ },
+
+ {
+ Header: 'Details', id: 'details',
+ accessor: x => {
+ if (x.type === 'scoutsuite_finding') {
+ return ;
+ } else if (x.type === 'monkey_finding') {
+ return ;
+ }
+ },
+ maxWidth: EVENTS_COLUMN_MAX_WIDTH
+ },
+
+ {
+ Header: 'Pillars', id: 'pillars',
+ accessor: x => {
+ const pillars = x.pillars;
+ const pillarLabels = pillars.map((pillar) =>
+
+ );
+ return {pillarLabels}
;
+ },
+ maxWidth: PILLARS_COLUMN_MAX_WIDTH,
+ style: {'whiteSpace': 'unset'}
+ }
+ ]
+ }
+ ];
+
render() {
return
{
} tests' findings
-
+
}
}
diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ResourceDropdown.js b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ResourceDropdown.js
new file mode 100644
index 000000000..996f62590
--- /dev/null
+++ b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ResourceDropdown.js
@@ -0,0 +1,75 @@
+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);
+
+ function getResourceDropdown() {
+ return (
+
+
+
+
+ );
+ }
+
+ 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()
+ }
+ }
+ return display_path;
+ }
+
+ function prettyPrintJson(data) {
+ return JSON.stringify(data, null, 4);
+ }
+
+ function getResourceDropdownContents() {
+ let parser = new ScoutSuiteDataParser(props.scoutsuite_data.data.services);
+ return (
+
+
+
Path:
+
{replacePathDotsWithArrows(props.resource_path)}
+
+
+
Value:
+
{prettyPrintJson(parser.getValueAt(props.resource_path))}
+
+
+ );
+ }
+
+ return getResourceDropdown();
+}
+
+ResourceDropdown.propTypes = {
+ resource_path: PropTypes.object,
+ scoutsuite_data: PropTypes.object
+};
diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/RuleDisplay.js b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/RuleDisplay.js
new file mode 100644
index 000000000..6078b3855
--- /dev/null
+++ b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/RuleDisplay.js
@@ -0,0 +1,56 @@
+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 (
+
+
+
{props.rule.description}({props.rule.service})
+
+
+
{props.rule.rationale}
+
+
+
Resources checked:
+
{props.rule.checked_items}
+
+
+
Resources flagged:
+
{props.rule.flagged_items}
+
+ {props.rule.references.length !== 0 ? getReferences() : ''}
+ {props.rule.items.length !== 0 ? getResources() : ''}
+
);
+
+ function getReferences() {
+ let references = []
+ props.rule.references.forEach(reference => {
+ references.push({reference})
+ })
+ return (
+
+
References:
+ {references}
+
)
+ }
+
+ function getResources() {
+ let resources = []
+ props.rule.items.forEach(item => {
+ resources.push()
+ })
+ return (
+
+
Resources:
+ {resources}
+
)
+ }
+}
+
+RuleDisplay.propTypes = {
+ rule: PropTypes.object,
+ scoutsuite_data: PropTypes.object
+};
diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteDataParser.js b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteDataParser.js
new file mode 100644
index 000000000..0129804f8
--- /dev/null
+++ b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteDataParser.js
@@ -0,0 +1,58 @@
+export default class ScoutSuiteDataParser {
+ constructor(runResults) {
+ this.runResults = runResults
+ }
+
+ getValueAt(path) {
+ return this.getValueAtRecursive(path, this.runResults)
+ }
+
+ getValueAtRecursive(path, source) {
+ let value = source;
+ let current_path = path;
+ let key;
+ // iterate over each path elements
+ while (current_path) {
+ // check if there are more elements to the path
+ if (current_path.indexOf('.') != -1) {
+ key = current_path.substr(0, current_path.indexOf('.'));
+ }
+ // last element
+ else {
+ key = current_path;
+ }
+
+ try {
+ // path containing an ".id"
+ if (key == 'id') {
+ let v = [];
+ let w;
+ for (let k in value) {
+ // process recursively
+ w = this.getValueAtRecursive(k + current_path.substr(current_path.indexOf('.'), current_path.length), value);
+ v = v.concat(
+ Object.values(w) // get values from array, otherwise it will be an array of key/values
+ );
+ }
+ return v;
+ }
+ // simple path, just return element in value
+ else {
+ value = value[key];
+ }
+ } catch (err) {
+ console.log('Error: ' + err)
+ }
+
+ // check if there are more elements to process
+ if (current_path.indexOf('.') != -1) {
+ current_path = current_path.substr(current_path.indexOf('.') + 1, current_path.length);
+ }
+ // otherwise we're done
+ else {
+ current_path = false;
+ }
+ }
+ return value;
+ }
+}
diff --git a/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteRuleButton.js b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteRuleButton.js
new file mode 100644
index 000000000..97c5f861a
--- /dev/null
+++ b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteRuleButton.js
@@ -0,0 +1,45 @@
+import React, {Component} from 'react';
+import {Badge, 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';
+
+export default class ScoutSuiteRuleButton extends Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ isModalOpen: false
+ }
+ }
+
+ toggleModal = () => {
+ this.setState({isModalOpen: !this.state.isModalOpen});
+ };
+
+ render() {
+ return (
+ <>
+
+
+
+
+ >);
+ }
+
+ createRuleCountBadge() {
+ const ruleCount = this.props.scoutsuite_rules.length > 9 ? '9+' : this.props.scoutsuite_rules.length;
+ return {ruleCount};
+ }
+}
+
+ScoutSuiteRuleButton.propTypes = {
+ scoutsuite_rules: PropTypes.array,
+ scoutsuite_data: PropTypes.object
+};
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
new file mode 100644
index 000000000..92fd430da
--- /dev/null
+++ b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteRuleModal.js
@@ -0,0 +1,58 @@
+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';
+
+
+export default function ScoutSuiteRuleModal(props) {
+ const [openRuleId, setOpenRuleId] = useState(null)
+
+ function toggleRuleDropdown(ruleId) {
+ if (openRuleId === ruleId) {
+ setOpenRuleId(null);
+ } else {
+ setOpenRuleId(ruleId);
+ }
+ }
+
+ function renderRuleDropdowns() {
+ let dropdowns = [];
+ props.scoutsuite_rules.forEach(rule => {
+ let dropdown = ( toggleRuleDropdown(rule.description)}
+ rule={rule}
+ scoutsuite_data={props.scoutsuite_data}/>)
+ dropdowns.push(dropdown)
+ });
+ return dropdowns;
+ }
+
+ return (
+
+
props.hideCallback()} className={'scoutsuite-rule-modal'}>
+
+
+
ScoutSuite rules
+
+
+
+ There {Pluralize('is', props.scoutsuite_rules.length)} {
+
{props.scoutsuite_rules.length}
+ } ScoutSuite {Pluralize('rule', props.scoutsuite_rules.length)} associated with finding.
+
+ {renderRuleDropdowns()}
+
+
+
+ );
+
+}
+
+ScoutSuiteRuleModal.propTypes = {
+ isModalOpen: PropTypes.bool,
+ scoutsuite_rules: PropTypes.array,
+ scoutsuite_data: PropTypes.object,
+ hideCallback: PropTypes.func
+};
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
new file mode 100644
index 000000000..1a931b154
--- /dev/null
+++ b/monkey/monkey_island/cc/ui/src/components/report-components/zerotrust/scoutsuite/ScoutSuiteSingleRuleDropdown.js
@@ -0,0 +1,90 @@
+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 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';
+
+export default function ScoutSuiteSingleRuleDropdown(props) {
+
+ function getRuleCollapse() {
+ return (
+
+
+
+
+ );
+ }
+
+ function getRuleIcon() {
+ let ruleStatus = getRuleStatus()
+ 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()
+ switch(ruleStatus) {
+ case STATUSES.STATUS_PASSED:
+ return "collapse-success";
+ case STATUSES.STATUS_VERIFY:
+ return "collapse-warning";
+ case STATUSES.STATUS_FAILED:
+ return "collapse-danger";
+ case STATUSES.STATUS_UNEXECUTED:
+ return "collapse-default";
+ }
+ }
+
+ function getRuleStatus(){
+ if(props.rule.checked_items === 0) {
+ return STATUSES.STATUS_UNEXECUTED
+ } else if (props.rule.items.length === 0) {
+ return STATUSES.STATUS_PASSED
+ } else if (props.rule.level === RULE_LEVELS.LEVEL_WARNING) {
+ return STATUSES.STATUS_VERIFY
+ } else {
+ return STATUSES.STATUS_FAILED
+ }
+ }
+
+ function renderRule() {
+ return
+ }
+
+ return getRuleCollapse();
+}
+
+ScoutSuiteSingleRuleDropdown.propTypes = {
+ isCollapseOpen: PropTypes.bool,
+ rule: PropTypes.object,
+ scoutsuite_data: PropTypes.object,
+ toggleCallback: PropTypes.func
+};
diff --git a/monkey/monkey_island/cc/ui/src/styles/Main.scss b/monkey/monkey_island/cc/ui/src/styles/Main.scss
index e26220d0d..16cb1cab8 100644
--- a/monkey/monkey_island/cc/ui/src/styles/Main.scss
+++ b/monkey/monkey_island/cc/ui/src/styles/Main.scss
@@ -12,6 +12,7 @@
@import 'components/PreviewPane';
@import 'components/AdvancedMultiSelect';
@import 'components/particle-component/ParticleBackground';
+@import 'components/scoutsuite/ResourceDropdown';
// Define custom elements after bootstrap import
diff --git a/monkey/monkey_island/cc/ui/src/styles/components/Collapse.scss b/monkey/monkey_island/cc/ui/src/styles/components/Collapse.scss
index 3e578d45c..369c93685 100644
--- a/monkey/monkey_island/cc/ui/src/styles/components/Collapse.scss
+++ b/monkey/monkey_island/cc/ui/src/styles/components/Collapse.scss
@@ -5,6 +5,7 @@ $disabled-color: #f2f2f2;
$info-color: #ade3eb;
$default-color: #8c8c8c;
$warning-color: #ffe28d;
+$success-color: #adf6a9;
.collapse-item button {
font-size: inherit;
@@ -39,6 +40,10 @@ $warning-color: #ffe28d;
}
}
+.collapse-success {
+ background-color: $success-color !important;
+}
+
.collapse-danger {
background-color: $danger-color !important;
}
@@ -99,3 +104,7 @@ $warning-color: #ffe28d;
display: inline-block;
min-width: 6em;
}
+
+.rule-collapse svg{
+ margin-right: 10px;
+}
diff --git a/monkey/monkey_island/cc/ui/src/styles/components/scoutsuite/ResourceDropdown.scss b/monkey/monkey_island/cc/ui/src/styles/components/scoutsuite/ResourceDropdown.scss
new file mode 100644
index 000000000..a5be0a4ae
--- /dev/null
+++ b/monkey/monkey_island/cc/ui/src/styles/components/scoutsuite/ResourceDropdown.scss
@@ -0,0 +1,20 @@
+.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 {
+ font-weight: 500;
+ margin-bottom: 0;
+}
diff --git a/monkey/monkey_island/cc/ui/src/styles/components/scoutsuite/RuleDisplay.scss b/monkey/monkey_island/cc/ui/src/styles/components/scoutsuite/RuleDisplay.scss
new file mode 100644
index 000000000..703e27370
--- /dev/null
+++ b/monkey/monkey_island/cc/ui/src/styles/components/scoutsuite/RuleDisplay.scss
@@ -0,0 +1,21 @@
+.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;
+}
diff --git a/monkey/monkey_island/cc/ui/src/styles/components/scoutsuite/RuleModal.scss b/monkey/monkey_island/cc/ui/src/styles/components/scoutsuite/RuleModal.scss
new file mode 100644
index 000000000..f201da303
--- /dev/null
+++ b/monkey/monkey_island/cc/ui/src/styles/components/scoutsuite/RuleModal.scss
@@ -0,0 +1,5 @@
+.scoutsuite-rule-modal .modal-dialog{
+ max-width: 1000px;
+ top: 0;
+ padding: 30px;
+}