com.fortify.bugtracker.src.ssc.processor.SSCSourceProcessorSubmitVulnsToTarget.java Source code

Java tutorial

Introduction

Here is the source code for com.fortify.bugtracker.src.ssc.processor.SSCSourceProcessorSubmitVulnsToTarget.java

Source

/*******************************************************************************
 * (c) Copyright 2017 EntIT Software LLC, a Micro Focus company
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a 
 * copy of this software and associated documentation files (the 
 * "Software"), to deal in the Software without restriction, including without 
 * limitation the rights to use, copy, modify, merge, publish, distribute, 
 * sublicense, and/or sell copies of the Software, and to permit persons to 
 * whom the Software is furnished to do so, subject to the following 
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be included 
 * in all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY 
 * KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE 
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
 * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 
 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 
 * IN THE SOFTWARE.
 ******************************************************************************/
package com.fortify.bugtracker.src.ssc.processor;

import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;

import com.fortify.bugtracker.common.src.processor.ISourceProcessorSubmitVulnsToTarget;
import com.fortify.bugtracker.common.src.updater.INewIssueVulnerabilityUpdater;
import com.fortify.bugtracker.common.ssc.cli.ICLIOptionsSSC;
import com.fortify.bugtracker.common.ssc.connection.SSCConnectionFactory;
import com.fortify.bugtracker.common.ssc.json.preprocessor.enrich.SSCJSONMapEnrichWithRevisionFromDetails;
import com.fortify.bugtracker.common.ssc.json.preprocessor.filter.SSCJSONMapFilterHasBugURL;
import com.fortify.bugtracker.common.tgt.issue.TargetIssueLocatorAndFields;
import com.fortify.bugtracker.common.tgt.processor.ITargetProcessorSubmitIssues;
import com.fortify.bugtracker.src.ssc.config.SSCSourceVulnerabilitiesConfiguration;
import com.fortify.client.ssc.api.SSCBugTrackerAPI;
import com.fortify.client.ssc.api.SSCCustomTagAPI;
import com.fortify.client.ssc.api.query.builder.SSCApplicationVersionIssuesQueryBuilder;
import com.fortify.client.ssc.api.query.builder.SSCApplicationVersionIssuesQueryBuilder.QueryMode;
import com.fortify.client.ssc.connection.SSCAuthenticatingRestConnection;
import com.fortify.processrunner.cli.CLIOptionDefinition;
import com.fortify.processrunner.cli.CLIOptionDefinitions;
import com.fortify.processrunner.context.Context;
import com.fortify.processrunner.context.ContextSpringExpressionUtil;
import com.fortify.processrunner.processor.IProcessor;
import com.fortify.util.rest.json.preprocessor.filter.AbstractJSONMapFilter.MatchMode;
import com.fortify.util.rest.query.AbstractRestConnectionQueryBuilder;

/**
 * TODO Update JavaDoc?
 * <p>This {@link IProcessor} implementation combines and configures 
 * {@link SSCSourceProcessorRetrieveVulnerabilities}, {@link SSCSourceVulnerabilitiesConfiguration} 
 * and {@link ITargetProcessorSubmitIssues} (provided by the bug tracker 
 * implementation) to allow for submitting SSC vulnerabilities to bug trackers or
 * other external systems.</p> 
 * 
 * <p>This combined configuration will retrieve all open SSC vulnerabilities based on
 * configured search/filtering criteria, optionally group the vulnerabilities based on
 * a configurable grouping expression (if supported by the bug tracker implementation),
 * and then submit the grouped vulnerabilities to the bug tracker or other external system.
 * Optionally, the bug tracker issue link can be stored in SSC for each submitted 
 * vulnerability, for state management purposes (see {@link SSCSourceProcessorUpdateVulnsOnTarget}) and
 * to allow the user to navigate back and forth between SSC and bug tracker. Additional
 * custom tags to hold information about the submitted bug tracker issue can be 
 * configured as well.</p> 
 * 
 * @author Ruud Senden
 */
@Component
public class SSCSourceProcessorSubmitVulnsToTarget extends AbstractSSCSourceVulnerabilityProcessor
        implements ISourceProcessorSubmitVulnsToTarget, INewIssueVulnerabilityUpdater {
    private static final Log LOG = LogFactory.getLog(SSCSourceProcessorSubmitVulnsToTarget.class);

    @Override
    protected void addSourceCLIOptionDefinitions(CLIOptionDefinitions cliOptionDefinitions) {
        if (getConfiguration().isAddNativeBugLink()) {
            cliOptionDefinitions.add(new CLIOptionDefinition("SSC", ICLIOptionsSSC.PRP_SSC_BUG_TRACKER_USER_NAME,
                    "SSC " + getConfiguration().getAddNativeBugLinkBugTrackerName()
                            + " bug tracker user name (required if SSC bug tracker requires authentication)",
                    false));
            cliOptionDefinitions
                    .add(new CLIOptionDefinition("SSC", ICLIOptionsSSC.PRP_SSC_BUG_TRACKER_PASSWORD,
                            "SSC " + getConfiguration().getAddNativeBugLinkBugTrackerName()
                                    + " bug tracker password",
                            false).isPassword(true).dependsOnOptions(ICLIOptionsSSC.PRP_SSC_BUG_TRACKER_USER_NAME));
        }
    }

    @Override
    protected SourceVulnerabilityProcessorHelper getSourceVulnerabilityProcessorHelper() {
        return new SSCSourceVulnerabilityProcessorHelperSubmit();
    }

    private class SSCSourceVulnerabilityProcessorHelperSubmit extends SourceVulnerabilityProcessorHelperSubmit {
        @Override
        public AbstractRestConnectionQueryBuilder<?, ?> createBaseVulnerabilityQueryBuilder(Context context) {
            SSCApplicationVersionIssuesQueryBuilder builder = createSSCVulnerabilityBaseQueryBuilder(context)
                    .paramQm(QueryMode.issues).includeHidden(false).includeRemoved(false).includeSuppressed(false)
                    .paramQ(getFullSSCFilterString());
            if (getVulnerabilityProcessor().isIgnorePreviouslySubmittedIssues()) {
                builder.preProcessor(new SSCJSONMapFilterHasBugURL(MatchMode.EXCLUDE));
            }
            if (getConfiguration().isEnableRevisionWorkAround()) {
                builder.preProcessor(new SSCJSONMapEnrichWithRevisionFromDetails());
            }
            return builder;
        }

        /**
         * Get the full SSC filter string for vulnerabilities that need to be submitted to the bug tracker
         * @return
         */
        private String getFullSSCFilterString() {
            String result = getConfiguration().getFilterStringForVulnerabilitiesToBeSubmitted();
            if (getVulnerabilityProcessor().isIgnorePreviouslySubmittedIssues()
                    && StringUtils.isNotBlank(getConfiguration().getBugLinkCustomTagName())) {
                result = StringUtils.isBlank(result) ? "" : (result + " ");
                result += getConfiguration().getBugLinkCustomTagName() + ":<none>";
            }
            // SSC doesn't allow filtering on bugURL, so this is handled in createFilterForVulnerabilitiesToBeSubmitted
            return result;
        }
    }

    @SuppressWarnings("unchecked")
    @Override
    public void updateVulnerabilityStateForNewIssue(Context context, String bugTrackerName,
            TargetIssueLocatorAndFields targetIssueLocatorAndFields, Collection<Object> vulnerabilities) {
        SSCAuthenticatingRestConnection conn = SSCConnectionFactory.getConnection(context);
        String applicationVersionId = ICLIOptionsSSC.CLI_SSC_APPLICATION_VERSION_ID.getValue(context);
        Map<String, String> customTagValues = getExtraCustomTagValues(context, targetIssueLocatorAndFields,
                vulnerabilities);

        if (StringUtils.isNotBlank(getConfiguration().getBugLinkCustomTagName())) {
            customTagValues.put(getConfiguration().getBugLinkCustomTagName(),
                    targetIssueLocatorAndFields.getLocator().getDeepLink());
        }
        if (!customTagValues.isEmpty()) {
            conn.api(SSCCustomTagAPI.class).setCustomTagValues(applicationVersionId, customTagValues,
                    vulnerabilities);
            LOG.info("[SSC] Updated custom tag values for SSC vulnerabilities");
        }
        if (getConfiguration().isAddNativeBugLink()) {
            Map<String, Object> issueDetails = new HashMap<String, Object>();
            issueDetails.put("existingBugLink", targetIssueLocatorAndFields.getLocator().getDeepLink());
            List<String> issueInstanceIds = ContextSpringExpressionUtil.evaluateExpression(context, vulnerabilities,
                    "#root.![issueInstanceId]", List.class);

            SSCBugTrackerAPI bugTrackerAPI = conn.api(SSCBugTrackerAPI.class);
            if (bugTrackerAPI.isBugTrackerAuthenticationRequired(applicationVersionId)) {
                // If SSC bug tracker username/password are not specified, we use dummy values;
                // 'Add Existing Bugs' doesn't care about credentials but requires authentication
                // to work around SSC 17.20+ bugs
                String btUserName = StringUtils.defaultIfBlank(
                        context.get(ICLIOptionsSSC.PRP_SSC_BUG_TRACKER_USER_NAME, String.class), "dummy");
                String btPassword = StringUtils.defaultIfBlank(
                        context.get(ICLIOptionsSSC.PRP_SSC_BUG_TRACKER_PASSWORD, String.class), "dummy");
                bugTrackerAPI.authenticateForBugFiling(applicationVersionId, btUserName, btPassword);
            }

            conn.api(SSCBugTrackerAPI.class).fileBug(applicationVersionId, issueDetails, issueInstanceIds);
            LOG.info("[SSC] Added bug link for SSC vulnerabilities using '"
                    + getConfiguration().getAddNativeBugLinkBugTrackerName() + "' bug tracker");
        }
    }

}