UNPKG

@soos-io/soos-sca

Version:

SOOS Core SCA Security Analysis - Check for vulnerabilities, licenses, policy violations and more! Register for your free trial at https://app.soos.io/register

194 lines (193 loc) 10.6 kB
#!/usr/bin/env node "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const tslib_1 = require("tslib"); const package_json_1 = require("../package.json"); const api_client_1 = require("@soos-io/api-client"); const utilities_1 = require("@soos-io/api-client/dist/utilities"); const constants_1 = require("./constants"); const process_1 = require("process"); 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 utilities_2 = require("./utilities"); const enums_1 = require("@soos-io/api-client/dist/enums"); class SOOSSCAAnalysis { args; constructor(args) { this.args = args; } static parseArgs() { const analysisArgumentParser = AnalysisArgumentParser_1.default.create(api_client_1.IntegrationName.SoosSca, api_client_1.IntegrationType.Script, api_client_1.ScanType.SCA, 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 (0, utilities_2.removeDuplicates)(value.split(",").map((pattern) => pattern.trim())); }, defaultValue: constants_1.SOOS_SCA_CONSTANTS.DefaultDirectoriesToExclude, }); analysisArgumentParser.addArgument("filesToExclude", "Listing of files or patterns patterns to exclude from the search for manifest files. eg: **/req**.txt/, **/requirements.txt", { argParser: (value) => { return value.split(",").map((pattern) => pattern.trim()); }, defaultValue: [], }); analysisArgumentParser.addEnumArgument("fileMatchType", enums_1.FileMatchTypeEnum, "The method to use to locate files for scanning, looking for manifest files and/or files to hash.", { defaultValue: enums_1.FileMatchTypeEnum.Manifest, }); analysisArgumentParser.addEnumArgument("packageManagers", { [api_client_1.PackageManagerType.CFamily]: api_client_1.PackageManagerType.CFamily, [api_client_1.PackageManagerType.Dart]: api_client_1.PackageManagerType.Dart, [api_client_1.PackageManagerType.Erlang]: api_client_1.PackageManagerType.Erlang, [api_client_1.PackageManagerType.Go]: api_client_1.PackageManagerType.Go, [api_client_1.PackageManagerType.Homebrew]: api_client_1.PackageManagerType.Homebrew, [api_client_1.PackageManagerType.Java]: api_client_1.PackageManagerType.Java, [api_client_1.PackageManagerType.NPM]: api_client_1.PackageManagerType.NPM, [api_client_1.PackageManagerType.NuGet]: api_client_1.PackageManagerType.NuGet, [api_client_1.PackageManagerType.Php]: api_client_1.PackageManagerType.Php, [api_client_1.PackageManagerType.Python]: api_client_1.PackageManagerType.Python, [api_client_1.PackageManagerType.Ruby]: api_client_1.PackageManagerType.Ruby, [api_client_1.PackageManagerType.Rust]: api_client_1.PackageManagerType.Rust, [api_client_1.PackageManagerType.Swift]: api_client_1.PackageManagerType.Swift, [api_client_1.PackageManagerType.Unity]: api_client_1.PackageManagerType.Unity, }, "A list of package managers, delimited by comma, to include when searching for manifest files.", { allowMultipleValues: true, }); analysisArgumentParser.addArgument("sourceCodePath", "Root path to begin recursive search for manifests.", { defaultValue: process.cwd(), }); analysisArgumentParser.addArgument("workingDirectory", "Absolute path where SOOS may write and read persistent files for the given build. eg Correct: /tmp/workspace/ | Incorrect: ./bin/start/", { 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.SCA; const analysisService = AnalysisService_1.default.create(this.args.apiKey, this.args.apiURL); let projectHash; let branchHash; let analysisId; let scanStatusUrl; let scanStatus; try { const result = await analysisService.setupScan({ clientId: this.args.clientId, projectName: this.args.projectName, branchName: this.args.branchName, commitHash: this.args.commitHash, buildVersion: this.args.buildVersion, buildUri: this.args.buildURI, branchUri: this.args.branchURI, operatingEnvironment: this.args.operatingEnvironment, integrationName: this.args.integrationName, integrationType: this.args.integrationType, appVersion: this.args.appVersion, scriptVersion: this.args.scriptVersion, contributingDeveloperAudit: [ { contributingDeveloperId: this.args.contributingDeveloperId, source: this.args.contributingDeveloperSource, sourceName: this.args.contributingDeveloperSourceName, }, ], scanType, commandLine: process.argv.length > 2 ? (0, utilities_1.obfuscateCommandLine)((0, utilities_1.reassembleCommandLine)(process.argv.slice(2)), constants_1.SOOS_SCA_CONSTANTS.ObfuscatedArguments.map((a) => `--${a}`)) : null, }); projectHash = result.projectHash; branchHash = result.branchHash; analysisId = result.analysisId; scanStatusUrl = result.scanStatusUrl; const { manifestFiles, hashManifests } = await analysisService.findManifestsAndHashableFiles({ clientId: this.args.clientId, projectHash, filesToExclude: this.args.filesToExclude, directoriesToExclude: this.args.directoriesToExclude, sourceCodePath: this.args.sourceCodePath, packageManagers: this.args.packageManagers ?? [], fileMatchType: this.args.fileMatchType, }); const { exitCode } = await analysisService.addManifestsAndHashableFilesToScan({ clientId: this.args.clientId, projectHash: result.projectHash, branchHash: result.branchHash, analysisId: result.analysisId, scanType, scanStatusUrl: result.scanStatusUrl, fileMatchType: this.args.fileMatchType, manifestFiles, hashManifests, }); if (exitCode !== 0) { (0, process_1.exit)(exitCode); } await analysisService.startScan({ clientId: this.args.clientId, projectHash, analysisId: result.analysisId, scanType, scanUrl: result.scanUrl, }); scanStatus = await analysisService.waitForScanToFinish({ scanStatusUrl: result.scanStatusUrl, scanUrl: result.scanUrl, scanType, }); if ((0, utilities_1.isScanDone)(scanStatus) && this.args.exportFormat !== enums_1.AttributionFormatEnum.Unknown && this.args.exportFileType !== enums_1.AttributionFileTypeEnum.Unknown) { await analysisService.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 { exitCode: analysisExitCode, message } = (0, utilities_1.getAnalysisExitCodeWithMessage)(scanStatus, this.args.integrationName, this.args.onFailure); api_client_1.soosLogger.always(`${message} - exit ${analysisExitCode}`); (0, process_1.exit)(analysisExitCode); } catch (e) { const errorMessage = e instanceof Error ? e.message : e; if (projectHash && branchHash && analysisId && (!scanStatus || !(0, utilities_1.isScanDone)(scanStatus))) await analysisService.updateScanStatus({ clientId: this.args.clientId, projectHash, branchHash, scanType, analysisId: analysisId, status: api_client_1.ScanStatus.Error, message: `Error while performing scan: ${errorMessage}`, scanStatusUrl, }); api_client_1.soosLogger.error(errorMessage); api_client_1.soosLogger.always(`Error: ${errorMessage} - 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 SCA Analysis"); api_client_1.soosLogger.debug(JSON.stringify((0, utilities_1.obfuscateProperties)(args, ["apiKey"]), null, 2)); const soosSCAAnalysis = new SOOSSCAAnalysis(args); await soosSCAAnalysis.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); } } } SOOSSCAAnalysis.createAndRun();