com.blackducksoftware.integration.hub.bamboo.tasks.HubScanTask.java Source code

Java tutorial

Introduction

Here is the source code for com.blackducksoftware.integration.hub.bamboo.tasks.HubScanTask.java

Source

/**
 * Black Duck Hub Plugin for Bamboo
 *
 * Copyright (C) 2017 Black Duck Software, Inc.
 * http://www.blackducksoftware.com/
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package com.blackducksoftware.integration.hub.bamboo.tasks;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;

import com.atlassian.bamboo.bandana.PlanAwareBandanaContext;
import com.atlassian.bamboo.build.artifact.ArtifactManager;
import com.atlassian.bamboo.build.logger.BuildLogger;
import com.atlassian.bamboo.configuration.ConfigurationMap;
import com.atlassian.bamboo.plan.PlanResultKey;
import com.atlassian.bamboo.plan.artifact.ArtifactDefinitionContext;
import com.atlassian.bamboo.plan.artifact.ArtifactDefinitionContextImpl;
import com.atlassian.bamboo.plan.artifact.ArtifactPublishingResult;
import com.atlassian.bamboo.process.EnvironmentVariableAccessor;
import com.atlassian.bamboo.security.SecureToken;
import com.atlassian.bamboo.task.TaskContext;
import com.atlassian.bamboo.task.TaskException;
import com.atlassian.bamboo.task.TaskResult;
import com.atlassian.bamboo.task.TaskResultBuilder;
import com.atlassian.bamboo.task.TaskState;
import com.atlassian.bamboo.task.TaskType;
import com.atlassian.bamboo.util.BuildUtils;
import com.atlassian.bamboo.v2.build.BuildContext;
import com.atlassian.bandana.BandanaManager;
import com.atlassian.plugin.PluginAccessor;
import com.blackducksoftware.integration.hub.api.codelocation.CodeLocationItem;
import com.blackducksoftware.integration.hub.api.codelocation.CodeLocationRequestService;
import com.blackducksoftware.integration.hub.api.item.MetaService;
import com.blackducksoftware.integration.hub.api.policy.PolicyStatusEnum;
import com.blackducksoftware.integration.hub.api.policy.PolicyStatusItem;
import com.blackducksoftware.integration.hub.api.project.version.ProjectVersionItem;
import com.blackducksoftware.integration.hub.api.project.version.ProjectVersionRequestService;
import com.blackducksoftware.integration.hub.api.scan.ScanSummaryItem;
import com.blackducksoftware.integration.hub.api.version.DistributionEnum;
import com.blackducksoftware.integration.hub.api.version.PhaseEnum;
import com.blackducksoftware.integration.hub.bamboo.HubBambooLogger;
import com.blackducksoftware.integration.hub.bamboo.HubBambooPluginHelper;
import com.blackducksoftware.integration.hub.bamboo.HubBambooUtils;
import com.blackducksoftware.integration.hub.builder.HubScanConfigBuilder;
import com.blackducksoftware.integration.hub.dataservice.cli.CLIDataService;
import com.blackducksoftware.integration.hub.dataservice.policystatus.PolicyStatusDescription;
import com.blackducksoftware.integration.hub.dataservice.report.RiskReportDataService;
import com.blackducksoftware.integration.hub.exception.HubIntegrationException;
import com.blackducksoftware.integration.hub.exception.ScanFailedException;
import com.blackducksoftware.integration.hub.global.HubServerConfig;
import com.blackducksoftware.integration.hub.rest.CredentialsRestConnection;
import com.blackducksoftware.integration.hub.rest.RestConnection;
import com.blackducksoftware.integration.hub.scan.HubScanConfig;
import com.blackducksoftware.integration.hub.scan.HubScanConfigFieldEnum;
import com.blackducksoftware.integration.hub.service.HubServicesFactory;
import com.blackducksoftware.integration.log.IntLogger;
import com.blackducksoftware.integration.phone.home.enums.ThirdPartyName;
import com.blackducksoftware.integration.util.CIEnvironmentVariables;

public class HubScanTask implements TaskType {

    private static final int DEFAULT_MAX_WAIT_TIME_MILLISEC = 5 * 60 * 1000;

    private static final int RISK_REPORT_MINIMUM_FILE_COUNT = 41;

    private static final String HUB_SCAN_TASK_ERROR = "Hub Scan Task error";

    private final static String CLI_FOLDER_NAME = "tools/HubCLI";

    public static final String HUB_RISK_REPORT_FILENAME = "hub_risk_report.json";

    private final EnvironmentVariableAccessor environmentVariableAccessor;

    private final BandanaManager bandanaManager;

    private final ArtifactManager artifactManager;

    private final PluginAccessor pluginAccessor;

    public HubScanTask(final EnvironmentVariableAccessor environmentVariableAccessor,
            final BandanaManager bandanaManager, final ArtifactManager artifactManager,
            final PluginAccessor pluginAccessor) {
        this.environmentVariableAccessor = environmentVariableAccessor;
        this.bandanaManager = bandanaManager;
        this.artifactManager = artifactManager;
        this.pluginAccessor = pluginAccessor;
    }

    @Override
    public TaskResult execute(final TaskContext taskContext) throws TaskException {
        final TaskResultBuilder resultBuilder = TaskResultBuilder.newBuilder(taskContext).success();
        TaskResult result;
        final HubBambooLogger logger = new HubBambooLogger(taskContext.getBuildLogger());
        final Map<String, String> envVars = HubBambooUtils.getInstance().getEnvironmentVariablesMap(
                environmentVariableAccessor.getEnvironment(),
                environmentVariableAccessor.getEnvironment(taskContext));

        final CIEnvironmentVariables commonEnvVars = new CIEnvironmentVariables();
        commonEnvVars.putAll(envVars);
        logger.setLogLevel(commonEnvVars);
        try {
            final HubBambooPluginHelper pluginHelper = new HubBambooPluginHelper(pluginAccessor);
            logger.alwaysLog("Initializing - Hub Bamboo Plugin : " + pluginHelper.getPluginVersion());
            final ConfigurationMap taskConfigMap = taskContext.getConfigurationMap();
            final HubServerConfig hubConfig = getHubServerConfig(logger);
            if (hubConfig == null) {
                logger.error("Please verify the correct dependent Hub configuration plugin is installed");
                logger.error("Please verify the configuration is correct if the plugin is installed.");
                result = resultBuilder.failedWithError().build();
                logTaskResult(logger, result);
                return result;
            }
            hubConfig.print(logger);

            final RestConnection restConnection = new CredentialsRestConnection(hubConfig);

            restConnection.connect();

            final HubServicesFactory services = new HubServicesFactory(restConnection);
            final MetaService metaService = services.createMetaService(logger);
            final CLIDataService cliDataService = services.createCLIDataService(logger);
            final File toolsDir = new File(HubBambooUtils.getInstance().getBambooHome(), CLI_FOLDER_NAME);

            final String thirdPartyVersion = BuildUtils.getCurrentVersion();
            final String pluginVersion = pluginHelper.getPluginVersion();
            final String shouldGenerateRiskReport = taskConfigMap
                    .get(HubScanConfigFieldEnum.GENERATE_RISK_REPORT.getKey());
            final String maxWaitTimeForRiskReport = taskConfigMap
                    .get(HubScanConfigFieldEnum.MAX_WAIT_TIME_FOR_BOM_UPDATE.getKey());
            boolean isRiskReportGenerated = false;
            long waitTimeForReport = DEFAULT_MAX_WAIT_TIME_MILLISEC;

            if (StringUtils.isNotBlank(shouldGenerateRiskReport)) {
                isRiskReportGenerated = Boolean.valueOf(shouldGenerateRiskReport);
            }

            if (StringUtils.isNotBlank(maxWaitTimeForRiskReport)) {
                waitTimeForReport = NumberUtils.toInt(maxWaitTimeForRiskReport);
                if (waitTimeForReport == 0) {
                    // 5 minutes is the default
                    waitTimeForReport = 5 * 60 * 1000;
                } else {
                    waitTimeForReport = waitTimeForReport * 60 * 1000;
                }
            } else {
                waitTimeForReport = 5 * 60 * 1000;
            }
            final HubScanConfig hubScanConfig = getScanConfig(taskConfigMap, taskContext.getWorkingDirectory(),
                    toolsDir, thirdPartyVersion, pluginVersion, logger);
            if (hubScanConfig == null) {
                result = resultBuilder.failedWithError().build();
                logTaskResult(logger, result);
                return result;
            }

            final boolean isFailOnPolicySelected = taskConfigMap
                    .getAsBoolean(HubScanConfigFieldEnum.FAIL_ON_POLICY_VIOLATION.getKey());

            List<ScanSummaryItem> scanSummaryList = null;
            try {
                scanSummaryList = cliDataService.installAndRunScan(hubConfig, hubScanConfig);

            } catch (final ScanFailedException e) {
                if (resultBuilder.getTaskState() != TaskState.SUCCESS) {
                    logger.error("Hub Scan Failed : " + e.getMessage());
                    result = resultBuilder.build();
                    logTaskResult(logger, result);
                    return result;
                }
            }
            if (!hubScanConfig.isDryRun()) {
                final ProjectVersionItem version = getProjectVersionFromScanStatus(
                        services.createCodeLocationRequestService(),
                        services.createProjectVersionRequestService(logger), metaService, scanSummaryList.get(0));

                if (isRiskReportGenerated || isFailOnPolicySelected) {
                    services.createScanStatusDataService(logger, waitTimeForReport)
                            .assertBomImportScansFinished(scanSummaryList);
                }
                if (isRiskReportGenerated) {
                    final SecureToken token = SecureToken.createFromString(
                            taskContext.getRuntimeTaskContext().get(HubBambooUtils.HUB_TASK_SECURE_TOKEN));
                    publishRiskReportFiles(logger, taskContext, token,
                            services.createRiskReportDataService(logger, waitTimeForReport), version);
                }
                if (isFailOnPolicySelected) {
                    final TaskResultBuilder policyResult = checkPolicyFailures(resultBuilder, taskContext, logger,
                            services, metaService, version, hubScanConfig.isDryRun());

                    result = policyResult.build();
                }
            } else {
                if (isRiskReportGenerated) {
                    logger.warn("Will not generate the risk report because this was a dry run scan.");
                }
                if (isFailOnPolicySelected) {
                    logger.warn("Will not run the Failure conditions because this was a dry run scan.");
                }
            }
        } catch (final Exception e) {
            logger.error(HUB_SCAN_TASK_ERROR, e);
            result = resultBuilder.failedWithError().build();
        }

        result = resultBuilder.build();
        logTaskResult(logger, result);
        return result;
    }

    private void logTaskResult(final IntLogger logger, final TaskResult result) {
        logger.info("HUB Scan Task result: " + result.getTaskState());
    }

    private ProjectVersionItem getProjectVersionFromScanStatus(
            final CodeLocationRequestService codeLocationRequestService,
            final ProjectVersionRequestService projectVersionRequestService, final MetaService metaService,
            final ScanSummaryItem scanSummaryItem) throws HubIntegrationException {
        final CodeLocationItem codeLocationItem = codeLocationRequestService
                .getItem(metaService.getFirstLink(scanSummaryItem, MetaService.CODE_LOCATION_BOM_STATUS_LINK));
        final String projectVersionUrl = codeLocationItem.getMappedProjectVersion();
        final ProjectVersionItem projectVersion = projectVersionRequestService.getItem(projectVersionUrl);
        return projectVersion;
    }

    private TaskResultBuilder checkPolicyFailures(final TaskResultBuilder resultBuilder,
            final TaskContext taskContext, final IntLogger logger, final HubServicesFactory services,
            final MetaService metaService, final ProjectVersionItem version, final boolean isDryRun) {
        try {
            if (isDryRun) {
                logger.warn("Will not run the Failure conditions because this was a dry run scan.");
                return resultBuilder.success();
            }
            final String policyStatusLink = metaService.getFirstLink(version, MetaService.POLICY_STATUS_LINK);

            final PolicyStatusItem policyStatusItem = services.createHubRequestService().getItem(policyStatusLink,
                    PolicyStatusItem.class);
            if (policyStatusItem == null) {
                logger.error("Could not find any information about the Policy status of the bom.");
                return resultBuilder.failed();
            }

            final PolicyStatusDescription policyStatusDescription = new PolicyStatusDescription(policyStatusItem);
            final String policyStatusMessage = policyStatusDescription.getPolicyStatusMessage();
            if (policyStatusItem.getOverallStatus() == PolicyStatusEnum.IN_VIOLATION) {
                logger.error(policyStatusMessage);
                return resultBuilder.failedWithError();
            }
            logger.info(policyStatusMessage);
            return resultBuilder.success();
        } catch (final HubIntegrationException e) {
            logger.error(e.getMessage(), e);
            return resultBuilder.failed();
        }
    }

    private HubServerConfig getHubServerConfig(final IntLogger logger) {
        try {
            final String hubUrl = getPersistedValue(HubConfigKeys.CONFIG_HUB_URL);
            final String hubUser = getPersistedValue(HubConfigKeys.CONFIG_HUB_USER);
            final String hubPass = getPersistedValue(HubConfigKeys.CONFIG_HUB_PASS);
            final String hubPassLength = getPersistedValue(HubConfigKeys.CONFIG_HUB_PASS_LENGTH);
            final String hubProxyUrl = getPersistedValue(HubConfigKeys.CONFIG_PROXY_HOST);
            final String hubProxyPort = getPersistedValue(HubConfigKeys.CONFIG_PROXY_PORT);
            final String hubProxyNoHost = getPersistedValue(HubConfigKeys.CONFIG_PROXY_NO_HOST);
            final String hubProxyUser = getPersistedValue(HubConfigKeys.CONFIG_PROXY_USER);
            final String hubProxyPass = getPersistedValue(HubConfigKeys.CONFIG_PROXY_PASS);
            final String hubProxyPassLength = getPersistedValue(HubConfigKeys.CONFIG_PROXY_PASS_LENGTH);

            final HubServerConfig result = HubBambooUtils.getInstance().buildConfigFromStrings(hubUrl, hubUser,
                    hubPass, hubPassLength, hubProxyUrl, hubProxyPort, hubProxyNoHost, hubProxyUser, hubProxyPass,
                    hubProxyPassLength);
            return result;
        } catch (final IllegalStateException e) {
            logger.error(e.getMessage());
            logger.debug("", e);
        }
        return null;
    }

    private HubScanConfig getScanConfig(final ConfigurationMap configMap, final File workingDirectory,
            final File toolsDir, final String thirdPartyVersion, final String pluginVersion, final IntLogger logger)
            throws IOException {
        try {
            final String project = configMap.get(HubScanConfigFieldEnum.PROJECT.getKey());
            final String version = configMap.get(HubScanConfigFieldEnum.VERSION.getKey());
            final String phase = configMap.get(HubScanConfigFieldEnum.PHASE.getKey());
            final String distribution = configMap.get(HubScanConfigFieldEnum.DISTRIBUTION.getKey());

            final String dryRun = configMap.get(HubScanConfigFieldEnum.DRY_RUN.getKey());
            final String cleanupLogsOnSuccess = configMap
                    .get(HubScanConfigFieldEnum.CLEANUP_LOGS_ON_SUCCESS.getKey());

            final String excludePatternsConfig = configMap.get(HubScanConfigFieldEnum.EXCLUDE_PATTERNS.getKey());

            final String[] excludePatterns = HubBambooUtils.getInstance()
                    .createExcludePatterns(excludePatternsConfig);

            final String scanMemory = configMap.get(HubScanConfigFieldEnum.SCANMEMORY.getKey());
            final String codeLocationName = configMap.get(HubScanConfigFieldEnum.CODE_LOCATION_ALIAS.getKey());
            final String targets = configMap.get(HubScanConfigFieldEnum.TARGETS.getKey());

            final String hubWorkspaceCheckString = getPersistedValue(HubConfigKeys.CONFIG_HUB_WORKSPACE_CHECK);

            Boolean hubWorkspaceCheck = true;
            if (StringUtils.isNotBlank(hubWorkspaceCheckString)) {
                hubWorkspaceCheck = Boolean.valueOf(hubWorkspaceCheckString);
            }

            final List<String> scanTargets = HubBambooUtils.getInstance().createScanTargetPaths(targets,
                    workingDirectory);

            if (scanTargets.isEmpty()) {
                // no targets specified assume the working directory.
                scanTargets.add(workingDirectory.getCanonicalPath());
            }

            final HubScanConfigBuilder hubScanConfigBuilder = new HubScanConfigBuilder();
            hubScanConfigBuilder.setProjectName(project);
            hubScanConfigBuilder.setVersion(version);
            hubScanConfigBuilder.setPhase(PhaseEnum.getPhaseByDisplayValue(phase).name());
            hubScanConfigBuilder
                    .setDistribution(DistributionEnum.getDistributionByDisplayValue(distribution).name());
            hubScanConfigBuilder.setWorkingDirectory(workingDirectory);
            hubScanConfigBuilder.setDryRun(Boolean.valueOf(dryRun));
            hubScanConfigBuilder.setCleanupLogsOnSuccess(Boolean.valueOf(cleanupLogsOnSuccess));
            hubScanConfigBuilder.setScanMemory(scanMemory);
            hubScanConfigBuilder.addAllScanTargetPaths(scanTargets);
            hubScanConfigBuilder.setExcludePatterns(excludePatterns);
            hubScanConfigBuilder.setToolsDir(toolsDir);
            hubScanConfigBuilder.setThirdPartyName(ThirdPartyName.BAMBOO);
            hubScanConfigBuilder.setThirdPartyVersion(thirdPartyVersion);
            hubScanConfigBuilder.setPluginVersion(pluginVersion);
            hubScanConfigBuilder.setCodeLocationAlias(codeLocationName);
            if (hubWorkspaceCheck) {
                hubScanConfigBuilder.enableScanTargetPathsWithinWorkingDirectoryCheck();
            }
            return hubScanConfigBuilder.build();
        } catch (final IllegalStateException e) {
            logger.error(e.getMessage());
            logger.debug("", e);
        }
        return null;
    }

    private String getPersistedValue(final String key) {
        return (String) bandanaManager.getValue(PlanAwareBandanaContext.GLOBAL_CONTEXT, key);
    }

    private void publishRiskReportFiles(final IntLogger logger, final TaskContext taskContext,
            final SecureToken token, final RiskReportDataService riskReportDataService,
            final ProjectVersionItem version) {

        final BuildContext buildContext = taskContext.getBuildContext();
        final PlanResultKey planResultKey = buildContext.getPlanResultKey();
        final BuildLogger buildLogger = taskContext.getBuildLogger();

        try {
            final File baseDirectory = new File(taskContext.getWorkingDirectory(),
                    HubBambooUtils.HUB_RISK_REPORT_ARTIFACT_NAME);
            riskReportDataService.createRiskReportFiles(baseDirectory, version);
            final Map<String, String> config = new HashMap<>();
            final ArtifactDefinitionContext artifact = createArtifactDefContext(token);
            final ArtifactPublishingResult publishResult = artifactManager.publish(buildLogger, planResultKey,
                    baseDirectory, artifact, config, RISK_REPORT_MINIMUM_FILE_COUNT);
            if (!publishResult.shouldContinueBuild()) {
                logger.error("Could not publish the artifacts for the Risk Report");
            }
            cleanupReportFiles(baseDirectory);
        } catch (final HubIntegrationException ex) {
            logger.error("Could not publish the Risk Report", ex);
        }
    }

    private void cleanupReportFiles(final File file) {
        if (file.isDirectory()) {
            for (final File subFile : file.listFiles()) {
                cleanupReportFiles(subFile);
            }
        }
        file.delete();
    }

    private ArtifactDefinitionContextImpl createArtifactDefContext(final SecureToken token) {
        final ArtifactDefinitionContextImpl artifact = new ArtifactDefinitionContextImpl(
                HubBambooUtils.HUB_RISK_REPORT_ARTIFACT_NAME, false, token);
        artifact.setCopyPattern("**/*");
        return artifact;
    }
}