diff --git a/monkey/monkey_island/cc/ui/src/components/configuration-components/ExportConfigModal.tsx b/monkey/monkey_island/cc/ui/src/components/configuration-components/ExportConfigModal.tsx index 469d91ec3..ef11dd67f 100644 --- a/monkey/monkey_island/cc/ui/src/components/configuration-components/ExportConfigModal.tsx +++ b/monkey/monkey_island/cc/ui/src/components/configuration-components/ExportConfigModal.tsx @@ -4,6 +4,7 @@ import React, {useState} from 'react'; import FileSaver from 'file-saver'; import '../../styles/components/configuration-components/ExportConfigModal.scss'; import {encryptText} from '../utils/PasswordBasedEncryptor'; +import {reformatConfig} from './ReformatHook'; type Props = { @@ -21,7 +22,7 @@ const ConfigExportModal = (props: Props) => { } function onSubmit() { - let config = props.configuration; + let config = reformatConfig(props.configuration, true); let config_export = {'metadata': {}, 'contents': null}; if (radioValue === 'password') { diff --git a/monkey/monkey_island/cc/ui/src/components/configuration-components/ImportConfigModal.tsx b/monkey/monkey_island/cc/ui/src/components/configuration-components/ImportConfigModal.tsx index a60a25c0f..cce66a521 100644 --- a/monkey/monkey_island/cc/ui/src/components/configuration-components/ImportConfigModal.tsx +++ b/monkey/monkey_island/cc/ui/src/components/configuration-components/ImportConfigModal.tsx @@ -20,8 +20,7 @@ type Props = { const ConfigImportModal = (props: Props) => { - // TODO: change this endpoint to the new configuration import endpoint - const configImportEndpoint = '/api/configuration/import'; + const configImportEndpoint = '/api/agent-configuration'; const [uploadStatus, setUploadStatus] = useState(UploadStatuses.clean); const [configContents, setConfigContents] = useState(null); @@ -71,18 +70,15 @@ const ConfigImportModal = (props: Props) => { { method: 'POST', headers: {'Content-Type': 'application/json'}, - body: JSON.stringify({ - config: configContents, - }) + body: JSON.stringify(configContents) } - ).then(res => res.json()) - .then(res => { - if (res['import_status'] === 'invalid_configuration') { - setUploadStatus(UploadStatuses.error); - setErrorMessage(res['message']); - } else if (res['import_status'] === 'imported') { + ).then(res => { + if (res.ok) { resetState(); props.onClose(true); + } else { + setUploadStatus(UploadStatuses.error); + setErrorMessage("Configuration file is corrupt or in an outdated format."); } }) } diff --git a/monkey/monkey_island/cc/ui/src/components/configuration-components/ReformatHook.js b/monkey/monkey_island/cc/ui/src/components/configuration-components/ReformatHook.js new file mode 100644 index 000000000..322882194 --- /dev/null +++ b/monkey/monkey_island/cc/ui/src/components/configuration-components/ReformatHook.js @@ -0,0 +1,8 @@ +export function reformatConfig(config, reverse = false) { + if (reverse) { + config['payloads'] = [{'name': 'ransomware', 'options': config['payloads']}] + } else { + config['payloads'] = config['payloads'][0]['options']; + } + return config; + } 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 d31a4fd2f..1587cc11a 100644 --- a/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js +++ b/monkey/monkey_island/cc/ui/src/components/pages/ConfigurePage.js @@ -18,6 +18,7 @@ import applyUiSchemaManipulators from '../configuration-components/UISchemaManip import HtmlFieldDescription from '../configuration-components/HtmlFieldDescription.js'; import CONFIGURATION_TABS_PER_MODE from '../configuration-components/ConfigurationTabs.js'; import {SCHEMA} from '../../services/configuration/config_schema.js'; +import {reformatConfig} from '../configuration-components/ReformatHook'; const CONFIG_URL = '/api/agent-configuration'; export const API_PBA_LINUX = '/api/file-upload/PBAlinux'; @@ -71,9 +72,7 @@ class ConfigurePageComponent extends AuthComponent { this.authFetch(CONFIG_URL).then(res => res.json()) .then(monkeyConfig => { let sections = []; - let monkeyConfig = data[0]; - // TODO: Fix when we add plugins - monkeyConfig['payloads'] = monkeyConfig['payloads'][0]['options']; + monkeyConfig = reformatConfig(monkeyConfig); this.setInitialConfig(monkeyConfig); for (let sectionKey of this.getSectionsOrder()) { @@ -110,13 +109,16 @@ class ConfigurePageComponent extends AuthComponent { this.setState({showUnsafeAttackOptionsWarning: false}); } - updateConfig = (callback = null) => { + updateConfig = () => { this.authFetch(CONFIG_URL) .then(res => res.json()) .then(data => { - this.setInitialConfig(data.configuration); - this.setState({configuration: data.configuration, - currentFormData: data.configuration[this.state.selectedSection]}, callback); + data = reformatConfig(data); + this.setInitialConfig(data); + this.setState({ + configuration: data, + currentFormData: data[this.state.selectedSection] + }); }) }; @@ -132,7 +134,7 @@ class ConfigurePageComponent extends AuthComponent { await this.updateConfigSection(); if (this.canSafelySubmitConfig(this.state.configuration)) { this.configSubmit(); - if(this.state.lastAction === configExportAction){ + if (this.state.lastAction === configExportAction) { this.setState({showConfigExportModal: true}) } } else { @@ -145,16 +147,14 @@ class ConfigurePageComponent extends AuthComponent { .then(res => res.json()) .then(res => { this.setState({ - lastAction: configSaveAction, - schema: res.schema, - configuration: res.configuration + lastAction: configSaveAction }); - this.setInitialConfig(res.configuration); + this.setInitialConfig(this.state.configuration); this.props.onStatusChange(); }).catch(error => { - console.log('Bad configuration: ' + error.toString()); - this.setState({lastAction: 'invalid_configuration'}); - }); + console.log('Bad configuration: ' + error.toString()); + this.setState({lastAction: 'invalid_configuration'}); + }); } onChange = ({formData}) => { @@ -187,10 +187,12 @@ class ConfigurePageComponent extends AuthComponent { } onClose = (importSuccessful) => { - if(importSuccessful === true){ + if (importSuccessful === true) { this.updateConfig(); - this.setState({lastAction: 'import_success', - showConfigImportModal: false}); + this.setState({ + lastAction: 'import_success', + showConfigImportModal: false + }); } else { this.setState({showConfigImportModal: false}); @@ -251,8 +253,8 @@ class ConfigurePageComponent extends AuthComponent { } } } catch (TypeError) { - if (JSON.stringify(this.initialConfig[this.currentSection]) === JSON.stringify(this.state.currentFormData)){ - return false; + if (JSON.stringify(this.initialConfig[this.currentSection]) === JSON.stringify(this.state.currentFormData)) { + return false; } } return true; @@ -285,6 +287,7 @@ class ConfigurePageComponent extends AuthComponent { }) .then(res => res.json()) .then(res => { + res.configuration = reformatConfig(res.configuration); this.setState({ lastAction: 'reset', schema: res.schema, @@ -319,12 +322,15 @@ class ConfigurePageComponent extends AuthComponent { }; sendConfig() { + let config = JSON.parse(JSON.stringify(this.state.configuration)) + config = reformatConfig(config, true); + return ( this.authFetch(CONFIG_URL, { method: 'POST', headers: {'Content-Type': 'application/json'}, - body: JSON.stringify(this.state.configuration) + body: JSON.stringify(config) }) .then(res => { if (!res.ok) { @@ -356,8 +362,8 @@ class ConfigurePageComponent extends AuthComponent { formProperties['liveValidate'] = true; applyUiSchemaManipulators(this.state.selectedSection, - formProperties['formData'], - formProperties['uiSchema']); + formProperties['formData'], + formProperties['uiSchema']); return (