Skip to content
This repository was archived by the owner on Feb 26, 2021. It is now read-only.

Commit 63a4255

Browse files
committed
Add createProduct, addEngagmgent
1 parent e811d9c commit 63a4255

File tree

8 files changed

+250
-7
lines changed

8 files changed

+250
-7
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
*
3+
* SecureCodeBox (SCB)
4+
* Copyright 2015-2018 iteratec GmbH
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
* /
18+
*/
19+
package io.securecodebox.persistence;
20+
21+
public class DefectDojoLoopException extends RuntimeException{
22+
public DefectDojoLoopException(String message) {
23+
super(message);
24+
}
25+
26+
public DefectDojoLoopException(String message, Throwable cause) {
27+
super(message, cause);
28+
}
29+
}

scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java

Lines changed: 111 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
*/
1919
package io.securecodebox.persistence;
2020

21-
2221
import io.securecodebox.persistence.models.*;
2322
import org.slf4j.Logger;
2423
import org.slf4j.LoggerFactory;
@@ -43,6 +42,8 @@
4342
import java.time.LocalDate;
4443
import java.time.format.DateTimeFormatter;
4544
import java.util.Arrays;
45+
import java.util.LinkedList;
46+
import java.util.List;
4647
import java.util.Optional;
4748

4849
@Component
@@ -181,8 +182,13 @@ public EngagementResponse createEngagement(EngagementPayload engagementPayload)
181182
throw new DefectDojoPersistenceException("Failed to create Engagement for SecurityTest", e);
182183
}
183184
}
184-
185185
public ImportScanResponse createFindings(String rawResult, long engagementId, long lead, String currentDate,String defectDojoScanName) {
186+
return createFindings(rawResult, engagementId, lead, currentDate,defectDojoScanName, "");
187+
}
188+
/**
189+
* Till version 1.5.4. testName (in defectdojo _test_type_) must be defectDojoScanName, afterwards, you can have somethings else
190+
*/
191+
public ImportScanResponse createFindings(String rawResult, long engagementId, long lead, String currentDate,String defectDojoScanName, String testName) {
186192
RestTemplate restTemplate = new RestTemplate();
187193
HttpHeaders headers = getHeaders();
188194
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
@@ -193,7 +199,12 @@ public ImportScanResponse createFindings(String rawResult, long engagementId, lo
193199
mvn.add("lead", Long.toString(lead));
194200
mvn.add("scan_date", currentDate);
195201
mvn.add("scan_type", defectDojoScanName);
196-
202+
mvn.add("close_old_findings", "true");
203+
mvn.add("skip_duplicates", "false");
204+
205+
if(!testName.isEmpty())
206+
mvn.add("test_type", testName);
207+
197208
try {
198209
ByteArrayResource contentsAsResource = new ByteArrayResource(rawResult.getBytes(StandardCharsets.UTF_8)) {
199210
@Override
@@ -214,10 +225,10 @@ public String getFilename() {
214225
}
215226
}
216227
public ImportScanResponse createFindingsForEngagementName(String engagementName, String rawResults, String defectDojoScanName, long productId, long lead){
217-
return createFindingsForEngagementName(engagementName, rawResults, defectDojoScanName, productId, lead, new EngagementPayload());
228+
return createFindingsForEngagementName(engagementName, rawResults, defectDojoScanName, productId, lead, new EngagementPayload(), "");
218229
}
219230

220-
public ImportScanResponse createFindingsForEngagementName(String engagementName, String rawResults, String defectDojoScanName, long productId, long lead, EngagementPayload engagementPayload){
231+
public ImportScanResponse createFindingsForEngagementName(String engagementName, String rawResults, String defectDojoScanName, long productId, long lead, EngagementPayload engagementPayload, String testName){
221232
Long engagementId = getEngagementIdByEngagementName(engagementName, productId).orElseGet(() -> {
222233
engagementPayload.setName(engagementName);
223234
engagementPayload.setProduct(productId);
@@ -227,7 +238,22 @@ public ImportScanResponse createFindingsForEngagementName(String engagementName,
227238
return createEngagement(engagementPayload).getId();
228239
});
229240

230-
return createFindings(rawResults, engagementId, lead, currentDate(), defectDojoScanName);
241+
return createFindings(rawResults, engagementId, lead, currentDate(), defectDojoScanName, testName);
242+
}
243+
244+
public ImportScanResponse createFindingsForEngagementName(String engagementName, String rawResults, String defectDojoScanName, String productName, long lead, EngagementPayload engagementPayload, String testName){
245+
long productId = 0;
246+
try {
247+
productId = retrieveProductId(productName);
248+
} catch(DefectDojoProductNotFound e) {
249+
LOG.debug("Given product does not exists");
250+
}
251+
if(productId == 0) {
252+
ProductResponse productResponse = createProduct(productName);
253+
productId = productResponse.getId();
254+
}
255+
256+
return createFindingsForEngagementName(engagementName, rawResults, defectDojoScanName, productId, lead, engagementPayload, testName);
231257
}
232258

233259
private Optional<Long> getEngagementIdByEngagementName(String engagementName, long productId){
@@ -257,4 +283,83 @@ private Optional<Long> getEngagementIdByEngagementName(String engagementName, lo
257283
LOG.warn("Engagement with name '{}' not found.", engagementName);
258284
return Optional.empty();
259285
}
286+
public ProductResponse createProduct(String productName) {
287+
RestTemplate restTemplate = new RestTemplate();
288+
ProductPayload productPayload = new ProductPayload(productName, "Description missing");
289+
HttpEntity<ProductPayload> payload = new HttpEntity<>(productPayload, getHeaders());
290+
291+
try {
292+
ResponseEntity<ProductResponse> response = restTemplate.exchange(defectDojoUrl + "/api/v2/products/", HttpMethod.POST, payload, ProductResponse.class);
293+
return response.getBody();
294+
} catch (HttpClientErrorException e) {
295+
LOG.warn("Failed to create product {}", e);
296+
LOG.warn("Failure response body. {}", e.getResponseBodyAsString());
297+
throw new DefectDojoPersistenceException("Failed to create product", e);
298+
}
299+
}
300+
301+
public void deleteUnusedBranches(List<String> existingBranches, String producName) {
302+
long productId = retrieveProductId(producName);
303+
deleteUnusedBranches(existingBranches, productId);
304+
}
305+
306+
/**
307+
* Deletes engagements based on branch tag
308+
* Be aware that the branch tag MUST be set, otherwise all engagments will be deleted
309+
*/
310+
public void deleteUnusedBranches(List<String> existingBranches, long productId) {
311+
RestTemplate restTemplate = new RestTemplate();
312+
313+
//get existing branches
314+
List<EngagementResponse> engagementPayloads = getEngagementsForProduct(productId, 0);
315+
for(EngagementResponse engagementPayload : engagementPayloads) {
316+
boolean branchExists = false;
317+
for(String existingBranchName : existingBranches) {
318+
if(existingBranchName.equals(engagementPayload.getBanch())) {
319+
branchExists = true;
320+
break;
321+
}
322+
}
323+
if(!branchExists) {
324+
deleteEnageament(engagementPayload.getId());
325+
LOG.info("Deleted engagement with id " + engagementPayload.getId() + ", branch " + engagementPayload.getBanch());
326+
}
327+
}
328+
}
329+
330+
private List<EngagementResponse> getEngagementsForProduct(long productId, long offset) throws DefectDojoLoopException{
331+
if(offset > 9999) {
332+
throw new DefectDojoLoopException("offset engagement products too much!");
333+
}
334+
UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(defectDojoUrl + "/api/v2/engagements")
335+
.queryParam("product", Long.toString(productId))
336+
.queryParam("limit", Long.toString(50L))
337+
.queryParam("offset", Long.toString(offset));
338+
339+
RestTemplate restTemplate = new RestTemplate();
340+
HttpEntity engagementRequest = new HttpEntity(getHeaders());
341+
342+
ResponseEntity<DefectDojoResponse<EngagementResponse>> engagementResponse = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, engagementRequest, new ParameterizedTypeReference<DefectDojoResponse<EngagementResponse>>(){});
343+
List<EngagementResponse> engagementPayloads = new LinkedList<EngagementResponse>();
344+
for(EngagementResponse engagement : engagementResponse.getBody().getResults()){
345+
engagementPayloads.add(engagement);
346+
}
347+
if(engagementResponse.getBody().getNext() != null){
348+
engagementPayloads.addAll(getEngagementsForProduct(productId, offset + 1));;
349+
}
350+
return engagementPayloads;
351+
}
352+
public void deleteEnageament(long engagementId){
353+
RestTemplate restTemplate = new RestTemplate();
354+
355+
String uri = defectDojoUrl + "/api/v2/engagements/" + engagementId + "/?id=" + engagementId;
356+
HttpEntity request = new HttpEntity(getHeaders());
357+
try {
358+
ResponseEntity<DefectDojoResponse> response = restTemplate.exchange(uri, HttpMethod.DELETE, request, DefectDojoResponse.class);
359+
} catch (HttpClientErrorException e) {
360+
LOG.warn("Failed to delete engagment {}, engagementId: " + engagementId, e);
361+
LOG.warn("Failure response body. {}", e.getResponseBodyAsString());
362+
throw new DefectDojoPersistenceException("Failed to delete product", e);
363+
}
364+
}
260365
}

scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/DefectDojoProduct.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,11 @@ public class DefectDojoProduct {
2121

2222
@JsonProperty("authorized_users")
2323
List<String> authorizedUsers;
24+
25+
public DefectDojoProduct() {}
26+
27+
public DefectDojoProduct(String productName, String productDescription) {
28+
name = productName;
29+
description = productDescription;
30+
}
2431
}

scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/EngagementPayload.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ public class EngagementPayload {
6363
protected String commitHash;
6464

6565
@JsonProperty("branch_tag")
66-
protected String branch;
66+
public String branch;
6767

6868
@JsonProperty("source_code_management_uri")
6969
protected String repo;
@@ -80,6 +80,9 @@ public class EngagementPayload {
8080
@JsonProperty
8181
protected String description;
8282

83+
@JsonProperty("deduplication_on_engagement")
84+
protected boolean deduplicationOnEngagement;
85+
8386
/**
8487
* Currently only contains the statuses relevant to us.
8588
* If you need others, feel free to add them ;)

scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/EngagementResponse.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@ public class EngagementResponse {
2727
@JsonProperty
2828
protected String name;
2929

30+
@JsonProperty("branch_tag")
31+
protected String branch;
32+
3033
public long getId() {
3134
return id;
3235
}
@@ -42,4 +45,12 @@ public String getName() {
4245
public void setName(String name) {
4346
this.name = name;
4447
}
48+
49+
public String getBanch() {
50+
return branch;
51+
}
52+
53+
public void setBranch(String branch) {
54+
this.branch = branch;
55+
}
4556
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
package io.securecodebox.persistence.models;
16+
17+
import com.fasterxml.jackson.annotation.JsonProperty;
18+
19+
import java.util.List;
20+
import lombok.Data;
21+
22+
@Data
23+
public class ProductPayload {
24+
@JsonProperty
25+
String name;
26+
27+
@JsonProperty
28+
String description;
29+
30+
public ProductPayload(String productName, String productDescription) {
31+
name = productName;
32+
description = productDescription;
33+
}
34+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
*
3+
* SecureCodeBox (SCB)
4+
* Copyright 2015-2018 iteratec GmbH
5+
*
6+
* Licensed under the Apache License, Version 2.0 (the "License");
7+
* you may not use this file except in compliance with the License.
8+
* You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
* /
18+
*/
19+
package io.securecodebox.persistence.models;
20+
21+
import com.fasterxml.jackson.annotation.JsonProperty;
22+
23+
public class ProductResponse {
24+
@JsonProperty
25+
protected long id;
26+
27+
@JsonProperty
28+
protected String name;
29+
30+
public long getId() {
31+
return id;
32+
}
33+
34+
public void setId(long id) {
35+
this.id = id;
36+
}
37+
38+
public String getName() {
39+
return name;
40+
}
41+
42+
public void setName(String name) {
43+
this.name = name;
44+
}
45+
}

scb-persistenceproviders/defectdojo-persistenceprovider/src/test/java/io/securecodebox/persistence/DefectDojoPersistenceProviderTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,4 +233,13 @@ public void createsFindingsForNonSupportedScanner() {
233233
eq("Generic Findings Import")
234234
);
235235
}
236+
237+
@Test
238+
public void createProduct() {
239+
String productName = "mytestproduct";
240+
defectDojoService.createProduct(productName);
241+
verify(defectDojoService, times(1)).createProduct(
242+
eq(productName)
243+
);
244+
}
236245
}

0 commit comments

Comments
 (0)