From 67b75068fde8dc8ce6c357fc4f9214a744d631ae Mon Sep 17 00:00:00 2001 From: itsKedar <37594766+itsKedar@users.noreply.github.com> Date: Tue, 10 Dec 2024 11:32:42 +0530 Subject: [PATCH] Added validate branch before config as code (#1405) * added validate branch before config as code * added mock for branch validation --- .../checkmarx/flow/service/GitHubService.java | 44 +++++++++++++++---- .../cxconfig/ConfigAsCodeBranchSteps.java | 20 ++++++++- 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/src/main/java/com/checkmarx/flow/service/GitHubService.java b/src/main/java/com/checkmarx/flow/service/GitHubService.java index 4d7bf12da..8f970d2e1 100644 --- a/src/main/java/com/checkmarx/flow/service/GitHubService.java +++ b/src/main/java/com/checkmarx/flow/service/GitHubService.java @@ -26,7 +26,6 @@ import com.checkmarx.sdk.ShardManager.ShardSession; import com.checkmarx.sdk.ShardManager.ShardSessionTracker; import com.checkmarx.sdk.config.CxProperties; -import com.checkmarx.sdk.config.CxPropertiesBase; import com.checkmarx.sdk.dto.cx.CxProject; import com.checkmarx.sdk.dto.sast.CxConfig; import com.checkmarx.sdk.dto.ScanResults; @@ -42,10 +41,7 @@ import org.json.JSONException; import org.json.JSONObject; import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.http.HttpEntity; -import org.springframework.http.HttpHeaders; -import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; +import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestClientException; @@ -54,8 +50,6 @@ import javax.naming.ConfigurationException; import java.io.IOException; -import java.net.MalformedURLException; -import java.net.URL; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.*; @@ -84,6 +78,7 @@ public class GitHubService extends RepoService { private final CxClient cxService; private static final String FILE_CONTENT = "/{namespace}/{repo}/contents/{config}?ref={branch}"; + private static final String VALIDATE_BRANCH ="/{namespace}/{repo}/branches/{branch}"; private static final String LANGUAGE_TYPES = "/{namespace}/{repo}/languages"; private static final String REPO_CONTENT = "/{namespace}/{repo}/contents?ref={branch}"; @@ -560,9 +555,13 @@ public CxConfig getCxConfigOverride(ScanRequest request) { private CxConfig loadConfigAsCode(String filename, ScanRequest request) { CxConfig result = null; - + String fileContent = null; String effectiveBranch = determineConfigAsCodeBranch(request); - String fileContent = downloadFileContent(filename, request, effectiveBranch); + if (!validateBranch( effectiveBranch,request )) { + log.warn("Branch '{}' does not exist", effectiveBranch); + return null; // Exit early if the branch doesn't exist + } + fileContent = downloadFileContent(filename, request, effectiveBranch); if (fileContent == null) { log.warn(HTTP_BODY_IS_NULL); } else { @@ -579,6 +578,33 @@ private CxConfig loadConfigAsCode(String filename, ScanRequest request) { return result; } + private boolean validateBranch(String branch, ScanRequest request) { + ResponseEntity response = null; + + if (StringUtils.isNotEmpty(branch)) { + log.info("validating branch if exists..."); + HttpHeaders headers = createAuthHeaders(request); + String urlTemplate = scmConfigOverrider.determineConfigApiUrl(properties, request).concat(VALIDATE_BRANCH); + try { + response = restTemplate.exchange( + urlTemplate, + HttpMethod.GET, + new HttpEntity<>(headers), + String.class, + request.getNamespace(), + request.getRepoName(), + branch); + } catch (HttpClientErrorException e) { + if(e.getStatusCode().value()!=404){ + log.error("Error occurred while validating branch. Http Error {} ", e.getStatusCode()); + } + } + } else { + log.warn("Unable to validate branch"); + } + return response != null && response.getStatusCode().value() == 200; + } + private String downloadFileContent(String filename, ScanRequest request, String branch) { ResponseEntity response = null; diff --git a/src/test/java/com/checkmarx/flow/cucumber/integration/cxconfig/ConfigAsCodeBranchSteps.java b/src/test/java/com/checkmarx/flow/cucumber/integration/cxconfig/ConfigAsCodeBranchSteps.java index a71012feb..8ebdabf1e 100644 --- a/src/test/java/com/checkmarx/flow/cucumber/integration/cxconfig/ConfigAsCodeBranchSteps.java +++ b/src/test/java/com/checkmarx/flow/cucumber/integration/cxconfig/ConfigAsCodeBranchSteps.java @@ -27,7 +27,7 @@ @RequiredArgsConstructor public class ConfigAsCodeBranchSteps { private static final int BRANCH_ARGUMENT_INDEX = 7; - + private static final int BRANCH_ARGUMENT_INDEX1 = 6; private final GitHubProperties gitHubProperties; private final FlowProperties flowProperties; private final CxProperties cxProperties; @@ -57,6 +57,22 @@ public void githubRepoDefaultBranchIs(String defaultBranch) { public void githubNotifiesCxFlow(String srcBranch) { log.info("Creating RestTemplate mock."); RestTemplate restTemplateMock = mock(RestTemplate.class); + + //added mock for branch validation + when(restTemplateMock.exchange( + anyString(), // Match any URL + eq(HttpMethod.GET), // Match GET method + any(HttpEntity.class), // Match any HttpEntity + eq(String.class), // Match response type + anyString(), // Match namespace + anyString(), // Match repoName + anyString() // Match branch + )).thenAnswer(invocation ->{ + assertEquals(BRANCH_ARGUMENT_INDEX1 + 1, invocation.getArguments().length, + "Unexpected argument count for the restTemplate call."); + actualBranch = invocation.getArgument(BRANCH_ARGUMENT_INDEX1); + return new ResponseEntity<>(actualBranch, HttpStatus.OK);}); + when(gettingFileFromRepo(restTemplateMock)).thenAnswer(this::interceptConfigAsCodeBranch); PullEvent pullEvent = CxConfigSteps.createPullEventDto(srcBranch, defaultBranch, gitHubProperties); @@ -116,6 +132,6 @@ private Object interceptConfigAsCodeBranch(InvocationOnMock invocation) { "Unexpected argument count for the restTemplate call."); actualBranch = invocation.getArgument(BRANCH_ARGUMENT_INDEX); - return null; + return new ResponseEntity<>(actualBranch, HttpStatus.OK); } }