UNPKG

@soos-io/soos-sast

Version:

SOOS Static Application Security Testing (SAST) scanning support. Register for a free SOOS trial at https://app.soos.io/register

167 lines (166 loc) 8.74 kB
#!/usr/bin/env node "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const api_client_1 = require("@soos-io/api-client"); const utilities_1 = require("@soos-io/api-client/dist/utilities"); const process_1 = require("process"); const package_json_1 = require("../package.json"); const AnalysisService_1 = tslib_1.__importDefault(require("@soos-io/api-client/dist/services/AnalysisService")); const AnalysisArgumentParser_1 = tslib_1.__importDefault(require("@soos-io/api-client/dist/services/AnalysisArgumentParser")); const constants_1 = require("./constants"); class SOOSSASTAnalysis { args; constructor(args) { this.args = args; } static parseArgs() { const analysisArgumentParser = AnalysisArgumentParser_1.default.create(api_client_1.IntegrationName.SoosSast, api_client_1.IntegrationType.Script, api_client_1.ScanType.SAST, package_json_1.version); analysisArgumentParser.addArgument("directoriesToExclude", "Listing of directories or patterns to exclude from the search for manifest files. eg: **bin/start/**, **/start/**", { argParser: (value) => { return value.split(",").map((pattern) => pattern.trim()); }, }); analysisArgumentParser.addArgument("filesToExclude", "Listing of files or patterns patterns to exclude from the search for manifest files. eg: **/sa**.sarif.json/, **/sast.sarif.json", { argParser: (value) => { return value.split(",").map((pattern) => pattern.trim()); }, }); analysisArgumentParser.addArgument("sourceCodePath", "The path to start searching for SAST files.", { defaultValue: process.cwd(), }); analysisArgumentParser.addArgument("outputDirectory", "Absolute path where SOOS will write exported reports and SBOMs. eg Correct: /out/sbom/ | Incorrect: ./out/sbom/", { defaultValue: process.cwd(), }); return analysisArgumentParser.parseArguments(); } async runAnalysis() { const scanType = api_client_1.ScanType.SAST; const soosAnalysisService = AnalysisService_1.default.create(this.args.apiKey, this.args.apiURL); let projectHash; let branchHash; let analysisId; let scanStatusUrl; let scanStatus; try { const result = await soosAnalysisService.setupScan({ clientId: this.args.clientId, projectName: this.args.projectName, commitHash: this.args.commitHash, contributingDeveloperAudit: !this.args.contributingDeveloperId || !this.args.contributingDeveloperSource || !this.args.contributingDeveloperSourceName ? [] : [ { contributingDeveloperId: this.args.contributingDeveloperId, source: this.args.contributingDeveloperSource, sourceName: this.args.contributingDeveloperSourceName, }, ], branchName: this.args.branchName, buildVersion: this.args.buildVersion, buildUri: this.args.buildURI, branchUri: this.args.branchURI, integrationType: this.args.integrationType, operatingEnvironment: this.args.operatingEnvironment, integrationName: this.args.integrationName, appVersion: this.args.appVersion, scanType, scriptVersion: this.args.scriptVersion, toolName: undefined, toolVersion: undefined, }); projectHash = result.projectHash; branchHash = result.branchHash; analysisId = result.analysisId; scanStatusUrl = result.scanStatusUrl; const { filePaths, hasMoreThanMaximumFiles } = await soosAnalysisService.findAnalysisFiles(scanType, this.args.sourceCodePath, constants_1.SOOS_SAST_CONSTANTS.FilePattern, this.args.filesToExclude, this.args.directoriesToExclude, constants_1.SOOS_SAST_CONSTANTS.MaxFiles); if (filePaths.length === 0) { const noFilesMessage = `No SAST input files found. Please ensure you have generated Sarif JSON files before running soos-sast. They need to match the pattern ${constants_1.SOOS_SAST_CONSTANTS.FilePattern}. See https://kb.soos.io/getting-started-with-sast-secrets for more information.`; await soosAnalysisService.updateScanStatus({ analysisId, clientId: this.args.clientId, projectHash, branchHash, scanType, status: api_client_1.ScanStatus.NoFiles, message: noFilesMessage, scanStatusUrl, }); api_client_1.soosLogger.error(noFilesMessage); api_client_1.soosLogger.always(`${noFilesMessage} - exit 1`); (0, process_1.exit)(1); } api_client_1.soosLogger.info("Uploading SAST File(s)..."); const formData = await soosAnalysisService.getAnalysisFilesAsFormData(filePaths, this.args.sourceCodePath); await soosAnalysisService.analysisApiClient.uploadScanToolResult({ clientId: this.args.clientId, projectHash, branchHash, scanType, scanId: analysisId, resultFile: formData, hasMoreThanMaximumFiles, }); api_client_1.soosLogger.info("Scan results uploaded successfully."); scanStatus = await soosAnalysisService.waitForScanToFinish({ scanStatusUrl, scanUrl: result.scanUrl, scanType, }); if ((0, utilities_1.isScanDone)(scanStatus) && this.args.exportFormat !== api_client_1.AttributionFormatEnum.Unknown && this.args.exportFileType !== api_client_1.AttributionFileTypeEnum.Unknown) { await soosAnalysisService.generateFormattedOutput({ clientId: this.args.clientId, projectHash: result.projectHash, projectName: this.args.projectName, branchHash: result.branchHash, analysisId: result.analysisId, format: this.args.exportFormat, fileType: this.args.exportFileType, includeDependentProjects: false, includeOriginalSbom: false, includeVulnerabilities: false, workingDirectory: this.args.outputDirectory, }); } const exitCodeWithMessage = (0, utilities_1.getAnalysisExitCodeWithMessage)(scanStatus, this.args.integrationName, this.args.onFailure); api_client_1.soosLogger.always(`${exitCodeWithMessage.message} - exit ${exitCodeWithMessage.exitCode}`); (0, process_1.exit)(exitCodeWithMessage.exitCode); } catch (error) { if (projectHash && branchHash && analysisId && (!scanStatus || !(0, utilities_1.isScanDone)(scanStatus))) await soosAnalysisService.updateScanStatus({ analysisId, clientId: this.args.clientId, projectHash, branchHash, scanType, status: api_client_1.ScanStatus.Error, message: `Error while performing scan.`, scanStatusUrl, }); api_client_1.soosLogger.error(error); api_client_1.soosLogger.always(`${error} - exit 1`); (0, process_1.exit)(1); } } static async createAndRun() { try { const args = this.parseArgs(); api_client_1.soosLogger.setMinLogLevel(args.logLevel); api_client_1.soosLogger.always("Starting SOOS SAST Analysis"); api_client_1.soosLogger.debug(JSON.stringify((0, utilities_1.obfuscateProperties)(args, ["apiKey"]), null, 2)); const soosSASTAnalysis = new SOOSSASTAnalysis(args); await soosSASTAnalysis.runAnalysis(); } catch (error) { api_client_1.soosLogger.error(`Error on createAndRun: ${error}`); api_client_1.soosLogger.always(`Error on createAndRun: ${error} - exit 1`); (0, process_1.exit)(1); } } } SOOSSASTAnalysis.createAndRun();