forked from p15670423/monkey
Island: Implements basics of page redirection when island mode is set
This commit is contained in:
parent
b03c6d9f92
commit
5743f8ea98
|
@ -0,0 +1,31 @@
|
||||||
|
import AuthComponent from "./AuthComponent";
|
||||||
|
import React from "react";
|
||||||
|
|
||||||
|
export class Response{
|
||||||
|
body: any
|
||||||
|
status: number
|
||||||
|
|
||||||
|
constructor(body: any, status: number) {
|
||||||
|
this.body = body
|
||||||
|
this.status = status
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class IslandHttpClient extends AuthComponent {
|
||||||
|
post(endpoint: string, contents: any): Promise<Response>{
|
||||||
|
return this.authFetch(endpoint,
|
||||||
|
{
|
||||||
|
method: 'POST',
|
||||||
|
headers: {'Content-Type': 'application/json'},
|
||||||
|
body: JSON.stringify(contents)
|
||||||
|
})
|
||||||
|
.then(res => new Response(res.json(), res.status));
|
||||||
|
}
|
||||||
|
|
||||||
|
get(endpoint: string): Promise<Response>{
|
||||||
|
return this.authFetch(endpoint)
|
||||||
|
.then(res => new Response(res.json(), res.status));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default new IslandHttpClient();
|
|
@ -12,6 +12,7 @@ import LicensePage from './pages/LicensePage';
|
||||||
import AuthComponent from './AuthComponent';
|
import AuthComponent from './AuthComponent';
|
||||||
import LoginPageComponent from './pages/LoginPage';
|
import LoginPageComponent from './pages/LoginPage';
|
||||||
import RegisterPageComponent from './pages/RegisterPage';
|
import RegisterPageComponent from './pages/RegisterPage';
|
||||||
|
import LandingPage from "./pages/LandingPage";
|
||||||
import Notifier from 'react-desktop-notification';
|
import Notifier from 'react-desktop-notification';
|
||||||
import NotFoundPage from './pages/NotFoundPage';
|
import NotFoundPage from './pages/NotFoundPage';
|
||||||
import GettingStartedPage from './pages/GettingStartedPage';
|
import GettingStartedPage from './pages/GettingStartedPage';
|
||||||
|
@ -24,10 +25,10 @@ import 'react-toggle/style.css';
|
||||||
import 'react-table/react-table.css';
|
import 'react-table/react-table.css';
|
||||||
import {StandardLayoutComponent} from './layouts/StandardLayoutComponent';
|
import {StandardLayoutComponent} from './layouts/StandardLayoutComponent';
|
||||||
import LoadingScreen from './ui-components/LoadingScreen';
|
import LoadingScreen from './ui-components/LoadingScreen';
|
||||||
import LandingPageComponent from "./pages/LandingPage";
|
|
||||||
import {DisabledSidebarLayoutComponent} from "./layouts/DisabledSidebarLayoutComponent";
|
import {DisabledSidebarLayoutComponent} from "./layouts/DisabledSidebarLayoutComponent";
|
||||||
import {CompletedSteps} from "./side-menu/CompletedSteps";
|
import {CompletedSteps} from "./side-menu/CompletedSteps";
|
||||||
import Timeout = NodeJS.Timeout;
|
import Timeout = NodeJS.Timeout;
|
||||||
|
import IslandHttpClient from "./IslandHttpClient";
|
||||||
|
|
||||||
|
|
||||||
let notificationIcon = require('../images/notification-logo-512x512.png');
|
let notificationIcon = require('../images/notification-logo-512x512.png');
|
||||||
|
@ -35,6 +36,11 @@ let notificationIcon = require('../images/notification-logo-512x512.png');
|
||||||
const reportZeroTrustRoute = '/report/zeroTrust';
|
const reportZeroTrustRoute = '/report/zeroTrust';
|
||||||
|
|
||||||
|
|
||||||
|
const Routes = {
|
||||||
|
LandingPage: '/landing-page',
|
||||||
|
GettingStartedPage: '/'
|
||||||
|
}
|
||||||
|
|
||||||
class AppComponent extends AuthComponent {
|
class AppComponent extends AuthComponent {
|
||||||
private interval: Timeout;
|
private interval: Timeout;
|
||||||
|
|
||||||
|
@ -43,7 +49,7 @@ class AppComponent extends AuthComponent {
|
||||||
let completedSteps = new CompletedSteps(false);
|
let completedSteps = new CompletedSteps(false);
|
||||||
this.state = {
|
this.state = {
|
||||||
completedSteps: completedSteps,
|
completedSteps: completedSteps,
|
||||||
islandMode: undefined,
|
islandMode: null,
|
||||||
noAuthLoginAttempted: undefined
|
noAuthLoginAttempted: undefined
|
||||||
};
|
};
|
||||||
this.interval = undefined;
|
this.interval = undefined;
|
||||||
|
@ -70,9 +76,12 @@ class AppComponent extends AuthComponent {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
this.checkMode();
|
|
||||||
|
|
||||||
if (res) {
|
if (res) {
|
||||||
|
this.checkMode()
|
||||||
|
.then(() => {
|
||||||
|
if(this.state.islandMode === null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
this.authFetch('/api')
|
this.authFetch('/api')
|
||||||
.then(res => res.json())
|
.then(res => res.json())
|
||||||
.then(res => {
|
.then(res => {
|
||||||
|
@ -88,17 +97,17 @@ class AppComponent extends AuthComponent {
|
||||||
this.setState({completedSteps: res['completed_steps']});
|
this.setState({completedSteps: res['completed_steps']});
|
||||||
this.showInfectionDoneNotification();
|
this.showInfectionDoneNotification();
|
||||||
}
|
}
|
||||||
});
|
});}
|
||||||
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
checkMode = () => {
|
checkMode = () => {
|
||||||
// TODO change to fetch the mode from UI
|
return IslandHttpClient.get('/api/island-mode')
|
||||||
this.authFetch('/api')
|
|
||||||
.then(res => res.json())
|
|
||||||
.then(res => {
|
.then(res => {
|
||||||
this.setState({IslandMode: undefined})
|
this.setState({islandMode: res.body.mode});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -106,8 +115,10 @@ class AppComponent extends AuthComponent {
|
||||||
let render_func = () => {
|
let render_func = () => {
|
||||||
switch (this.state.isLoggedIn) {
|
switch (this.state.isLoggedIn) {
|
||||||
case true:
|
case true:
|
||||||
if(this.state.islandMode === undefined){
|
if (this.state.islandMode === null && route_path !== Routes.LandingPage) {
|
||||||
return this.getLandingPage();
|
return <Redirect to={{pathname: Routes.LandingPage}}/>
|
||||||
|
} else if(route_path === Routes.LandingPage && this.state.islandMode !== null){
|
||||||
|
return <Redirect to={{pathname: Routes.GettingStartedPage}}/>
|
||||||
}
|
}
|
||||||
return page_component;
|
return page_component;
|
||||||
case false:
|
case false:
|
||||||
|
@ -131,12 +142,6 @@ class AppComponent extends AuthComponent {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
getLandingPage() {
|
|
||||||
return <DisabledSidebarLayoutComponent component={LandingPageComponent}
|
|
||||||
completedSteps={new CompletedSteps()}
|
|
||||||
onStatusChange={this.updateStatus}/>
|
|
||||||
}
|
|
||||||
|
|
||||||
redirectTo = (userPath, targetPath) => {
|
redirectTo = (userPath, targetPath) => {
|
||||||
let pathQuery = new RegExp(userPath + '[/]?$', 'g');
|
let pathQuery = new RegExp(userPath + '[/]?$', 'g');
|
||||||
if (window.location.pathname.match(pathQuery)) {
|
if (window.location.pathname.match(pathQuery)) {
|
||||||
|
@ -160,7 +165,11 @@ class AppComponent extends AuthComponent {
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path='/login' render={() => (<LoginPageComponent onStatusChange={this.updateStatus}/>)}/>
|
<Route path='/login' render={() => (<LoginPageComponent onStatusChange={this.updateStatus}/>)}/>
|
||||||
<Route path='/register' render={() => (<RegisterPageComponent onStatusChange={this.updateStatus}/>)}/>
|
<Route path='/register' render={() => (<RegisterPageComponent onStatusChange={this.updateStatus}/>)}/>
|
||||||
{this.renderRoute('/',
|
{this.renderRoute(Routes.LandingPage,
|
||||||
|
<DisabledSidebarLayoutComponent component={LandingPage}
|
||||||
|
completedSteps={new CompletedSteps()}
|
||||||
|
onStatusChange={this.updateStatus}/>)}
|
||||||
|
{this.renderRoute(Routes.GettingStartedPage,
|
||||||
<StandardLayoutComponent component={GettingStartedPage}
|
<StandardLayoutComponent component={GettingStartedPage}
|
||||||
completedSteps={this.state.completedSteps}
|
completedSteps={this.state.completedSteps}
|
||||||
onStatusChange={this.updateStatus}
|
onStatusChange={this.updateStatus}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react'
|
import React from 'react';
|
||||||
import {Route} from 'react-router-dom'
|
import {Route} from 'react-router-dom';
|
||||||
import SideNavComponent from '../SideNavComponent.tsx'
|
import SideNavComponent from '../SideNavComponent.tsx';
|
||||||
import {Col, Row} from 'react-bootstrap';
|
import {Col, Row} from 'react-bootstrap';
|
||||||
|
|
||||||
export const DisabledSidebarLayoutComponent = ({component: Component, ...rest}) => (
|
export const DisabledSidebarLayoutComponent = ({component: Component, ...rest}) => (
|
||||||
|
|
|
@ -4,59 +4,68 @@ import {Link} from 'react-router-dom';
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
||||||
import {faFileCode, faLightbulb} from '@fortawesome/free-solid-svg-icons';
|
import {faFileCode, faLightbulb} from '@fortawesome/free-solid-svg-icons';
|
||||||
import '../../styles/pages/LandingPage.scss';
|
import '../../styles/pages/LandingPage.scss';
|
||||||
import AuthComponent from '../AuthComponent';
|
import IslandHttpClient from "../IslandHttpClient";
|
||||||
|
|
||||||
|
|
||||||
class LandingPageComponent extends AuthComponent {
|
const LandingPageComponent = (props) => {
|
||||||
constructor(props) {
|
|
||||||
super(props);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return (
|
return (
|
||||||
<Col sm={{offset: 3, span: 9}} md={{offset: 3, span: 9}}
|
<Col sm={{offset: 3, span: 9}} md={{offset: 3, span: 9}}
|
||||||
lg={{offset: 3, span: 9}} xl={{offset: 2, span: 7}}
|
lg={{offset: 3, span: 9}} xl={{offset: 2, span: 7}}
|
||||||
className={'landing-page'}>
|
className={'landing-page'}>
|
||||||
<h1 className="page-title">Welcome to the Monkey Island Server</h1>
|
<h1 className="page-title">Welcome to the Monkey Island Server</h1>
|
||||||
<div style={{'fontSize': '1.2em'}}>
|
<div style={{'fontSize': '1.2em'}}>
|
||||||
<ScenarioButtons />
|
<ScenarioButtons/>
|
||||||
<br/>
|
<br/>
|
||||||
</div>
|
</div>
|
||||||
</Col>
|
</Col>
|
||||||
);
|
);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function ScenarioButtons() {
|
function ScenarioButtons() {
|
||||||
return (
|
return (
|
||||||
<section>
|
<section>
|
||||||
<h2 className={'scenario-choice-title'}>Choose a scenario:</h2>
|
<h2 className={'scenario-choice-title'}>Choose a scenario:</h2>
|
||||||
<div className="container">
|
<div className="container">
|
||||||
<Row className="justify-content-center">
|
<Row className="justify-content-center">
|
||||||
<div className="col-lg-6 col-sm-6">
|
<div className="col-lg-6 col-sm-6">
|
||||||
<Link to="/run-monkey" className="px-4 py-5 bg-white shadow text-center d-block">
|
<Link to="/run-monkey"
|
||||||
|
className="px-4 py-5 bg-white shadow text-center d-block"
|
||||||
|
onClick={() => {
|
||||||
|
setScenario('ransomware')
|
||||||
|
}}>
|
||||||
<h4><FontAwesomeIcon icon={faFileCode}/> Ransomware</h4>
|
<h4><FontAwesomeIcon icon={faFileCode}/> Ransomware</h4>
|
||||||
<p>Simulate ransomware infection in the network.</p>
|
<p>Simulate ransomware infection in the network.</p>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
<div className="col-lg-6 col-sm-6">
|
<div className="col-lg-6 col-sm-6">
|
||||||
<Link to="/configure" className="px-4 py-5 bg-white shadow text-center d-block">
|
<Link to="/configure"
|
||||||
|
className="px-4 py-5 bg-white shadow text-center d-block"
|
||||||
|
onClick={() => {
|
||||||
|
setScenario('advanced')
|
||||||
|
}}>
|
||||||
<h4><FontAwesomeIcon icon={faLightbulb}/> Custom</h4>
|
<h4><FontAwesomeIcon icon={faLightbulb}/> Custom</h4>
|
||||||
<p>Fine tune the simulation to your needs.</p>
|
<p>Fine tune the simulation to your needs.</p>
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</Row>
|
</Row>
|
||||||
<MonkeyInfo />
|
<MonkeyInfo/>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setScenario(scenario: string) {
|
||||||
|
IslandHttpClient.post('/api/island-mode', {'mode': scenario});
|
||||||
|
props.onStatusChange();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function MonkeyInfo() {
|
function MonkeyInfo() {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<h4 className={'monkey-description-title'}>What is Infection Monkey?</h4>
|
<h4 className={'monkey-description-title'}>What is Infection Monkey?</h4>
|
||||||
<strong>Infection Monkey</strong> is an open-source security tool for testing a data center's resiliency to perimeter
|
<strong>Infection Monkey</strong> 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
|
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.
|
and reports to this Monkey Island Command and Control server.
|
||||||
</>
|
</>
|
||||||
|
|
Loading…
Reference in New Issue