Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit d9432ab

Browse files
committedMar 17, 2025·
alertFilters: Add param descriptions for Web API
Signed-off-by: kingthorin <kingthorin@users.noreply.github.com>
1 parent bdf2d49 commit d9432ab

File tree

4 files changed

+245
-3
lines changed

4 files changed

+245
-3
lines changed
 

‎addOns/alertFilters/CHANGELOG.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ All notable changes to this add-on will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
55

66
## Unreleased
7-
7+
### Added
8+
- Added parameter descriptions for the ZAP API.
89

910
## [23] - 2025-01-09
1011
### Changed

‎addOns/alertFilters/src/main/java/org/zaproxy/zap/extension/alertFilters/AlertFilterAPI.java

+5
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,11 @@ public String getPrefix() {
207207
return PREFIX;
208208
}
209209

210+
@Override
211+
protected String getI18nPrefix() {
212+
return ExtensionAlertFilters.PREFIX;
213+
}
214+
210215
@Override
211216
public ApiResponse handleApiView(String name, JSONObject params) throws ApiException {
212217
LOGGER.debug("handleApiView {} {}", name, params);

‎addOns/alertFilters/src/main/resources/org/zaproxy/zap/extension/alertFilters/resources/Messages.properties

+56-2
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,68 @@
1-
alertFilters.api.action.addAlertFilter = Adds a new alert filter for the context with the given ID.
2-
alertFilters.api.action.addGlobalAlertFilter = Adds a new global alert filter.
1+
alertFilters.api.action.addAlertFilter = Adds a new alert filter for the context with the given ID.
2+
alertFilters.api.action.addAlertFilter.param.attack = The attack value for which the filter should apply (can be regex).
3+
alertFilters.api.action.addAlertFilter.param.attackIsRegex = A boolean indicating whether or not the attack value is a regex.
4+
alertFilters.api.action.addAlertFilter.param.contextId = The numeric ID of the context for which the filter should be added.
5+
alertFilters.api.action.addAlertFilter.param.enabled = A boolean indicating whether or not the filter should be enabled.
6+
alertFilters.api.action.addAlertFilter.param.evidence = The evidence value for which the filter should apply (can be regex).
7+
alertFilters.api.action.addAlertFilter.param.evidenceIsRegex = A boolean indicating whether or not the evidence value is a regex.
8+
alertFilters.api.action.addAlertFilter.param.methods = The HTTP methods (comma separated) for which the filter should apply.
9+
alertFilters.api.action.addAlertFilter.param.newLevel = The numeric risk representation ('0 - Informational' through '3 - High') ['-1 - False Positive'].
10+
alertFilters.api.action.addAlertFilter.param.parameter = The parameter name for which the filter should apply (can be regex).
11+
alertFilters.api.action.addAlertFilter.param.parameterIsRegex = A boolean indicating whether or not the parameter name is a regex.
12+
alertFilters.api.action.addAlertFilter.param.ruleId = The numeric ID of the rule for which the filter should apply.
13+
alertFilters.api.action.addAlertFilter.param.url = The URL for which the filter should apply (can be regex).
14+
alertFilters.api.action.addAlertFilter.param.urlIsRegex = A boolean indicating whether or not the URL is a regex.
15+
alertFilters.api.action.addGlobalAlertFilter = Adds a new global alert filter.
16+
alertFilters.api.action.addGlobalAlertFilter.param.attack = The attack value for which the filter should apply (can be regex).
17+
alertFilters.api.action.addGlobalAlertFilter.param.attackIsRegex = A boolean indicating whether or not the attack value is a regex.
18+
alertFilters.api.action.addGlobalAlertFilter.param.contextId = The numeric ID of the context for which the filter should be added.
19+
alertFilters.api.action.addGlobalAlertFilter.param.enabled = A boolean indicating whether or not the filter should be enabled.
20+
alertFilters.api.action.addGlobalAlertFilter.param.evidence = The evidence value for which the filter should apply (can be regex).
21+
alertFilters.api.action.addGlobalAlertFilter.param.evidenceIsRegex = A boolean indicating whether or not the evidence value is a regex.
22+
alertFilters.api.action.addGlobalAlertFilter.param.methods = The HTTP methods (comma separated) for which the filter should apply.
23+
alertFilters.api.action.addGlobalAlertFilter.param.newLevel = The numeric risk representation ('0 - Informational' through '3 - High') ['-1 - False Positive'].
24+
alertFilters.api.action.addGlobalAlertFilter.param.parameter = The parameter name for which the filter should apply (can be regex).
25+
alertFilters.api.action.addGlobalAlertFilter.param.parameterIsRegex = A boolean indicating whether or not the parameter name is a regex.
26+
alertFilters.api.action.addGlobalAlertFilter.param.ruleId = The numeric ID of the rule for which the filter should apply.
27+
alertFilters.api.action.addGlobalAlertFilter.param.url = The URL for which the filter should apply (can be regex).
28+
alertFilters.api.action.addGlobalAlertFilter.param.urlIsRegex = A boolean indicating whether or not the URL is a regex.
329
alertFilters.api.action.applyAll = Applies all currently enabled Global and Context alert filters.
430
alertFilters.api.action.applyContext = Applies all currently enabled Context alert filters.
531
alertFilters.api.action.applyGlobal = Applies all currently enabled Global alert filters.
632
alertFilters.api.action.removeAlertFilter = Removes an alert filter from the context with the given ID.
33+
alertFilters.api.action.removeAlertFilter.param.attack = The attack value for which the filter applies (can be regex).
34+
alertFilters.api.action.removeAlertFilter.param.attackIsRegex = A boolean indicating whether or not the attack value is a regex.
35+
alertFilters.api.action.removeAlertFilter.param.contextId = The numeric ID of the context for which the filter should be removed.
36+
alertFilters.api.action.removeAlertFilter.param.enabled = A boolean indicating whether or not the filter should be enabled.
37+
alertFilters.api.action.removeAlertFilter.param.evidence = The evidence value for which the filter applies (can be regex).
38+
alertFilters.api.action.removeAlertFilter.param.evidenceIsRegex = A boolean indicating whether or not the evidence value is a regex.
39+
alertFilters.api.action.removeAlertFilter.param.methods = The HTTP methods (comma separated) for which the filter applies.
40+
alertFilters.api.action.removeAlertFilter.param.newLevel = The numeric risk representation ('0 - Informational' through '3 - High') ['-1 - False Positive'].
41+
alertFilters.api.action.removeAlertFilter.param.parameter = The parameter name for which the filter should apply (can be regex).
42+
alertFilters.api.action.removeAlertFilter.param.parameterIsRegex = A boolean indicating whether or not the parameter name is a regex.
43+
alertFilters.api.action.removeAlertFilter.param.ruleId = The numeric ID of the rule for which the filter applies.
44+
alertFilters.api.action.removeAlertFilter.param.url = The URL for which the filter applies (can be regex).
45+
alertFilters.api.action.removeAlertFilter.param.urlIsRegex = A boolean indicating whether or not the URL is a regex.
746
alertFilters.api.action.removeGlobalAlertFilter = Removes a global alert filter.
47+
alertFilters.api.action.removeGlobalAlertFilter.param.attack = The attack value for which the filter applies (can be regex).
48+
alertFilters.api.action.removeGlobalAlertFilter.param.attackIsRegex = A boolean indicating whether or not the attack value is a regex.
49+
alertFilters.api.action.removeGlobalAlertFilter.param.contextId = The numeric ID of the context for which the filter should be removed.
50+
alertFilters.api.action.removeGlobalAlertFilter.param.enabled = A boolean indicating whether or not the filter should be enabled.
51+
alertFilters.api.action.removeGlobalAlertFilter.param.evidence = The evidence value for which the filter applies (can be regex).
52+
alertFilters.api.action.removeGlobalAlertFilter.param.evidenceIsRegex = A boolean indicating whether or not the evidence value is a regex.
53+
alertFilters.api.action.removeGlobalAlertFilter.param.methods = The HTTP methods (comma separated) for which the filter applies.
54+
alertFilters.api.action.removeGlobalAlertFilter.param.newLevel = The numeric risk representation ('0 - Informational' through '3 - High') ['-1 - False Positive'].
55+
alertFilters.api.action.removeGlobalAlertFilter.param.parameter = The parameter name for which the filter should apply (can be regex).
56+
alertFilters.api.action.removeGlobalAlertFilter.param.parameterIsRegex = A boolean indicating whether or not the parameter name is a regex.
57+
alertFilters.api.action.removeGlobalAlertFilter.param.ruleId = The numeric ID of the rule for which the filter applies.
58+
alertFilters.api.action.removeGlobalAlertFilter.param.url = The URL for which the filter applies (can be regex).
59+
alertFilters.api.action.removeGlobalAlertFilter.param.urlIsRegex = A boolean indicating whether or not the URL is a regex.
860
alertFilters.api.action.testAll = Tests all currently enabled Global and Context alert filters.
961
alertFilters.api.action.testContext = Tests all currently enabled Context alert filters.
1062
alertFilters.api.action.testGlobal = Tests all currently enabled Global alert filters.
63+
alertFilters.api.desc = Facilitates the configuration and use of Alert Filters functionality.
1164
alertFilters.api.view.alertFilterList = Lists the alert filters of the context with the given ID.
65+
alertFilters.api.view.alertFilterList.param.contextId = The numeric ID of the context for which the filters should be listed.
1266
alertFilters.api.view.globalAlertFilterList = Lists the global alert filters.
1367

1468
alertFilters.automation.desc = Alert Filters Automation Framework Integration
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,182 @@
1+
/*
2+
* Zed Attack Proxy (ZAP) and its related class files.
3+
*
4+
* ZAP is an HTTP/HTTPS proxy for assessing web application security.
5+
*
6+
* Copyright 2025 The ZAP Development Team
7+
*
8+
* Licensed under the Apache License, Version 2.0 (the "License");
9+
* you may not use this file except in compliance with the License.
10+
* You may obtain a copy of the License at
11+
*
12+
* http://www.apache.org/licenses/LICENSE-2.0
13+
*
14+
* Unless required by applicable law or agreed to in writing, software
15+
* distributed under the License is distributed on an "AS IS" BASIS,
16+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17+
* See the License for the specific language governing permissions and
18+
* limitations under the License.
19+
*/
20+
package org.zaproxy.zap.extension.alertFilters;
21+
22+
import static org.hamcrest.MatcherAssert.assertThat;
23+
import static org.hamcrest.Matchers.empty;
24+
import static org.hamcrest.Matchers.emptyString;
25+
import static org.hamcrest.Matchers.equalTo;
26+
import static org.hamcrest.Matchers.hasSize;
27+
import static org.hamcrest.Matchers.is;
28+
import static org.hamcrest.Matchers.not;
29+
import static org.junit.jupiter.api.Assertions.assertThrows;
30+
31+
import java.util.ArrayList;
32+
import java.util.List;
33+
import net.sf.json.JSONObject;
34+
import org.junit.jupiter.api.AfterAll;
35+
import org.junit.jupiter.api.BeforeEach;
36+
import org.junit.jupiter.api.Test;
37+
import org.junit.jupiter.params.ParameterizedTest;
38+
import org.junit.jupiter.params.provider.EmptySource;
39+
import org.junit.jupiter.params.provider.ValueSource;
40+
import org.parosproxy.paros.Constant;
41+
import org.parosproxy.paros.network.HttpMessage;
42+
import org.zaproxy.zap.extension.api.API;
43+
import org.zaproxy.zap.extension.api.API.RequestType;
44+
import org.zaproxy.zap.extension.api.ApiElement;
45+
import org.zaproxy.zap.extension.api.ApiException;
46+
import org.zaproxy.zap.extension.api.ApiImplementor;
47+
import org.zaproxy.zap.extension.api.ApiParameter;
48+
import org.zaproxy.zap.testutils.TestUtils;
49+
50+
/** Unit test for {@link AlertFilterAPI}. */
51+
class AlertFilterApiUnitTest extends TestUtils {
52+
53+
private AlertFilterAPI alertFiltersApi;
54+
55+
@BeforeEach
56+
void setUp() {
57+
mockMessages(new ExtensionAlertFilters());
58+
59+
alertFiltersApi = new AlertFilterAPI();
60+
}
61+
62+
@AfterAll
63+
static void cleanUp() {
64+
Constant.messages = null;
65+
}
66+
67+
@Test
68+
void shouldHavePrefix() {
69+
// Given / When
70+
String prefix = alertFiltersApi.getPrefix();
71+
// Then
72+
assertThat(prefix, is(equalTo("alertFilter")));
73+
}
74+
75+
@Test
76+
void shouldAddApiElements() {
77+
// Given / When
78+
alertFiltersApi = new AlertFilterAPI();
79+
// Then
80+
assertThat(alertFiltersApi.getApiActions(), hasSize(10));
81+
assertThat(alertFiltersApi.getApiViews(), hasSize(2));
82+
assertThat(alertFiltersApi.getApiOthers(), hasSize(0));
83+
}
84+
85+
@ParameterizedTest
86+
@EmptySource
87+
@ValueSource(strings = {"unknown", "something"})
88+
void shouldThrowApiExceptionForUnknownAction(String name) {
89+
// Given
90+
JSONObject params = new JSONObject();
91+
// When
92+
ApiException exception =
93+
assertThrows(
94+
ApiException.class, () -> alertFiltersApi.handleApiAction(name, params));
95+
// Then
96+
assertThat(exception.getType(), is(equalTo(ApiException.Type.BAD_ACTION)));
97+
}
98+
99+
@ParameterizedTest
100+
@EmptySource
101+
@ValueSource(strings = {"unknown", "something"})
102+
void shouldThrowApiExceptionForUnknownOther(String name) {
103+
// Given
104+
HttpMessage message = new HttpMessage();
105+
JSONObject params = new JSONObject();
106+
// When
107+
ApiException exception =
108+
assertThrows(
109+
ApiException.class,
110+
() -> alertFiltersApi.handleApiOther(message, name, params));
111+
// Then
112+
assertThat(exception.getType(), is(equalTo(ApiException.Type.BAD_OTHER)));
113+
}
114+
115+
@ParameterizedTest
116+
@EmptySource
117+
@ValueSource(strings = {"unknown", "something"})
118+
void shouldThrowApiExceptionForUnknownView(String name) {
119+
// Given
120+
JSONObject params = new JSONObject();
121+
// When
122+
ApiException exception =
123+
assertThrows(ApiException.class, () -> alertFiltersApi.handleApiView(name, params));
124+
// Then
125+
assertThat(exception.getType(), is(equalTo(ApiException.Type.BAD_VIEW)));
126+
}
127+
128+
@Test
129+
void shouldHaveDescriptionsForAllApiElements() {
130+
alertFiltersApi = new AlertFilterAPI();
131+
List<String> missingKeys = new ArrayList<>();
132+
List<String> missingDescriptions = new ArrayList<>();
133+
checkKey(alertFiltersApi.getDescriptionKey(), missingKeys, missingDescriptions);
134+
checkApiElements(
135+
alertFiltersApi,
136+
alertFiltersApi.getApiActions(),
137+
API.RequestType.action,
138+
missingKeys,
139+
missingDescriptions);
140+
checkApiElements(
141+
alertFiltersApi,
142+
alertFiltersApi.getApiOthers(),
143+
API.RequestType.other,
144+
missingKeys,
145+
missingDescriptions);
146+
checkApiElements(
147+
alertFiltersApi,
148+
alertFiltersApi.getApiViews(),
149+
API.RequestType.view,
150+
missingKeys,
151+
missingDescriptions);
152+
assertThat(missingKeys, is(empty()));
153+
assertThat(missingDescriptions, is(empty()));
154+
}
155+
156+
private static void checkKey(String key, List<String> missingKeys, List<String> missingDescs) {
157+
if (!Constant.messages.containsKey(key)) {
158+
missingKeys.add(key);
159+
} else if (Constant.messages.getString(key).isBlank()) {
160+
missingDescs.add(key);
161+
}
162+
}
163+
164+
private static void checkApiElements(
165+
ApiImplementor api,
166+
List<? extends ApiElement> elements,
167+
RequestType type,
168+
List<String> missingKeys,
169+
List<String> missingDescriptions) {
170+
elements.sort((a, b) -> a.getName().compareTo(b.getName()));
171+
for (ApiElement element : elements) {
172+
assertThat(
173+
"API " + type + " element: " + api.getPrefix() + "/" + element.getName(),
174+
element.getDescriptionTag(),
175+
is(not(emptyString())));
176+
checkKey(element.getDescriptionTag(), missingKeys, missingDescriptions);
177+
element.getParameters().stream()
178+
.map(ApiParameter::getDescriptionKey)
179+
.forEach(key -> checkKey(key, missingKeys, missingDescriptions));
180+
}
181+
}
182+
}

0 commit comments

Comments
 (0)
Please sign in to comment.