89 lines
5.3 KiB
TypeScript
89 lines
5.3 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import type { UnifiedResultProjection } from '../../src/domain/unified-result';
|
|
import { materializeResultDb } from '../../src/domain/result-db-materialization';
|
|
|
|
const comparator = (relation: 'match' | 'different', expected: string) => ({
|
|
version: 1 as const, comparator: { kind: 'equality' as const }, relation,
|
|
actual: { kind: 'text' as const, value: '0' }, baseline: { kind: 'text' as const, value: expected }, diagnosticCodes: []
|
|
});
|
|
|
|
/** One GPO baseline comparison, as the evaluation stores it per compared baseline release. */
|
|
function comparison(id: string, overrides: Partial<UnifiedResultProjection> = {}, expected = '1'): UnifiedResultProjection {
|
|
const relation = overrides.policyClassification === 'match' ? 'match' : 'different';
|
|
return {
|
|
resultProjectionId: `policy-evaluation-comparison:${id}`, sourceKind: 'policy-evaluation', sourceResultId: id,
|
|
projectId: 'project-1', assessmentId: 'assessment-1', collectionRunId: 'aggregation-1', evaluationRunId: 'evaluation-1',
|
|
sourceTool: 'GPOs', sourceRuleId: 'gpo-identity-1', title: 'Synthetic setting · SyntheticValue',
|
|
severityOriginal: null, severityNormalized: 'unknown', outcomeOriginal: 'confirmed_configured_deviation',
|
|
outcomeNormalized: 'fail', technicalExecutionState: 'completed', resultType: 'policy_deviation',
|
|
isIoe: false, isDeviation: true, lifecycleState: 'unknown', mappingConfidence: 1,
|
|
reviewStatus: 'unreviewed', importedAt: '2026-10-06T08:00:00.000Z', createdAt: '2026-10-06T08:00:00.000Z',
|
|
policyScope: 'computer', policyDeliveryMechanism: 'registry-policy', policyIdentityKey: 'gpo-identity-1',
|
|
policyBaselineId: `baseline-${id}`, policyBaselineLabel: 'Windows Server 2022 Security Baseline',
|
|
policyBaselineValue: { kind: 'text', value: expected }, policyActualValue: { kind: 'text', value: '0' },
|
|
policyBaselineVariantAssessment: { version: 1, scope: 'backup-configuration',
|
|
decision: relation === 'match' ? 'all-pass' : 'all-fail', actualValues: [],
|
|
variants: [{ settingId: `setting-${id}`, baselineValues: [], comparator: comparator(relation, expected) }], diagnosticCodes: [] },
|
|
policyComparisonRelation: relation, policyCustomerState: 'configured', policyClassification: 'misconfigured',
|
|
frameworkReferences: [], categories: [],
|
|
...overrides
|
|
};
|
|
}
|
|
|
|
const passed = { outcomeNormalized: 'pass', isDeviation: false, policyClassification: 'match',
|
|
policyComparisonRelation: 'match' } as const;
|
|
|
|
function gpoRows(sources: UnifiedResultProjection[]): UnifiedResultProjection[] {
|
|
return materializeResultDb(sources, new Map(), 1, '2026-10-06T08:00:00.000Z').rows
|
|
.filter(row => row.sourceKind === 'policy-evaluation');
|
|
}
|
|
|
|
describe('Result DB GPO comparisons: one row per setting like Work (user decision 2026-10-06)', () => {
|
|
it('combines every baseline release and family of one setting into one row', () => {
|
|
const rows = gpoRows([
|
|
comparison('b-server-2025', { policyBaselineLabel: 'Windows Server 2025 Security Baseline' }),
|
|
comparison('a-server-2022'),
|
|
comparison('c-client', { policyBaselineLabel: 'Windows 11 v24H2 Security Baseline' })
|
|
]);
|
|
expect(rows).toHaveLength(1);
|
|
expect(rows[0]).toMatchObject({
|
|
resultProjectionId: 'policy-evaluation-comparison:a-server-2022',
|
|
policyBaselineLabel: 'Microsoft Security Baseline - Windows Client; Microsoft Security Baseline - Windows Server',
|
|
policyBaselineValue: { kind: 'text', value: '1' }
|
|
});
|
|
expect(rows[0].policyBaselineVariantAssessment?.variants).toHaveLength(1);
|
|
expect(rows[0].disclosureTrace?.redactions).toContainEqual({ field: 'row', rule: 'baseline-comparisons-combined', count: 2 });
|
|
});
|
|
|
|
it('takes the strongest verdict and keeps every distinct expectation', () => {
|
|
const [row] = gpoRows([
|
|
comparison('a-client', { ...passed, policyBaselineLabel: 'Windows 11 v24H2 Security Baseline' }, '0'),
|
|
comparison('b-server', {}, '1')
|
|
]);
|
|
expect(row).toMatchObject({ outcomeNormalized: 'fail', isDeviation: true, policyClassification: 'misconfigured',
|
|
resultProjectionId: 'policy-evaluation-comparison:a-client', policyBaselineValue: undefined });
|
|
expect(row.policyBaselineVariantAssessment).toMatchObject({ decision: 'mixed' });
|
|
expect(row.policyBaselineVariantAssessment?.variants.map(variant => variant.comparator.baseline))
|
|
.toEqual([{ kind: 'text', value: '0' }, { kind: 'text', value: '1' }]);
|
|
});
|
|
|
|
it('keeps different settings apart even when their visible content is identical', () => {
|
|
const rows = gpoRows([
|
|
comparison('a'),
|
|
comparison('b', { policyIdentityKey: 'gpo-identity-2' }),
|
|
comparison('c', { policyScope: 'user' }),
|
|
comparison('d', { collectionRunId: 'aggregation-2', assessmentId: 'assessment-2', evaluationRunId: 'evaluation-2' })
|
|
]);
|
|
expect(rows).toHaveLength(4);
|
|
});
|
|
|
|
it('never combines scanner findings', () => {
|
|
const scanner = (id: string): UnifiedResultProjection => ({
|
|
...comparison(id), resultProjectionId: `scanner-finding:${id}`, sourceKind: 'scanner-finding', sourceTool: 'maester',
|
|
sourceRuleId: 'MT.1001', title: 'Synthetic rule', resultType: 'compliance_check'
|
|
});
|
|
const { rows } = materializeResultDb([scanner('1'), scanner('2')], new Map(), 1, '2026-10-06T08:00:00.000Z');
|
|
expect(rows).toHaveLength(2);
|
|
});
|
|
});
|