Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

2698 plugin selector core #2841

Merged
merged 10 commits into from
Jan 17, 2023
Original file line number Diff line number Diff line change
@@ -1,48 +1,89 @@
import {ObjectFieldTemplateProps} from '@rjsf/utils';
import {getDefaultFormState, 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>
)
}
import ChildCheckboxContainer from '../ui-components/ChildCheckbox';
import {AdvancedMultiSelectHeader} from '../ui-components/AdvancedMultiSelect';
import {MasterCheckboxState} from '../ui-components/MasterCheckbox';


export default function PluginSelectorTemplate(props: ObjectFieldTemplateProps) {

function getPluginDisplay(plugin, allPlugins){
let [selectedPlugin, setSelectedPlugin] = useState(null);

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

let [element, setElement] = useState(null);
function getOptions() {
let selectorOptions = [];
for (let [name, schema] of Object.entries(props.schema.properties)) {
selectorOptions.push({label: schema.title, value: name});
}
return selectorOptions;
}

function togglePluggin(pluginName) {
let plugins = new Set(props.formContext.selectedExploiters);
if (props.formContext.selectedExploiters.has(pluginName)) {
plugins.delete(pluginName);
} else {
plugins.add(pluginName);
}
props.formContext.setSelectedExploiters(plugins)
}

function getMasterCheckboxState(selectValues) {
if (Object.keys(selectValues).length === 0) {
return MasterCheckboxState.NONE;
}

if (Object.keys(selectValues).length !== getOptions().length) {
return MasterCheckboxState.MIXED;
}

return MasterCheckboxState.ALL;
}

function generateDefaultConfig() {
return getDefaultFormState(props.registry.schemaUtils.validator,
props.schema, {}, props.registry.rootSchema, true);
}

function onMasterPluginCheckboxClick() {
let checkboxState = getMasterCheckboxState(props.formContext.selectedExploiters);
if (checkboxState == MasterCheckboxState.ALL) {
props.formContext.setSelectedExploiters({});
} else {
props.formContext.setSelectedExploiters(generateDefaultConfig());
}
}

function isPluginSafe(itemKey) {
let itemSchema = Object.entries(props.schema.properties).filter(e => e[0] == itemKey)[0][1];
return itemSchema['safe'];
}

return (
<div>
{props.title}
{props.description}
<PluginSelector plugins={{"TODO": {"title": "pass in actual schema"}}}
onClick={(pluginName) => {
setElement(pluginName)
}}/>
{getPluginDisplay(element, props.properties)}
<div className={'advanced-multi-select'}>
<AdvancedMultiSelectHeader title={props.schema.title}
onCheckboxClick={onMasterPluginCheckboxClick}
checkboxState={
getMasterCheckboxState(
[...props.formContext.selectedExploiters])}
hideReset={false}
onResetClick={() => {
}}/>

<ChildCheckboxContainer id={'abc'} multiple={true} required={false}
autoFocus={false}
selectedValues={[...props.formContext.selectedExploiters]}
onCheckboxClick={togglePluggin}
isSafe={isPluginSafe}
onPaneClick={setSelectedPlugin}
enumOptions={getOptions()}/>
{getPluginDisplay(selectedPlugin, props.properties)}
</div>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ const sectionOrder = [

const initialSection = sectionOrder[0];

export const EXPLOITERS_PATH_PROPAGATION = 'exploitation.exploiters';
export const EXPLOITERS_CONFIG_PATH = 'propagation.' + EXPLOITERS_PATH_PROPAGATION;

export default function PropagationConfig(props) {
const {
schema,
Expand All @@ -23,8 +26,11 @@ export default function PropagationConfig(props) {
className,
configuration,
credentials,
onCredentialChange
onCredentialChange,
selectedExploiters,
setSelectedExploiters
} = props;

const [selectedSection, setSelectedSection] = useState(initialSection);

const onFormDataChange = (formData) => {
Expand Down Expand Up @@ -75,7 +81,11 @@ export default function PropagationConfig(props) {
key={selectedSection}
liveValidate
// children={true} hides the submit button
children={true}/>
children={true}
formContext={{
'selectedExploiters': selectedExploiters,
'setSelectedExploiters': setSelectedExploiters
}}/>
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export default function UiSchema(props) {
propagation: {
exploitation: {
exploiters: {
classNames: 'config-template-no-header',
'ui:classNames': 'config-template-no-header',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could've been a separate PR, but for the sake of speed left it here

'ui:ObjectFieldTemplate': PluginSelectorTemplate
},
options: {
Expand All @@ -31,19 +31,19 @@ export default function UiSchema(props) {
},
exploit_password_list: {
items: {
classNames: 'config-template-no-header',
'ui:classNames': 'config-template-no-header',
'ui:widget': SensitiveTextInput
}
},
exploit_lm_hash_list: {
items: {
classNames: 'config-template-no-header',
'ui:classNames': 'config-template-no-header',
'ui:widget': SensitiveTextInput
}
},
exploit_ntlm_hash_list: {
items: {
classNames: 'config-template-no-header',
'ui:classNames': 'config-template-no-header',
'ui:widget': SensitiveTextInput
}
}
Expand All @@ -52,42 +52,42 @@ export default function UiSchema(props) {
targets: {
blocked_ips: {
items: {
classNames: 'config-template-no-header'
'ui:classNames': 'config-template-no-header'
}
},
inaccessible_subnets: {
items: {
classNames: 'config-template-no-header'
'ui:classNames': 'config-template-no-header'
}
},
info_box_scan_my_networks: {
'ui:field': WarningBox
},
subnets: {
items: {
classNames: 'config-template-no-header'
'ui:classNames': 'config-template-no-header'
}
}
},
tcp: {
ports: {
items: {
classNames: 'config-template-no-header'
'ui:classNames': 'config-template-no-header'
}
}
},
fingerprinters: {
classNames: 'config-template-no-header',
'ui:classNames': 'config-template-no-header',
'ui:widget': AdvancedMultiSelect,
fingerprinter_classes: {
classNames: 'config-template-no-header'
'ui:classNames': 'config-template-no-header'
}

}
}
},
payloads: {
classNames: 'config-template-no-header',
'ui:classNames': 'config-template-no-header',
encryption: {
info_box: {
'ui:field': InfoBox
Expand All @@ -110,10 +110,10 @@ export default function UiSchema(props) {
}
},
credential_collectors: {
classNames: 'config-template-no-header',
'ui:classNames': 'config-template-no-header',
'ui:widget': AdvancedMultiSelect,
credential_collectors_classes: {
classNames: 'config-template-no-header'
'ui:classNames': 'config-template-no-header'
}
}
};
Expand Down
Loading