Skip to content

Commit

Permalink
feat(scan): print warnings on scan run (#544)
Browse files Browse the repository at this point in the history
closes #545
  • Loading branch information
nzvtrk authored May 14, 2024
1 parent b6d75b0 commit 0b0b148
Show file tree
Hide file tree
Showing 5 changed files with 169 additions and 8 deletions.
146 changes: 145 additions & 1 deletion src/Commands/RunScan.spec.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,26 @@
import 'reflect-metadata';
import { Logger, logger } from '../Utils';
import { RunScan } from './RunScan';
import { anything, reset, spy, verify, when } from 'ts-mockito';
import {
AttackParamLocation,
Exclusions,
Module,
Scans,
ScanWarning,
TestType
} from '../Scan';
import {
anything,
instance,
mock,
objectContaining,
reset,
spy,
verify,
when
} from 'ts-mockito';
import { container } from 'tsyringe';
import { Arguments } from 'yargs';

describe('RunScan', () => {
let processSpy!: NodeJS.Process;
Expand Down Expand Up @@ -67,4 +86,129 @@ describe('RunScan', () => {
expect(act).toThrowError(SyntaxError);
});
});

describe('handler', () => {
let runScan!: RunScan;
const mockedScans = mock<Scans>();

beforeEach(() => {
container.registerInstance(Scans, instance(mockedScans));
runScan = new RunScan();
});

afterEach(() => {
container.clearInstances();
reset(mockedScans);
});

it('should correctly pass scan config from args', async () => {
// arrange
const args = {
test: ['test1', 'test2'],
name: 'test-scan',
module: 'test-module',
auth: 'test-auth',
project: 'test-project',
template: 'test-template',
bucket: ['test-bucket'],
hostFilter: ['test-host'],
header: ['header1', 'header2'],
crawler: ['test-crawler'],
archive: 'test-archive',
repeater: ['test-repeater'],
smart: true,
param: ['param1', 'param2'],
excludeEntryPoint: ['exclude-entry-point'],
excludeParam: ['exclude-param'],
_: [],
$0: ''
} as Arguments;

when(processSpy.exit(anything())).thenReturn(undefined);
when(
mockedScans.create(
objectContaining({
tests: args.test as TestType[],
name: args.name as string,
module: args.module as Module,
authObjectId: args.auth as string,
projectId: args.project as string,
templateId: args.template as string,
buckets: args.bucket as string[],
hostsFilter: args.hostFilter as string[],
crawlerUrls: args.crawler as string[],
fileId: args.archive as string,
repeaters: args.repeater as string[],
smart: args.smart as boolean,
attackParamLocations: args.param as AttackParamLocation[],
exclusions: {
requests: args.excludeEntryPoint,
params: args.excludeParam
} as Exclusions
})
)
).thenResolve({ id: 'test-scan-id', warnings: [] });

// act
await runScan.handler(args);

// assert
verify(processSpy.exit(0)).once();
verify(loggerSpy.error(anything())).never();
verify(loggerSpy.warn(anything())).never();
});

it('should throw an error on create request fall', async () => {
// arrange
const args = {
name: 'test-scan',
_: [],
$0: ''
} as Arguments;
const errMessage = 'request error';

when(processSpy.exit(anything())).thenReturn(undefined);
when(
mockedScans.create(
objectContaining({
name: args.name as string
})
)
).thenReject(new Error(errMessage));

// act
await runScan.handler(args);

// assert
verify(processSpy.exit(1)).once();
verify(loggerSpy.error(`Error during "scan:run": ${errMessage}`)).once();
});

it('should display warnings when present', async () => {
// arrange
const args = {
name: 'test-scan',
_: [],
$0: ''
} as Arguments;

const warnings: ScanWarning[] = [
{ message: 'Warning message 1', code: '123' },
{ message: 'Warning message 2', code: '124' }
];

when(processSpy.exit(anything())).thenReturn(undefined);
when(mockedScans.create(anything())).thenResolve({
id: 'test-scan-id',
warnings
});

// act
await runScan.handler(args);

// assert
verify(processSpy.exit(0)).once();
verify(loggerSpy.warn('Warning message 1\nWarning message 2\n')).once();
});
});
});
8 changes: 7 additions & 1 deletion src/Commands/RunScan.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export class RunScan implements CommandModule {
try {
const scanManager: Scans = container.resolve(Scans);

const scanId: string = await scanManager.create({
const { id: scanId, warnings = [] } = await scanManager.create({
tests: args.test,
name: args.name,
module: args.module,
Expand All @@ -198,6 +198,12 @@ export class RunScan implements CommandModule {
// eslint-disable-next-line no-console
console.log(scanId);

if (warnings.length) {
logger.warn(
`${warnings.map((warning) => warning.message).join('\n')}\n`
);
}

process.exit(0);
} catch (e) {
logger.error(`Error during "scan:run": ${e.error || e.message}`);
Expand Down
2 changes: 1 addition & 1 deletion src/Scan/RestScans.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ describe('RestScans', () => {
const result = await restScans.create(scanConfig);

// assert
expect(result).toEqual(postResponse.id);
expect(result).toEqual({ id: postResponse.id });
expect(parsedBody).toMatchObject({
discoveryTypes: expect.arrayContaining<Discovery>([expected])
});
Expand Down
9 changes: 5 additions & 4 deletions src/Scan/RestScans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ import {
SourceType,
StorageFile,
SCAN_TESTS_TO_RUN_BY_DEFAULT,
ATTACK_PARAM_LOCATIONS_DEFAULT
ATTACK_PARAM_LOCATIONS_DEFAULT,
ScanCreateResponse
} from './Scans';
import { CliInfo } from '../Config';
import { ProxyFactory } from '../Utils';
Expand Down Expand Up @@ -56,15 +57,15 @@ export class RestScans implements Scans {
});
}

public async create(body: ScanConfig): Promise<string> {
public async create(body: ScanConfig): Promise<ScanCreateResponse> {
const scanConfig = await this.prepareScanConfig({ ...body });

const res = await this.client.post<{ id: string }>(
const res = await this.client.post<ScanCreateResponse>(
'/api/v1/scans',
scanConfig
);

return res.data.id;
return res.data;
}

public async retest(scanId: string): Promise<string> {
Expand Down
12 changes: 11 additions & 1 deletion src/Scan/Scans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,8 +195,18 @@ export interface StorageFile {
type: SourceType;
}

export interface ScanWarning {
code: string;
message: string;
}

export interface ScanCreateResponse {
id: string;
warnings: ScanWarning[];
}

export interface Scans {
create(body: ScanConfig): Promise<string>;
create(body: ScanConfig): Promise<ScanCreateResponse>;

retest(scanId: string): Promise<string>;

Expand Down

0 comments on commit 0b0b148

Please sign in to comment.