perf(core): Lazyload security audit reporters (#7696)

Also converting to service.

Followup to https://github.com/n8n-io/n8n/pull/7663
This commit is contained in:
Iván Ovejero
2023-11-13 11:50:43 +01:00
committed by GitHub
parent a08fca51d9
commit b2ca050031
24 changed files with 779 additions and 718 deletions

View File

@@ -1,7 +1,7 @@
import { v4 as uuid } from 'uuid';
import config from '@/config';
import { audit } from '@/audit';
import { CREDENTIALS_REPORT } from '@/audit/constants';
import { SecurityAuditService } from '@/security-audit/SecurityAudit.service';
import { CREDENTIALS_REPORT } from '@/security-audit/constants';
import { getRiskSection } from './utils';
import * as testDb from '../shared/testDb';
import { generateNanoId } from '@db/utils/generators';
@@ -11,8 +11,12 @@ import { CredentialsRepository } from '@db/repositories/credentials.repository';
import { ExecutionRepository } from '@db/repositories/execution.repository';
import { ExecutionDataRepository } from '@db/repositories/executionData.repository';
let securityAuditService: SecurityAuditService;
beforeAll(async () => {
await testDb.init();
securityAuditService = new SecurityAuditService(Container.get(WorkflowRepository));
});
beforeEach(async () => {
@@ -54,7 +58,7 @@ test('should report credentials not in any use', async () => {
Container.get(WorkflowRepository).save(workflowDetails),
]);
const testAudit = await audit(['credentials']);
const testAudit = await securityAuditService.run(['credentials']);
const section = getRiskSection(
testAudit,
@@ -99,7 +103,7 @@ test('should report credentials not in active use', async () => {
await Container.get(WorkflowRepository).save(workflowDetails);
const testAudit = await audit(['credentials']);
const testAudit = await securityAuditService.run(['credentials']);
const section = getRiskSection(
testAudit,
@@ -167,7 +171,7 @@ test('should report credential in not recently executed workflow', async () => {
workflowData: workflow,
});
const testAudit = await audit(['credentials']);
const testAudit = await securityAuditService.run(['credentials']);
const section = getRiskSection(
testAudit,
@@ -236,7 +240,7 @@ test('should not report credentials in recently executed workflow', async () =>
workflowData: workflow,
});
const testAudit = await audit(['credentials']);
const testAudit = await securityAuditService.run(['credentials']);
expect(testAudit).toBeEmptyArray();
});

View File

@@ -1,18 +1,22 @@
import { v4 as uuid } from 'uuid';
import { audit } from '@/audit';
import { SecurityAuditService } from '@/security-audit/SecurityAudit.service';
import {
DATABASE_REPORT,
SQL_NODE_TYPES,
SQL_NODE_TYPES_WITH_QUERY_PARAMS,
} from '@/audit/constants';
} from '@/security-audit/constants';
import { getRiskSection, saveManualTriggerWorkflow } from './utils';
import * as testDb from '../shared/testDb';
import { generateNanoId } from '@db/utils/generators';
import { WorkflowRepository } from '@db/repositories/workflow.repository';
import Container from 'typedi';
let securityAuditService: SecurityAuditService;
beforeAll(async () => {
await testDb.init();
securityAuditService = new SecurityAuditService(Container.get(WorkflowRepository));
});
beforeEach(async () => {
@@ -56,7 +60,7 @@ test('should report expressions in queries', async () => {
await Promise.all(promises);
const testAudit = await audit(['database']);
const testAudit = await securityAuditService.run(['database']);
const section = getRiskSection(
testAudit,
@@ -111,7 +115,7 @@ test('should report expressions in query params', async () => {
await Promise.all(promises);
const testAudit = await audit(['database']);
const testAudit = await securityAuditService.run(['database']);
const section = getRiskSection(
testAudit,
@@ -163,7 +167,7 @@ test('should report unused query params', async () => {
await Promise.all(promises);
const testAudit = await audit(['database']);
const testAudit = await securityAuditService.run(['database']);
const section = getRiskSection(
testAudit,
@@ -183,7 +187,7 @@ test('should report unused query params', async () => {
test('should not report non-database node', async () => {
await saveManualTriggerWorkflow();
const testAudit = await audit(['database']);
const testAudit = await securityAuditService.run(['database']);
expect(testAudit).toBeEmptyArray();
});

View File

@@ -1,13 +1,17 @@
import { v4 as uuid } from 'uuid';
import { audit } from '@/audit';
import { FILESYSTEM_INTERACTION_NODE_TYPES, FILESYSTEM_REPORT } from '@/audit/constants';
import { SecurityAuditService } from '@/security-audit/SecurityAudit.service';
import { FILESYSTEM_INTERACTION_NODE_TYPES, FILESYSTEM_REPORT } from '@/security-audit/constants';
import { getRiskSection, saveManualTriggerWorkflow } from './utils';
import * as testDb from '../shared/testDb';
import { WorkflowRepository } from '@db/repositories/workflow.repository';
import Container from 'typedi';
let securityAuditService: SecurityAuditService;
beforeAll(async () => {
await testDb.init();
securityAuditService = new SecurityAuditService(Container.get(WorkflowRepository));
});
beforeEach(async () => {
@@ -48,7 +52,7 @@ test('should report filesystem interaction nodes', async () => {
await Promise.all(promises);
const testAudit = await audit(['filesystem']);
const testAudit = await securityAuditService.run(['filesystem']);
const section = getRiskSection(
testAudit,
@@ -68,7 +72,7 @@ test('should report filesystem interaction nodes', async () => {
test('should not report non-filesystem-interaction node', async () => {
await saveManualTriggerWorkflow();
const testAudit = await audit(['filesystem']);
const testAudit = await securityAuditService.run(['filesystem']);
expect(testAudit).toBeEmptyArray();
});

View File

@@ -1,6 +1,6 @@
import { v4 as uuid } from 'uuid';
import { audit } from '@/audit';
import { INSTANCE_REPORT, WEBHOOK_VALIDATOR_NODE_TYPES } from '@/audit/constants';
import { SecurityAuditService } from '@/security-audit/SecurityAudit.service';
import { INSTANCE_REPORT, WEBHOOK_VALIDATOR_NODE_TYPES } from '@/security-audit/constants';
import {
getRiskSection,
saveManualTriggerWorkflow,
@@ -9,15 +9,19 @@ import {
simulateUpToDateInstance,
} from './utils';
import * as testDb from '../shared/testDb';
import { toReportTitle } from '@/audit/utils';
import { toReportTitle } from '@/security-audit/utils';
import config from '@/config';
import { generateNanoId } from '@db/utils/generators';
import { WorkflowRepository } from '@db/repositories/workflow.repository';
import Container from 'typedi';
let securityAuditService: SecurityAuditService;
beforeAll(async () => {
await testDb.init();
securityAuditService = new SecurityAuditService(Container.get(WorkflowRepository));
simulateUpToDateInstance();
});
@@ -56,7 +60,7 @@ test('should report webhook lacking authentication', async () => {
await Container.get(WorkflowRepository).save(details);
const testAudit = await audit(['instance']);
const testAudit = await securityAuditService.run(['instance']);
const section = getRiskSection(
testAudit,
@@ -103,10 +107,12 @@ test('should not report webhooks having basic or header auth', async () => {
await Promise.all(promises);
const testAudit = await audit(['instance']);
if (Array.isArray(testAudit)) fail('audit is empty');
const testAudit = await securityAuditService.run(['instance']);
if (Array.isArray(testAudit)) fail('Audit is empty');
const report = testAudit[toReportTitle('instance')];
if (!report) {
fail('Expected test audit to have instance risk report');
}
@@ -164,7 +170,7 @@ test('should not report webhooks validated by direct children', async () => {
await Promise.all(promises);
const testAudit = await audit(['instance']);
const testAudit = await securityAuditService.run(['instance']);
if (Array.isArray(testAudit)) fail('audit is empty');
const report = testAudit[toReportTitle('instance')];
@@ -180,7 +186,7 @@ test('should not report webhooks validated by direct children', async () => {
test('should not report non-webhook node', async () => {
await saveManualTriggerWorkflow();
const testAudit = await audit(['instance']);
const testAudit = await securityAuditService.run(['instance']);
if (Array.isArray(testAudit)) fail('audit is empty');
const report = testAudit[toReportTitle('instance')];
@@ -197,7 +203,7 @@ test('should not report non-webhook node', async () => {
test('should report outdated instance when outdated', async () => {
simulateOutdatedInstanceOnce();
const testAudit = await audit(['instance']);
const testAudit = await securityAuditService.run(['instance']);
const section = getRiskSection(
testAudit,
@@ -215,7 +221,7 @@ test('should report outdated instance when outdated', async () => {
});
test('should not report outdated instance when up to date', async () => {
const testAudit = await audit(['instance']);
const testAudit = await securityAuditService.run(['instance']);
if (Array.isArray(testAudit)) fail('audit is empty');
const report = testAudit[toReportTitle('instance')];
@@ -231,7 +237,7 @@ test('should not report outdated instance when up to date', async () => {
test('should report security settings', async () => {
config.set('diagnostics.enabled', true);
const testAudit = await audit(['instance']);
const testAudit = await securityAuditService.run(['instance']);
const section = getRiskSection(
testAudit,

View File

@@ -1,8 +1,8 @@
import { v4 as uuid } from 'uuid';
import { Container } from 'typedi';
import { audit } from '@/audit';
import { OFFICIAL_RISKY_NODE_TYPES, NODES_REPORT } from '@/audit/constants';
import { toReportTitle } from '@/audit/utils';
import { SecurityAuditService } from '@/security-audit/SecurityAudit.service';
import { OFFICIAL_RISKY_NODE_TYPES, NODES_REPORT } from '@/security-audit/constants';
import { toReportTitle } from '@/security-audit/utils';
import { LoadNodesAndCredentials } from '@/LoadNodesAndCredentials';
import { NodeTypes } from '@/NodeTypes';
import { CommunityPackagesService } from '@/services/communityPackages.service';
@@ -18,8 +18,12 @@ mockInstance(NodeTypes);
const communityPackagesService = mockInstance(CommunityPackagesService);
Container.set(CommunityPackagesService, communityPackagesService);
let securityAuditService: SecurityAuditService;
beforeAll(async () => {
await testDb.init();
securityAuditService = new SecurityAuditService(Container.get(WorkflowRepository));
});
beforeEach(async () => {
@@ -59,7 +63,7 @@ test('should report risky official nodes', async () => {
await Promise.all(promises);
const testAudit = await audit(['nodes']);
const testAudit = await securityAuditService.run(['nodes']);
const section = getRiskSection(
testAudit,
@@ -80,10 +84,12 @@ test('should not report non-risky official nodes', async () => {
communityPackagesService.getAllInstalledPackages.mockResolvedValue(MOCK_PACKAGE);
await saveManualTriggerWorkflow();
const testAudit = await audit(['nodes']);
const testAudit = await securityAuditService.run(['nodes']);
if (Array.isArray(testAudit)) return;
const report = testAudit[toReportTitle('nodes')];
if (!report) return;
for (const section of report.sections) {
@@ -94,7 +100,7 @@ test('should not report non-risky official nodes', async () => {
test('should report community nodes', async () => {
communityPackagesService.getAllInstalledPackages.mockResolvedValue(MOCK_PACKAGE);
const testAudit = await audit(['nodes']);
const testAudit = await securityAuditService.run(['nodes']);
const section = getRiskSection(
testAudit,

View File

@@ -1,9 +1,9 @@
import nock from 'nock';
import config from '@/config';
import { v4 as uuid } from 'uuid';
import { toReportTitle } from '@/audit/utils';
import { toReportTitle } from '@/security-audit/utils';
import * as constants from '@/constants';
import type { Risk } from '@/audit/types';
import type { Risk } from '@/security-audit/types';
import type { InstalledNodes } from '@db/entities/InstalledNodes';
import type { InstalledPackages } from '@db/entities/InstalledPackages';
import { WorkflowRepository } from '@db/repositories/workflow.repository';