Skip to content

Commit 762179f

Browse files
authored
Feature 4169 fix bug in CheckmarxResilienceConsultant (#4170)
1 parent 1c88165 commit 762179f

File tree

4 files changed

+164
-127
lines changed

4 files changed

+164
-127
lines changed

sechub-adapter-checkmarx/src/main/java/com/mercedesbenz/sechub/adapter/checkmarx/CheckmarxResilienceConsultant.java

Lines changed: 59 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66

77
import org.slf4j.Logger;
88
import org.slf4j.LoggerFactory;
9-
import org.springframework.web.client.HttpClientErrorException;
9+
import org.springframework.web.client.HttpStatusCodeException;
10+
import org.springframework.web.client.RestClientException;
1011

1112
import com.mercedesbenz.sechub.commons.core.resilience.ResilienceConsultant;
1213
import com.mercedesbenz.sechub.commons.core.resilience.ResilienceContext;
@@ -32,59 +33,76 @@ public CheckmarxResilienceConfiguration getResilienceConfig() {
3233

3334
@Override
3435
public ResilienceProposal consultFor(ResilienceContext context) {
35-
Objects.requireNonNull(context);
36+
Objects.requireNonNull(context, "Resilience context must not be null");
37+
3638
Throwable rootCause = StacktraceUtil.findRootCause(context.getCurrentError());
3739
if (rootCause == null) {
3840
LOG.warn("Cannot make any proposal when root cause is null!");
3941
return null;
4042
}
41-
String message = rootCause.getMessage();
4243

43-
if (message != null) {
44-
if (message.contains("Changes exceeded the threshold limit")) {
45-
LOG.warn("Checkmarx delta scan exceeded treshold limit. Will suggest to do a retry with fullscan enabled");
46-
context.setValue(CONTEXT_ID_FALLBACK_CHECKMARX_FULLSCAN, true);
47-
48-
return new SimpleRetryResilienceProposal("checkmarx too many changes - retry fullscan handling", 1, 500);
49-
}
44+
if (isThresholdLimitExceeded(rootCause)) {
45+
return handleThresholdLimitExceeded(context);
5046
}
5147

5248
if (rootCause instanceof SocketException) {
53-
LOG.info("Propose retry for socket exception");
54-
return new SimpleRetryResilienceProposal("checkmarx network error handling", resilienceConfig.getNetworkErrorMaxRetries(),
55-
resilienceConfig.getNetworkErrorRetryTimeToWaitInMilliseconds());
49+
return handleSocketException();
5650
}
5751

58-
if (rootCause instanceof HttpClientErrorException) {
59-
HttpClientErrorException hce = (HttpClientErrorException) rootCause;
60-
int statusCode = hce.getStatusCode().value();
61-
if (statusCode == 400) {
62-
/*
63-
* BAD request - this can happen for same project scans put to queue because
64-
* there can a CHECKMARX server error happen
65-
*/
66-
LOG.info("Propose retry for bad request");
67-
return new SimpleRetryResilienceProposal("checkmarx bad request handling", resilienceConfig.getBadRequestMaxRetries(),
68-
resilienceConfig.getBadRequestRetryTimeToWaitInMilliseconds());
69-
70-
} else if (statusCode == 500) {
71-
/*
72-
* An internal server error happened - lets assume that this is temporary and do
73-
* a retry
74-
*/
75-
LOG.info("Propose retry for internal server error");
76-
return new SimpleRetryResilienceProposal("checkmarx internal server error handling", resilienceConfig.getInternalServerErrortMaxRetries(),
77-
resilienceConfig.getInternalServerErrorRetryTimeToWaitInMilliseconds());
78-
79-
} else {
80-
LOG.info("Can't make proposal for http client error exception:{}", StacktraceUtil.createDescription(rootCause));
81-
}
82-
} else {
83-
// unexpected problem - so log as warning and exception, so full stack trace
84-
// availabe in logs
85-
LOG.warn("Can't make proposal for exception with root cause: {}", rootCause.getClass().getSimpleName(), rootCause);
52+
if (rootCause instanceof RestClientException) {
53+
return handleRestClientException(rootCause);
8654
}
55+
56+
LOG.warn("No proposal available for exception: {}", rootCause.getClass().getSimpleName());
8757
return null;
8858
}
8959

60+
private boolean isThresholdLimitExceeded(Throwable rootCause) {
61+
String message = rootCause.getMessage();
62+
if (message == null) {
63+
return false;
64+
}
65+
return message.contains("Changes exceeded the threshold limit");
66+
}
67+
68+
private ResilienceProposal handleThresholdLimitExceeded(ResilienceContext context) {
69+
LOG.warn("Checkmarx delta scan exceeded threshold limit. Will suggest to do a retry with fullscan enabled");
70+
context.setValue(CONTEXT_ID_FALLBACK_CHECKMARX_FULLSCAN, true);
71+
72+
return new SimpleRetryResilienceProposal("checkmarx too many changes - retry fullscan handling", 1, 500);
73+
}
74+
75+
private ResilienceProposal handleSocketException() {
76+
LOG.info("Propose retry for socket exception");
77+
return new SimpleRetryResilienceProposal("checkmarx network error handling", resilienceConfig.getNetworkErrorMaxRetries(),
78+
resilienceConfig.getNetworkErrorRetryTimeToWaitInMilliseconds());
79+
}
80+
81+
private ResilienceProposal handleRestClientException(Throwable rootCause) {
82+
if (rootCause instanceof HttpStatusCodeException) {
83+
return handleHttpStatusCodeException((HttpStatusCodeException) rootCause);
84+
}
85+
86+
LOG.warn("Unexpected RestClientException: {}", StacktraceUtil.createDescription(rootCause));
87+
return null;
88+
}
89+
90+
private ResilienceProposal handleHttpStatusCodeException(HttpStatusCodeException exception) {
91+
int statusCode = exception.getStatusCode().value();
92+
93+
if (statusCode == 400) {
94+
LOG.info("Propose retry for bad request");
95+
return new SimpleRetryResilienceProposal("checkmarx bad request handling", resilienceConfig.getBadRequestMaxRetries(),
96+
resilienceConfig.getBadRequestRetryTimeToWaitInMilliseconds());
97+
}
98+
99+
if (statusCode >= 500 && statusCode <= 599) {
100+
LOG.info("Propose retry for server error with status code: {}", statusCode);
101+
return new SimpleRetryResilienceProposal("checkmarx server error handling", resilienceConfig.getInternalServerErrortMaxRetries(),
102+
resilienceConfig.getInternalServerErrorRetryTimeToWaitInMilliseconds());
103+
}
104+
105+
LOG.warn("No proposal for HTTP status code: {}", statusCode);
106+
return null;
107+
}
90108
}

sechub-adapter-checkmarx/src/test/java/com/mercedesbenz/sechub/adapter/checkmarx/CheckmarxAdapterV1WireMockTest.java

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ public void when_checkmarx_has_only_unsupported_files_the_result_is_canceled() t
118118
simulateUpdateScanSettingsForProjectWereSuccessful(fetchScanSettingsResultMap, serverReturnedEngineConfigurationId);
119119

120120
/* upload */
121-
simulateUploadZipFileWasSuccesful();
121+
simulateUploadZipFileWasSuccessful();
122122

123123
/* scan start */
124124
simulateStartScanAccepted();
@@ -155,7 +155,7 @@ public void simulate_start__create_new_project_and_scan_token_expires_very_often
155155

156156
/* upload */
157157
simulateExpiredBearerTokenLeadsToLoginRequest();
158-
simulateUploadZipFileWasSuccesful();
158+
simulateUploadZipFileWasSuccessful();
159159

160160
simulateExpiredBearerTokenLeadsToLoginRequest();
161161
simulateStartScanAccepted();
@@ -175,7 +175,7 @@ public void simulate_start__create_new_project_and_scan_token_expires_very_often
175175
simulateCheckScanAvailableReturns("Finished");
176176

177177
simulateExpiredBearerTokenLeadsToLoginRequest();
178-
simulateStartReportCreationWasSuccesful();
178+
simulateStartReportCreationWasSuccessful();
179179

180180
simulateExpiredBearerTokenLeadsToLoginRequest();
181181
simulateWaitForReportResultsReturns("Something");
@@ -185,7 +185,7 @@ public void simulate_start__create_new_project_and_scan_token_expires_very_often
185185
simulateWaitForReportResultsReturns("Created");
186186

187187
simulateExpiredBearerTokenLeadsToLoginRequest();
188-
simulateDownloadReportSuccesful();
188+
simulateDownloadReportSuccessful();
189189

190190
/* execute */
191191
AdapterExecutionResult adapterResult = executeAndLogHistoryOnFailure(() -> adapterToTest.start(config, callback));
@@ -224,14 +224,14 @@ public void simulate_restart_upload_done_but_no_scan() throws Exception {
224224
simulateCheckScanAvailableReturns("Finished");
225225

226226
/* report start */
227-
simulateStartReportCreationWasSuccesful();
227+
simulateStartReportCreationWasSuccessful();
228228

229229
simulateWaitForReportResultsReturns("Something");
230230
simulateWaitForReportResultsReturns("Something");
231231
simulateWaitForReportResultsReturns("Created");
232232

233233
/* download report */
234-
simulateDownloadReportSuccesful();
234+
simulateDownloadReportSuccessful();
235235

236236
}
237237

@@ -255,13 +255,13 @@ public void simulate_restart_scan_already_exists_and_has_finished_but_no_report(
255255

256256
/* report start */
257257
/* report start */
258-
simulateStartReportCreationWasSuccesful();
258+
simulateStartReportCreationWasSuccessful();
259259

260260
simulateWaitForReportResultsReturns("Something");
261261
simulateWaitForReportResultsReturns("Created");
262262

263263
/* download report */
264-
simulateDownloadReportSuccesful();
264+
simulateDownloadReportSuccessful();
265265

266266
/* execute */
267267
AdapterExecutionResult adapterResult = executeAndLogHistoryOnFailure(() -> adapterToTest.start(config, callback));
@@ -296,7 +296,7 @@ public void simulate_restart_and_scan_already_exists_and_also_report_exists_and_
296296
simulateWaitForReportResultsReturns("Created");
297297

298298
/* download report */
299-
simulateDownloadReportSuccesful();
299+
simulateDownloadReportSuccessful();
300300

301301
/* execute */
302302
AdapterExecutionResult adapterResult = executeAndLogHistoryOnFailure(() -> adapterToTest.start(config, callback));
@@ -327,7 +327,7 @@ public void simulate_start__create_new_project_and_scan_token_expires_one_hour_a
327327
simulateUpdateScanSettingsForProjectWereSuccessful(fetchScanSettingsResultMap, serverReturnedEngineConfigurationId);
328328

329329
/* upload */
330-
simulateUploadZipFileWasSuccesful();
330+
simulateUploadZipFileWasSuccessful();
331331

332332
/* scan start */
333333
simulateStartScanAccepted();
@@ -341,14 +341,14 @@ public void simulate_start__create_new_project_and_scan_token_expires_one_hour_a
341341
simulateCheckScanAvailableReturns("Finished");
342342

343343
/* report start */
344-
simulateStartReportCreationWasSuccesful();
344+
simulateStartReportCreationWasSuccessful();
345345

346346
simulateWaitForReportResultsReturns("Something");
347347
simulateWaitForReportResultsReturns("Something");
348348
simulateWaitForReportResultsReturns("Created");
349349

350350
/* download report */
351-
simulateDownloadReportSuccesful();
351+
simulateDownloadReportSuccessful();
352352

353353
/* execute */
354354
AdapterExecutionResult adapterResult = executeAndLogHistoryOnFailure(() -> adapterToTest.start(config, callback));
@@ -361,12 +361,12 @@ public void simulate_start__create_new_project_and_scan_token_expires_one_hour_a
361361

362362
}
363363

364-
private void simulateDownloadReportSuccesful() {
364+
private void simulateDownloadReportSuccessful() {
365365
stubFor(get(urlEqualTo(history.rememberGET(apiURLSupport.nextURL("/cxrestapi/reports/sastScan/" + CHECKMARX_REPORT_ID))))
366366
.willReturn(aResponse().withStatus(HttpStatus.OK.value()).withHeader("Content-Type", APPLICATION_JSON).withBody(CONTENT_FROM_CHECKMARX)));
367367
}
368368

369-
private void simulateStartReportCreationWasSuccesful() {
369+
private void simulateStartReportCreationWasSuccessful() {
370370
LinkedHashMap<String, Object> scanReportCreation = new LinkedHashMap<>();
371371
scanReportCreation.put("reportType", "XML");
372372
scanReportCreation.put("scanId", CHECKMARX_SCAN_ID);
@@ -400,7 +400,7 @@ private void simulateStartScanAccepted() {
400400
.withBody(JSONTestUtil.toJSONContainingNullValues(startScanResult))));
401401
}
402402

403-
private void simulateUploadZipFileWasSuccesful() {
403+
private void simulateUploadZipFileWasSuccessful() {
404404
stubFor(post(urlEqualTo(history.rememberPOST(apiURLSupport.nextURL("/cxrestapi/projects/" + CHECKMARX_PROJECT_ID + "/sourceCode/attachments"))))
405405
.withHeader("content-type", containing("multipart/form-data;boundary="))
406406
.withMultipartRequestBody(aMultipart().withBody(equalTo("pseudo-zip-content")).withName("zippedSource"))
@@ -624,5 +624,4 @@ private AdapterExecutionResult executeAndLogHistoryOnFailure(Callable<AdapterExe
624624
throw e;
625625
}
626626
}
627-
628627
}

0 commit comments

Comments
 (0)