Search in sources :

Example 1 with CxPropertiesBase

use of com.checkmarx.sdk.config.CxPropertiesBase in project cx-flow by checkmarx-ltd.

the class CxFlowRunner method commandLineRunner.

private void commandLineRunner(ApplicationArguments args) throws ExitThrowable {
    String bugTracker;
    String application;
    String namespace;
    String repoName;
    String repoUrl;
    String branch;
    String mergeId;
    String mergeNoteUri = null;
    int mergeProjectId = 0;
    String projectId;
    String assignee;
    List<String> emails;
    String file;
    String libFile;
    String preset;
    String team;
    String cxProject;
    String altProject;
    String altFields;
    String config;
    String scanTag;
    List<String> severity;
    List<String> cwe;
    List<String> category;
    List<String> status;
    List<String> excludeFiles;
    List<String> excludeFolders;
    ScanRequest.Repository repoType = ScanRequest.Repository.NA;
    boolean osa;
    boolean force;
    FlowOverride flowOverride = null;
    ObjectMapper mapper = new ObjectMapper();
    String uid = helperService.getShortUid();
    MDC.put(FlowConstants.MAIN_MDC_ENTRY, uid);
    if (args.containsOption("branch-create")) {
        exit(ExitCode.SUCCESS);
    }
    if (args.containsOption("branch-delete")) {
        exit(ExitCode.SUCCESS);
    }
    if (!args.containsOption("scan") && !args.containsOption(PARSE_OPTION) && !args.containsOption(BATCH_OPTION) && !args.containsOption("project") && !args.containsOption(IAST_OPTION)) {
        log.error("--scan | --parse | --batch | --iast | --project option must be specified");
        exit(1);
    }
    // override with config
    if (args.containsOption("config")) {
        config = args.getOptionValues("config").get(0);
        try {
            flowOverride = mapper.readValue(new File(config), FlowOverride.class);
        } catch (IOException e) {
            log.error("Error reading config file, ignoring...", e);
        }
    }
    /*Collect command line options (String)*/
    bugTracker = getOptionValues(args, "bug-tracker");
    file = getOptionValues(args, "f");
    libFile = getOptionValues(args, "lib-file");
    repoName = getOptionValues(args, "repo-name");
    repoUrl = getOptionValues(args, "repo-url");
    branch = getOptionValues(args, "branch");
    namespace = getOptionValues(args, "namespace");
    projectId = getOptionValues(args, "project-id");
    team = getOptionValues(args, "cx-team");
    altProject = getOptionValues(args, "alt-project");
    altFields = getOptionValues(args, "alt-fields");
    cxProject = getOptionValues(args, "cx-project");
    application = getOptionValues(args, "app");
    assignee = getOptionValues(args, "assignee");
    mergeId = getOptionValues(args, "merge-id");
    preset = getOptionValues(args, "preset");
    scanTag = getOptionValues(args, "scan-tag");
    osa = args.getOptionValues("osa") != null;
    force = args.getOptionValues("forcescan") != null;
    /*Collect command line options (List of Strings)*/
    emails = args.getOptionValues("emails");
    severity = args.getOptionValues("severity");
    category = args.getOptionValues("category");
    cwe = args.getOptionValues("cwe");
    status = args.getOptionValues("status");
    excludeFiles = args.getOptionValues("exclude-files");
    excludeFolders = args.getOptionValues("exclude-folders");
    boolean usingBitBucketCloud = args.containsOption("bb");
    boolean usingBitBucketServer = args.containsOption("bbs");
    boolean disableCertificateValidation = args.containsOption("trust-cert");
    CxPropertiesBase cxProperties = cxScannerService.getProperties();
    Map<String, String> projectCustomFields = makeCustomFieldMap(args.getOptionValues("project-custom-field"));
    Map<String, String> scanCustomFields = makeCustomFieldMap(args.getOptionValues("scan-custom-field"));
    if (((ScanUtils.empty(namespace) && ScanUtils.empty(repoName) && ScanUtils.empty(branch)) && ScanUtils.empty(application)) && !args.containsOption(BATCH_OPTION) && !args.containsOption(IAST_OPTION)) {
        log.error("Namespace/Repo/Branch or Application (app) must be provided");
        exit(1);
    }
    if (args.containsOption(IAST_OPTION) && StringUtils.isEmpty(scanTag)) {
        log.error("--scan-tag must be provided for IAST tracking");
        exit(1);
    }
    ControllerRequest controllerRequest = new ControllerRequest(severity, cwe, category, status, null);
    FilterConfiguration filter = filterFactory.getFilter(controllerRequest, flowProperties);
    // Adding default file/folder exclusions from properties if they are not provided as an override
    if (excludeFiles == null && !ScanUtils.empty(cxProperties.getExcludeFiles())) {
        excludeFiles = Arrays.asList(cxProperties.getExcludeFiles().split(","));
    }
    if (excludeFolders == null && !ScanUtils.empty(cxProperties.getExcludeFolders())) {
        excludeFolders = Arrays.asList(cxProperties.getExcludeFolders().split(","));
    }
    if (ScanUtils.empty(bugTracker)) {
        bugTracker = flowProperties.getBugTracker();
    }
    BugTracker.Type bugType = getBugTrackerType(bugTracker);
    ScanRequest.Product product;
    if (osa) {
        if (libFile == null) {
            log.error("Both vulnerabilities file (f) and libraries file (lib-file) must be provided for OSA");
            exit(1);
        }
        product = ScanRequest.Product.CXOSA;
    } else {
        product = ScanRequest.Product.CX;
    }
    if (ScanUtils.empty(preset)) {
        preset = cxProperties.getScanPreset();
    }
    BugTracker bt = null;
    String gitAuthUrl = null;
    switch(bugType) {
        case WAIT:
        case wait:
            log.info("No bug tracker will be used...waiting for scan to complete");
            bugType = BugTracker.Type.WAIT;
            bt = BugTracker.builder().type(bugType).build();
            break;
        case NONE:
            log.info("No bug tracker will be used");
            bugType = BugTracker.Type.NONE;
            bt = BugTracker.builder().type(bugType).build();
            break;
        case JIRA:
            bt = jiraPropertiesToBugTracker().type(bugType).assignee(assignee).build();
            break;
        case ADOPULL:
        case adopull:
            bugType = BugTracker.Type.ADOPULL;
            bt = BugTracker.builder().type(bugType).build();
            repoType = ScanRequest.Repository.ADO;
            if (ScanUtils.empty(namespace) || ScanUtils.empty(repoName) || ScanUtils.empty(mergeId)) {
                log.error("Namespace/Repo/MergeId must be provided for ADOPULL bug tracking");
                exit(1);
            }
            mergeNoteUri = adoProperties.getMergeNoteUri(namespace, repoName, mergeId);
            break;
        case GITHUBPULL:
        case githubpull:
            bugType = BugTracker.Type.GITHUBPULL;
            bt = BugTracker.builder().type(bugType).build();
            repoType = ScanRequest.Repository.GITHUB;
            if (ScanUtils.empty(namespace) || ScanUtils.empty(repoName) || ScanUtils.empty(mergeId)) {
                log.error("--namespace, --repo and --merge-id must be provided for GITHUBPULL bug tracking");
                exit(1);
            }
            mergeNoteUri = gitHubProperties.getMergeNoteUri(namespace, repoName, mergeId);
            repoUrl = getNonEmptyRepoUrl(namespace, repoName, repoUrl, gitHubProperties.getGitUri(namespace, repoName));
            break;
        case GITLABMERGE:
        case gitlabmerge:
            log.info("Handling GitLab merge request for project: {}, merge id: {}", projectId, mergeId);
            bugType = BugTracker.Type.GITLABMERGE;
            bt = BugTracker.builder().type(bugType).build();
            repoType = ScanRequest.Repository.GITLAB;
            if (ScanUtils.empty(projectId) || ScanUtils.empty(mergeId)) {
                log.error("--project-id and --merge-id must be provided for GITLABMERGE bug tracking");
                exit(1);
            }
            mergeNoteUri = gitLabProperties.getMergeNoteUri(projectId, mergeId);
            mergeProjectId = Integer.parseInt(projectId);
            if (!ScanUtils.empty(namespace) && !ScanUtils.empty(repoName)) {
                repoUrl = getNonEmptyRepoUrl(namespace, repoName, repoUrl, gitLabProperties.getGitUri(namespace, repoName));
            }
            break;
        case BITBUCKETPULL:
        case bitbucketserverpull:
            log.info("BitBucket Pull not currently supported from command line");
            exit(1);
            break;
        case EMAIL:
            break;
        case CUSTOM:
            log.info("Using custom bean implementation  for bug tracking");
            bt = BugTracker.builder().type(bugType).customBean(bugTracker).build();
            break;
        default:
            log.warn("No supported bug tracking type provided");
    }
    ScanRequest request = ScanRequest.builder().application(application).product(product).namespace(namespace).team(team).project(cxProject).repoName(repoName).mergeNoteUri(mergeNoteUri).repoUrl(repoUrl).repoUrlWithAuth(gitAuthUrl).repoType(repoType).branch(branch).refs(null).email(emails).incremental(cxProperties.getIncremental()).scanPreset(preset).excludeFolders(excludeFolders).excludeFiles(excludeFiles).bugTracker(bt).filter(filter).altProject(altProject).altFields(altFields).forceScan(force).disableCertificateValidation(disableCertificateValidation).cxFields(projectCustomFields).scanFields(scanCustomFields).build();
    if (projectId != null) {
        try {
            Integer repoProjectId = Integer.parseInt(projectId);
            request.setRepoProjectId(repoProjectId);
        } catch (RuntimeException e) {
            log.error("Can't parse project-id", e);
        }
    }
    request = configOverrider.overrideScanRequestProperties(flowOverride, request);
    /*Determine if BitBucket Cloud/Server is being used - this will determine formatting of URL that links to file/line in repository */
    request.setId(uid);
    if (usingBitBucketCloud) {
        request.setRepoType(ScanRequest.Repository.BITBUCKETSERVER);
    // TODO create browse code url
    } else if (usingBitBucketServer) {
        request.setRepoType(ScanRequest.Repository.BITBUCKETSERVER);
        repoUrl = getBitBuckerServerBrowseUrl(repoUrl);
        request.putAdditionalMetadata("BITBUCKET_BROWSE", repoUrl);
    } else if (bugType.equals(BugTracker.Type.GITLABMERGE)) {
        request.setRepoProjectId(mergeProjectId);
        request.putAdditionalMetadata(FlowConstants.MERGE_ID, mergeId);
    }
    try {
        if (args.containsOption(PARSE_OPTION)) {
            File f = new File(file);
            if (!f.exists()) {
                log.error("Result File not found {}", file);
                exit(ExitCode.ARGUMENT_NOT_PROVIDED);
            }
            if (osa) {
                // grab the libs file if OSA results
                File libs = new File(libFile);
                if (!libs.exists()) {
                    log.error("Library File not found {}", file);
                    exit(ExitCode.ARGUMENT_NOT_PROVIDED);
                }
                cxOsaParse(request, f, libs);
            } else {
                // SAST
                List<String> enabledScanners = flowProperties.getEnabledVulnerabilityScanners();
                if (args.containsOption("offline")) {
                    cxProperties.setOffline(true);
                }
                log.info("Processing Checkmarx result file {}", file);
                if ((bugType.equals(BugTracker.Type.CUSTOM))) {
                    if (request.getBugTracker().getCustomBean().equalsIgnoreCase("CxXml")) {
                        log.error("The CxXml bugtracker is not support for parse mode{}");
                        exit(ExitCode.BUILD_INTERRUPTED);
                    }
                }
                if (enabledScanners.contains("sast") && enabledScanners.contains("sca")) {
                    log.error("At a time only single scanner type is supported for parse mode implementation{}");
                    exit(ExitCode.BUILD_INTERRUPTED);
                }
                cxParse(request, f);
            }
        } else if (args.containsOption(BATCH_OPTION)) {
            log.info("Executing batch process");
            cxBatch(request);
        } else if (args.containsOption("project")) {
            if (ScanUtils.empty(cxProject)) {
                log.error("cx-project must be provided when --project option is used");
                exit(ExitCode.ARGUMENT_NOT_PROVIDED);
            }
            request.setCliMode(CliMode.PROJECT);
            publishLatestScanResults(request);
        } else if (args.containsOption("scan") || args.containsOption(IAST_OPTION)) {
            log.info("Executing scan process");
            request.setCliMode(CliMode.SCAN);
            // GitHub Scan with Git Clone
            if (args.containsOption("github")) {
                repoUrl = getNonEmptyRepoUrl(namespace, repoName, repoUrl, gitHubProperties.getGitUri(namespace, repoName));
                String token = gitHubProperties.getToken();
                gitAuthUrl = repoUrl.replace(Constants.HTTPS, Constants.HTTPS.concat(token).concat("@"));
                gitAuthUrl = gitAuthUrl.replace(Constants.HTTP, Constants.HTTP.concat(token).concat("@"));
                scanRemoteRepo(request, repoUrl, gitAuthUrl, branch, ScanRequest.Repository.GITHUB, args);
            } else // GitLab Scan with Git Clone
            if (args.containsOption("gitlab") && !ScanUtils.anyEmpty(namespace, repoName)) {
                repoUrl = getNonEmptyRepoUrl(namespace, repoName, repoUrl, gitLabProperties.getGitUri(namespace, repoName));
                String token = gitLabProperties.getToken();
                gitAuthUrl = repoUrl.replace(Constants.HTTPS, Constants.HTTPS_OAUTH2.concat(token).concat("@"));
                gitAuthUrl = gitAuthUrl.replace(Constants.HTTP, Constants.HTTP_OAUTH2.concat(token).concat("@"));
                scanRemoteRepo(request, repoUrl, gitAuthUrl, branch, ScanRequest.Repository.GITLAB, args);
            } else if (args.containsOption("bitbucket") && containsRepoArgs(namespace, repoName, branch)) {
                log.warn("Bitbucket git clone scan not implemented");
            } else if (args.containsOption("ado") && containsRepoArgs(namespace, repoName, branch)) {
                if (!args.containsOption(IAST_OPTION)) {
                    // Azure implement for IAST integration
                    log.warn("Azure DevOps git clone scan not implemented");
                }
            } else if (file != null) {
                scanLocalPath(request, file);
            } else {
                log.error("No valid option was provided for driving scan");
            }
            if (args.containsOption(IAST_OPTION)) {
                configureIast(request, scanTag, args);
            }
        }
    } catch (Exception e) {
        log.error("An error occurred while processing request", e);
        exit(ExitCode.BUILD_INTERRUPTED);
    }
    log.info("Completed Successfully");
    exit(ExitCode.SUCCESS);
}
Also used : CxPropertiesBase(com.checkmarx.sdk.config.CxPropertiesBase) FilterConfiguration(com.checkmarx.sdk.dto.filtering.FilterConfiguration) IOException(java.io.IOException) JiraClientException(com.checkmarx.flow.exception.JiraClientException) IOException(java.io.IOException) InvocationTargetException(java.lang.reflect.InvocationTargetException) MachinaRuntimeException(com.checkmarx.flow.exception.MachinaRuntimeException) MachinaException(com.checkmarx.flow.exception.MachinaException) MachinaRuntimeException(com.checkmarx.flow.exception.MachinaRuntimeException) File(java.io.File) ObjectMapper(com.fasterxml.jackson.databind.ObjectMapper)

Aggregations

JiraClientException (com.checkmarx.flow.exception.JiraClientException)1 MachinaException (com.checkmarx.flow.exception.MachinaException)1 MachinaRuntimeException (com.checkmarx.flow.exception.MachinaRuntimeException)1 CxPropertiesBase (com.checkmarx.sdk.config.CxPropertiesBase)1 FilterConfiguration (com.checkmarx.sdk.dto.filtering.FilterConfiguration)1 ObjectMapper (com.fasterxml.jackson.databind.ObjectMapper)1 File (java.io.File)1 IOException (java.io.IOException)1 InvocationTargetException (java.lang.reflect.InvocationTargetException)1