Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Contrast results #19

Merged
merged 12 commits into from
May 30, 2024
17 changes: 16 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Detailed description of the inputs exposed by the `pixee/upload-tool-results-act
- uses: pixee/upload-tool-results-action
with:
# The supported code scanning tool that produced the results being uploaded to Pixeebot.
# Allowed values: 'sonar', 'codeql', 'semgrep'
# Allowed values: 'sonar', 'codeql', 'semgrep', 'defectdojo', 'contrast'
# Required
tool:

Expand All @@ -47,6 +47,21 @@ Detailed description of the inputs exposed by the `pixee/upload-tool-results-act
# Base URL of the DefectDojo API.
defectdojo-api-url:

# Base URL of the Contrast API.
contrast-api-url:

# Unique identifier for the organization in Contrast that needs to be analyzed.
contrast-org-id:

# Unique identifier for the specific application within Contrast.
contrast-app-id:

# Api key for authenticating requests to Contrast.
contrast-api-key:

# Token for authenticating requests to Contrast.
contrast-token:

# Path to the tool's results file to upload to Pixeebot. This does not apply to SonarCloud integration, because the action retrieves the results directly from SonarCloud.
# Required, when `tool` is not "sonar"
file:
Expand Down
15 changes: 15 additions & 0 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,21 @@ inputs:
defectdojo-product-name:
description: Key identifying the DefectDojo product to be analyzed.
required: false
contrast-api-url:
description: Base URL of the Contrast API.
required: false
contrast-org-id:
description: Unique identifier for the organization in Contrast that needs to be analyzed.
required: false
contrast-app-id:
description: Unique identifier for the specific application within Contrast.
required: false
contrast-api-key:
description: Api key for authenticating requests to Contrast.
required: false
contrast-token:
description: Token for authenticating requests to Contrast.
required: false

runs:
using: "node20"
Expand Down
22 changes: 22 additions & 0 deletions examples/contrast-pixeebot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
name: Fix Contrast Findings with Pixeebot
on:
pull_request:
branches:
- master

permissions:
id-token: write

jobs:
share:
name: Upload Contrast Findings to Pixeebot
runs-on: ubuntu-latest
steps:
- uses: pixee/upload-tool-results-action@v1
with:
tool: contrast
contrast-api-url: ${{ secrets.CONTRAST_API_URL }}
contrast-org-id: ${{ secrets.CONTRAST_ORG_ID }}
contrast-app-id: ${{ secrets.CONTRAST_APP_ID }}
contrast-api-key: ${{ secrets.CONTRAST_API_KEY }}
contrast-token: ${{ secrets.CONTRAST_TOKEN }}
101 changes: 91 additions & 10 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
"@actions/github": "^6.0.0",
"@actions/http-client": "^2.2.0",
"axios": "^1.6.7",
"form-data": "^4.0.0"
"form-data": "^4.0.0",
"jszip": "^3.10.1"
},
"devDependencies": {
"@types/jest": "^29.5.12",
Expand Down
36 changes: 24 additions & 12 deletions src/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { triggerPrAnalysis, uploadInputFile } from "./pixee-platform";
import { SONAR_RESULT, getSonarCloudInputs, retrieveSonarCloudHotspots, retrieveSonarCloudIssues } from "./sonar";
import { getDefectDojoInputs, retrieveDefectDojoResults } from "./defect-dojo";
import { getGitHubContext, getTempDir } from "./github";
import {getContrastInputs, retrieveContrastResults} from "./contrast";

/**
* Runs the action.
Expand Down Expand Up @@ -37,13 +38,13 @@ export async function run() {
core.info(`Uploaded ${hotspotFile} to Pixeebot for analysis`);
break;
default:
if (!core.getInput("file")) {
const inputFile = core.getInput("file");
if (!inputFile) {
throw new Error(`Tool "${tool}" requires a file input`);
}

const resultFile = await fetchOrLocateResultsFile(tool, null, "");
await uploadInputFile(tool, resultFile);
core.info(`Uploaded ${resultFile} for ${tool} to Pixeebot for analysis`);
await uploadInputFile(tool, inputFile);
core.info(`Uploaded ${inputFile} for ${tool} to Pixeebot for analysis`);
}

const { prNumber } = getGitHubContext();
Expand All @@ -63,12 +64,10 @@ async function fetchOrLocateDefectDojoResultsFile() {
}

async function fetchOrLocateContrastResultsFile() {
let file = core.getInput("file");
if (file !== "") {
return file;
}
let results = await fetchContrastFindings();
let fileName = "contrast-findings.xml";

throw new Error("Contrast requires a file to be provided");
return fetchOrLocateResultsFile("contrast", results, fileName, false);
}

async function fetchOrLocateSonarResultsFile(resultType : SONAR_RESULT) {
Expand All @@ -78,16 +77,21 @@ async function fetchOrLocateSonarResultsFile(resultType : SONAR_RESULT) {
return fetchOrLocateResultsFile("sonar", results, fileName);
}

async function fetchOrLocateResultsFile(tool: Tool, results: any, fileName: string) {
async function fetchOrLocateResultsFile(tool: Tool, results: any, fileName: string, stringifyResults: boolean = true) {
let file = core.getInput("file");
if (file !== "") {
return file;
}

const tmp = getTempDir();
file = core.toPlatformPath(`${tmp}/${fileName}`);
fs.writeFileSync(file, JSON.stringify(results));
core.info(`Saved ${tool} results to ${file}`);

const fileContent = stringifyResults ? JSON.stringify(results) : results;
fs.writeFileSync(file, fileContent);

const logMessage = `Saved ${tool} results to ${file}`;
core.info(logMessage);

return file;
}

Expand Down Expand Up @@ -125,3 +129,11 @@ async function fetchDefectDojoFindings(){

return findings;
}

async function fetchContrastFindings(): Promise<any>{
const inputs = getContrastInputs();
const results = await retrieveContrastResults(inputs);

core.info(`Found Contrast findings`);
return results;
}
Loading