Skip to content

Commit

Permalink
Improve findings retrieval
Browse files Browse the repository at this point in the history
- Allow filtering by product only
- Increase findings fetch limit
  • Loading branch information
GaelGirodon committed Dec 21, 2023
1 parent 5d88c84 commit 595ab48
Show file tree
Hide file tree
Showing 5 changed files with 27 additions and 18 deletions.
3 changes: 2 additions & 1 deletion src/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ const expectedOptions = [
name: "engagement",
env: "DEFECTDOJO_ENGAGEMENT",
description: "Engagement name on DefectDojo",
pattern: /^[\w/.-]+$/
pattern: /^[\w/.-]+$/,
default: null
},
{
name: "status",
Expand Down
24 changes: 16 additions & 8 deletions src/defectdojo.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,22 +75,30 @@ export class DefectDojoApiClient {
}

/**
* Fetch vulnerabilities associated to one or multiple engagements.
* Fetch vulnerabilities associated to one or multiple products
* and engagements.
*
* @param {string[]} engagements Engagements ids
* @param {string[]} products Products ids
* @param {string[]} engagements Engagements ids (optional)
* @param {string[]} statuses Statuses to filter
* @returns Vulnerabilities
* @throws Request error
*/
async getFindings(engagements, statuses) {
console.log(`[info] Fetching findings for engagement(s) ${engagements.join(", ")}`);
async getFindings(products, engagements, statuses) {
console.log(`[info] Fetching findings for product(s) [${products.join(", ")}]`
+ ` and engagement(s) [${engagements.join(", ")}]`);
try {
const filters = statuses.map(s => s[0] !== "!" ? s + "=true" : s.slice(1) + "=false").join("&");
let findingsUrl = `/findings?test__engagement=${engagements.join(",")}`
+ `&limit=100&${filters}&related_fields=true`;
const query = [];
query.push(`test__engagement__product=${products.join(",")}`);
if (engagements?.length > 0) {
query.push(`test__engagement=${engagements.join(",")}`);
}
query.push(...statuses.map(s => s[0] !== "!" ? s + "=true" : s.slice(1) + "=false"));
query.push("limit=100", "related_fields=true");
let findingsUrl = "/findings?" + query.join("&");
const findings = [];
let findingsPage = 0;
while (findingsUrl && findingsPage < 20) {
while (findingsUrl && findingsPage < 100) {
console.log(`[info] Fetching findings (page ${findingsPage}): ${findingsUrl}`);
let findingsResponse = await this.http.get(findingsUrl);
let findingsData = findingsResponse.data;
Expand Down
15 changes: 8 additions & 7 deletions src/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,17 @@ export async function main() {
}, []);

// Fetch engagements
const engagements = await products.reduce(async (prevResults, p) => {
const results = await prevResults;
const engagement = await defectDojo.getEngagement(p.id, opts.engagement)
.catch((e) => { console.error(`[error] ${e.message}`); process.exit(1); });
return [...results, engagement];
}, []);
const engagements = !opts.engagement ? [] :
await products.reduce(async (prevResults, p) => {
const results = await prevResults;
const engagement = await defectDojo.getEngagement(p.id, opts.engagement)
.catch((e) => { console.error(`[error] ${e.message}`); process.exit(1); });
return [...results, engagement];
}, []);

// Fetch vulnerabilities
const findings = await defectDojo
.getFindings(engagements.map(e => e.id), opts.status)
.getFindings(products.map(p => p.id), engagements.map(e => e.id), opts.status)
.catch((e) => { console.error(`[error] ${e.message}`); process.exit(1); });

/*
Expand Down
1 change: 0 additions & 1 deletion test/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ describe("cli", function () {
{ name: "reject an invalid token", cli: [...url, "--token", "invalid", ...product, ...engagement], code: 1 },
{ name: "require the product", cli: [...url, ...token, ...engagement], code: 1 },
{ name: "reject an invalid product", cli: [...url, ...token, "--product", "***", ...engagement], code: 1 },
{ name: "require the engagement", cli: [...url, ...token, ...product], code: 1 },
{ name: "reject an invalid engagement", cli: [...url, ...token, ...product, "--engagement", "***"], code: 1 },
{ name: "reject an invalid config file", cli: [...cli, "--config", "./notfound.json"], code: 1 }
];
Expand Down
2 changes: 1 addition & 1 deletion test/defectdojo.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe("DefectDojoApiClient", function () {
describe("#getFindings()", function () {
it("should return findings", async function () {
let findings;
await assert.doesNotReject(async () => findings = await client.getFindings([], []));
await assert.doesNotReject(async () => findings = await client.getFindings([], [], []));
assert.strictEqual(10, findings.length);
});
it("should throw if something went wrong", async function () {
Expand Down

0 comments on commit 595ab48

Please sign in to comment.