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

Feature/code ql control #61

Merged
merged 15 commits into from
Apr 15, 2024
10 changes: 7 additions & 3 deletions src/branchprotection/BranchProtectionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,14 @@ export class BranchProtectionService {

core.exportVariable('numberOfReviewers', numberOfReviewers);
} catch (error) {
core.warning('Error getting branch protection!');
console.log('Error:', error.message);
if (error.status === 403) {
// Status code '404' means 'Branch not protected'
if (error.status === 404) {
console.log('Branch protection is not enabled for this repository');
core.exportVariable('numberOfReviewers', 0);
} else {
core.warning('Error getting branch protection!');
console.log('ERROR STATUS:', error.status);
console.log(error);
}
}
}
Expand Down
74 changes: 74 additions & 0 deletions src/sasttools/CodeQLService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import * as core from '@actions/core';
import * as github from '@actions/github';
import { Octokit } from '@octokit/rest';
import GITHUB_TOOL_SEVERITY_LEVEL from '../types/GithubToolSeverityLevel';
import { GetResponseDataTypeFromEndpointMethod, OctokitResponse } from '@octokit/types';

export class CodeQLService {
public static async setCodeQLFindings(): Promise<void> {
try {
const { owner, repo }: { owner: string; repo: string } = github.context.repo;
const token: string = core.getInput('PAT-token');

const octokit: Octokit = new Octokit({
auth: token,
});

type CodeScanningAlertsForRepoResponseDataType = GetResponseDataTypeFromEndpointMethod<
typeof octokit.codeScanning.listAlertsForRepo
>;

// https://www.npmjs.com/package/octokit#pagination
const iterator: AsyncIterableIterator<OctokitResponse<CodeScanningAlertsForRepoResponseDataType>> =
octokit.paginate.iterator(octokit.codeScanning.listAlertsForRepo, {
owner: owner,
repo: repo,
per_page: 100,
state: 'open',
tool_name: 'CodeQL',
});

let sastNumberOfSeverity1: number = 0;
let sastNumberOfSeverity2: number = 0;
let sastNumberOfSeverity3: number = 0;
let sastNumberOfSeverity4: number = 0;

for await (const { data: alerts } of iterator) {
for (const alert of alerts) {
switch (alert.rule.security_severity_level) {
case GITHUB_TOOL_SEVERITY_LEVEL.LOW:
sastNumberOfSeverity1++;
break;
case GITHUB_TOOL_SEVERITY_LEVEL.MEDIUM:
sastNumberOfSeverity2++;
break;
case GITHUB_TOOL_SEVERITY_LEVEL.HIGH:
sastNumberOfSeverity3++;
break;
case GITHUB_TOOL_SEVERITY_LEVEL.CRITICAL:
sastNumberOfSeverity4++;
break;
default:
break;
}
}
}

console.log('SASTNumberOfSeveritylow: ' + sastNumberOfSeverity1);
console.log('SASTNumberOfSeverityMedium: ' + sastNumberOfSeverity2);
console.log('SASTNumberOfSeverityHigh: ' + sastNumberOfSeverity3);
console.log('SASTNumberOfSeverityCritical: ' + sastNumberOfSeverity4);

core.exportVariable('SASTnumberOfSeverity1', sastNumberOfSeverity1);
core.exportVariable('SASTnumberOfSeverity2', sastNumberOfSeverity2);
core.exportVariable('SASTnumberOfSeverity3', sastNumberOfSeverity3);
core.exportVariable('SASTnumberOfSeverity4', sastNumberOfSeverity4);
} catch (error) {
core.warning('Could not set CodeQL severities');
core.exportVariable('SASTnumberOfSeverity1', 0);
core.exportVariable('SASTnumberOfSeverity2', 0);
core.exportVariable('SASTnumberOfSeverity3', 0);
core.exportVariable('SASTnumberOfSeverity4', 0);
}
}
}
23 changes: 14 additions & 9 deletions src/sasttools/SastService.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import * as core from '@actions/core';
import { CodeQLService } from './CodeQLService';

export class SastService {
public static async getStateOfSastTool(sastTool: { nameOfTool: string }): Promise<void> {
console.log('\n Running SAST control');
let sast: string = sastTool.nameOfTool;
if (process.env.sastTool) {
console.log(`SAST Tool: ${process.env.sastTool}`);
core.exportVariable('sastTool', process.env.sastTool);
} else {
if (!sastTool.nameOfTool || sastTool.nameOfTool === 'name-of-tool') {
core.warning('SAST Tool is not set!');
return;
}
console.log(`SAST Tool: ${sastTool.nameOfTool}`);
core.exportVariable('sastTool', sastTool.nameOfTool);
sast = process.env.sastTool;
}
console.log(`SAST Tool: ${sast}`);
core.exportVariable('sastTool', sast);

if (!sast || sast === '' || sast === 'name-of-tool') {
core.warning('SAST Tool is not set!');
return;
}

if (sast.toLowerCase() === 'codeql') {
CodeQLService.setCodeQLFindings();
}
}
}
23 changes: 13 additions & 10 deletions src/scatools/DependabotService.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import * as core from '@actions/core';
import * as github from '@actions/github';
import { Octokit } from '@octokit/rest';
import { OctokitResponse } from '@octokit/types';
import GITHUB_TOOL_SEVERITY_LEVEL from '../types/GithubToolSeverityLevel';
import { GetResponseDataTypeFromEndpointMethod, OctokitResponse } from '@octokit/types';

export class DependabotService {
public static async setDependabotFindings(): Promise<void> {
Expand All @@ -13,16 +14,18 @@ export class DependabotService {
auth: token,
});

type DependabotAlertsForRepoResponseDataType = GetResponseDataTypeFromEndpointMethod<
typeof octokit.dependabot.listAlertsForRepo
>;

// https://www.npmjs.com/package/octokit#pagination
const iterator: AsyncIterableIterator<OctokitResponse<any>> = octokit.paginate.iterator(
octokit.dependabot.listAlertsForRepo,
{
const iterator: AsyncIterableIterator<OctokitResponse<DependabotAlertsForRepoResponseDataType>> =
octokit.paginate.iterator(octokit.dependabot.listAlertsForRepo, {
owner: owner,
repo: repo,
per_page: 100,
state: 'open',
}
);
});

let scaNumberOfSeverity1: number = 0;
let scaNumberOfSeverity2: number = 0;
Expand All @@ -32,16 +35,16 @@ export class DependabotService {
for await (const { data: alerts } of iterator) {
for (const alert of alerts) {
switch (alert.security_vulnerability.severity) {
case 'low':
case GITHUB_TOOL_SEVERITY_LEVEL.LOW:
scaNumberOfSeverity1++;
break;
case 'medium':
case GITHUB_TOOL_SEVERITY_LEVEL.MEDIUM:
scaNumberOfSeverity2++;
break;
case 'high':
case GITHUB_TOOL_SEVERITY_LEVEL.HIGH:
scaNumberOfSeverity3++;
break;
case 'critical':
case GITHUB_TOOL_SEVERITY_LEVEL.CRITICAL:
scaNumberOfSeverity4++;
break;
}
Expand Down
8 changes: 8 additions & 0 deletions src/types/GithubToolSeverityLevel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
enum GITHUB_TOOL_SEVERITY_LEVEL {
LOW = 'low',
MEDIUM = 'medium',
HIGH = 'high',
CRITICAL = 'critical',
}

export default GITHUB_TOOL_SEVERITY_LEVEL;
8 changes: 4 additions & 4 deletions tests/branchprotection.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,20 @@ describe('BranchProtectionService', () => {
expect(warningStub.called).to.be.true;
expect(exportVariableStub.calledWith('numberOfReviewers', 0)).to.be.true;
});
it('should call warning and set numberOfReviewers to 0 when github repo is private (status = 403)', async () => {
it('should call warning and set numberOfReviewers to 0 when github repo is private (status = 404)', async () => {
getOctokitStub.returns({
rest: {
repos: {
getBranchProtection: sinon.stub().rejects({
status: 403,
message: 'Forbidden',
status: 404,
message: 'Branch not protected',
}),
},
},
});

await BranchProtectionService.getStateOfBranchProtection();
expect(warningStub.called).to.be.true;
expect(warningStub.called).to.be.false;
expect(exportVariableStub.calledWith('numberOfReviewers', 0)).to.be.true;
});
});
Loading