Skip to content

Commit 3d46243

Browse files
authored
Merge pull request #38 from thc202/ant-reports
Add an Ant task to create ZAP reports
2 parents 739d7b5 + feee775 commit 3d46243

File tree

4 files changed

+180
-2
lines changed

4 files changed

+180
-2
lines changed

CHANGES.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,22 @@ Summary of the changes done in each version.
44

55
## 1.4.0-SNAPSHOT (Not yet released)
66

7+
### Ant Tasks
8+
9+
- New task to create ZAP reports:
10+
```XML
11+
<!-- Defined the task: -->
12+
<taskdef name="reportTask" classname="org.zaproxy.clientapi.ant.ReportTask" />
13+
<!-- Call the task: -->
14+
<reportTask zapAddress="localhost" zapPort="8080" apikey="API-KEY"
15+
type="html" file="report.html" overwrite="true" />
16+
<!--
17+
type - the type/format of the report (e.g. HTML, XML, MD), defaults to HTML.
18+
file - where the report should be created (can be an absolute path, if relative it is resolved against the build directory).
19+
overwrite - if the file should be overwritten.
20+
-->
21+
```
22+
723
## 1.3.0 (2017-06-23)
824

925
### New APIs
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
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 2017 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.clientapi.ant;
21+
22+
import java.io.File;
23+
import java.io.IOException;
24+
import java.io.OutputStream;
25+
import java.nio.file.Files;
26+
import java.util.Arrays;
27+
import java.util.List;
28+
import java.util.Locale;
29+
30+
import org.apache.tools.ant.BuildException;
31+
32+
public class ReportTask extends ZapTask {
33+
34+
private static final String HTML_REPORT_TYPE = "html";
35+
private static final String MD_REPORT_TYPE = "md";
36+
private static final String XML_REPORT_TYPE = "xml";
37+
private static final String DEFAULT_REPORT_TYPE = HTML_REPORT_TYPE;
38+
39+
private static final List<String> SUPPORTED_REPORT_TYPES = Arrays.asList(HTML_REPORT_TYPE, MD_REPORT_TYPE, XML_REPORT_TYPE);
40+
41+
private String type = DEFAULT_REPORT_TYPE;
42+
private File file;
43+
private boolean overwrite;
44+
45+
public void setType(String type) {
46+
this.type = type;
47+
}
48+
49+
public void setFile(String file) {
50+
this.file = new File(file);
51+
if (!this.file.isAbsolute()) {
52+
this.file = new File(getProject().getBaseDir(), file);
53+
}
54+
}
55+
56+
public void setOverwrite(boolean overwrite) {
57+
this.overwrite = overwrite;
58+
}
59+
60+
@Override
61+
public void execute() throws BuildException {
62+
validateTaskAttributes();
63+
64+
byte[] reportContents;
65+
try {
66+
switch (type.toLowerCase()) {
67+
case MD_REPORT_TYPE:
68+
reportContents = this.getClientApi().core.mdreport();
69+
break;
70+
case XML_REPORT_TYPE:
71+
reportContents = this.getClientApi().core.xmlreport();
72+
break;
73+
case HTML_REPORT_TYPE:
74+
default:
75+
reportContents = this.getClientApi().core.htmlreport();
76+
break;
77+
}
78+
} catch (Exception e) {
79+
throw new BuildException("Failed to obtain the report from ZAP: " + e.getMessage(), e);
80+
}
81+
82+
try (OutputStream os = Files.newOutputStream(file.toPath())) {
83+
os.write(reportContents);
84+
} catch (IOException e) {
85+
throw new BuildException("Failed to save the report: " + e.getMessage(), e);
86+
}
87+
88+
}
89+
90+
private void validateTaskAttributes() {
91+
if (type == null || type.isEmpty()) {
92+
type = DEFAULT_REPORT_TYPE;
93+
} else {
94+
type = type.toLowerCase(Locale.ROOT);
95+
if (!SUPPORTED_REPORT_TYPES.contains(type)) {
96+
throw new BuildException("Unknown report type [" + type + "], supported types: " + SUPPORTED_REPORT_TYPES);
97+
}
98+
}
99+
100+
if (file == null) {
101+
throw new BuildException("The 'file' attribute must be provided.");
102+
}
103+
104+
if (file.isFile()) {
105+
if (!file.canWrite()) {
106+
throw new BuildException("The provided file is not writable: " + file.getAbsolutePath());
107+
}
108+
109+
if (!overwrite) {
110+
throw new BuildException(
111+
"The file already exists but 'overwrite' attribute is not set to 'true': " + file.getAbsolutePath());
112+
}
113+
} else if (!file.exists()) {
114+
File dir = file.getParentFile();
115+
if (dir == null) {
116+
throw new BuildException(
117+
"Unable to determine parent directory of the file provided: " + file.getAbsolutePath());
118+
}
119+
120+
dir.mkdirs();
121+
if (!dir.canWrite()) {
122+
throw new BuildException("The provided directory does not exist or is not writable: " + dir.getAbsolutePath());
123+
}
124+
} else {
125+
throw new BuildException("The 'file' attribute does not specify a file: " + file.getAbsolutePath());
126+
}
127+
}
128+
129+
}

subprojects/zap-clientapi-ant/src/test/java/org/zaproxy/clientapi/ant/BuildTest.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,10 @@
2121

2222
import static org.junit.Assert.assertTrue;
2323

24+
import java.io.File;
2425
import java.io.IOException;
26+
import java.io.InputStream;
27+
import java.nio.file.Files;
2528
import java.util.HashMap;
2629
import java.util.Map;
2730

@@ -33,6 +36,7 @@
3336
import org.junit.BeforeClass;
3437
import org.junit.Rule;
3538
import org.junit.Test;
39+
import org.junit.rules.TemporaryFolder;
3640
import org.zaproxy.clientapi.core.ClientApiException;
3741

3842
import fi.iki.elonen.NanoHTTPD;
@@ -43,11 +47,14 @@
4347
public class BuildTest {
4448

4549
private static final String BUILD_FILE_NAME = "build.xml";
46-
private static final String BUILD_FILE_PATH = BuildTest.class.getResource(BUILD_FILE_NAME).toString().replace("file:", "");
50+
private static final String REPORT_PATH = "report.html";
4751

4852
private static SimpleServer zap;
4953
private static SimpleServer targetSite;
5054

55+
@Rule
56+
public final TemporaryFolder buildDir = new TemporaryFolder();
57+
5158
@Rule
5259
public final BuildFileRule buildRule = new BuildFileRule();
5360

@@ -64,14 +71,28 @@ public static void setUp() throws IOException {
6471
public void setUpBuildFile() {
6572
zap.clearResponses();
6673

67-
buildRule.configureProject(BUILD_FILE_PATH);
74+
File buildFile = new File(buildDir.getRoot(), BUILD_FILE_NAME);
75+
if (!buildFile.exists()) {
76+
try {
77+
try (InputStream is = BuildTest.class.getResourceAsStream(BUILD_FILE_NAME)) {
78+
Files.copy(is, buildFile.toPath());
79+
}
80+
} catch (IOException e) {
81+
throw new RuntimeException("Failed to set up the test:", e);
82+
}
83+
}
84+
85+
buildRule.configureProject(buildFile.getAbsolutePath());
6886

6987
// Properties used in build.xml file
7088
buildRule.getProject().setProperty("zap.addr", "localhost");
7189
buildRule.getProject().setProperty("zap.port", Integer.toString(zap.getListeningPort()));
7290
buildRule.getProject().setProperty("zap.key", "API_KEY");
7391
buildRule.getProject().setProperty("zap.targetUrl", "http://localhost:" + targetSite.getListeningPort());
7492
buildRule.getProject().setProperty("zap.session", "session");
93+
buildRule.getProject().setProperty("zap.report.path", REPORT_PATH);
94+
buildRule.getProject().setProperty("zap.report.type", "html");
95+
buildRule.getProject().setProperty("zap.report.overwrite", "false");
7596
}
7697

7798
@AfterClass
@@ -141,6 +162,12 @@ public void shouldExecuteTargetStopZap() {
141162
buildRule.executeTarget("stopZap");
142163
}
143164

165+
@Test
166+
public void shouldExecuteReport() {
167+
buildRule.executeTarget("report");
168+
assertTrue("Report file not created.", new File(buildDir.getRoot(), REPORT_PATH).exists());
169+
}
170+
144171
private static class SimpleServer extends NanoHTTPD {
145172

146173
private final String mimeType;

subprojects/zap-clientapi-ant/src/test/resources/org/zaproxy/clientapi/ant/build.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
<taskdef name="saveSessionTask" classname="org.zaproxy.clientapi.ant.SaveSessionTask" />
1111
<taskdef name="spiderUrlTask" classname="org.zaproxy.clientapi.ant.SpiderUrlTask" />
1212
<taskdef name="stopZapTask" classname="org.zaproxy.clientapi.ant.StopZapTask" />
13+
<taskdef name="reportTask" classname="org.zaproxy.clientapi.ant.ReportTask" />
1314

1415
<target name="accessUrl">
1516
<accessUrlTask zapAddress="${zap.addr}" zapPort="${zap.port}" debug="true" apikey="${zap.key}" url="${zap.targetUrl}" />
@@ -58,4 +59,9 @@
5859
<stopZapTask zapAddress="${zap.addr}" zapPort="${zap.port}" debug="true" apikey="${zap.key}" />
5960
</target>
6061

62+
<target name="report">
63+
<reportTask zapAddress="${zap.addr}" zapPort="${zap.port}" debug="true" apikey="${zap.key}"
64+
type="${zap.report.type}" file="${zap.report.path}" overwrite="${zap.report.overwrite}" />
65+
</target>
66+
6167
</project>

0 commit comments

Comments
 (0)