Skip to content

Commit

Permalink
Replacer: Support automation framework
Browse files Browse the repository at this point in the history
Signed-off-by: Simon Bennetts <[email protected]>
  • Loading branch information
psiinon committed Aug 26, 2023
1 parent ed8f046 commit 85139a6
Show file tree
Hide file tree
Showing 25 changed files with 1,644 additions and 26 deletions.
1 change: 1 addition & 0 deletions addOns/automation/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
### Fixed
- Address error logged when using the Active Scan job.
- Do not fail to load plans without jobs.
- Support converting Lists to arrays when updating objects.

## [0.30.0] - 2023-07-11
### Changed
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -226,18 +226,16 @@ public void reset() {
}

public void applyParameters(AutomationProgress progress) {
verifyOrApplyParameters(
this.getParamMethodObject(), this.getParamMethodName(), progress, false);
verifyOrApplyParameters(this.getParamMethodName(), progress, false);
}

public void verifyParameters(AutomationProgress progress) {
verifyOrApplyParameters(
this.getParamMethodObject(), this.getParamMethodName(), progress, true);
verifyOrApplyParameters(this.getParamMethodName(), progress, true);
}

@SuppressWarnings({"unchecked", "rawtypes"})
void verifyOrApplyParameters(
Object obj, String optionsGetterName, AutomationProgress progress, boolean verify) {
String optionsGetterName, AutomationProgress progress, boolean verify) {
if (this.jobData == null) {
return;
}
Expand Down Expand Up @@ -270,7 +268,7 @@ void verifyOrApplyParameters(
progress.error(
Constant.messages.getString(
"automation.error.options.methods",
obj.getClass().getCanonicalName(),
options.getClass().getCanonicalName(),
optionsGetterName,
e1.getMessage()));
return;
Expand Down Expand Up @@ -353,15 +351,15 @@ void verifyOrApplyParameters(
progress.error(
Constant.messages.getString(
"automation.error.options.badcall",
obj.getClass().getCanonicalName(),
options.getClass().getCanonicalName(),
paramMethodName,
e.getMessage()));
}
} else {
progress.error(
Constant.messages.getString(
"automation.error.options.badtype",
obj.getClass().getCanonicalName(),
options.getClass().getCanonicalName(),
paramMethodName,
optMethod.getParameterTypes()[0]
.getCanonicalName()));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.file.Files;
Expand Down Expand Up @@ -442,7 +443,7 @@ private static Class<?> toBaseClass(Class<?> origClass) {
}

@SuppressWarnings({"unchecked", "rawtypes"})
static <T> T objectToType(Object obj, T t) {
static <T> T objectToType(Object obj, Class<?> t) {
if (String.class.equals(t)) {
return (T) obj.toString();
} else if (Integer.class.equals(t) || int.class.equals(t)) {
Expand All @@ -469,7 +470,7 @@ static <T> T objectToType(Object obj, T t) {

} else if (List.class.equals(t)) {
if (obj instanceof List) {
List<String> list = new ArrayList<>();
List<T> list = new ArrayList<>();
list.addAll((ArrayList) obj);
return (T) list;
} else {
Expand All @@ -483,8 +484,29 @@ static <T> T objectToType(Object obj, T t) {
}
throw new IllegalArgumentException(
"Enum value must be one of " + EnumUtils.getEnumList((Class<Enum>) t));
} else if (t.isArray()) {
if (obj instanceof List) {
List objList = (List) obj;
try {
// This is nasty, but it works ;)
String arrayClassName = t.getCanonicalName();
String arrayBaseClassName =
arrayClassName.substring(0, arrayClassName.length() - 2);
T[] array =
(T[])
Array.newInstance(
Class.forName(arrayBaseClassName), objList.size());
objList.toArray(array);
return (T) array;
} catch (Exception e) {
LOGGER.error("Unable to map to an array from a list", e);
return null;
}
} else {
LOGGER.error(
"Unable to map to an array from {}", obj.getClass().getCanonicalName());
}
}

return null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1005,7 +1005,7 @@ void shouldFailOnBadOptionsGetterName() {

// When
job.setJobData(jobData);
job.verifyOrApplyParameters(tpc, "getBadTestParam", progress, false);
job.verifyOrApplyParameters("getBadTestParam", progress, false);

// Then
assertThat(progress.hasErrors(), is(equalTo(true)));
Expand All @@ -1014,6 +1014,27 @@ void shouldFailOnBadOptionsGetterName() {
assertThat(progress.getErrors().get(0), is(equalTo("!automation.error.options.method!")));
}

@SuppressWarnings({"unchecked", "rawtypes"})
@Test
void shouldNotFailToVerifyIfNoObject() {
// Given
AutomationJob job = new AutomationJobImpl(null, "getNullParam");
AutomationProgress progress = new AutomationProgress();

Map map = new HashMap();
LinkedHashMap<?, ?> params = new LinkedHashMap(map);
LinkedHashMap<String, Object> jobData = new LinkedHashMap();
jobData.put("parameters", params);

// When
job.setJobData(jobData);
job.verifyOrApplyParameters("getBadTestParam", progress, false);

// Then
assertThat(progress.hasErrors(), is(equalTo(false)));
assertThat(progress.hasWarnings(), is(equalTo(false)));
}

@Test
void shouldReturnDefaultConfigFileData() {
// Given
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,10 @@

import java.io.File;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import org.junit.jupiter.api.BeforeAll;
Expand Down Expand Up @@ -178,7 +180,7 @@ public String getParamMethodName() {
}

@Test
void shouldApplyObjectToType() {
void shouldApplyObjectToType() throws ClassNotFoundException {
// Given
HashMap<String, String> hmap = new HashMap<>();
hmap.put("aaa", "bbb");
Expand All @@ -198,6 +200,17 @@ void shouldApplyObjectToType() {
Object enumBBB = JobUtils.objectToType("bbB", enumeration.class);
Object map = JobUtils.objectToType(hmap, Map.class);

Class stringArrayClass = Class.forName("[L" + String.class.getName() + ";");
List<String> strList = new ArrayList<>();
strList.add("str");
Object strArray = JobUtils.objectToType(strList, stringArrayClass);

Class intArrayClass = Class.forName("[L" + Integer.class.getName() + ";");
List<Integer> intList = new ArrayList<>();
intList.add(3);
intList.add(9);
Object intArray = JobUtils.objectToType(intList, intArrayClass);

// Then
assertThat(string, is(equalTo("string")));
assertThat(integer5, is(equalTo(5)));
Expand All @@ -212,6 +225,13 @@ void shouldApplyObjectToType() {
assertThat(enumBBB, is(equalTo(enumeration.bbb)));
assertThat(map.getClass(), is(equalTo(HashMap.class)));
assertThat(((Map<?, ?>) map).size(), is(equalTo(2)));
assertThat(strArray.getClass(), is(equalTo(stringArrayClass)));
assertThat(((String[]) strArray).length, is(equalTo(1)));
assertThat(((String[]) strArray)[0], is(equalTo("str")));
assertThat(intArray.getClass(), is(equalTo(intArrayClass)));
assertThat(((Integer[]) intArray).length, is(equalTo(2)));
assertThat(((Integer[]) intArray)[0], is(equalTo(3)));
assertThat(((Integer[]) intArray)[1], is(equalTo(9)));
}

@Test
Expand Down
3 changes: 3 additions & 0 deletions addOns/replacer/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ All notable changes to this add-on will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).

## Unreleased
### Added
- Support for the Automation Framework

### Changed
- Document that Token Processing applies just to string match types and disable the field in
the dialogue when other match types are selected.
Expand Down
15 changes: 15 additions & 0 deletions addOns/replacer/replacer.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,20 @@ zapAddOn {
manifest {
author.set("ZAP Dev Team")
url.set("https://www.zaproxy.org/docs/desktop/addons/replacer/")
extensions {
register("org.zaproxy.zap.extension.replacer.automation.ExtensionReplacerAutomation") {
classnames {
allowed.set(listOf("org.zaproxy.zap.extension.replacer.automation"))
}
dependencies {
addOns {
register("automation") {
version.set(">=0.31.0")
}
}
}
}
}
}

apiClientGen {
Expand All @@ -18,5 +32,6 @@ zapAddOn {
}

dependencies {
zapAddOn("automation")
testImplementation(project(":testutils"))
}
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,6 @@ public ReplacerParamRule showAddDialogue() {
new ReplaceRuleAddDialog(
(Window) View.getSingleton().getOptionsDialog(null),
"replacer.add.title",
replacerParam,
(OptionsReplacerTableModel) model);
addDialog.pack();
}
Expand All @@ -157,7 +156,6 @@ public ReplacerParamRule showModifyDialogue(ReplacerParamRule r) {
new ReplaceRuleModifyDialog(
(Window) View.getSingleton().getOptionsDialog(null),
"replacer.modify.title",
replacerParam,
(OptionsReplacerTableModel) model);
modifyDialog.pack();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import java.util.List;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.swing.JCheckBox;
import org.parosproxy.paros.Constant;
import org.parosproxy.paros.network.HttpSender;
import org.zaproxy.zap.extension.replacer.ReplacerParamRule.MatchType;
Expand Down Expand Up @@ -63,17 +64,14 @@ public class ReplaceRuleAddDialog extends StandardFieldsDialog {
protected static final String INIT_TYPE_USER_FIELD = "replacer.label.init.user";
protected static final String INIT_TYPE_TOKEN_GEN_FIELD = "replacer.label.init.tokengen";

private ReplacerParam replacerParam;
private ReplacerParamRule rule;
private OptionsReplacerTableModel replacerModel;

public ReplaceRuleAddDialog(
Window owner,
String title,
ReplacerParam replacerParam,
OptionsReplacerTableModel replacerModel) {
super(owner, title, DisplayUtils.getScaledDimension(500, 350), ADV_TAB_LABELS, true);
this.replacerParam = replacerParam;
this.replacerModel = replacerModel;
initFields();
}
Expand Down Expand Up @@ -175,13 +173,15 @@ public OptionsReplacerTableModel getReplacerModel() {
return this.replacerModel;
}

/*
public ReplacerParam getReplacerParam() {
return replacerParam;
}
public void setReplacerParam(ReplacerParam replacerParam) {
this.replacerParam = replacerParam;
}
*/

private void setRule(ReplacerParamRule rule, MatchType selectedMatchType) {
this.rule = rule;
Expand Down Expand Up @@ -299,7 +299,10 @@ public void saveImpl() {
}

protected String checkIfUnique() {
if (this.replacerModel.containsRule(this.getStringValue(DESC_FIELD))) {
// this.replacerModel will be null when used with the AF - plans may be run on other systems
// or delete all existing rules
if (this.replacerModel != null
&& this.replacerModel.containsRule(this.getStringValue(DESC_FIELD))) {
return Constant.messages.getString("replacer.add.warning.existdesc");
}
return null;
Expand Down Expand Up @@ -492,12 +495,31 @@ private ReplacerParamRule.MatchType getSelectedMatchType() {
}
}

/**
* Allows callers to specify that rules added will always be enabled.
*
* @param enableEnabled
*/
public void setEnableEnabled(boolean enableEnabled) {
JCheckBox enabledField = (JCheckBox) this.getField(ENABLE_FIELD);
if (!enableEnabled) {
enabledField.setSelected(true);
}
enabledField.setEnabled(enableEnabled);
}

public void clear() {
this.rule = null;
setEnableEnabled(true);
this.setFieldValue(DESC_FIELD, "");
this.setFieldValue(MATCH_STR_FIELD, "");
this.setFieldValue(REPLACEMENT_FIELD, "");
this.setFieldValue(ENABLE_FIELD, false);
this.setFieldValue(ENABLE_TOKEN_PROCESSING, false);
}

@Override
public String getHelpIndex() {
return "replacer";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,8 @@ public class ReplaceRuleModifyDialog extends ReplaceRuleAddDialog {
private String originalDesc;

public ReplaceRuleModifyDialog(
Window owner,
String title,
ReplacerParam replacerParam,
OptionsReplacerTableModel replacerModel) {
super(owner, title, replacerParam, replacerModel);
Window owner, String title, OptionsReplacerTableModel replacerModel) {
super(owner, title, replacerModel);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,11 @@ public void setRules(List<ReplacerParamRule> rules) {
saveRules();
}

public void clearRules() {
this.rules = new ArrayList<>();
saveRules();
}

private void saveRules() {

((HierarchicalConfiguration) getConfig()).clearTree(ALL_RULES_KEY);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@ public ReplacerParamRule(
this.matchType = matchType;
this.matchString = matchString;
this.matchRegex = matchRegex;
this.escapedReplacement = HexString.compile(replacement);
if (replacement != null) {
this.escapedReplacement = HexString.compile(replacement);
}
this.replacement = replacement;
this.initiators = initiators;
this.tokenProcessingEnabled = tokenProcessingEnabled;
Expand Down
Loading

0 comments on commit 85139a6

Please sign in to comment.