From 53b470a3f8d0a5fcde20803b2047a4b818f41abc Mon Sep 17 00:00:00 2001 From: Timo Pagel Date: Fri, 16 Aug 2019 09:31:57 +0200 Subject: [PATCH 1/9] Add tests --- .../persistence/DefectDojoService.java | 121 ++++++++++++++++-- .../persistence/models/TestPayload.java | 59 +++++++++ .../persistence/models/TestResponse.java | 46 +++++++ 3 files changed, 212 insertions(+), 14 deletions(-) create mode 100644 scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/TestPayload.java create mode 100644 scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/TestResponse.java diff --git a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java index 55ffda9b..687b9bd6 100644 --- a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java +++ b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java @@ -128,6 +128,19 @@ public long retrieveProductId(String product){ throw new DefectDojoProductNotFound(MessageFormat.format("Could not find product: \"{0}\" in DefectDojo", product)); } } + private long retrieveOrCreateProduct(String productName) { + long productId = 0; + try { + productId = retrieveProductId(productName); + } catch(DefectDojoProductNotFound e) { + LOG.debug("Given product does not exists"); + } + if(productId == 0) { + ProductResponse productResponse = createProduct(productName); + productId = productResponse.getId(); + } + return productId; + } public Long retrieveOrCreateToolConfiguration(String toolUrl, String toolType){ if (toolUrl == null){ @@ -184,6 +197,7 @@ public EngagementResponse createEngagement(EngagementPayload engagementPayload) throw new DefectDojoPersistenceException("Failed to create Engagement for SecurityTest", e); } } + public ImportScanResponse createFindings(String rawResult, long engagementId, long lead, String currentDate,String defectDojoScanName) { return createFindings(rawResult, engagementId, lead, currentDate,defectDojoScanName, ""); } @@ -226,11 +240,102 @@ public String getFilename() { throw new DefectDojoPersistenceException("Failed to attach findings to engagement."); } } + private Optional getTestIdByEngagementName(long engagementId, String testName, long offset) { + UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(defectDojoUrl + "/api/v2/tests") + .queryParam("engagement", Long.toString(engagementId)) + .queryParam("title", testName) + .queryParam("limit", Long.toString(50L)) + .queryParam("offset", Long.toString(offset)); + + RestTemplate restTemplate = new RestTemplate(); + HttpEntity engagementRequest = new HttpEntity(getHeaders()); + + ResponseEntity> response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, engagementRequest, new ParameterizedTypeReference>(){}); + + for(TestResponse engagement : response.getBody().getResults()){ + if(engagement.getTitle().equals(testName)){ + return Optional.of(engagement.getId()); + } + } + if(response.getBody().getNext() != null){ + return getTestIdByEngagementName(engagementId, testName, offset + 1); + } + LOG.warn("Test with name '{}' not found.", testName); + return Optional.empty(); + } + private EngagementResponse createTest(TestPayload testPayload) { + RestTemplate restTemplate = new RestTemplate(); + + HttpEntity payload = new HttpEntity<>(testPayload, getHeaders()); + + try { + ResponseEntity response = restTemplate.exchange(defectDojoUrl + "/api/v2/tests/", HttpMethod.POST, payload, EngagementResponse.class); + return response.getBody(); + } catch (HttpClientErrorException e) { + LOG.warn("Failed to create Test for SecurityTest. {}", e); + LOG.warn("Failure response body. {}", e.getResponseBodyAsString()); + throw new DefectDojoPersistenceException("Failed to create Test for SecurityTest", e); + } + } + private long getTestIdOrCreate(long engagementId, TestPayload testPayload) { + Long testId = getTestIdByEngagementName(engagementId, testPayload.getTitle(), 0).orElseGet(() -> { + testPayload.setEngagement(Long.toString(engagementId)); + testPayload.setTargetStart(currentDate()); + testPayload.setTargetEnd(currentDate()); + return createTest(testPayload).getId(); + }); + } + + public ImportScanResponse createFindingsReImport(String rawResult, String productName, String engagementName, long lead, String currentDate, String defectDojoScanName, EngagementPayload engagementPayload, TestPayload testPayload) { + long productId = retrieveOrCreateProduct(productName); + long engagementId = getEngagementIdByEngagementNameOrCreate(productId, engagementName, engagementPayload, lead); + long testId = getTestIdOrCreate(engagementId, testPayload); + return createFindingsReImport(rawResult, testId, lead, currentDate, defectDojoScanName); + } + + public ImportScanResponse createFindingsReImport(String rawResult, long testId, long lead, String currentDate,String defectDojoScanName) { + RestTemplate restTemplate = new RestTemplate(); + HttpHeaders headers = getHeaders(); + headers.setContentType(MediaType.MULTIPART_FORM_DATA); + restTemplate.setMessageConverters(Arrays.asList(new FormHttpMessageConverter(), new ResourceHttpMessageConverter(), new MappingJackson2HttpMessageConverter())); + + MultiValueMap mvn = new LinkedMultiValueMap<>(); + mvn.add("test", Long.toString(testId)); + mvn.add("lead", Long.toString(lead)); + mvn.add("scan_date", currentDate); + mvn.add("scan_type", defectDojoScanName); + mvn.add("close_old_findings", "true"); + mvn.add("skip_duplicates", "false"); + + try { + ByteArrayResource contentsAsResource = new ByteArrayResource(rawResult.getBytes(StandardCharsets.UTF_8)) { + @Override + public String getFilename() { + return "this_needs_to_be_here_but_doesnt_really_matter.txt"; + } + }; + + mvn.add("file", contentsAsResource); + + HttpEntity payload = new HttpEntity<>(mvn, headers); + + return restTemplate.exchange(defectDojoUrl + "/api/v2/reimport-scan/", HttpMethod.POST, payload, ImportScanResponse.class).getBody(); + } catch (HttpClientErrorException e) { + LOG.warn("Failed to import findings to DefectDojo. Request failed with status code: '{}'.", e.getStatusCode()); + LOG.warn("Failure body: {}", e.getResponseBodyAsString()); + throw new DefectDojoPersistenceException("Failed to attach findings to engagement."); + } + } public ImportScanResponse createFindingsForEngagementName(String engagementName, String rawResults, String defectDojoScanName, long productId, long lead){ return createFindingsForEngagementName(engagementName, rawResults, defectDojoScanName, productId, lead, new EngagementPayload(), ""); } - public ImportScanResponse createFindingsForEngagementName(String engagementName, String rawResults, String defectDojoScanName, long productId, long lead, EngagementPayload engagementPayload, String testName){ + public ImportScanResponse getEngagementIdByEngagementNameOrCreate(String engagementName, String rawResults, String defectDojoScanName, long productId, long lead, EngagementPayload engagementPayload, String testName){ + Long engagementId = getEngagementIdByEngagementName(engagementName, productId, engagementPayload, lead); + + return createFindings(rawResults, engagementId, lead, currentDate(), defectDojoScanName, testName); + } + private long getEngagementIdByEngagementNameOrCreate(long productId, String engagementName, EngagementPayload engagementPayload, long lead) { Long engagementId = getEngagementIdByEngagementName(engagementName, productId).orElseGet(() -> { engagementPayload.setName(engagementName); engagementPayload.setProduct(productId); @@ -239,21 +344,10 @@ public ImportScanResponse createFindingsForEngagementName(String engagementName, engagementPayload.setLead(lead); return createEngagement(engagementPayload).getId(); }); - - return createFindings(rawResults, engagementId, lead, currentDate(), defectDojoScanName, testName); } public ImportScanResponse createFindingsForEngagementName(String engagementName, String rawResults, String defectDojoScanName, String productName, long lead, EngagementPayload engagementPayload, String testName){ - long productId = 0; - try { - productId = retrieveProductId(productName); - } catch(DefectDojoProductNotFound e) { - LOG.debug("Given product does not exists"); - } - if(productId == 0) { - ProductResponse productResponse = createProduct(productName); - productId = productResponse.getId(); - } + long productId = retrieveOrCreateProduct(productName); return createFindingsForEngagementName(engagementName, rawResults, defectDojoScanName, productId, lead, engagementPayload, testName); } @@ -267,7 +361,6 @@ private Optional getEngagementIdByEngagementName(String engagementName, lo } private Optional getEngagementIdByEngagementName(String engagementName, long productId, long offset){ - UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(defectDojoUrl + "/api/v2/engagements") .queryParam("product", Long.toString(productId)) .queryParam("limit", Long.toString(50L)) diff --git a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/TestPayload.java b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/TestPayload.java new file mode 100644 index 00000000..49cfc377 --- /dev/null +++ b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/TestPayload.java @@ -0,0 +1,59 @@ +/* + * + * SecureCodeBox (SCB) + * Copyright 2015-2018 iteratec GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * / + */ +package io.securecodebox.persistence.models; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; + +import java.util.Arrays; +import java.util.Collections; +import java.util.LinkedList; +import java.util.List; + + +@Data +public class TestPayload { + @JsonProperty + protected String title; + + @JsonProperty("target_start") + protected String targetStart; + + @JsonProperty("target_end") + protected String targetEnd; + @JsonProperty + protected List tags = new LinkedList<>(); + + @JsonProperty + protected String engagement; + + @JsonProperty + protected ENVIRONMENT environment = ENVIRONMENT.DEVELOPMENT; + + /** + * Currently only contains the statuses relevant to us. + * If you need others, feel free to add them ;) + */ + public static enum ENVIRONMENT { + @JsonProperty("Development") + DEVELOPMENT, + @JsonProperty("Production") + PRODUCTION + } +} diff --git a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/TestResponse.java b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/TestResponse.java new file mode 100644 index 00000000..d350bbeb --- /dev/null +++ b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/TestResponse.java @@ -0,0 +1,46 @@ +/* + * + * SecureCodeBox (SCB) + * Copyright 2015-2018 iteratec GmbH + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * / + */ +package io.securecodebox.persistence.models; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class TestResponse { + @JsonProperty + protected long id; + + @JsonProperty + protected String title; + + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } +} From e1d2e411d4a52d64480c6fa9b373a2ea89f649c5 Mon Sep 17 00:00:00 2001 From: Timo Pagel Date: Fri, 16 Aug 2019 13:22:15 +0200 Subject: [PATCH 2/9] Fix Findings --- .../persistence/DefectDojoService.java | 93 ++++++++++++------- .../persistence/models/TestPayload.java | 25 +++-- 2 files changed, 75 insertions(+), 43 deletions(-) diff --git a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java index 687b9bd6..99c04eb8 100644 --- a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java +++ b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java @@ -41,6 +41,7 @@ import java.text.MessageFormat; import java.time.Clock; import java.time.LocalDate; +import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.LinkedList; @@ -61,12 +62,16 @@ public class DefectDojoService { protected String defectDojoDefaultUserName; protected static final String DATE_FORMAT = "yyyy-MM-dd"; + protected static final String DATE_TIME_FORMAT = "yyyy-MM-dd hh:m:ss"; Clock clock = Clock.systemDefaultZone(); private String currentDate() { return LocalDate.now(clock).format(DateTimeFormatter.ofPattern(DATE_FORMAT)); } + private String currentDateTime() { + return LocalDateTime.now(clock).format(DateTimeFormatter.ofPattern(DATE_TIME_FORMAT)); + } private static final Logger LOG = LoggerFactory.getLogger(DefectDojoService.class); @@ -198,13 +203,13 @@ public EngagementResponse createEngagement(EngagementPayload engagementPayload) } } - public ImportScanResponse createFindings(String rawResult, long engagementId, long lead, String currentDate,String defectDojoScanName) { - return createFindings(rawResult, engagementId, lead, currentDate,defectDojoScanName, ""); + public ImportScanResponse createFindings(String rawResult, long engagementId, long lead, String currentDate, String defectDojoScanName) { + return createFindings(rawResult, engagementId, lead, currentDate,defectDojoScanName, "", new LinkedMultiValueMap<>()); } /** - * Till version 1.5.4. testName (in defectdojo _test_type_) must be defectDojoScanName, afterwards, you can have somethings else + * Before version 1.5.4. testName (in DefectDojo _test_type_) must be defectDojoScanName, afterwards, you can have somethings else */ - public ImportScanResponse createFindings(String rawResult, long engagementId, long lead, String currentDate,String defectDojoScanName, String testName) { + public ImportScanResponse createFindings(String rawResult, long engagementId, long lead, String currentDate,String defectDojoScanName, String testName, MultiValueMap options) { RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = getHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); @@ -217,9 +222,18 @@ public ImportScanResponse createFindings(String rawResult, long engagementId, lo mvn.add("scan_type", defectDojoScanName); mvn.add("close_old_findings", "true"); mvn.add("skip_duplicates", "false"); - + if(!testName.isEmpty()) mvn.add("test_type", testName); + + Iterator it = options.keySet().iterator(); + while(it.hasNext()){ + String theKey = (String)it.next(); + if(mvn.containsKey(theKey)) { + mvn.remove(theKey); + } + } + mvn.addAll(options); try { ByteArrayResource contentsAsResource = new ByteArrayResource(rawResult.getBytes(StandardCharsets.UTF_8)) { @@ -240,10 +254,12 @@ public String getFilename() { throw new DefectDojoPersistenceException("Failed to attach findings to engagement."); } } + /** + * When DefectDojo >= 1.5.4 is used, add testType to queryParam, till then, the first test in engagement is returned + */ private Optional getTestIdByEngagementName(long engagementId, String testName, long offset) { UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(defectDojoUrl + "/api/v2/tests") .queryParam("engagement", Long.toString(engagementId)) - .queryParam("title", testName) .queryParam("limit", Long.toString(50L)) .queryParam("offset", Long.toString(offset)); @@ -252,10 +268,10 @@ private Optional getTestIdByEngagementName(long engagementId, String testN ResponseEntity> response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, engagementRequest, new ParameterizedTypeReference>(){}); - for(TestResponse engagement : response.getBody().getResults()){ - if(engagement.getTitle().equals(testName)){ - return Optional.of(engagement.getId()); - } + for(TestResponse test : response.getBody().getResults()){ + //if(test.getTitle().equals(testName)){ + return Optional.of(test.getId()); + //} } if(response.getBody().getNext() != null){ return getTestIdByEngagementName(engagementId, testName, offset + 1); @@ -277,23 +293,25 @@ private EngagementResponse createTest(TestPayload testPayload) { throw new DefectDojoPersistenceException("Failed to create Test for SecurityTest", e); } } - private long getTestIdOrCreate(long engagementId, TestPayload testPayload) { + private long getTestIdOrCreate(long engagementId, TestPayload testPayload, String testType) { Long testId = getTestIdByEngagementName(engagementId, testPayload.getTitle(), 0).orElseGet(() -> { testPayload.setEngagement(Long.toString(engagementId)); - testPayload.setTargetStart(currentDate()); - testPayload.setTargetEnd(currentDate()); + testPayload.setTargetStart(currentDateTime()); + testPayload.setTargetEnd(currentDateTime()); + testPayload.setTestType(Integer.toString(TestPayload.getTestTypeIdForName(testType))); return createTest(testPayload).getId(); }); + return testId.longValue(); } - public ImportScanResponse createFindingsReImport(String rawResult, String productName, String engagementName, long lead, String currentDate, String defectDojoScanName, EngagementPayload engagementPayload, TestPayload testPayload) { + public ImportScanResponse createFindingsReImport(String rawResult, String productName, String engagementName, long lead, String currentDate, String defectDojoScanName, EngagementPayload engagementPayload, TestPayload testPayload, MultiValueMap options) { long productId = retrieveOrCreateProduct(productName); long engagementId = getEngagementIdByEngagementNameOrCreate(productId, engagementName, engagementPayload, lead); - long testId = getTestIdOrCreate(engagementId, testPayload); - return createFindingsReImport(rawResult, testId, lead, currentDate, defectDojoScanName); + long testId = getTestIdOrCreate(engagementId, testPayload, defectDojoScanName); + return createFindingsReImport(rawResult, testId, lead, currentDate, defectDojoScanName, options); } - - public ImportScanResponse createFindingsReImport(String rawResult, long testId, long lead, String currentDate,String defectDojoScanName) { + + public ImportScanResponse createFindingsReImport(String rawResult, long testId, long lead, String currentDate,String defectDojoScanName, MultiValueMap options) { RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = getHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); @@ -306,6 +324,15 @@ public ImportScanResponse createFindingsReImport(String rawResult, long testId, mvn.add("scan_type", defectDojoScanName); mvn.add("close_old_findings", "true"); mvn.add("skip_duplicates", "false"); + + Iterator it = options.keySet().iterator(); + while(it.hasNext()){ + String theKey = (String)it.next(); + if(mvn.containsKey(theKey)) { + mvn.remove(theKey); + } + } + mvn.addAll(options); try { ByteArrayResource contentsAsResource = new ByteArrayResource(rawResult.getBytes(StandardCharsets.UTF_8)) { @@ -325,15 +352,17 @@ public String getFilename() { LOG.warn("Failure body: {}", e.getResponseBodyAsString()); throw new DefectDojoPersistenceException("Failed to attach findings to engagement."); } - } + } + + public ImportScanResponse createFindingsForEngagementName(String engagementName, String rawResults, String defectDojoScanName, long productId, long lead){ - return createFindingsForEngagementName(engagementName, rawResults, defectDojoScanName, productId, lead, new EngagementPayload(), ""); + return getEngagementIdByEngagementNameOrCreate(engagementName, rawResults, defectDojoScanName, productId, lead, new EngagementPayload(), "", new LinkedMultiValueMap<>()); } - public ImportScanResponse getEngagementIdByEngagementNameOrCreate(String engagementName, String rawResults, String defectDojoScanName, long productId, long lead, EngagementPayload engagementPayload, String testName){ - Long engagementId = getEngagementIdByEngagementName(engagementName, productId, engagementPayload, lead); + public ImportScanResponse getEngagementIdByEngagementNameOrCreate(String engagementName, String rawResults, String defectDojoScanName, long productId, long lead, EngagementPayload engagementPayload, String testName, MultiValueMap options){ + long engagementId = getEngagementIdByEngagementNameOrCreate(productId, engagementName, engagementPayload, lead); - return createFindings(rawResults, engagementId, lead, currentDate(), defectDojoScanName, testName); + return createFindings(rawResults, engagementId, lead, currentDate(), defectDojoScanName, testName, options); } private long getEngagementIdByEngagementNameOrCreate(long productId, String engagementName, EngagementPayload engagementPayload, long lead) { Long engagementId = getEngagementIdByEngagementName(engagementName, productId).orElseGet(() -> { @@ -344,12 +373,12 @@ private long getEngagementIdByEngagementNameOrCreate(long productId, String enga engagementPayload.setLead(lead); return createEngagement(engagementPayload).getId(); }); + return engagementId.longValue(); } - - public ImportScanResponse createFindingsForEngagementName(String engagementName, String rawResults, String defectDojoScanName, String productName, long lead, EngagementPayload engagementPayload, String testName){ + public ImportScanResponse createFindingsForEngagementName(String engagementName, String rawResults, String defectDojoScanName, String productName, long lead, EngagementPayload engagementPayload, String testName, MultiValueMap options){ long productId = retrieveOrCreateProduct(productName); - return createFindingsForEngagementName(engagementName, rawResults, defectDojoScanName, productId, lead, engagementPayload, testName); + return getEngagementIdByEngagementNameOrCreate(engagementName, rawResults, defectDojoScanName, productId, lead, engagementPayload, testName, options); } private Optional getEngagementIdByEngagementName(String engagementName, String productName){ @@ -503,15 +532,9 @@ private UriComponentsBuilder prepareParameters(LinkedMultiValueMap receiveNonHandeldFindings(String productName, String engagementName, String minimumServerity, LinkedMultiValueMap options){ + public List receiveNonHandledFindings(String productName, String engagementName, String minimumServerity, LinkedMultiValueMap options){ Long engagementId = getEngagementIdByEngagementName(engagementName, productName).orElse(0L); - //getCurrentFindings - List findings = new LinkedList(); - for (String serverity : Finding.getServeritiesAndHigherServerities(minimumServerity)) { - LinkedMultiValueMap optionTemp = options.clone(); - optionTemp.add("serverity", serverity); - findings.addAll(getCurrentFindings(engagementId, optionTemp)); - } - return findings; + options.add("serverity", minimumServerity); + return getCurrentFindings(engagementId, options); } } diff --git a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/TestPayload.java b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/TestPayload.java index 49cfc377..39ed7a91 100644 --- a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/TestPayload.java +++ b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/TestPayload.java @@ -40,20 +40,29 @@ public class TestPayload { @JsonProperty protected List tags = new LinkedList<>(); + @JsonProperty("test_type") + protected String testType; + @JsonProperty protected String engagement; + /** + * 1 Development + * 3 Production + */ @JsonProperty - protected ENVIRONMENT environment = ENVIRONMENT.DEVELOPMENT; + protected String environment = "1"; /** - * Currently only contains the statuses relevant to us. - * If you need others, feel free to add them ;) + * + * @return OWASP DefectDojo test type id, -1 in case it is not found */ - public static enum ENVIRONMENT { - @JsonProperty("Development") - DEVELOPMENT, - @JsonProperty("Production") - PRODUCTION + public static int getTestTypeIdForName(String name) { + switch (name) { + case "Dependency Check Scan": + return 18; + default: + return -1; + } } } From c7a3b0c46046fa5ab1cb305ecff0a3e5ff75eef2 Mon Sep 17 00:00:00 2001 From: Timo Pagel Date: Sun, 18 Aug 2019 13:51:47 +0200 Subject: [PATCH 3/9] Use empty testName --- .../persistence/DefectDojoService.java | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java index 99c04eb8..8ff6e6f4 100644 --- a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java +++ b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java @@ -255,24 +255,30 @@ public String getFilename() { } } /** - * When DefectDojo >= 1.5.4 is used, add testType to queryParam, till then, the first test in engagement is returned + * When DefectDojo >= 1.5.4 is used, testType can be given. Add testName in case DefectDojo >= 1.5.4 is used */ private Optional getTestIdByEngagementName(long engagementId, String testName, long offset) { UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(defectDojoUrl + "/api/v2/tests") .queryParam("engagement", Long.toString(engagementId)) .queryParam("limit", Long.toString(50L)) .queryParam("offset", Long.toString(offset)); + if(testName!= null) builder.queryParam("testType", testName); RestTemplate restTemplate = new RestTemplate(); HttpEntity engagementRequest = new HttpEntity(getHeaders()); ResponseEntity> response = restTemplate.exchange(builder.toUriString(), HttpMethod.GET, engagementRequest, new ParameterizedTypeReference>(){}); + Optional testResponseId = null; for(TestResponse test : response.getBody().getResults()){ - //if(test.getTitle().equals(testName)){ - return Optional.of(test.getId()); - //} + if(testName == null || test.getTitle().equals(testName)){ + testResponseId = Optional.of(test.getId()); + } + } + if(testResponseId != null) { + return testResponseId; } + if(response.getBody().getNext() != null){ return getTestIdByEngagementName(engagementId, testName, offset + 1); } @@ -534,7 +540,7 @@ private UriComponentsBuilder prepareParameters(LinkedMultiValueMap receiveNonHandledFindings(String productName, String engagementName, String minimumServerity, LinkedMultiValueMap options){ Long engagementId = getEngagementIdByEngagementName(engagementName, productName).orElse(0L); - options.add("serverity", minimumServerity); + options.add("serverity", minimumServerity); return getCurrentFindings(engagementId, options); } } From 08d4713e5d2c617c83f5a04554ed029041951a76 Mon Sep 17 00:00:00 2001 From: Timo Pagel Date: Sun, 18 Aug 2019 13:58:41 +0200 Subject: [PATCH 4/9] Beautify --- .../java/io/securecodebox/persistence/models/TestPayload.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/TestPayload.java b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/TestPayload.java index 39ed7a91..bc3b24f1 100644 --- a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/TestPayload.java +++ b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/TestPayload.java @@ -20,9 +20,6 @@ import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; - -import java.util.Arrays; -import java.util.Collections; import java.util.LinkedList; import java.util.List; From 098657b84764245353800bda848911427d0f353b Mon Sep 17 00:00:00 2001 From: Timo Pagel Date: Mon, 19 Aug 2019 11:43:30 +0200 Subject: [PATCH 5/9] Add error hint --- .../java/io/securecodebox/persistence/DefectDojoService.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java index 8ff6e6f4..145bf922 100644 --- a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java +++ b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java @@ -442,6 +442,9 @@ public void deleteUnusedBranches(List existingBranches, String producNam * Be aware that the branch tag MUST be set, otherwise all engagments will be deleted */ public void deleteUnusedBranches(List existingBranches, long productId) { + if(existingBranches == null) { + LOG.error("No existing branches given, this will lead to nullpointer"); + } RestTemplate restTemplate = new RestTemplate(); //get existing branches From 43e13cab149099f1d00561214073c06c875f501d Mon Sep 17 00:00:00 2001 From: Timo Pagel Date: Mon, 19 Aug 2019 12:29:53 +0200 Subject: [PATCH 6/9] Fix: Delete --- .../java/io/securecodebox/persistence/DefectDojoService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java index 145bf922..297993f2 100644 --- a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java +++ b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java @@ -492,7 +492,7 @@ public void deleteEnageament(long engagementId){ String uri = defectDojoUrl + "/api/v2/engagements/" + engagementId + "/?id=" + engagementId; HttpEntity request = new HttpEntity(getHeaders()); try { - ResponseEntity response = restTemplate.exchange(uri, HttpMethod.GET, request, DefectDojoResponse.class); + ResponseEntity response = restTemplate.exchange(uri, HttpMethod.DELETE, request, DefectDojoResponse.class); } catch (HttpClientErrorException e) { LOG.warn("Failed to delete engagment {}, engagementId: " + engagementId, e); LOG.warn("Failure response body. {}", e.getResponseBodyAsString()); From 4d3c51fadca30f446c0de01c2ae01b2ec57b040e Mon Sep 17 00:00:00 2001 From: Timo Pagel Date: Mon, 19 Aug 2019 12:39:56 +0200 Subject: [PATCH 7/9] Beautify --- .../java/io/securecodebox/persistence/DefectDojoService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java index 297993f2..88e4b6f9 100644 --- a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java +++ b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java @@ -492,7 +492,7 @@ public void deleteEnageament(long engagementId){ String uri = defectDojoUrl + "/api/v2/engagements/" + engagementId + "/?id=" + engagementId; HttpEntity request = new HttpEntity(getHeaders()); try { - ResponseEntity response = restTemplate.exchange(uri, HttpMethod.DELETE, request, DefectDojoResponse.class); + restTemplate.exchange(uri, HttpMethod.DELETE, request, DefectDojoResponse.class); } catch (HttpClientErrorException e) { LOG.warn("Failed to delete engagment {}, engagementId: " + engagementId, e); LOG.warn("Failure response body. {}", e.getResponseBodyAsString()); From 662a29ab3f32abf0afaa9836073b70886500330a Mon Sep 17 00:00:00 2001 From: Timo Pagel Date: Mon, 19 Aug 2019 19:30:51 +0200 Subject: [PATCH 8/9] Fix Naming --- .../io/securecodebox/persistence/DefectDojoService.java | 8 ++++---- .../persistence/models/EngagementResponse.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java index 88e4b6f9..1af859f2 100644 --- a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java +++ b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java @@ -450,16 +450,16 @@ public void deleteUnusedBranches(List existingBranches, long productId) //get existing branches List engagementPayloads = getEngagementsForProduct(productId, 0); for(EngagementResponse engagementPayload : engagementPayloads) { - boolean branchExists = false; + boolean branchExists = false for(String existingBranchName : existingBranches) { - if(existingBranchName.equals(engagementPayload.getBanch())) { + if(existingBranchName.equals(engagementPayload.getBranch())) { branchExists = true; - break; + continue; } } if(!branchExists) { deleteEnageament(engagementPayload.getId()); - LOG.info("Deleted engagement with id " + engagementPayload.getId() + ", branch " + engagementPayload.getBanch()); + LOG.info("Deleted engagement with id " + engagementPayload.getId() + ", branch " + engagementPayload.getBranch()); } } } diff --git a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/EngagementResponse.java b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/EngagementResponse.java index f221ae63..74ee9ffe 100644 --- a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/EngagementResponse.java +++ b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/models/EngagementResponse.java @@ -46,7 +46,7 @@ public void setName(String name) { this.name = name; } - public String getBanch() { + public String getBranch() { return branch; } From f245d8070f2a7e529cfa333e8000b26ffcdf9e60 Mon Sep 17 00:00:00 2001 From: Jannik Hollenbach Date: Mon, 19 Aug 2019 20:37:58 +0200 Subject: [PATCH 9/9] Add missing semi colon --- .../java/io/securecodebox/persistence/DefectDojoService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java index 1af859f2..4cfe3803 100644 --- a/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java +++ b/scb-persistenceproviders/defectdojo-persistenceprovider/src/main/java/io/securecodebox/persistence/DefectDojoService.java @@ -450,7 +450,7 @@ public void deleteUnusedBranches(List existingBranches, long productId) //get existing branches List engagementPayloads = getEngagementsForProduct(productId, 0); for(EngagementResponse engagementPayload : engagementPayloads) { - boolean branchExists = false + boolean branchExists = false; for(String existingBranchName : existingBranches) { if(existingBranchName.equals(engagementPayload.getBranch())) { branchExists = true;