Skip to content

Commit 2151b22

Browse files
committed
Change testType to be a proper model
TestType ids are unstable between DefectDojo releases. Only way to properly use them is to look their id's up beforehand in the API. TestTypes and ScanTypes are identical in the API, so the enums have been merged
1 parent 8eb3731 commit 2151b22

File tree

6 files changed

+188
-139
lines changed

6 files changed

+188
-139
lines changed

src/main/java/io/securecodebox/persistence/defectdojo/ScanType.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ public enum ScanType {
66
ACUNETIX_SCAN("Acunetix Scan"),
77
ANCHORE_ENGINE_SCAN("Anchore Engine Scan"),
88
ANCHORE_ENTERPRISE_POLICY_CHECK("Anchore Enterprise Policy Check"),
9+
API_TEST("API Test"),
910
APP_SPIDER_SCAN("AppSpider Scan"),
1011
AQUA_SCAN("Aqua Scan"),
1112
ARACHNI_SCAN("Arachni Scan"),
@@ -36,8 +37,8 @@ public enum ScanType {
3637
ES_LINT_SCAN("ESLint Scan"),
3738
FORTIFY("Fortify"),
3839
GENERIC_FINDINGS_IMPORT("Generic Findings Import"),
39-
GIT_LAB_SAST_REPORT("GitLab SAST Report"),
4040
GITLEAKS_SCAN("Gitleaks Scan"),
41+
GIT_LAB_SAST_REPORT("GitLab SAST Report"),
4142
GOSEC_SCANNER("Gosec Scanner"),
4243
HACKER_ONE_CASES("HackerOne Cases"),
4344
HADOLINT_DOCKERFILE_CHECK("Hadolint Dockerfile check"),
@@ -47,6 +48,7 @@ public enum ScanType {
4748
IMMUNIWEB_SCAN("Immuniweb Scan"),
4849
J_FROG_XRAY_SCAN("JFrog Xray Scan"),
4950
KIUWAN_SCAN("Kiuwan Scan"),
51+
MANUAL_CODE_REVIEW("Manual Code Review"),
5052
MICROFOCUS_WEBINSPECT_SCAN("Microfocus Webinspect Scan"),
5153
MOB_SF_SCANNER("MobSF Scanner"),
5254
MOZILLA_OBSERVATORY_SCAN("Mozilla Observatory Scan"),
@@ -60,6 +62,7 @@ public enum ScanType {
6062
OPENSCAP_VULNERABILITY_SCAN("Openscap Vulnerability Scan"),
6163
OPEN_VAS_CSV("OpenVAS CSV"),
6264
OUTPOST24_SCAN("Outpost24 Scan"),
65+
PEN_TEST("Pen Test"),
6366
PHP_SECURITY_AUDIT_V2("PHP Security Audit v2"),
6467
PHP_SYMFONY_SECURITY_CHECKER("PHP Symfony Security Checker"),
6568
QUALYS_INFRASTRUCTURE_SCAN_WEB_GUI_XML("Qualys Infrastructure Scan (WebGUI XML)"),
@@ -68,23 +71,27 @@ public enum ScanType {
6871
RETIRE_JS_SCAN("Retire.js Scan"),
6972
RISK_RECON_API_IMPORTER("Risk Recon API Importer"),
7073
SAFETY_SCAN("Safety Scan"),
74+
SECURITY_RESEARCH("Security Research"),
7175
SKF_SCAN("SKF Scan"),
7276
SNYK_SCAN("Snyk Scan"),
7377
SONAR_QUBE("SonarQube"),
7478
SONATYPE_APPLICATION_SCAN("Sonatype Application Scan"),
7579
SPOT_BUGS("SpotBugs"),
76-
SSL_LABS_SCAN("SSL Labs Scan"),
7780
SSLSCAN("Sslscan"),
78-
SS_LYZE_3_SCAN_JSON("SSLyze 3 Scan (JSON)"),
7981
SSLYZE_SCAN("Sslyze Scan"),
82+
SSL_LABS_SCAN("SSL Labs Scan"),
83+
SS_LYZE_3_SCAN_JSON("SSLyze 3 Scan (JSON)"),
84+
STATIC_CHECK("Static Check"),
8085
TESTSSL_SCAN("Testssl Scan"),
86+
THREAT_MODELING("Threat Modeling"),
8187
TRIVY_SCAN("Trivy Scan"),
8288
TRUFFLEHOG("Trufflehog"),
8389
TRUSTWAVE("Trustwave"),
8490
TWISTLOCK_IMAGE_SCAN("Twistlock Image Scan"),
8591
VCG_SCAN("VCG Scan"),
8692
VERACODE_SCAN("Veracode Scan"),
8793
WAPITI_SCAN("Wapiti Scan"),
94+
WEB_APPLICATION_TEST("Web Application Test"),
8895
WHITESOURCE_SCAN("Whitesource Scan"),
8996
WPSCAN("Wpscan"),
9097
XANITIZER_SCAN("Xanitizer Scan"),

src/main/java/io/securecodebox/persistence/defectdojo/TestType.java

Lines changed: 0 additions & 24 deletions
This file was deleted.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package io.securecodebox.persistence.defectdojo.models;
2+
3+
import com.fasterxml.jackson.annotation.JsonInclude;
4+
import com.fasterxml.jackson.annotation.JsonProperty;
5+
import lombok.*;
6+
7+
import java.util.Map;
8+
9+
@Data
10+
@Builder
11+
@NoArgsConstructor
12+
@AllArgsConstructor
13+
@EqualsAndHashCode(callSuper = true)
14+
@JsonInclude(JsonInclude.Include.NON_NULL)
15+
public class TestType extends DefectDojoModel {
16+
@JsonProperty
17+
Long id;
18+
19+
@JsonProperty
20+
@NonNull
21+
String name;
22+
23+
@JsonProperty("static_tool")
24+
Boolean staticTool;
25+
26+
@JsonProperty("dynamic_tool")
27+
Boolean dynamicTool;
28+
29+
30+
@Override
31+
public boolean equalsQueryString(Map<String, Object> queryParams) {
32+
if (queryParams.containsKey("id") && queryParams.get("id").equals(this.id)) {
33+
return true;
34+
}
35+
if (queryParams.containsKey("name") && queryParams.get("name").equals(this.name)) {
36+
return true;
37+
}
38+
39+
return false;
40+
}
41+
}

src/main/java/io/securecodebox/persistence/defectdojo/service/GenericDefectDojoService.java

Lines changed: 104 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -21,145 +21,144 @@
2121
import java.util.*;
2222

2323
abstract public class GenericDefectDojoService<T extends DefectDojoModel> {
24-
protected String defectDojoUrl;
25-
protected String defectDojoApiKey;
24+
protected String defectDojoUrl;
25+
protected String defectDojoApiKey;
2626

27-
protected ObjectMapper objectMapper;
28-
protected ObjectMapper searchStringMapper;
27+
protected ObjectMapper objectMapper;
28+
protected ObjectMapper searchStringMapper;
2929

30-
public GenericDefectDojoService(DefectDojoConfig config){
31-
this.defectDojoUrl = config.getUrl();
32-
this.defectDojoApiKey = config.getApiKey();
30+
public GenericDefectDojoService(DefectDojoConfig config) {
31+
this.defectDojoUrl = config.getUrl();
32+
this.defectDojoApiKey = config.getApiKey();
3333

34-
this.objectMapper = new ObjectMapper();
35-
this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
34+
this.objectMapper = new ObjectMapper();
35+
this.objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
3636

37-
this.searchStringMapper = new ObjectMapper();
38-
this.searchStringMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
39-
this.searchStringMapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
40-
}
37+
this.searchStringMapper = new ObjectMapper();
38+
this.searchStringMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
39+
this.searchStringMapper.setSerializationInclusion(JsonInclude.Include.NON_DEFAULT);
40+
}
4141

4242

43+
protected long DEFECT_DOJO_OBJET_LIMIT = 100L;
4344

44-
protected long DEFECT_DOJO_OBJET_LIMIT = 100L;
45+
/**
46+
* @return The DefectDojo Authentication Header
47+
*/
48+
private HttpHeaders getDefectDojoAuthorizationHeaders() {
49+
HttpHeaders headers = new HttpHeaders();
50+
headers.set("Authorization", "Token " + defectDojoApiKey);
51+
return headers;
52+
}
4553

46-
/**
47-
* @return The DefectDojo Authentication Header
48-
*/
49-
private HttpHeaders getDefectDojoAuthorizationHeaders() {
50-
HttpHeaders headers = new HttpHeaders();
51-
headers.set("Authorization", "Token " + defectDojoApiKey);
52-
return headers;
53-
}
54+
protected abstract String getUrlPath();
5455

55-
protected abstract String getUrlPath();
56+
protected abstract Class<T> getModelClass();
5657

57-
protected abstract Class<T> getModelClass();
58+
protected abstract DefectDojoResponse<T> deserializeList(String response) throws JsonProcessingException;
5859

59-
protected abstract DefectDojoResponse<T> deserializeList(String response) throws JsonProcessingException;
60+
public T get(long id) {
61+
RestTemplate restTemplate = new RestTemplate();
62+
HttpEntity<String> payload = new HttpEntity<>(getDefectDojoAuthorizationHeaders());
6063

61-
public T get(long id) {
62-
RestTemplate restTemplate = new RestTemplate();
63-
HttpEntity<String> payload = new HttpEntity<>(getDefectDojoAuthorizationHeaders());
64+
ResponseEntity<T> response = restTemplate.exchange(
65+
defectDojoUrl + "/api/v2/" + this.getUrlPath() + "/" + id,
66+
HttpMethod.GET,
67+
payload,
68+
getModelClass()
69+
);
6470

65-
ResponseEntity<T> response = restTemplate.exchange(
66-
defectDojoUrl + "/api/v2/" + this.getUrlPath() + "/" + id,
67-
HttpMethod.GET,
68-
payload,
69-
getModelClass()
70-
);
71+
return response.getBody();
72+
}
7173

72-
return response.getBody();
73-
}
74+
protected DefectDojoResponse<T> internalSearch(Map<String, Object> queryParams, long limit, long offset) throws JsonProcessingException, URISyntaxException {
75+
RestTemplate restTemplate = new RestTemplate();
76+
HttpEntity<String> payload = new HttpEntity<>(getDefectDojoAuthorizationHeaders());
7477

75-
protected DefectDojoResponse<T> internalSearch(Map<String, Object> queryParams, long limit, long offset) throws JsonProcessingException, URISyntaxException {
76-
RestTemplate restTemplate = new RestTemplate();
77-
HttpEntity<String> payload = new HttpEntity<>(getDefectDojoAuthorizationHeaders());
78+
var mutableQueryParams = new HashMap<String, Object>(queryParams);
7879

79-
var mutableQueryParams = new HashMap<String, Object>(queryParams);
80+
mutableQueryParams.put("limit", String.valueOf(limit));
81+
mutableQueryParams.put("offset", String.valueOf(offset));
8082

81-
mutableQueryParams.put("limit", String.valueOf(limit));
82-
mutableQueryParams.put("offset", String.valueOf(offset));
83+
var multiValueMap = new LinkedMultiValueMap<String, String>();
84+
for (var entry : mutableQueryParams.entrySet()) {
85+
multiValueMap.set(entry.getKey(), String.valueOf(entry.getValue()));
86+
}
8387

84-
var multiValueMap = new LinkedMultiValueMap<String, String>();
85-
for (var entry : mutableQueryParams.entrySet()) {
86-
multiValueMap.set(entry.getKey(), String.valueOf(entry.getValue()));
87-
}
88+
var url = new URI(defectDojoUrl + "/api/v2/" + this.getUrlPath() + "/");
89+
var uriBuilder = UriComponentsBuilder.fromUri(url).queryParams(multiValueMap);
8890

89-
var url = new URI(defectDojoUrl + "/api/v2/" + this.getUrlPath() + "/");
90-
var uriBuilder = UriComponentsBuilder.fromUri(url).queryParams(multiValueMap);
91+
ResponseEntity<String> responseString = restTemplate.exchange(
92+
uriBuilder.build(mutableQueryParams),
93+
HttpMethod.GET,
94+
payload,
95+
String.class
96+
);
9197

92-
ResponseEntity<String> responseString = restTemplate.exchange(
93-
uriBuilder.build(mutableQueryParams),
94-
HttpMethod.GET,
95-
payload,
96-
String.class
97-
);
98-
99-
return deserializeList(responseString.getBody());
100-
}
98+
return deserializeList(responseString.getBody());
99+
}
101100

102-
public List<T> search(Map<String, Object> queryParams) throws URISyntaxException, JsonProcessingException {
103-
List<T> objects = new LinkedList<>();
101+
public List<T> search(Map<String, Object> queryParams) throws URISyntaxException, JsonProcessingException {
102+
List<T> objects = new LinkedList<>();
104103

105-
boolean hasNext = false;
106-
long page = 0;
107-
do {
108-
var response = internalSearch(queryParams, DEFECT_DOJO_OBJET_LIMIT, DEFECT_DOJO_OBJET_LIMIT * page++);
109-
objects.addAll(response.getResults());
104+
boolean hasNext = false;
105+
long page = 0;
106+
do {
107+
var response = internalSearch(queryParams, DEFECT_DOJO_OBJET_LIMIT, DEFECT_DOJO_OBJET_LIMIT * page++);
108+
objects.addAll(response.getResults());
110109

111-
hasNext = response.getNext() != null;
112-
if (page > 100) {
113-
throw new DefectDojoLoopException("Found too many response object. Quitting after " + page + " paginated API pages of " + DEFECT_DOJO_OBJET_LIMIT + " each.");
114-
}
115-
} while (hasNext);
110+
hasNext = response.getNext() != null;
111+
if (page > 100) {
112+
throw new DefectDojoLoopException("Found too many response object. Quitting after " + page + " paginated API pages of " + DEFECT_DOJO_OBJET_LIMIT + " each.");
113+
}
114+
} while (hasNext);
116115

117-
return objects;
118-
}
116+
return objects;
117+
}
119118

120-
public List<T> search() throws URISyntaxException, JsonProcessingException {
121-
return search(new LinkedHashMap<>());
122-
}
119+
public List<T> search() throws URISyntaxException, JsonProcessingException {
120+
return search(new LinkedHashMap<>());
121+
}
123122

124-
@SuppressWarnings("unchecked")
125-
public Optional<T> searchUnique(T searchObject) throws URISyntaxException, JsonProcessingException {
126-
Map<String, Object> queryParams = searchStringMapper.convertValue(searchObject, Map.class);
123+
@SuppressWarnings("unchecked")
124+
public Optional<T> searchUnique(T searchObject) throws URISyntaxException, JsonProcessingException {
125+
Map<String, Object> queryParams = searchStringMapper.convertValue(searchObject, Map.class);
127126

128-
var objects = search(queryParams);
127+
var objects = search(queryParams);
129128

130-
return objects.stream()
131-
.filter((object) -> object != null && object.equalsQueryString(queryParams))
132-
.findFirst();
133-
}
129+
return objects.stream()
130+
.filter((object) -> object != null && object.equalsQueryString(queryParams))
131+
.findFirst();
132+
}
134133

135-
public Optional<T> searchUnique(Map<String, Object> queryParams) throws URISyntaxException, JsonProcessingException {
136-
var objects = search(queryParams);
134+
public Optional<T> searchUnique(Map<String, Object> queryParams) throws URISyntaxException, JsonProcessingException {
135+
var objects = search(queryParams);
137136

138-
return objects.stream()
139-
.filter((object) -> object.equalsQueryString(queryParams))
140-
.findFirst();
141-
}
137+
return objects.stream()
138+
.filter((object) -> object.equalsQueryString(queryParams))
139+
.findFirst();
140+
}
142141

143-
public T create(T object) {
144-
RestTemplate restTemplate = new RestTemplate();
145-
HttpEntity<T> payload = new HttpEntity<T>(object, getDefectDojoAuthorizationHeaders());
142+
public T create(T object) {
143+
RestTemplate restTemplate = new RestTemplate();
144+
HttpEntity<T> payload = new HttpEntity<T>(object, getDefectDojoAuthorizationHeaders());
146145

147-
ResponseEntity<T> response = restTemplate.exchange(defectDojoUrl + "/api/v2/" + getUrlPath() + "/", HttpMethod.POST, payload, getModelClass());
148-
return response.getBody();
149-
}
146+
ResponseEntity<T> response = restTemplate.exchange(defectDojoUrl + "/api/v2/" + getUrlPath() + "/", HttpMethod.POST, payload, getModelClass());
147+
return response.getBody();
148+
}
150149

151-
public void delete(long id) {
152-
RestTemplate restTemplate = new RestTemplate();
153-
HttpEntity<String> payload = new HttpEntity<>(getDefectDojoAuthorizationHeaders());
150+
public void delete(long id) {
151+
RestTemplate restTemplate = new RestTemplate();
152+
HttpEntity<String> payload = new HttpEntity<>(getDefectDojoAuthorizationHeaders());
154153

155-
restTemplate.exchange(defectDojoUrl + "/api/v2/" + getUrlPath() + "/" + id + "/", HttpMethod.DELETE, payload, String.class);
156-
}
154+
restTemplate.exchange(defectDojoUrl + "/api/v2/" + getUrlPath() + "/" + id + "/", HttpMethod.DELETE, payload, String.class);
155+
}
157156

158-
public T update(T object, long objectId) {
159-
RestTemplate restTemplate = new RestTemplate();
160-
HttpEntity<T> payload = new HttpEntity<T>(object, getDefectDojoAuthorizationHeaders());
157+
public T update(T object, long objectId) {
158+
RestTemplate restTemplate = new RestTemplate();
159+
HttpEntity<T> payload = new HttpEntity<T>(object, getDefectDojoAuthorizationHeaders());
161160

162-
ResponseEntity<T> response = restTemplate.exchange(defectDojoUrl + "/api/v2/" + getUrlPath() + "/" + objectId + "/", HttpMethod.PUT, payload, getModelClass());
163-
return response.getBody();
164-
}
161+
ResponseEntity<T> response = restTemplate.exchange(defectDojoUrl + "/api/v2/" + getUrlPath() + "/" + objectId + "/", HttpMethod.PUT, payload, getModelClass());
162+
return response.getBody();
163+
}
165164
}

0 commit comments

Comments
 (0)