Assessor_2.0/tests/features/mitre-graph.test.ts

93 lines
3.7 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { buildFindingPathItems, extractFindingMitreFocus, sharedEntityIds, type MitreEntity, type MitreGraphData } from '../../src/features/mitre-graph/mitre-graph';
import type { FindingRecord } from '../../src/domain/finding';
const record = (value: string): FindingRecord => ({
id: value,
index: 0,
title: 'Finding',
fields: [{ label: 'MITRE ATT&CK', value, index: 0 }],
filled: [],
meta: []
});
describe('MITRE graph', () => {
it('erkennt Technik-IDs und Taktiknamen aus Findings', () => {
const focus = extractFindingMitreFocus(
[record('T1059.001; Persistence / Privilege Escalation')],
['Persistence', 'Privilege Escalation']
);
expect([...focus.techniqueIds]).toEqual(['T1059.001']);
expect([...focus.tactics]).toEqual(['Persistence', 'Privilege Escalation']);
expect(focus.findingCount).toBe(1);
});
it('ordnet Findings als Pfadschritte einer primären Taktik zu', () => {
const data: MitreGraphData = {
version: 'test',
tacticOrder: ['Execution', 'Persistence'],
techniques: [{ id: 'T1059.001', name: 'PowerShell', tactics: ['Execution'], platforms: ['Windows'], parent: 'T1059', url: '', sourceCount: 1 }],
entities: []
};
const item = buildFindingPathItems([record('T1059.001, Persistence')], data)[0];
expect(item.primaryTactic).toBe('Execution');
expect(item.tactics).toEqual(['Execution', 'Persistence']);
expect(item.techniqueIds).toEqual(['T1059.001']);
});
it('bewahrt mehrere Kategorien und D3FEND-Beziehungen für den Netzwerkgraphen', () => {
const source = record('Execution / Persistence');
source.fields.push(
{ label: 'Category', value: 'Identity | Lateral Movement', index: 1 },
{ label: 'MITRE D3FEND', value: 'Harden - Credential Hardening; Detect - Account Monitoring', index: 2 },
{ label: 'Target', value: 'DC-01 | Tier 0', index: 3 }
);
const data: MitreGraphData = {
version: 'test',
tacticOrder: ['Execution', 'Persistence'],
techniques: [],
entities: []
};
const item = buildFindingPathItems([source], data)[0];
expect(item.categories).toEqual(['Identity', 'Lateral Movement']);
expect(item.defenses).toEqual(['Harden - Credential Hardening', 'Detect - Account Monitoring']);
expect(item.targets).toEqual(['DC-01', 'Tier 0']);
expect(item.tactics).toEqual(['Execution', 'Persistence']);
});
it('erzeugt keine Kategorie aus dem Quellblatt oder All-Records-Kontext', () => {
const source = { ...record('Execution'), sourceSheet: 'Dummy · All Records' };
const data: MitreGraphData = { version: 'test', tacticOrder: ['Execution'], techniques: [], entities: [] };
const item = buildFindingPathItems([source], data)[0];
expect(item.category).toBe('');
expect(item.categories).toEqual([]);
expect(item.targets).toEqual([]);
});
it('leitet CIS-Kategorien aus allen Eltern einer Benchmark-Regelnummer ab', () => {
const source = record('');
source.fields.push({ label: 'Rule ID', value: '17.2.4', index: 1 });
const data: MitreGraphData = { version: 'test', tacticOrder: [], techniques: [], entities: [] };
const item = buildFindingPathItems([source], data, '', 'cis-cat')[0];
expect(item.categories).toEqual(['CIS 17', 'CIS 17.2']);
});
it('ermittelt gemeinsame MITRE-Kontexte nach Typ', () => {
const entities: MitreEntity[] = [
{ id: 'G1', name: 'Group', type: 'group', techniques: ['T1', 'T2'] },
{ id: 'S1', name: 'Software', type: 'software', techniques: ['T1', 'T2'] }
];
expect(sharedEntityIds('T1', 'T2', entities, 'all')).toEqual(['G1', 'S1']);
expect(sharedEntityIds('T1', 'T2', entities, 'group')).toEqual(['G1']);
});
});