Package com.denimgroup.threadfix.webapp.controller.rest

Source Code of com.denimgroup.threadfix.webapp.controller.rest.ScanQueueTaskRestController$RestAuthenticationFailedException

////////////////////////////////////////////////////////////////////////
//
//     Copyright (c) 2009-2014 Denim Group, Ltd.
//
//     The contents of this file are subject to the Mozilla Public 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.mozilla.org/MPL/
//
//     Software distributed under the License is distributed on an "AS IS"
//     basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
//     License for the specific language governing rights and limitations
//     under the License.
//
//     The Original Code is ThreadFix.
//
//     The Initial Developer of the Original Code is Denim Group, Ltd.
//     Portions created by Denim Group, Ltd. are Copyright (C)
//     Denim Group, Ltd. All Rights Reserved.
//
//     Contributor(s): Denim Group, Ltd.
//
////////////////////////////////////////////////////////////////////////

package com.denimgroup.threadfix.webapp.controller.rest;

import com.denimgroup.threadfix.data.entities.Application;
import com.denimgroup.threadfix.data.entities.Document;
import com.denimgroup.threadfix.data.entities.ScanQueueTask;
import com.denimgroup.threadfix.data.entities.Task;
import com.denimgroup.threadfix.data.ScanCheckResultBean;
import com.denimgroup.threadfix.data.ScanImportStatus;
import com.denimgroup.threadfix.importer.interop.ScanTypeCalculationService;
import com.denimgroup.threadfix.remote.response.RestResponse;
import com.denimgroup.threadfix.service.*;
import com.denimgroup.threadfix.service.enterprise.EnterpriseTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("/rest/tasks/")
public class ScanQueueTaskRestController extends RestController {
 
  public final static String OPERATION_QUEUE_SCAN = "queueScan",
      OPERATION_TASK_STATUS_UPDATE = "taskStatusUpdate",
        OPERATION_COMPLETE_TASK = "completeTask",
        OPERATION_FAIL_TASK = "failTask",
        OPERATION_REQUEST_TASK = "requestTask",
        OPERATION_SET_TASK_CONFIG = "setTaskConfig";

  public final static String TASK_KEY_SUCCESS = "Secure task key was accepted.";
  public final static String TASK_KEY_NOT_FOUND_ERROR = "No secure task key found error.";
  public final static String TASK_KEY_ERROR = "Secure task key was not recognized.";

    @Autowired
  private DocumentService documentService;
    @Autowired(required = false)
  private ScanQueueService scanQueueService;
    @Autowired
  private ScanTypeCalculationService scanTypeCalculationService;
    @Autowired
  private ScanService scanService;
    @Autowired
  private ScanMergeService scanMergeService;

    private boolean checkKeyAndEnterprise(HttpServletRequest request, String methodName)
            throws RestAuthenticationFailedException {
        String result = checkKey(request, methodName);
        if (!result.equals(API_KEY_SUCCESS)) {
            throw new RestAuthenticationFailedException(result);
        }

        if (!EnterpriseTest.isEnterprise()) {
            throw new RestAuthenticationFailedException(EnterpriseTest.ENTERPRISE_FEATURE_ERROR);
        }

        return true;
    }

    class RestAuthenticationFailedException extends Exception {
        public RestAuthenticationFailedException(String message) {
            super(message);
        }
    }

  /**
   * Queue a new scan
   *
     * @see com.denimgroup.threadfix.remote.ThreadFixRestClient#queueScan(String, String)
   */
  @RequestMapping(headers="Accept=application/json", value="queueScan", method=RequestMethod.POST)
  public @ResponseBody RestResponse<ScanQueueTask> queueScan(HttpServletRequest request,
      @RequestParam("applicationId") int applicationId,
      @RequestParam("scannerType") String scannerType) {

    log.info("Received REST request for a queueing a new " + scannerType
          + " scan for applicationId " + applicationId);

        try {
            checkKeyAndEnterprise(request, OPERATION_QUEUE_SCAN);
        } catch (RestAuthenticationFailedException e) {
            return RestResponse.failure(e.getMessage());
        }

    ScanQueueTask task = scanQueueService.queueScan(applicationId, scannerType);
   
    return RestResponse.success(task);
  }
 
  /**
   * TODO - Add scanner versions and OS/version to the incoming parameters
   * TODO move to CLI library
     *
     * @see com.denimgroup.threadfix.remote.ThreadFixRestClient#requestTask(String, String)
   * @param request
   * @param scanners comma-separated list of scanners available from the agent
   * @param agentConfig information about the agent's environment
   * @return
   */
  @RequestMapping(headers="Accept=application/json", value="requestTask", method=RequestMethod.POST)
  public @ResponseBody RestResponse<Task> requestTask(HttpServletRequest request,
      @RequestParam("scanners") String scanners,
      @RequestParam("agentConfig") String agentConfig) {

    log.info("Received a REST request to get a scan to run");

        try {
            checkKeyAndEnterprise(request, OPERATION_REQUEST_TASK);
        } catch (RestAuthenticationFailedException e) {
            return RestResponse.failure(e.getMessage());
        }

    String secureTaskKey = this.apiKeyService.generateNewSecureRandomKey();

        Task returnTask = null;
        String errorMessage = null;

        try {
            returnTask = this.scanQueueService.requestTask(scanners, agentConfig, secureTaskKey);
            if (returnTask == null) {
                log.info("No exception was thrown and we didn't get a return task from ScanQueueService.requestTask.");
                errorMessage = "No task found.";
            }
        } catch (ScanQueueTaskConfigException e) {
            errorMessage = e.getMessage();
            log.error("Exception thrown while trying to get task information. Message: " + e.getMessage());
        }

        if (returnTask == null) {
            return RestResponse.failure(errorMessage);
        } else {
            return RestResponse.success(returnTask);
        }
  }

    /**
     *
     * @see com.denimgroup.threadfix.remote.ThreadFixRestClient#taskStatusUpdate(String, String)
     *
     * @param request
     * @param scanQueueTaskId
     * @param message
     * @return
     */
  @RequestMapping(headers="Accept=application/json", value="taskStatusUpdate", method=RequestMethod.POST)
  public @ResponseBody RestResponse<String> taskStatusUpdate(HttpServletRequest request,
      @RequestParam("scanQueueTaskId") int scanQueueTaskId,
      @RequestParam("message") String message) {

    log.info("Received a REST request to update the status of scan " + scanQueueTaskId);

        try {
            checkKeyAndEnterprise(request, OPERATION_TASK_STATUS_UPDATE);
        } catch (RestAuthenticationFailedException e) {
            return RestResponse.failure(e.getMessage());
        }
   
    if (this.scanQueueService.taskStatusUpdate(scanQueueTaskId, message)) {
            return RestResponse.success("Successfully updated ScanQueueTask");
        } else {
            return RestResponse.failure("Failed to update the ScanQueueTask");
        }
  }

    /**
     * @see com.denimgroup.threadfix.remote.ThreadFixRestClient#setTaskConfig(String, String, String)
     */
  @RequestMapping(headers="Accept=application/json", value="setTaskConfig", method=RequestMethod.POST)
  public @ResponseBody RestResponse<String> setTaskConfig(HttpServletRequest request,
      @RequestParam("appId") int appId,
      @RequestParam("scannerType") String scannerType,
      @RequestParam("file") MultipartFile file) {

        try {
            checkKeyAndEnterprise(request, OPERATION_SET_TASK_CONFIG);
        } catch (RestAuthenticationFailedException e) {
            return RestResponse.failure(e.getMessage());
        }

    if(!ScanQueueTask.validateScanner(scannerType)) {
            String message = "Bad scanner type of: " + scannerType + " provided. Will not save scan config.";
      log.warn(message);
            return RestResponse.failure(message);
    } else {
      String filename = ScanQueueTask.makeScanAgentConfigFileName(scannerType);
      Document document = this.documentService.saveFileToApp(appId, file, filename);
            String returnedFilename = document == null ? null : document.getName();

      log.debug("Filename of: " + filename + " resulted in final filename of: " + returnedFilename);
            String message = "Scan configuration for scanner: " + scannerType + " saved for appId: " + appId;
      log.info(message);
      return RestResponse.success(message);
    }
  }
 
  /**
   *  Allows a remote ScanAgent to notify the server that a task has been completed successfully and
   *  provide the results from the scanning.
   *
     * @see com.denimgroup.threadfix.remote.ThreadFixRestClient#completeTask(String, String, String)
   *  @param scanQueueTaskId id for the ScanQueueTask
   *  @param file result file from the scanning operation
   */
  @RequestMapping(headers="Accept=application/json", value="completeTask", method=RequestMethod.POST)
  public @ResponseBody RestResponse<ScanQueueTask> completeTask(HttpServletRequest request,
      @RequestParam("scanQueueTaskId") int scanQueueTaskId,
      @RequestParam("file") MultipartFile file) {
   
    log.info("Received REST request to complete scan queue task: " + scanQueueTaskId);

        try {
            checkKeyAndEnterprise(request, OPERATION_COMPLETE_TASK);
        } catch (RestAuthenticationFailedException e) {
            return RestResponse.failure(e.getMessage());
        }
   
    String result = checkTaskKey(request, scanQueueTaskId);
    if (!result.equals(TASK_KEY_SUCCESS)) {
      return RestResponse.failure(result);
    }
       
    ScanQueueTask myTask = this.scanQueueService.retrieveById(scanQueueTaskId);
    Application taskApp = myTask.getApplication();
   
    //  TODO - Add some checking so you can't just upload any file as the result of a specific scanner's task
    //  For now, passing NULL should force the calculation
    Integer myChannelId = scanTypeCalculationService.calculateScanType(taskApp.getId(), file, null);
   
    try {
      String fileName = scanTypeCalculationService.saveFile(myChannelId, file);
     
      ScanCheckResultBean returnValue = scanService.checkFile(myChannelId, fileName);
     
      if (ScanImportStatus.SUCCESSFUL_SCAN == returnValue.getScanCheckResult()) {
        scanMergeService.saveRemoteScanAndRun(myChannelId, fileName);
        //  Scan has been saved. Let's update the ScanQueueTask
        this.scanQueueService.completeTask(scanQueueTaskId);
        log.info("Results from scan queue task: " + myTask.getId() + " saved successfully.");
        return RestResponse.success(myTask);
      } else if (ScanImportStatus.EMPTY_SCAN_ERROR == returnValue.getScanCheckResult()) {
        String message = "Task appeared to complete successfully, but results provided were empty.";
        this.scanQueueService.failTask(scanQueueTaskId, message);
        log.warn("When saving scan queue task: " + myTask.getId() + ": " + message);
        return RestResponse.failure(message);
      } else {
        String message = "Task appeared to complete successfully, but the scan upload attempt returned this message: " + returnValue.getScanCheckResult();
        this.scanQueueService.failTask(scanQueueTaskId, message);
        log.warn("When saving scan queue task: " + myTask.getId() + ": " + message);
        return RestResponse.failure(message);
      }
    } catch (Exception e) {
      //  Something went wrong trying to save the file. Mark the scan as a failure.
      String message = "Exception thrown while trying to save scan.";
      String longMessage = message + " Message was : " + e.getMessage();
      this.scanQueueService.failTask(scanQueueTaskId, longMessage);
      log.error(longMessage, e);
      return RestResponse.failure(message);
    }
  }
 
  /**
   * Allows a remote ScanAgent to notify the server that a task has failed and provide a reason for the failure.
   *
     * @see com.denimgroup.threadfix.remote.ThreadFixRestClient#failTask(String, String, String)
   *  @param scanQueueTaskId id for the ScanQueueTask to fail
   *  @param message scanagent-provided reason for the scan failure
   *  @return true if the scan failure was accepted and noted, false if some sort of error occurred
   */
  @RequestMapping(headers="Accept=application/json", value="failTask", method=RequestMethod.POST)
  public @ResponseBody RestResponse<String> failTask(HttpServletRequest request,
      @RequestParam("scanQueueTaskId") int scanQueueTaskId,
      @RequestParam("message") String message) {

    log.info("Received a REST request to fail for the scan " + scanQueueTaskId);

        try {
            checkKeyAndEnterprise(request, OPERATION_SET_TASK_CONFIG);
        } catch (RestAuthenticationFailedException e) {
            return RestResponse.failure(e.getMessage());
        }
   
    String result = checkTaskKey(request, scanQueueTaskId);
    if (!result.equals(TASK_KEY_SUCCESS)) {
      return RestResponse.failure(result);
    }
   
    String serverMessage = "ScanAgent reported that the scan task: " + scanQueueTaskId
                  + " had failed client-side for the following reason: " + message;
    this.scanQueueService.failTask(scanQueueTaskId, serverMessage);
    log.info(serverMessage);

    return RestResponse.success(serverMessage);
  }
 
  private String checkTaskKey(HttpServletRequest request, int scanQueueTaskId){
    String taskKey = request.getParameter("secureTaskKey");

    if (taskKey == null) {
      log.warn("Request to " + request.getPathInfo()
          + " did not contain an Task Key.");
      return TASK_KEY_NOT_FOUND_ERROR;
    }
    ScanQueueTask myTask = this.scanQueueService.retrieveById(scanQueueTaskId);
   
    if (myTask.getSecureKey() == null || !myTask.getSecureKey().equals(taskKey)) {
      log.warn("Task key " + taskKey + " is not correct");
      return TASK_KEY_ERROR;
    }

    log.info("Task key was verified ");
    return TASK_KEY_SUCCESS;
     
  }
}
TOP

Related Classes of com.denimgroup.threadfix.webapp.controller.rest.ScanQueueTaskRestController$RestAuthenticationFailedException

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.