diff --git a/action.yml b/action.yml index a9083e5..5fcfbae 100644 --- a/action.yml +++ b/action.yml @@ -55,15 +55,18 @@ inputs: summary_output_file: description: 'Enter the filename of the scan results summary file. The file is stored in the current directory. Default is results.txt.' required: false + default: 'results.txt' json_output: description: 'Enter true to save the scan results in JSON format. Default is true.' required: false json_output_file: description: 'Rename the JSON file that contains the scan results. The file is stored in the current directory. Default filename is results.json.' required: false + default: 'results.json' filtered_json_output_file: description: 'Enter the filename in the current directory to save results that violate pass-fail criteria. Default is filtered_results.json.' required: false + default: 'filtered_results.json' project_name: description: 'Enter the name of the CI/CD code repository that runs a Pipeline Scan. This parameter adds the repository name to the scan results, which can help you track scans across repositories.' required: false @@ -97,6 +100,9 @@ inputs: include: description: 'Enter a case-sensitive, comma-separated list of name patterns that represent the names of the modules to scan as top-level modules. Veracode identifies these modules during prescan. The * wildcard matches zero or more characters. The ? wildcard matches exactly one character. For example, to include various module names that contain module: --include "module 1, module-*, module2.jar". The scan results show the names of the modules that Veracode identified and the modules included in the scan. This parameter does not pause, stop, or impact the performance of your pipeline.' required: false + artifact_name: + description: 'Enter the name of the artifact to be uploaded to Github.' + required: false runs: using: 'node20' diff --git a/dist/index.js b/dist/index.js index 0cfe3cb..a9c2991 100644 --- a/dist/index.js +++ b/dist/index.js @@ -106987,7 +106987,7 @@ function checkParameters(parameters) { core.info('---- ' + JSON.stringify(parameters)); core.info('---- DEBUG OUTPUT END ----'); } - let scanCommand = 'java -jar pipeline-scan.jar -vid ' + parameters.vid + ' -vkey ' + parameters.vkey + ' -jf results.json -fjf filtered_results.json'; + let scanCommand = 'java -jar pipeline-scan.jar -vid ' + parameters.vid + ' -vkey ' + parameters.vkey; let policyCommand = ""; if (parameters.veracode_policy_name != "") { core.info('Veracode Policy evaluation is required'); @@ -107092,7 +107092,7 @@ function checkParameters(parameters) { //this will go away in thex version of the action, function is deprecated - end core.info('create pipeline-scan scan command'); Object.entries(parameters).forEach(([key, value], index) => { - if (key != 'vid' && key != 'vkey' && key != 'run_method' && key != 'request_policy' && key != 'veracode_policy_name' && value != "") { + if (key != 'vid' && key != 'vkey' && key != 'run_method' && key != 'request_policy' && key != 'veracode_policy_name' && key != 'artifact_name' && value != "") { if (parameters.debug == 1) { core.info('---- DEBUG OUTPUT START ----'); core.info('---- check-parameters.ts / checkParameters() - run full scan----'); @@ -107263,6 +107263,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; Object.defineProperty(exports, "__esModule", ({ value: true })); +const fs_1 = __nccwpck_require__(57147); const core = __importStar(__nccwpck_require__(95127)); const pipeline_scan_1 = __nccwpck_require__(5514); const pipeline_scan_2 = __nccwpck_require__(5514); @@ -107313,13 +107314,10 @@ const json_output = core.getInput('json_output', { required: false }); parameters['json_output'] = json_output; const include = core.getInput('include', { required: false }); parameters['include'] = include; -/* -const json_output_file = core.getInput('json_output_file', {required: false} ); -parameters['json_output_file'] = json_output_file - -const filtered_json_output_file = core.getInput('filtered_json_output_file', {required: false} ); -parameters['filtered_json_output_file'] = filtered_json_output_file -*/ +const json_output_file = core.getInput('json_output_file', { required: false }); +parameters['json_output_file'] = json_output_file; +const filtered_json_output_file = core.getInput('filtered_json_output_file', { required: false }); +parameters['filtered_json_output_file'] = filtered_json_output_file; const project_name = core.getInput('project_name', { required: false }); parameters['project_name'] = project_name; const project_url = core.getInput('project_url', { required: false }); @@ -107343,6 +107341,9 @@ parameters['create_baseline_from'] = create_baseline_from; const fail_build = core.getInput('fail_build', { required: false }); parameters['fail_build'] = fail_build; //true or false +const artifact_name = core.getInput('artifact_name', { required: false }); +parameters['artifact_name'] = artifact_name; +//string function run(parameters) { var _a; return __awaiter(this, void 0, void 0, function* () { @@ -107358,19 +107359,98 @@ function run(parameters) { let scanCommandOutput = yield (0, pipeline_scan_2.runScan)(scanCommandValue, parameters); core.info('Pipeline Scan Output'); core.info(scanCommandOutput); - //store output files as artifacts - const { DefaultArtifactClient } = __nccwpck_require__(32481); - const artifactClient = new DefaultArtifactClient(); - const artifactName = 'Veracode Pipeline-Scan Results'; - const files = [ - 'results.json', - 'filtered_results.json' - ]; + //check if the results files exist and if not create empty files + if (!(0, fs_1.existsSync)('results.json')) { + core.info('results.json does not exist - creating empty file'); + let emptyResults = { + "findings": [] + }; + let emptyResultsString = JSON.stringify(emptyResults); + let emptyResultsFile = 'results.json'; + let emptyResultsFilteredFile = 'filtered_results.json'; + try { + (0, fs_1.writeFileSync)(emptyResultsFile, emptyResultsString); + } + catch (error) { + core.info('Error creating empty results files'); + } + } const rootDirectory = process.cwd(); - const options = { - continueOnError: true - }; - const uploadResult = yield artifactClient.uploadArtifact(artifactName, files, rootDirectory, options); + if (parameters.debug == 1) { + core.info('---- DEBUG OUTPUT START ----'); + core.info('---- index.ts / run() before create artifacts ----'); + core.info('---- Roof folder: ' + rootDirectory); + core.info('---- Results Json File: ' + rootDirectory + '/' + parameters.json_output_file); + core.info('---- Filtered Results Json File: ' + rootDirectory + '/' + parameters.filtered_json_output_file); + core.info('---- Summary Output File: ' + rootDirectory + '/' + parameters.summary_output_file); + core.info('---- DEBUG OUTPUT END ----'); + } + //check if results files exists and if so store them as artifacts + if ((0, fs_1.existsSync)(rootDirectory + '/' + parameters.json_output_file && rootDirectory + '/' + parameters.filtered_json_output_file && rootDirectory + '/' + parameters.summary_output_file)) { + core.info('Results files exist - storing as artifact'); + //store output files as artifacts + const { DefaultArtifactClient } = __nccwpck_require__(32481); + const artifactClient = new DefaultArtifactClient(); + const artifactName = 'Veracode Pipeline-Scan Results - ' + parameters.artifact_name; + const files = [ + parameters.json_output_file, + parameters.filtered_json_output_file, + parameters.summary_output_file + ]; + const rootDirectory = process.cwd(); + const options = { + continueOnError: true + }; + try { + const uploadResult = yield artifactClient.uploadArtifact(artifactName, files, rootDirectory, options); + core.info('Artifact upload result:'); + core.info(uploadResult); + } + catch (error) { + core.info('Artifact upload failed:'); + core.info(String(error)); + } + if (parameters.debug == 1) { + core.info('---- DEBUG OUTPUT START ----'); + core.info('---- index.ts / run() create artifacts ----'); + core.info('---- Artifact filenames: ' + files); + core.info('---- DEBUG OUTPUT END ----'); + } + } + else { + core.info('Results files do not exist - no artifact to store'); + core.info(parameters.filtered_json_output_file + ' does not exist - creating empty file'); + let emptyResults = { + "findings": [] + }; + let emptyResultsString = JSON.stringify(emptyResults); + let emptyResultsFilteredFile = parameters.filtered_json_output_file; + try { + (0, fs_1.writeFileSync)(emptyResultsFilteredFile, emptyResultsString); + } + catch (error) { + core.info('Error creating empty results files'); + } + const { DefaultArtifactClient } = __nccwpck_require__(32481); + const artifactClient = new DefaultArtifactClient(); + const artifactName = 'Veracode Pipeline-Scan Results - ' + parameters.artifact_name; + const files = [ + parameters.filtered_json_output_file + ]; + const rootDirectory = process.cwd(); + const options = { + continueOnError: true + }; + try { + const uploadResult = yield artifactClient.uploadArtifact(artifactName, files, rootDirectory, options); + core.info('Artifact upload result:'); + core.info(uploadResult); + } + catch (error) { + core.info('Artifact upload failed:'); + core.info(String(error)); + } + } if (parameters.store_baseline_file == 'true') { core.info('Baseline File should be stored'); let commitCommandOutput = yield (0, commit_1.commitBasline)(parameters); @@ -107429,14 +107509,15 @@ function run(parameters) { } if (parameters.fail_build == "true") { core.info('Check if we need to fail the build'); - let failBuild = scanCommandOutput.indexOf("FAILURE"); + const failureRegex = /FAILURE: Found \d+ issues!/; + let failBuild = failureRegex.test(scanCommandOutput); if (parameters.debug == 1) { core.info('---- DEBUG OUTPUT START ----'); core.info('---- index.ts / run() check if we need to fail the build ----'); core.info('---- Fail build value found : ' + failBuild); core.info('---- DEBUG OUTPUT END ----'); } - if (failBuild >= 1) { + if (failBuild) { core.info('There are flaws found that require the build to fail'); core.setFailed(scanCommandOutput); } @@ -107511,9 +107592,10 @@ function runScan(scanCommand, parameters) { } let commandOutput = ''; try { - (0, child_process_1.execSync)(scanCommand); + commandOutput = (0, child_process_1.execSync)(scanCommand).toString(); } catch (ex) { + core.info("Pipeline-scan command failed.\n" + ex.stdout.toString()); commandOutput = ex.stdout.toString(); } return commandOutput; diff --git a/src/check-parameters.ts b/src/check-parameters.ts index f6b899f..d38355c 100644 --- a/src/check-parameters.ts +++ b/src/check-parameters.ts @@ -14,7 +14,7 @@ export async function checkParameters (parameters:any):Promise { core.info('---- DEBUG OUTPUT END ----') } - let scanCommand:string = 'java -jar pipeline-scan.jar -vid '+parameters.vid+' -vkey '+parameters.vkey+' -jf results.json -fjf filtered_results.json' + let scanCommand:string = 'java -jar pipeline-scan.jar -vid '+parameters.vid+' -vkey '+parameters.vkey let policyCommand:string = "" if ( parameters.veracode_policy_name !="" ){ @@ -140,7 +140,7 @@ export async function checkParameters (parameters:any):Promise { core.info('create pipeline-scan scan command') Object.entries(parameters).forEach(([key, value], index) => { - if ( key != 'vid' && key != 'vkey' && key != 'run_method' && key != 'request_policy' && key != 'veracode_policy_name' && value != "") { + if ( key != 'vid' && key != 'vkey' && key != 'run_method' && key != 'request_policy' && key != 'veracode_policy_name' && key != 'artifact_name' && value != "") { if (parameters.debug == 1 ){ core.info('---- DEBUG OUTPUT START ----') diff --git a/src/index.ts b/src/index.ts index dd8e1c5..de1f848 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,4 @@ -import { readFileSync, existsSync} from 'fs'; +import { readFileSync, existsSync, fstat, writeFileSync} from 'fs'; import * as core from '@actions/core' import { downloadJar } from "./pipeline-scan"; import { runScan } from "./pipeline-scan"; @@ -76,13 +76,11 @@ parameters['json_output'] = json_output const include = core.getInput('include', {required: false} ); parameters['include'] = include -/* const json_output_file = core.getInput('json_output_file', {required: false} ); parameters['json_output_file'] = json_output_file const filtered_json_output_file = core.getInput('filtered_json_output_file', {required: false} ); parameters['filtered_json_output_file'] = filtered_json_output_file -*/ const project_name = core.getInput('project_name', {required: false} ); parameters['project_name'] = project_name @@ -117,6 +115,10 @@ const fail_build = core.getInput('fail_build', {required: false} ); parameters['fail_build'] = fail_build //true or false +const artifact_name = core.getInput('artifact_name', {required: false} ); +parameters['artifact_name'] = artifact_name +//string + @@ -137,22 +139,112 @@ async function run (parameters:any){ core.info('Pipeline Scan Output') core.info(scanCommandOutput) - - //store output files as artifacts - const { DefaultArtifactClient } = require('@actions/artifact') - const artifactClient = new DefaultArtifactClient() - const artifactName = 'Veracode Pipeline-Scan Results'; - const files = [ - 'results.json', - 'filtered_results.json' - ] + + //check if the results files exist and if not create empty files + if ( !existsSync('results.json') ){ + core.info('results.json does not exist - creating empty file') + let emptyResults = { + "findings": [] + } + let emptyResultsString = JSON.stringify(emptyResults) + let emptyResultsFile = 'results.json' + let emptyResultsFilteredFile = 'filtered_results.json' + + try { + writeFileSync(emptyResultsFile,emptyResultsString) + } catch (error) { + core.info('Error creating empty results files') + } + } const rootDirectory = process.cwd() - const options = { - continueOnError: true + if (parameters.debug == 1 ){ + core.info('---- DEBUG OUTPUT START ----') + core.info('---- index.ts / run() before create artifacts ----') + core.info('---- Roof folder: '+rootDirectory) + core.info('---- Results Json File: '+rootDirectory+'/'+parameters.json_output_file) + core.info('---- Filtered Results Json File: '+rootDirectory+'/'+parameters.filtered_json_output_file) + core.info('---- Summary Output File: '+rootDirectory+'/'+parameters.summary_output_file) + core.info('---- DEBUG OUTPUT END ----') } - const uploadResult = await artifactClient.uploadArtifact(artifactName, files, rootDirectory, options) + //check if results files exists and if so store them as artifacts + if ( existsSync(rootDirectory+'/'+parameters.json_output_file && rootDirectory+'/'+parameters.filtered_json_output_file && rootDirectory+'/'+parameters.summary_output_file) ){ + core.info('Results files exist - storing as artifact') + + + //store output files as artifacts + const { DefaultArtifactClient } = require('@actions/artifact') + const artifactClient = new DefaultArtifactClient() + const artifactName = 'Veracode Pipeline-Scan Results - '+parameters.artifact_name; + const files = [ + parameters.json_output_file, + parameters.filtered_json_output_file, + parameters.summary_output_file + ] + + + const rootDirectory = process.cwd() + const options = { + continueOnError: true + } + + try { + const uploadResult = await artifactClient.uploadArtifact(artifactName, files, rootDirectory, options) + core.info('Artifact upload result:') + core.info(uploadResult) + } catch (error) { + core.info('Artifact upload failed:') + core.info(String(error)) + } + + + if (parameters.debug == 1 ){ + core.info('---- DEBUG OUTPUT START ----') + core.info('---- index.ts / run() create artifacts ----') + core.info('---- Artifact filenames: '+files) + core.info('---- DEBUG OUTPUT END ----') + } + + } + else { + core.info('Results files do not exist - no artifact to store') + + core.info(parameters.filtered_json_output_file+' does not exist - creating empty file') + let emptyResults = { + "findings": [] + } + let emptyResultsString = JSON.stringify(emptyResults) + let emptyResultsFilteredFile = parameters.filtered_json_output_file + + try { + writeFileSync(emptyResultsFilteredFile,emptyResultsString) + } catch (error) { + core.info('Error creating empty results files') + } + + const { DefaultArtifactClient } = require('@actions/artifact') + const artifactClient = new DefaultArtifactClient() + const artifactName = 'Veracode Pipeline-Scan Results - '+parameters.artifact_name; + const files = [ + parameters.filtered_json_output_file + ] + + + const rootDirectory = process.cwd() + const options = { + continueOnError: true + } + + try { + const uploadResult = await artifactClient.uploadArtifact(artifactName, files, rootDirectory, options) + core.info('Artifact upload result:') + core.info(uploadResult) + } catch (error) { + core.info('Artifact upload failed:') + core.info(String(error)) + } + } if ( parameters.store_baseline_file == 'true'){ @@ -224,7 +316,9 @@ async function run (parameters:any){ if ( parameters.fail_build == "true" ){ core.info('Check if we need to fail the build') - let failBuild = scanCommandOutput.indexOf("FAILURE") + const failureRegex = /FAILURE: Found \d+ issues!/ + let failBuild = failureRegex.test(scanCommandOutput) + if (parameters.debug == 1 ){ core.info('---- DEBUG OUTPUT START ----') @@ -234,7 +328,7 @@ async function run (parameters:any){ } - if ( failBuild >= 1 ){ + if ( failBuild ){ core.info('There are flaws found that require the build to fail') core.setFailed(scanCommandOutput) } diff --git a/src/pipeline-scan.ts b/src/pipeline-scan.ts index 26d58b6..4ce6cd5 100644 --- a/src/pipeline-scan.ts +++ b/src/pipeline-scan.ts @@ -44,8 +44,9 @@ export function runScan (scanCommand:any,parameters:any){ let commandOutput = '' try { - execSync(scanCommand) + commandOutput = execSync(scanCommand).toString() } catch (ex:any){ + core.info("Pipeline-scan command failed.\n"+ex.stdout.toString()) commandOutput = ex.stdout.toString() } return commandOutput