Skip to content

Commit

Permalink
Bitbucket (Cloud & Server) Support for Config-as-Code and Auto Profil…
Browse files Browse the repository at this point in the history
…ing. (#380)

* Added 'Config as code' support for Bitbucket Cloud & Bitbucket Server.

* Added support for Auto Profiling within Bitbucket Cloud & Bitbucket Server.
  • Loading branch information
Mithilesh Pawar authored Aug 12, 2020
1 parent b03b7fa commit a9f8ee8
Show file tree
Hide file tree
Showing 15 changed files with 967 additions and 196 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,44 +3,45 @@
import com.checkmarx.flow.config.BitBucketProperties;
import com.checkmarx.flow.config.FlowProperties;
import com.checkmarx.flow.config.JiraProperties;
import com.checkmarx.flow.dto.*;
import com.checkmarx.flow.dto.BugTracker;
import com.checkmarx.flow.dto.ControllerRequest;
import com.checkmarx.flow.dto.EventResponse;
import com.checkmarx.flow.dto.ScanRequest;
import com.checkmarx.flow.dto.bitbucket.*;
import com.checkmarx.flow.exception.InvalidTokenException;
import com.checkmarx.flow.service.ConfigurationOverrider;
import com.checkmarx.flow.service.FilterFactory;
import com.checkmarx.flow.service.FlowService;
import com.checkmarx.flow.service.HelperService;
import com.checkmarx.flow.service.*;
import com.checkmarx.flow.utils.HTMLHelper;
import com.checkmarx.flow.utils.ScanUtils;
import com.checkmarx.sdk.config.Constants;
import com.checkmarx.sdk.config.CxProperties;
import com.checkmarx.sdk.dto.CxConfig;
import com.checkmarx.sdk.dto.filtering.FilterConfiguration;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping(value = "/" )
@RequestMapping(value = "/")
public class BitbucketCloudController extends WebhookController {

private static final String EVENT = "X-Event-Key";
private static final String PUSH = EVENT + "=repo:push";
private static final String MERGE = EVENT + "=pullrequest:created";
private static final Logger log = org.slf4j.LoggerFactory.getLogger(BitbucketCloudController.class);

private final FlowProperties flowProperties;
private final BitBucketProperties properties;
private final CxProperties cxProperties;
private final JiraProperties jiraProperties;
private final FlowService flowService;
private final HelperService helperService;
private final BitBucketService bitbucketService;
private final FilterFactory filterFactory;
private final ConfigurationOverrider configOverrider;

Expand All @@ -54,18 +55,17 @@ public ResponseEntity<EventResponse> pushRequest(
ControllerRequest controllerRequest,
@RequestParam(value = "token") String token

){
) {
String uid = helperService.getShortUid();
MDC.put("cx", uid);
validateBitBucketRequest(token);
log.info("Processing BitBucket MERGE request");
FlowOverride o = ScanUtils.getMachinaOverride(controllerRequest.getOverride());
controllerRequest = ensureNotNull(controllerRequest);

try {
Repository repository = body.getRepository();
String app = repository.getName();
if(!ScanUtils.empty(controllerRequest.getApplication())){
if (!ScanUtils.empty(controllerRequest.getApplication())) {
app = controllerRequest.getApplication();
}

Expand All @@ -74,18 +74,19 @@ public ResponseEntity<EventResponse> pushRequest(
bugType = ScanUtils.getBugTypeEnum(controllerRequest.getBug(), flowProperties.getBugTrackerImpl());
}

if(controllerRequest.getAppOnly() != null){
if (controllerRequest.getAppOnly() != null) {
flowProperties.setTrackApplicationOnly(controllerRequest.getAppOnly());
}

if(ScanUtils.empty(product)){
if (ScanUtils.empty(product)) {
product = ScanRequest.Product.CX.getProduct();
}
ScanRequest.Product p = ScanRequest.Product.valueOf(product.toUpperCase(Locale.ROOT));
Pullrequest pullRequest = body.getPullrequest();
String currentBranch = pullRequest.getSource().getBranch().getName();
String targetBranch = pullRequest.getDestination().getBranch().getName();
List<String> branches = getBranches(controllerRequest, flowProperties);
String hash = pullRequest.getSource().getCommit().getHash();

BugTracker bt = ScanUtils.getBugTracker(controllerRequest.getAssignee(), bugType, jiraProperties, controllerRequest.getBug());

Expand All @@ -97,7 +98,7 @@ public ResponseEntity<EventResponse> pushRequest(
String mergeEndpoint = pullRequest.getLinks().getComments().getHref();

String scanPreset = cxProperties.getScanPreset();
if(!ScanUtils.empty(controllerRequest.getPreset())){
if (!ScanUtils.empty(controllerRequest.getPreset())) {
scanPreset = controllerRequest.getPreset();
}

Expand All @@ -106,7 +107,7 @@ public ResponseEntity<EventResponse> pushRequest(
.product(p)
.project(controllerRequest.getProject())
.team(controllerRequest.getTeam())
.namespace(repository.getOwner().getDisplayName().replace(" ","_"))
.namespace(repository.getOwner().getDisplayName().replace(" ", "_"))
.repoName(repository.getName())
.repoUrl(gitUrl)
.repoUrlWithAuth(gitUrl.replace(Constants.HTTPS, Constants.HTTPS.concat(properties.getToken()).concat("@")))
Expand All @@ -122,10 +123,11 @@ public ResponseEntity<EventResponse> pushRequest(
.excludeFiles(controllerRequest.getExcludeFiles())
.bugTracker(bt)
.filter(filter)
.hash(hash)
.build();

request = configOverrider.overrideScanRequestProperties(o, request);
request.putAdditionalMetadata(HTMLHelper.WEB_HOOK_PAYLOAD, body.toString());
fillRequestWithAdditionalData(request, repository, body.toString());
checkForConfigAsCode(request);
request.setId(uid);

if (helperService.isBranch2Scan(request, branches)) {
Expand All @@ -149,36 +151,35 @@ public ResponseEntity<EventResponse> pushRequest(
ControllerRequest controllerRequest,
@RequestParam(value = "token") String token

){
) {
String uid = helperService.getShortUid();
MDC.put("cx", uid);
validateBitBucketRequest(token);
controllerRequest = ensureNotNull(controllerRequest);

FlowOverride o = ScanUtils.getMachinaOverride(controllerRequest.getOverride());

try {
Repository repository = body.getRepository();
String app = repository.getName();
if(!ScanUtils.empty(controllerRequest.getApplication())){
if (!ScanUtils.empty(controllerRequest.getApplication())) {
app = controllerRequest.getApplication();
}

//set the default bug tracker as per yml
setBugTracker(flowProperties, controllerRequest);
BugTracker.Type bugType = ScanUtils.getBugTypeEnum(controllerRequest.getBug(), flowProperties.getBugTrackerImpl());

if(controllerRequest.getAppOnly() != null){
if (controllerRequest.getAppOnly() != null) {
flowProperties.setTrackApplicationOnly(controllerRequest.getAppOnly());
}

if(ScanUtils.empty(product)){
if (ScanUtils.empty(product)) {
product = ScanRequest.Product.CX.getProduct();
}
ScanRequest.Product p = ScanRequest.Product.valueOf(product.toUpperCase(Locale.ROOT));
List<Change> changeList = body.getPush().getChanges();
List<Change> changeList = body.getPush().getChanges();
String currentBranch = changeList.get(0).getNew().getName();
List<String> branches = getBranches(controllerRequest, flowProperties);
String hash = changeList.get(0).getNew().getTarget().getHash();

BugTracker bt = ScanUtils.getBugTracker(controllerRequest.getAssignee(), bugType, jiraProperties, controllerRequest.getBug());

Expand All @@ -189,10 +190,10 @@ public ResponseEntity<EventResponse> pushRequest(
/*Determine emails*/
List<String> emails = new ArrayList<>();

for(Change ch: changeList){
for(Commit c: ch.getCommits()){
for (Change ch : changeList) {
for (Commit c : ch.getCommits()) {
String author = c.getAuthor().getRaw();
if(!ScanUtils.empty(author)){
if (!ScanUtils.empty(author)) {
emails.add(author);
}
}
Expand All @@ -201,7 +202,7 @@ public ResponseEntity<EventResponse> pushRequest(
String gitUrl = repository.getLinks().getHtml().getHref().concat(".git");

String scanPreset = cxProperties.getScanPreset();
if(!ScanUtils.empty(controllerRequest.getPreset())){
if (!ScanUtils.empty(controllerRequest.getPreset())) {
scanPreset = controllerRequest.getPreset();
}

Expand All @@ -210,7 +211,7 @@ public ResponseEntity<EventResponse> pushRequest(
.product(p)
.project(controllerRequest.getProject())
.team(controllerRequest.getTeam())
.namespace(repository.getOwner().getDisplayName().replace(" ","_"))
.namespace(repository.getOwner().getDisplayName().replace(" ", "_"))
.repoName(repository.getName())
.repoUrl(gitUrl)
.repoUrlWithAuth(gitUrl.replace(Constants.HTTPS, Constants.HTTPS.concat(properties.getToken()).concat("@")))
Expand All @@ -224,10 +225,11 @@ public ResponseEntity<EventResponse> pushRequest(
.excludeFiles(controllerRequest.getExcludeFiles())
.bugTracker(bt)
.filter(filter)
.hash(hash)
.build();

request = configOverrider.overrideScanRequestProperties(o, request);
request.putAdditionalMetadata(HTMLHelper.WEB_HOOK_PAYLOAD, body.toString());
fillRequestWithAdditionalData(request, repository, body.toString());
checkForConfigAsCode(request);
request.setId(uid);

if (helperService.isBranch2Scan(request, branches)) {
Expand All @@ -242,12 +244,24 @@ public ResponseEntity<EventResponse> pushRequest(
/**
* Token/Credential validation
*/
private void validateBitBucketRequest(String token){
private void validateBitBucketRequest(String token) {
log.info("Validating BitBucket request token");
if(!properties.getWebhookToken().equals(token)){
if (!properties.getWebhookToken().equals(token)) {
log.error("BitBucket request token validation failed");
throw new InvalidTokenException();
}
log.info("Validation successful");
}

private void checkForConfigAsCode(ScanRequest request) {
CxConfig cxConfig = bitbucketService.getCxConfigOverride(request);
configOverrider.overrideScanRequestProperties(cxConfig, request);
}

private void fillRequestWithAdditionalData(ScanRequest request, Repository repository, String hookPayload) {
String repoSelfUrl = repository.getLinks().getSelf().getHref();
request.putAdditionalMetadata(BitBucketService.REPO_SELF_URL, repoSelfUrl);
request.putAdditionalMetadata(HTMLHelper.WEB_HOOK_PAYLOAD, hookPayload);
}

}
Loading

0 comments on commit a9f8ee8

Please sign in to comment.