Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 94 additions & 63 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

Veracode Pipeline Scan Action runs the Veracode pipeline-scan as an action on any GitHub pipeline

The only pre-requisites is to have the application compiled/packaged according the Veracode Packaging Instructions [here](https://docs.veracode.com/r/compilation_packaging)
The only pre-requisites is to have the application compiled/packaged according the Veracode Packaging Instructions [here](https://docs.veracode.com/r/compilation_packaging)

## About

Expand All @@ -16,19 +16,19 @@ For more information on Pipeline Scan, visit the [Veracode Docs](https://docs.ve

## Usage

Intended usage is to add a job to your CI/CD pipeline, after a build job, uploads the "application", scans it and returns the results.
A build can be failed upon findings, as well the action allows you to generate a new baseline file and commit it back into a different branch of your repository where it can be used to sort out previous findings in order to report on net-new findings. Please refere to the Veracode documentation [here](https://docs.veracode.com/r/Using_a_Pipeline_Scan_Baseline_File).
If the action will run within a PR, it will automatically add a comment with all results to the PR. This is done for easy review and approval processes.
![](/media/pr-comment.png)
If the parameter `fail_build` is set to `true`, the action will fail the step upon findings. If set to `false`, the step will not show as failed.
![](/media/fail-build.png)
The full output of the action can still be reviewed on the action run overview and on the command line output.
![](/media/action-overview.png)
![](/media/command-line-output.png)
Intended usage is to add a job to your CI/CD pipeline, after a build job, uploads the "application", scans it and returns the results.
A build can be failed upon findings, as well the action allows you to generate a new baseline file and commit it back into a different branch of your repository where it can be used to sort out previous findings in order to report on net-new findings. Please refere to the Veracode documentation [here](https://docs.veracode.com/r/Using_a_Pipeline_Scan_Baseline_File).

If the action will run within a PR, it will automatically add a comment with all results to the PR. This is done for easy review and approval processes.
![](/media/pr-comment.png)

If the parameter `fail_build` is set to `true`, the action will fail the step upon findings. If set to `false`, the step will not show as failed.
![](/media/fail-build.png)

The full output of the action can still be reviewed on the action run overview and on the command line output.
![](/media/action-overview.png)
![](/media/command-line-output.png)


The tool will need some information passed to it as parameters (many are optional):

Expand Down Expand Up @@ -75,6 +75,7 @@ The tool will need some information passed to it as parameters (many are optiona
* app_id
* development_stage
* include
* upload_results

* Baseline file
* if a baseline file should be stored from the scan all paramters are required
Expand All @@ -83,30 +84,30 @@ The tool will need some information passed to it as parameters (many are optiona
* store_baseline_file_branch:
* Enter the branch name where the baseline file should be stored
* create_baseline_from:
* From which results should the baseline file be created. standard = full results || filtered = filtered results
### ATTENTION
* From which results should the baseline file be created. standard = full results || filtered = filtered results

### ATTENTION
If you store a baseline file from a pipeline scan the action will commit and push that file to a specified branch on the same repository using these commands:
```sh
git config --global user.name "${ process.env.GITHUB_ACTOR }"
git config --global user.email "[email protected]"
git add "${baselineFileName}"
git stash
git pull origin ${parameters.store_baseline_file_branch} || echo "Couldn't find remote branch"
git checkout stash -- .
git commit -m "Veracode Baseline File push from pipeline"
git push origin HEAD:${parameters.store_baseline_file_branch} --force-with-lease
```
Make sure that doesn't have any side effects on your repository. If you are not sure, don't store the baseline file from the action itself, instead store it as an artifact and commit/push it yourself to the place where it should be stored.

## Examples
All examples follow the same strucutre, the will all `need` the `build` to be finished before the they will start running. Veraocde's static analysis is mainly binary static analysis, therefore a compile/build action is required before a pipeline scan can be started. Please read about the packaging and compilation requirements here: https://docs.veracode.com/r/compilation_packaging.
The examples will checkout the repository, they will download the previously generated build artefact, that is named `verademo.war` and then run the action.

The basic yml
```yml
git config --global user.name "${ process.env.GITHUB_ACTOR }"
git config --global user.email "[email protected]"
git add "${baselineFileName}"
git stash
git pull origin ${parameters.store_baseline_file_branch} || echo "Couldn't find remote branch"
git checkout stash -- .
git commit -m "Veracode Baseline File push from pipeline"
git push origin HEAD:${parameters.store_baseline_file_branch} --force-with-lease
```
Make sure that doesn't have any side effects on your repository. If you are not sure, don't store the baseline file from the action itself, instead store it as an artifact and commit/push it yourself to the place where it should be stored.

## Examples
All examples follow the same strucutre, the will all `need` the `build` to be finished before the they will start running. Veraocde's static analysis is mainly binary static analysis, therefore a compile/build action is required before a pipeline scan can be started. Please read about the packaging and compilation requirements here: https://docs.veracode.com/r/compilation_packaging.
The examples will checkout the repository, they will download the previously generated build artefact, that is named `verademo.war` and then run the action.


The basic yml

```yml
pipeline_scan:
# needs the build step before this job will start running
needs: build
Expand All @@ -116,7 +117,7 @@ The basic yml
steps:
- name: checkout repo
uses: actions/checkout@v4

# get the compiled binary from a previous job
- name: get archive
uses: actions/download-artifact@v4
Expand All @@ -130,13 +131,13 @@ The basic yml
with:
vid: ${{ secrets.VID }}
vkey: ${{ secrets.VKEY }}
file: "verademo.war"
```
file: "verademo.war"
```


Rate the findings according to a policy and fail the build
```yml
Rate the findings according to a policy and fail the build

```yml
pipeline_scan:
# needs the build step before this job will start running
needs: build
Expand All @@ -146,7 +147,7 @@ Rate the findings according to a policy and fail the build
steps:
- name: checkout repo
uses: actions/checkout@v4

# get the compiled binary from a previous job
- name: get archive
uses: actions/download-artifact@v4
Expand All @@ -160,15 +161,15 @@ Rate the findings according to a policy and fail the build
with:
vid: ${{ secrets.VID }}
vkey: ${{ secrets.VKEY }}
file: "verademo.war"
file: "verademo.war"
veracode_policy_name: "VeraDemo Policy"
fail_build: true
```
```


Sort out previous findings using a baseline file
```yml
Sort out previous findings using a baseline file

```yml
pipeline_scan:
# needs the build step before this job will start running
needs: build
Expand All @@ -178,7 +179,7 @@ Sort out previous findings using a baseline file
steps:
- name: checkout repo
uses: actions/checkout@v4

# get the compiled binary from a previous job
- name: get archive
uses: actions/download-artifact@v4
Expand All @@ -192,16 +193,16 @@ Sort out previous findings using a baseline file
with:
vid: ${{ secrets.VID }}
vkey: ${{ secrets.VKEY }}
file: "verademo.war"
file: "verademo.war"
baseline_file: "veracode-pipeline-scan-baseline-file.json"
fail_build: true
```
```




Sort out previous findings using a baseline file, create a new baseline file and store on a specified branch
```yml
Sort out previous findings using a baseline file, create a new baseline file and store on a specified branch

```yml
pipeline_scan:
# needs the build step before this job will start running
needs: build
Expand All @@ -211,7 +212,7 @@ Sort out previous findings using a baseline file, create a new baseline file and
steps:
- name: checkout repo
uses: actions/checkout@v4

# get the compiled binary from a previous job
- name: get archive
uses: actions/download-artifact@v4
Expand All @@ -225,17 +226,47 @@ Sort out previous findings using a baseline file, create a new baseline file and
with:
vid: ${{ secrets.VID }}
vkey: ${{ secrets.VKEY }}
file: "verademo.war"
file: "verademo.war"
store_baseline_file: true
store_baseline_file_branch: my-featur-branch
create_baseline_from: standard
baseline_file: "veracode-pipeline-scan-baseline-file.json"
fail_build: true
```
```

Disable upload of scan results as artifacts

```yml
pipeline_scan:
# needs the build step before this job will start running
needs: build
runs-on: ubuntu-latest
name: pipeline scan

steps:
- name: checkout repo
uses: actions/checkout@v4

# get the compiled binary from a previous job
- name: get archive
uses: actions/download-artifact@v4
with:
name: verademo.war

# run the pipeline scan action
- name: pipeline-scan action step
id: pipeline-scan
uses: veracode/[email protected]
with:
vid: ${{ secrets.VID }}
vkey: ${{ secrets.VKEY }}
file: "verademo.war"
upload_results: false
```

## Compile the action
The action comes pre-compiled as transpiled JavaScript. If you want to fork and build it on your own you need NPM to be installed, use `ncc` to compile all node modules into a single file, so they don't need to be installed on every action run. The command to build is simply
## Compile the action
The action comes pre-compiled as transpiled JavaScript. If you want to fork and build it on your own you need NPM to be installed, use `ncc` to compile all node modules into a single file, so they don't need to be installed on every action run. The command to build is simply

```sh
ncc build ./src/index.ts
ncc build ./src/index.ts
```
6 changes: 5 additions & 1 deletion action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,16 @@ inputs:
fail_build:
description: 'Fail the build upon findings. Takes true or false'
required: false
include:
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
upload_results:
description: 'Upload scan results as GitHub artifacts. Takes true or false. Default is true.'
required: false
default: 'true'

runs:
using: 'node20'
Expand Down
80 changes: 42 additions & 38 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,19 @@ parameters['store_baseline_file_branch'] = store_baseline_file_branch

const create_baseline_from = core.getInput('create_baseline_from', {required: false} );
parameters['create_baseline_from'] = create_baseline_from
//standard or filtered
//standard or filtered

const fail_build = core.getInput('fail_build', {required: false} );
parameters['fail_build'] = fail_build
//true or false
//true or false

const artifact_name = core.getInput('artifact_name', {required: false} );
parameters['artifact_name'] = artifact_name
//string


//string

const upload_results = core.getInput('upload_results', {required: false} );
parameters['upload_results'] = upload_results
//true or false


async function run (parameters:any){
Expand Down Expand Up @@ -168,44 +169,47 @@ async function run (parameters:any){
core.info('---- DEBUG OUTPUT END ----')
}

//check if upload_result is enabled
if (parameters.upload_results == 'true') {
//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
]
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')


const rootDirectory = process.cwd()
const options = {
continueOnError: true
}
//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
]

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))
}

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 ----')
}

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')
Expand Down Expand Up @@ -324,7 +328,7 @@ async function run (parameters:any){
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 ----')
core.info('---- DEBUG OUTPUT END ----')
}


Expand All @@ -336,4 +340,4 @@ async function run (parameters:any){

}

run(parameters)
run(parameters)