diff --git a/monkey/monkey_island/cc/ui/src/components/IslandHttpClient.tsx b/monkey/monkey_island/cc/ui/src/components/IslandHttpClient.tsx index 93035193f87..b2e804748be 100644 --- a/monkey/monkey_island/cc/ui/src/components/IslandHttpClient.tsx +++ b/monkey/monkey_island/cc/ui/src/components/IslandHttpClient.tsx @@ -17,7 +17,6 @@ export enum APIEndpoint { machines = '/api/machines', nodes = '/api/nodes', agentEvents = '/api/agent-events', - mode = '/api/island/mode', monkey_exploitation = '/api/exploitations/monkey', stolenCredentials = '/api/propagation-credentials/stolen-credentials', linuxMasque = '/api/agent-binaries/linux/masque', diff --git a/monkey/monkey_island/cc/ui/src/components/Main.tsx b/monkey/monkey_island/cc/ui/src/components/Main.tsx index d2144acd978..46d6070a376 100644 --- a/monkey/monkey_island/cc/ui/src/components/Main.tsx +++ b/monkey/monkey_island/cc/ui/src/components/Main.tsx @@ -10,7 +10,6 @@ import LicensePage from './pages/LicensePage'; import AuthComponent from './AuthComponent'; import LoginPageComponent from './pages/LoginPage'; import RegisterPageComponent from './pages/RegisterPage'; -import LandingPage from "./pages/LandingPage"; import Notifier from 'react-desktop-notification'; import NotFoundPage from './pages/NotFoundPage'; import GettingStartedPage from './pages/GettingStartedPage'; @@ -29,7 +28,6 @@ import LogoutPage from './pages/LogoutPage'; let notificationIcon = require('../images/notification-logo-512x512.png'); export const IslandRoutes = { - LandingPage: '/landing-page', GettingStartedPage: '/', Report: '/report', SecurityReport: '/report/security', @@ -55,10 +53,8 @@ class AppComponent extends AuthComponent { super(props); this.state = { completedSteps: new CompletedSteps(false), - islandMode: undefined, }; this.interval = undefined; - this.setMode(); } updateStatus = () => { @@ -84,72 +80,52 @@ class AppComponent extends AuthComponent { } if (res) { - this.setMode() - .then(() => { - if (this.state.islandMode === "unset") { - return - } - - // update status: report generation - this.authFetch('/api/report-generation-status', {}, false) - .then(res => res.json()) - .then(res => { - this.setState({ - completedSteps: new CompletedSteps( - this.state.completedSteps.runMonkey, - this.state.completedSteps.infectionDone, - res.report_done - ) - }); - }) - - // update status: if any agent ran - doesAnyAgentExist(false).then(anyAgentExists => { - this.setState({ - completedSteps: new CompletedSteps( - anyAgentExists, - this.state.completedSteps.infectionDone, - this.state.completedSteps.reportDone - ) - }); + // update status: report generation + this.authFetch('/api/report-generation-status', {}, false) + .then(res => res.json()) + .then(res => { + this.setState({ + completedSteps: new CompletedSteps( + this.state.completedSteps.runMonkey, + this.state.completedSteps.infectionDone, + res.report_done + ) }); + }) - // update status: if infection (running and shutting down of all agents) finished - didAllAgentsShutdown(false).then(allAgentsShutdown => { - let infectionDone = this.state.completedSteps.runMonkey && allAgentsShutdown; - if(this.state.completedSteps.infectionDone === false - && infectionDone){ - this.showInfectionDoneNotification(); - } - this.setState({ - completedSteps: new CompletedSteps( - this.state.completedSteps.runMonkey, - infectionDone, - this.state.completedSteps.reportDone - ) - }); - }); + // update status: if any agent ran + doesAnyAgentExist(false).then(anyAgentExists => { + this.setState({ + completedSteps: new CompletedSteps( + anyAgentExists, + this.state.completedSteps.infectionDone, + this.state.completedSteps.reportDone + ) + }); + }); + + // update status: if infection (running and shutting down of all agents) finished + didAllAgentsShutdown(false).then(allAgentsShutdown => { + let infectionDone = this.state.completedSteps.runMonkey && allAgentsShutdown; + if(this.state.completedSteps.infectionDone === false + && infectionDone){ + this.showInfectionDoneNotification(); } - ) + this.setState({ + completedSteps: new CompletedSteps( + this.state.completedSteps.runMonkey, + infectionDone, + this.state.completedSteps.reportDone + ) + }); + }); } }; - setMode = () => { - return IslandHttpClient.getJSON(APIEndpoint.mode) - .then(res => { - this.setState({islandMode: res.body}); - }); - } - renderRoute = (route_path, page_component) => { let render_func = () => { switch (this.state.isLoggedIn) { case true: - if (this.needsRedirectionToLandingPage(route_path)) { - return ; - } else if (this.needsRedirectionToGettingStarted(route_path)) { - return ; - } return page_component; case false: switch (this.state.needsRegistration) { @@ -168,15 +144,6 @@ class AppComponent extends AuthComponent { return ; }; - needsRedirectionToLandingPage = (route_path) => { - return (this.state.islandMode === "unset" && route_path !== IslandRoutes.LandingPage) - } - - needsRedirectionToGettingStarted = (route_path) => { - return route_path === IslandRoutes.LandingPage && - this.state.islandMode !== "unset" && this.state.islandMode !== undefined - } - redirectTo = (userPath, targetPath) => { let pathQuery = new RegExp(userPath + '[/]?$', 'g'); if (window.location.pathname.match(pathQuery)) { @@ -194,36 +161,14 @@ class AppComponent extends AuthComponent { } getDefaultReport() { - if(this.state.islandMode === 'ransomware'){ - return IslandRoutes.RansomwareReport; - } else { - return IslandRoutes.SecurityReport; - } - } - - getIslandModeTitle(){ - if(this.state.islandMode === 'ransomware'){ - return this.formIslandModeTitle("Ransomware", faFileCode); - } else { - return this.formIslandModeTitle("Custom", faLightbulb); - } - } - - formIslandModeTitle(title, icon){ - return (<> -
- {title} -
- ) + return IslandRoutes.SecurityReport; } render() { let defaultSideNavProps = {completedSteps: this.state.completedSteps, onStatusChange: this.updateStatus, - islandMode: this.state.islandMode, defaultReport: this.getDefaultReport(), - sideNavHeader: this.getIslandModeTitle(), onLogout: () => {this.auth.logout() .then(() => this.updateStatus())}}; @@ -234,12 +179,6 @@ class AppComponent extends AuthComponent { }/> }/> }/> - {this.renderRoute(IslandRoutes.LandingPage, - )} {this.renderRoute(IslandRoutes.GettingStartedPage, )} {this.renderRoute(IslandRoutes.ConfigurePage, @@ -253,15 +192,12 @@ class AppComponent extends AuthComponent { {this.redirectToReport()} {this.renderRoute(IslandRoutes.SecurityReport, )} {this.renderRoute(IslandRoutes.RansomwareReport, )} {this.renderRoute(IslandRoutes.LicensePage, )} }/> @@ -271,11 +207,7 @@ class AppComponent extends AuthComponent { } redirectToReport() { - if (this.state.islandMode === 'ransomware') { - return this.redirectTo(IslandRoutes.Report, IslandRoutes.RansomwareReport) - } else { - return this.redirectTo(IslandRoutes.Report, IslandRoutes.SecurityReport) - } + return this.redirectTo(IslandRoutes.Report, IslandRoutes.SecurityReport) } showInfectionDoneNotification() { diff --git a/monkey/monkey_island/cc/ui/src/components/configuration-components/ConfigurationTabs.js b/monkey/monkey_island/cc/ui/src/components/configuration-components/ConfigurationTabs.js index 4452ef98224..b329161942a 100644 --- a/monkey/monkey_island/cc/ui/src/components/configuration-components/ConfigurationTabs.js +++ b/monkey/monkey_island/cc/ui/src/components/configuration-components/ConfigurationTabs.js @@ -7,7 +7,7 @@ const CONFIGURATION_TABS = { ADVANCED: 'advanced' }; -const advancedModeConfigTabs = [ +const CONFIGURATION_TABS_ORDER = [ CONFIGURATION_TABS.PROPAGATION, CONFIGURATION_TABS.PAYLOADS, CONFIGURATION_TABS.CREDENTIALS_COLLECTORS, @@ -16,17 +16,4 @@ const advancedModeConfigTabs = [ CONFIGURATION_TABS.ADVANCED ]; -const ransomwareModeConfigTabs = [ - CONFIGURATION_TABS.PROPAGATION, - CONFIGURATION_TABS.PAYLOADS, - CONFIGURATION_TABS.MASQUERADE, - CONFIGURATION_TABS.POLYMORPHISM, - CONFIGURATION_TABS.ADVANCED -]; - -const CONFIGURATION_TABS_PER_MODE = { - 'advanced': advancedModeConfigTabs, - 'ransomware': ransomwareModeConfigTabs -}; - -export default CONFIGURATION_TABS_PER_MODE; +export default CONFIGURATION_TABS_ORDER; diff --git a/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js b/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js index 8d7cb59253e..4727dcf277d 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js @@ -24,7 +24,7 @@ import { import ConfigExportModal from '../configuration-components/ExportConfigModal'; import ConfigImportModal from '../configuration-components/ImportConfigModal'; import applyUiSchemaManipulators from '../configuration-components/UISchemaManipulators.tsx'; -import CONFIGURATION_TABS_PER_MODE from '../configuration-components/ConfigurationTabs.js'; +import CONFIGURATION_TABS_ORDER from '../configuration-components/ConfigurationTabs.js'; import {SCHEMA} from '../../services/configuration/configSchema.js'; import { reformatConfig, @@ -52,7 +52,7 @@ class ConfigurePageComponent extends AuthComponent { constructor(props) { super(props); - this.currentSection = this.getSectionsOrder()[0]; + this.currentSection = CONFIGURATION_TABS_ORDER[0]; this.validator = customizeValidator( {customFormats: formValidationFormats}); this.state = { @@ -72,13 +72,6 @@ class ConfigurePageComponent extends AuthComponent { }; } - componentDidUpdate() { - if (!this.getSectionsOrder()?.includes(this.currentSection)) { - this.currentSection = this.getSectionsOrder()?.[0]; - this.setState({selectedSection: this.currentSection}); - } - } - setCredentialsState = (rows = [], errors = [], isRequiredToUpdateId) => { let newState = {credentials: {credentialsData: rows, errors: errors, id: this.state.credentials.id}}; if(isRequiredToUpdateId) { @@ -91,12 +84,6 @@ class ConfigurePageComponent extends AuthComponent { this.setState({lastAction: 'none'}); } - getSectionsOrder() { - let islandModeSet = (this.props.islandMode !== 'unset' && this.props.islandMode !== undefined) - let islandMode = islandModeSet ? this.props.islandMode : 'advanced' - return CONFIGURATION_TABS_PER_MODE[islandMode]; - } - componentDidMount = () => { this.authFetch(SCHEMA_URL, {}, true).then(res => res.json()) .then((schema) => { @@ -111,7 +98,7 @@ class ConfigurePageComponent extends AuthComponent { let sections = []; monkeyConfig = reformatConfig(monkeyConfig); - for (let sectionKey of this.getSectionsOrder()) { + for (let sectionKey of CONFIGURATION_TABS_ORDER) { sections.push({ key: sectionKey, title: SCHEMA.properties[sectionKey].title diff --git a/monkey/monkey_island/cc/ui/src/components/pages/LandingPage.tsx b/monkey/monkey_island/cc/ui/src/components/pages/LandingPage.tsx deleted file mode 100644 index 64ae5317d34..00000000000 --- a/monkey/monkey_island/cc/ui/src/components/pages/LandingPage.tsx +++ /dev/null @@ -1,119 +0,0 @@ -import React from 'react'; -import {Col, Row} from 'react-bootstrap'; -import {Link} from 'react-router-dom'; -import {FontAwesomeIcon} from '@fortawesome/react-fontawesome'; -import {faFileCode, faLightbulb} from '@fortawesome/free-solid-svg-icons'; -import '../../styles/pages/LandingPage.scss'; -import IslandHttpClient from '../IslandHttpClient'; - -import ParticleBackground from '../ui-components/ParticleBackground'; -import Logo from '../logo/LogoComponent'; - -const monkeyIcon = require('../../images/monkey-icon.svg') -const infectionMonkey = require('../../images/infection-monkey.svg') - -type Props = { - onStatusChange: () => void -} - -const LandingPageComponent = (props: Props) => { - return ( - <> - - - -
- -
- - - -
-
-
- - - - ); - - - function ScenarioButtons() { - return ( -
-

Choose a scenario:

-
- - -
- { - setScenario('ransomware') - }}> -

Ransomware

-

Simulate ransomware infection in the network.

- -
-
- { - setScenario('advanced') - }}> -

Custom

-

Fine tune the simulation to your needs.

- -
-
- -
-
- ); - } - - function setScenario(scenario: string) { - IslandHttpClient.putJSON('/api/island/mode', scenario, true) - .then(() => { - props.onStatusChange(); - }); - } -} - -function MonkeyInfo() { - return ( - <> -

What is Infection Monkey?

- Infection Monkey is an open-source security tool for testing a data center's resiliency to - perimeter - breaches and internal server infections. The Monkey uses various methods to propagate across a data center - and reports to this Monkey Island Command and Control server. - - ); -} - -function ScenarioInfo() { - return ( - <> -
- Check the Infection Monkey documentation hub for more information - on - scenarios - . -
- - ); -} - -function MonkeyBanner(props) { - return ( -
- - -
- ); -} - -export default LandingPageComponent; diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RegisterPage.js b/monkey/monkey_island/cc/ui/src/components/pages/RegisterPage.js index bcb40674bc6..b3f42d32111 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RegisterPage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RegisterPage.js @@ -34,7 +34,7 @@ class RegisterPageComponent extends React.Component { }; redirectToHome = () => { - window.location.href = '/landing-page'; + window.location.href = '/'; }; constructor(props) { diff --git a/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.tsx b/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.tsx index faa18bb8732..6b6d9f20341 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.tsx +++ b/monkey/monkey_island/cc/ui/src/components/pages/ReportPage.tsx @@ -9,18 +9,14 @@ import {doesAnyAgentExist, didAllAgentsShutdown} from '../utils/ServerUtils' import {useNavigate} from 'react-router-dom'; -type Props = { - islandMode: string, -}; - -function ReportPage(props: Props) { +function ReportPage() { const sections = ['security', 'ransomware']; const [securityReport, setSecurityReport] = useState({}); const [ransomwareReport, setRansomwareReport] = useState({}); const [allMonkeysAreDead, setAllMonkeysAreDead] = useState(false); const [runStarted, setRunStarted] = useState(true); const [selectedSection, setSelectedSection] = useState(selectReport(sections)); - const [orderedSections, setOrderedSections] = useState([{key: 'security', title: 'Security report'}]); + const orderedSections = [{key: 'security', title: 'Security report'}, {key: 'ransomware', title: 'Ransomware report'}]; const authComponent = new AuthComponent({}); function selectReport(reports) { @@ -99,32 +95,9 @@ function ReportPage(props: Props) { } }; - function addRansomwareTab() { - let ransomwareTab = {key: 'ransomware', title: 'Ransomware report'}; - if(isRansomwareTabMissing(ransomwareTab)){ - if (props.islandMode === 'ransomware') { - orderedSections.splice(0, 0, ransomwareTab); - } - else { - orderedSections.push(ransomwareTab); - } - } - }; - - function isRansomwareTabMissing(ransomwareTab) { - return ( - props.islandMode !== undefined && - !orderedSections.some(tab => - (tab.key === ransomwareTab.key - && tab.title === ransomwareTab.title) - )); - }; - function renderContent() { let content = ; - addRansomwareTab(); - if (runStarted) { content = getReportContent(); } diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunMonkeyPage.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunMonkeyPage.js index f12507f7d2c..11051e62f5b 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunMonkeyPage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunMonkeyPage.js @@ -19,7 +19,7 @@ class RunMonkeyPageComponent extends AuthComponent { configuration)

- + ); } diff --git a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js index 90247e8dcc3..2f133b97d40 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/RunMonkeyPage/RunOptions.js @@ -45,11 +45,7 @@ function RunOptions(props) { return InlineSelection(defaultContents, newProps); } - function isNotRansomwareMode(islandMode){ - return islandMode !== 'ransomware'; - } - - function defaultContents(props) { + function defaultContents() { return ( <> - {isNotRansomwareMode(props.islandMode) && } + { } ); } diff --git a/monkey/monkey_island/cc/ui/src/components/ui-components/IslandResetModal.tsx b/monkey/monkey_island/cc/ui/src/components/ui-components/IslandResetModal.tsx index 1ac47b51e1e..15fe2a7aa8f 100644 --- a/monkey/monkey_island/cc/ui/src/components/ui-components/IslandResetModal.tsx +++ b/monkey/monkey_island/cc/ui/src/components/ui-components/IslandResetModal.tsx @@ -29,6 +29,7 @@ const IslandResetModal = (props: Props) => { return ( { + setResetAll(Idle); setDeleteStatus(Idle); props.onClose() }} size={'lg'}> @@ -80,7 +81,6 @@ const IslandResetModal = (props: Props) => { setResetAll(Done); props.onReset(); }); - props.onClose(); } catch (err) { // TODO: Display error message to user console.error(err) @@ -109,28 +109,25 @@ const IslandResetModal = (props: Props) => { return auth.authFetch('/api/reset-agent-configuration', {method: 'POST'}) .then(res => { if (res.ok) { - return auth.authFetch('/api/clear-simulation-data', {method: 'POST'}) + return auth.authFetch('/api/clear-simulation-data', {method: 'POST'}) }}) - .then(res => { - if (res.ok) { - return auth.authFetch('/api/propagation-credentials/configured-credentials', {method: 'PUT', body:'[]'}) - }}) - .then(res => { + .then(res => { + if (res.ok) { + return auth.authFetch('/api/propagation-credentials/configured-credentials', {method: 'PUT', body:'[]'}) + }}) + .then(res => { if (res.ok) { - return auth.authFetch( - '/api/island/mode', - { - method: 'PUT', - headers: {'Content-Type': 'application/json'}, - body: '"unset"' - } - ) + return auth.authFetch('/api/agent-binaries/linux/masque', {method: 'PUT'}) + .then(res => { + if (res.ok) { + return auth.authFetch('/api/agent-binaries/windows/masque', {method: 'PUT'}) + } + }) }}) .then(res => { if (! res.ok) { throw 'Error resetting the simulation' - } - }) + }}) } function showModalButtons() { diff --git a/monkey/monkey_island/cc/ui/src/styles/pages/LandingPage.scss b/monkey/monkey_island/cc/ui/src/styles/pages/LandingPage.scss deleted file mode 100644 index 56b6db1b544..00000000000 --- a/monkey/monkey_island/cc/ui/src/styles/pages/LandingPage.scss +++ /dev/null @@ -1,65 +0,0 @@ -.landing-page { - background-color: rgba(255, 255, 255, 0.89); - height: 100%; - bottom: 0; -} - -.landing-page h1.page-title { - margin-top: 20px; - margin-bottom: 20px; -} - -.landing-page h2.scenario-choice-title { - margin-bottom: 20px; - margin-left: 12px; -} - -.landing-page .scenario-info { - margin-bottom: 20px; -} - -.landing-page .monkey-description-title { - margin-top: 30px; -} - -.landing-page .d-block { - height: 100%; -} - -.akamai-logo .license-text { - position: relative; -} - -.akamai-logo .version-text { - position: relative; -} - -.landing-page-banner { - display: block; - background-color: #ffcc00; - height:200px; - margin-right: -15px; - margin-left: -15px; -} - -.landing-banner-component { - display: block; - margin-left: auto; - margin-right: auto; - padding-top: 10px; -} - -.landing-banner-monkey-icon { - max-height: 65%; -} - -.landing-banner-title { - padding-bottom: 10px; - max-height: 35%; -} - -.landing-page .scenario-header { - font-size: 1.2em; - margin-top: 30px; - margin-left: 20px; -}