Skip to content

Commit

Permalink
Merge branch '2698-plugin-selector-UI-schema' into develop
Browse files Browse the repository at this point in the history
Issue #2698
PR #2822
  • Loading branch information
mssalvatore committed Jan 11, 2023
2 parents 2df0133 + 50889ea commit c0d5fbd
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 146 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {ObjectFieldTemplateProps} from '@rjsf/utils';
import React, {useState} from 'react';
import {Dropdown} from 'react-bootstrap';

const PluginSelector = (props) => {
let selectOptions = [];
for (const [name, plugin] of Object.entries(props.plugins)) {
selectOptions.push(
<Dropdown.Item onClick={() => props.onClick(name)}
eventKey={`plugin['title']`}>
{plugin['title']}</Dropdown.Item>
)}

return (
<Dropdown>
<Dropdown.Toggle variant="success" id="dropdown-basic">
Select a plugin
</Dropdown.Toggle>
<Dropdown.Menu>
{selectOptions}
</Dropdown.Menu>
</Dropdown>
)
}


export default function PluginSelectorTemplate(props: ObjectFieldTemplateProps) {

function getPluginDisplay(plugin, allPlugins){
let selectedPlugin = allPlugins.filter((pluginInArray) => pluginInArray.name == plugin)
if(selectedPlugin.length === 1){
return <div className="property-wrapper">{selectedPlugin[0].content}</div>
}
}

let [element, setElement] = useState(null);
return (
<div>
{props.title}
{props.description}
<PluginSelector plugins={{"TODO": {"title": "pass in actual schema"}}}
onClick={(pluginName) => {
setElement(pluginName)
}}/>
{getPluginDisplay(element, props.properties)}
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ import InfoBox from './InfoBox';
import TextBox from './TextBox.js';
import WarningBox from './WarningBox';
import SensitiveTextInput from '../ui-components/SensitiveTextInput';
import PluginSelectorTemplate from './PluginSelectorTemplate';

export default function UiSchema(props) {
const UiSchema = {
propagation: {
exploitation: {
exploiters: {
classNames: 'config-template-no-header',
'ui:widget': AdvancedMultiSelect
'ui:ObjectFieldTemplate': PluginSelectorTemplate
},
options: {
http_ports: {
Expand Down
19 changes: 17 additions & 2 deletions monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import React from 'react';
import Form from '@rjsf/bootstrap-4';
import {Col, Nav} from 'react-bootstrap';
import _ from 'lodash';
import AuthComponent from '../AuthComponent';
import UiSchema from '../configuration-components/UiSchema';
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
Expand All @@ -26,6 +27,7 @@ import {
import validator from '@rjsf/validator-ajv8';

const CONFIG_URL = '/api/agent-configuration';
const SCHEMA_URL = '/api/agent-configuration-schema';
const RESET_URL = '/api/reset-agent-configuration';
const CONFIGURED_PROPAGATION_CREDENTIALS_URL = '/api/propagation-credentials/configured-credentials';

Expand All @@ -46,7 +48,7 @@ class ConfigurePageComponent extends AuthComponent {
currentFormData: {},
importCandidateConfig: null,
lastAction: 'none',
schema: {},
schema: SCHEMA,
sections: [],
selectedSection: this.currentSection,
showUnsafeOptionsConfirmation: false,
Expand Down Expand Up @@ -77,7 +79,21 @@ class ConfigurePageComponent extends AuthComponent {
this.initialConfig = JSON.parse(JSON.stringify(config));
}

injectExploitersIntoLegacySchema = (newSchema) => {
// legacy schema is defined in UI,
// but we should use the schema provided by "/api/agent-configuration-schema"
// Remove when #2750 is done
let injectedSchema = _.cloneDeep(this.state.schema);
injectedSchema['properties']['propagation']['properties']['exploitation']['properties']['exploiters'] =
newSchema['definitions']['ExploitationConfiguration']['properties']['exploiters']
return injectedSchema;
}

componentDidMount = () => {
this.authFetch(SCHEMA_URL).then(res => res.json())
.then(schema => {
this.setState({schema: this.injectExploitersIntoLegacySchema(schema)})
})
this.authFetch(CONFIG_URL).then(res => res.json())
.then(monkeyConfig => {
let sections = [];
Expand All @@ -92,7 +108,6 @@ class ConfigurePageComponent extends AuthComponent {
}

this.setState({
schema: SCHEMA,
configuration: monkeyConfig,
sections: sections,
currentFormData: monkeyConfig[this.state.selectedSection]
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import EXPLOITATION_OPTIONS_CONFIGURATION_SCHEMA from '../exploitationOptions.js';
import {EXPLOITERS} from '../exploiterClasses';


const EXPLOITATION_CONFIGURATION_SCHEMA = {
'title': 'Propagation',
'properties': {
'exploiters': {
'items': EXPLOITERS,
'title': 'Exploiters',
'type': 'array',
'uniqueItems': true
},
// Exploiters get injected from schema generated on the back end
},

'options': EXPLOITATION_OPTIONS_CONFIGURATION_SCHEMA
},
'type': 'object'
Expand Down

0 comments on commit c0d5fbd

Please sign in to comment.