496 lines
33 KiB
TypeScript
496 lines
33 KiB
TypeScript
import { describe, expect, it } from 'vitest';
|
|
import { buildPolicyEvaluation } from '../../server/gpo/gpo-policy-evaluation-service';
|
|
import { buildPolicyFindingRun } from '../../server/gpo/gpo-policy-finding-service';
|
|
import type { MicrosoftSecurityBaselineRecord } from '../../src/domain/microsoft-security-baseline';
|
|
import type { StoredMicrosoftSecurityBaselineAnalysis } from '../../src/domain/microsoft-security-baseline-analysis';
|
|
import type { GpoPolicyValue, GpoRegistryPolicyValue } from '../../src/domain/gpo-policy';
|
|
import type { GpoTechnicalPolicyIdentity } from '../../src/domain/gpo-policy-identity';
|
|
import type { EnvironmentProfile, StoredPolicySnapshotAggregation } from '../../src/domain/gpo-snapshot-aggregation';
|
|
import type { PolicyEvaluationRuleCatalog } from '../../src/domain/policy-evaluation-rules';
|
|
import { storedPolicyEvaluationValidationErrors, type StoredPolicyEvaluation } from '../../src/domain/policy-evaluation';
|
|
import { createPolicyEvaluationUnifiedResult, type UnifiedResultProjection, selectCurrentPolicyEvaluations } from '../../src/domain/unified-result';
|
|
import { appendPolicyObservationsToDataset } from '../../src/features/project-import/policy-observations-to-dataset';
|
|
import { buildPolicyGuidance } from '../../src/profiles/group-policy/guidance';
|
|
import { filterAndSortRecords } from '../../src/features/search-filter/filter-records';
|
|
import { policyComparisonDisposition } from '../../src/domain/policy-comparison-disposition';
|
|
import { selectWorkFacets } from '../../src/features/search-filter/work-facets';
|
|
import { genericProfile } from '../../src/profiles/generic/generic-profile';
|
|
import { createElement } from 'react';
|
|
import { renderToStaticMarkup } from 'react-dom/server';
|
|
import { ResultRow } from '../../src/features/results-browser/ResultsBrowser';
|
|
|
|
const timestamp = '2026-09-06T10:00:00.000Z';
|
|
const projectId = 'synthetic-policy-project';
|
|
const identity: GpoTechnicalPolicyIdentity = {
|
|
version: 1, id: 'gpo-policy-identity-' + '1'.repeat(32),
|
|
resolver: { id: 'gpo-technical-registry-target', version: '1.0.0' }, scope: 'computer',
|
|
target: { kind: 'registry-value', hive: 'HKEY_LOCAL_MACHINE', key: 'Software\\Policies\\Synthetic', valueName: 'Mode' },
|
|
admx: { status: 'not-found' }
|
|
};
|
|
const profile: EnvironmentProfile = {
|
|
version: 1, id: 'synthetic-profile', projectId, name: 'Synthetic', revision: 1,
|
|
contexts: [{ version: 1, id: 'all', kind: 'operating-system', productFamily: 'Group Policy',
|
|
productVersion: 'All imported baselines', role: 'Any', scope: 'mixed' }], createdAt: timestamp
|
|
};
|
|
const ruleCatalog: PolicyEvaluationRuleCatalog = {
|
|
version: 1, id: 'synthetic-empty-catalog',
|
|
catalog: { id: 'policy-evaluation-rule-catalog', version: '1.0.0' }, status: 'released', rules: []
|
|
};
|
|
|
|
function value(number: number): GpoRegistryPolicyValue {
|
|
return { kind: 'registry-policy', operation: 'set-value', key: 'Software\\Policies\\Synthetic',
|
|
valueName: 'Mode', typeCode: 4, data: { kind: 'uint32', value: number } };
|
|
}
|
|
|
|
function aggregation(actual?: number, options: { partial?: boolean; conflicted?: boolean; unresolvedMember?: boolean } = {}): StoredPolicySnapshotAggregation {
|
|
const configuredValues: GpoPolicyValue[] = actual === undefined ? []
|
|
: options.conflicted ? [value(actual), value(actual + 1)] : [value(actual)];
|
|
if (options.unresolvedMember) configuredValues.push({ kind: 'service-preference', serviceName: 'Synthetic',
|
|
serviceAction: 'start', startupType: 'automatic', passwordAttributePresent: false });
|
|
const states = actual === undefined ? [] : [{
|
|
version: 1 as const, id: 'synthetic-state', aggregationRunId: 'synthetic-aggregation', identity,
|
|
deliveryMechanism: 'registry-policy' as const, status: options.conflicted ? 'conflicted' as const : 'configured' as const,
|
|
values: configuredValues,
|
|
observationIds: ['synthetic-observation'], backupInstanceIds: ['synthetic-backup'], applicableContextIds: ['all'],
|
|
ordering: options.conflicted ? 'cross-gpo-conflict' as const : 'single-gpo' as const,
|
|
targeting: 'none' as const, completeness: 'complete' as const, effectiveState: 'unknown' as const, diagnosticCodes: []
|
|
}];
|
|
return {
|
|
version: 1,
|
|
run: { version: 1, id: 'synthetic-aggregation', projectId, environmentProfileId: profile.id,
|
|
sourceAnalysisRunIds: ['synthetic-analysis'], snapshotId: 'synthetic-snapshot',
|
|
aggregator: { id: 'gpo-policy-snapshot-aggregation', version: '1.1.0' },
|
|
status: options.partial ? 'partial' : 'complete', stateCount: states.length,
|
|
conflictCount: options.conflicted ? 1 : 0, unresolvedIdentityCount: 0, reviewHintCount: 0,
|
|
permitsFindingGeneration: false, diagnosticCodes: options.partial ? ['policy-aggregation-snapshot-incomplete'] : [],
|
|
startedAt: timestamp, completedAt: timestamp },
|
|
snapshot: { version: 1, id: 'synthetic-snapshot', projectId,
|
|
domain: { status: 'resolved', key: 'synthetic.example', evidence: 'backup-metadata' },
|
|
backupSetId: 'synthetic-set', instanceIds: ['synthetic-backup'], status: 'consistent',
|
|
completeness: options.partial ? 'selected-subset' : 'complete', permitsSetAbsenceConclusions: !options.partial,
|
|
diagnosticCodes: [], createdAt: timestamp },
|
|
states,
|
|
reviewHints: []
|
|
};
|
|
}
|
|
|
|
function baseline(name: string, recommended: number): {
|
|
record: MicrosoftSecurityBaselineRecord;
|
|
analysis: StoredMicrosoftSecurityBaselineAnalysis;
|
|
} {
|
|
const baselineId = `baseline-${name}`;
|
|
const analysisId = `baseline-analysis-${name}`;
|
|
const sha256 = name.padEnd(64, 'a').slice(0, 64).replace(/[^a-f0-9]/g, 'a');
|
|
return {
|
|
record: { version: 1, id: baselineId, fileName: `${name}.zip`, sha256, sizeBytes: 100,
|
|
storageKey: `baseline/${name}`, importedAt: timestamp, status: 'eligible',
|
|
metadata: { roles: ['Any'], scopes: ['mixed'], source: 'confirmed' } },
|
|
analysis: { version: 1, analysis: { version: 1, id: analysisId, baselineId, packageSha256: sha256,
|
|
analyzer: { id: 'microsoft-baseline-gpo-settings', version: '1.1.0' }, analyzedAt: timestamp,
|
|
status: 'complete', admxCatalog: { version: 1, id: `catalog-${name}`,
|
|
parser: { id: 'admx-policy-metadata-catalog', version: '1.0.0' },
|
|
source: { kind: 'microsoft-security-baseline', baselineId, packageSha256: sha256 },
|
|
status: 'complete', policies: [], languageResources: [], diagnosticCodes: [] },
|
|
backupCount: 1, registryPolicyFileCount: 1, settings: [{ version: 1, id: `setting-${name}`,
|
|
baselineId, backupId: `backup-${name}`, observation: { sourcePath: 'synthetic/Registry.pol',
|
|
sourceSha256: 'b'.repeat(64), scope: 'computer', deliveryMechanism: 'registry-policy',
|
|
parser: { id: 'registry-policy-preg', version: '1.0.0' },
|
|
reducer: { id: 'registry-policy-reducer', version: '1.0.0' }, state: 'instruction',
|
|
values: [value(recommended)], registryPolicy: { sequence: 0, operation: 'set-value' },
|
|
effectiveState: 'unknown', diagnosticCodes: [] },
|
|
identity: { version: 1, status: 'resolved', identity } }], diagnosticCodes: [] } }
|
|
};
|
|
}
|
|
|
|
function evaluate(actual: number | undefined, sources = [baseline('primary', 1)], options: {
|
|
partial?: boolean; conflicted?: boolean; unresolvedMember?: boolean
|
|
} = {}) {
|
|
return buildPolicyEvaluation({ profile, aggregation: aggregation(actual, options),
|
|
baselineRecords: sources.map(source => source.record), baselineAnalyses: sources.map(source => source.analysis),
|
|
ruleCatalog, startedAt: timestamp, completedAt: timestamp });
|
|
}
|
|
|
|
describe('baseline-driven policy evaluation', () => {
|
|
function templates() {
|
|
const source = baseline('roles', 1);
|
|
const original = source.analysis.analysis.settings[0];
|
|
source.analysis.analysis.settings = ['Client', 'Member Server', 'Domain Controller'].map((role, index) => ({
|
|
...structuredClone(original), id: `role-setting-${index}`, backupId: `role-backup-${index}`,
|
|
observation: { ...structuredClone(original.observation), values: [value(index === 2 ? 1 : 0)] },
|
|
template: { names: [{ value: `Synthetic ${role}`, sourcePath: `Synthetic/${index}/Backup.xml`, sourceSha256: 'a'.repeat(64) }],
|
|
context: { productFamily: index === 0 ? 'Windows 10' : 'Windows Server', productVersion: index === 0 ? '1607' : '2016',
|
|
role: role as 'Client' | 'Member Server' | 'Domain Controller' } }
|
|
}));
|
|
return source;
|
|
}
|
|
function evaluateTemplates(source = templates(), target?: Partial<EnvironmentProfile['contexts'][number]>) {
|
|
const selectedProfile = target ? { ...profile, contexts: [{ ...profile.contexts[0], productFamily: 'Windows Server',
|
|
productVersion: '2016', role: 'Domain Controller', ...target }] } : profile;
|
|
return buildPolicyEvaluation({ profile: selectedProfile, aggregation: aggregation(1),
|
|
baselineRecords: [source.record], baselineAnalyses: [source.analysis], ruleCatalog,
|
|
startedAt: timestamp, completedAt: timestamp });
|
|
}
|
|
it('selects only the explicit comparison role and retains all candidate evidence', () => {
|
|
const source = templates();
|
|
const before = JSON.stringify(source);
|
|
const output = evaluateTemplates(source, {});
|
|
expect(output.results[0]).toMatchObject({ classification: 'configured_match', baselineSettingIds: ['role-setting-2'],
|
|
baselineTemplateSelection: { status: 'selected', candidateSettingIds: ['role-setting-0', 'role-setting-1', 'role-setting-2'] } });
|
|
expect(output.results[0].diagnosticCodes).not.toContain('policy-evaluation-baseline-consensus-conflict');
|
|
expect(output.evidence.filter(item => item.kind === 'baseline-setting')).toHaveLength(3);
|
|
expect(JSON.stringify(source)).toBe(before);
|
|
expect(evaluateTemplates(source, { role: 'Member Server' }).results[0].classification).toBe('confirmed_configured_deviation');
|
|
});
|
|
it('does not use observed inventory or a generic profile to choose the matching variant', () => {
|
|
for (const output of [evaluateTemplates(), evaluateTemplates(templates(), { sourceObservationIds: ['synthetic-os'] })]) {
|
|
expect(output.results[0].classification).toBe('review_required');
|
|
expect(output.results[0].diagnosticCodes).toContain('policy-evaluation-template-context-required');
|
|
expect(output.results[0].baselineSettingIds).toHaveLength(3);
|
|
}
|
|
});
|
|
it('keeps unanimous values comparable without a target-role decision', () => {
|
|
const source = templates();
|
|
source.analysis.analysis.settings.forEach(item => { item.observation.values = [value(1)]; });
|
|
expect(evaluateTemplates(source).results[0].classification).toBe('configured_match');
|
|
});
|
|
it('does not ignore unknown templates or conflicting values in the selected role', () => {
|
|
const unknown = templates();
|
|
unknown.analysis.analysis.settings[0].template = undefined;
|
|
expect(evaluateTemplates(unknown, {}).results[0].classification).toBe('review_required');
|
|
const conflict = templates();
|
|
const copy = structuredClone(conflict.analysis.analysis.settings[2]);
|
|
copy.id = 'role-setting-other'; copy.observation.values = [value(0)];
|
|
conflict.analysis.analysis.settings.push(copy);
|
|
expect(evaluateTemplates(conflict, {}).results[0]).toMatchObject({ classification: 'review_required',
|
|
baselineVariantAssessment: { decision: 'unavailable', diagnosticCodes: ['policy-evaluation-template-values-ambiguous'] } });
|
|
expect(evaluateTemplates(conflict, {}).results[0].diagnosticCodes).not.toContain('policy-evaluation-baseline-consensus-conflict');
|
|
expect(evaluate(2, [conflict]).results[0].classification).toBe('review_required');
|
|
});
|
|
it('does not produce Pass or Fail for a mismatching OS version', () => {
|
|
expect(evaluateTemplates(templates(), { productVersion: '2025' }).results[0]).toMatchObject({
|
|
classification: 'review_required', baselineTemplateSelection: { status: 'no-match' }
|
|
});
|
|
});
|
|
it('reports exact values as Passed and different values as deviations', () => {
|
|
expect(evaluate(1)).toMatchObject({ run: { status: 'complete', matchCount: 1, deviationCount: 0 },
|
|
results: [{ customerState: 'configured', classification: 'configured_match',
|
|
comparator: { relation: 'match' }, findingEligibility: 'ineligible' }] });
|
|
expect(evaluate(2)).toMatchObject({ run: { status: 'complete', matchCount: 0, deviationCount: 1 },
|
|
results: [{ customerState: 'configured', classification: 'confirmed_configured_deviation',
|
|
comparator: { relation: 'different' }, findingEligibility: 'ineligible' }] });
|
|
});
|
|
|
|
it('evaluates Registry.pol absence, key-presence and empty-text requirements in Work', () => {
|
|
const operation = (kind: 'delete-value' | 'delete-all-values' | 'create-key'): GpoRegistryPolicyValue => ({
|
|
kind: 'registry-policy', operation: kind, key: 'Software\\Policies\\Synthetic',
|
|
...(kind === 'delete-value' ? { valueName: 'Mode' } : {}),
|
|
...(kind === 'create-key' ? { typeCode: 0 as const, data: { kind: 'none' as const } } : {})
|
|
});
|
|
const assess = (expected: GpoRegistryPolicyValue, actual?: GpoRegistryPolicyValue) => {
|
|
const source = baseline(`operation-${expected.operation}-${actual?.operation ?? 'missing'}`, 1);
|
|
source.analysis.analysis.settings[0].observation.values = [expected];
|
|
const customer = actual ? aggregation(1) : aggregation(undefined);
|
|
if (actual) customer.states[0].values = [actual];
|
|
return buildPolicyEvaluation({ profile, aggregation: customer, baselineRecords: [source.record],
|
|
baselineAnalyses: [source.analysis], ruleCatalog, startedAt: timestamp, completedAt: timestamp });
|
|
};
|
|
const workStatus = (evaluation: StoredPolicyEvaluation) => {
|
|
const sheet = appendPolicyObservationsToDataset(null, 'Synthetic', [], [evaluation], new Map())!.sheets[0];
|
|
return sheet.rows[1][sheet.rows[0].indexOf('Status')];
|
|
};
|
|
|
|
for (const expected of [operation('delete-value'), operation('delete-all-values')]) {
|
|
const evaluation = assess(expected);
|
|
const absent = evaluation.results[0];
|
|
expect(absent).toMatchObject({ customerState: 'missing', classification: 'configured_match',
|
|
baselineState: 'explicit-recommendation', baselineVariantAssessment: { decision: 'all-pass' },
|
|
comparator: { relation: 'match', actual: { kind: 'registry-state', state: 'absent' } } });
|
|
expect(storedPolicyEvaluationValidationErrors(assess(expected))).toEqual([]);
|
|
expect(workStatus(evaluation)).toBe('Pass');
|
|
}
|
|
|
|
const missingKeyEvaluation = assess(operation('create-key'));
|
|
const missingKey = missingKeyEvaluation.results[0];
|
|
expect(missingKey).toMatchObject({ customerState: 'missing', classification: 'confirmed_configured_deviation',
|
|
baselineVariantAssessment: { decision: 'all-fail' } });
|
|
expect(policyComparisonDisposition(missingKey)).toBe('misconfigured');
|
|
expect(workStatus(missingKeyEvaluation)).toBe('Fail');
|
|
expect(assess(operation('create-key'), operation('create-key')).results[0]).toMatchObject({
|
|
customerState: 'configured', classification: 'configured_match', baselineVariantAssessment: { decision: 'all-pass' }
|
|
});
|
|
expect(assess(operation('delete-value'), value(1)).results[0]).toMatchObject({
|
|
classification: 'confirmed_configured_deviation', baselineVariantAssessment: { decision: 'all-fail' }
|
|
});
|
|
|
|
const assessKeyWithConfiguredChild = (expected: GpoRegistryPolicyValue) => {
|
|
const source = baseline(`key-child-${expected.operation}`, 1);
|
|
const keyIdentity: GpoTechnicalPolicyIdentity = { ...identity,
|
|
id: 'gpo-policy-identity-' + '2'.repeat(32),
|
|
target: { kind: 'registry-key', hive: 'HKEY_LOCAL_MACHINE', key: 'Software\\Policies\\Synthetic' } };
|
|
source.analysis.analysis.settings[0].identity = { version: 1, status: 'resolved', identity: keyIdentity };
|
|
source.analysis.analysis.settings[0].observation.values = [expected];
|
|
return buildPolicyEvaluation({ profile, aggregation: aggregation(1), baselineRecords: [source.record],
|
|
baselineAnalyses: [source.analysis], ruleCatalog, startedAt: timestamp, completedAt: timestamp });
|
|
};
|
|
expect(assessKeyWithConfiguredChild(operation('delete-all-values')).results[0]).toMatchObject({
|
|
customerState: 'configured', classification: 'confirmed_configured_deviation', observationIds: ['synthetic-observation'],
|
|
aggregationStateId: undefined, aggregationStateIds: ['synthetic-state'],
|
|
comparator: { actual: { kind: 'registry-state', state: 'key-present' },
|
|
baseline: { kind: 'registry-state', state: 'key-empty' } }
|
|
});
|
|
expect(assessKeyWithConfiguredChild(operation('create-key')).results[0]).toMatchObject({
|
|
customerState: 'configured', classification: 'configured_match', observationIds: ['synthetic-observation'],
|
|
comparator: { actual: { kind: 'registry-state', state: 'key-present' },
|
|
baseline: { kind: 'registry-state', state: 'key-present' } }
|
|
});
|
|
|
|
const empty = { kind: 'registry-policy', operation: 'set-value', key: 'Software\\Policies\\Synthetic',
|
|
valueName: 'Mode', typeCode: 2, data: { kind: 'string', value: '' } } as const;
|
|
expect(assess(empty, empty).results[0]).toMatchObject({
|
|
classification: 'configured_match', baselineVariantAssessment: { decision: 'all-pass' }
|
|
});
|
|
const missingEmptyEvaluation = assess(empty);
|
|
const missingEmpty = missingEmptyEvaluation.results[0];
|
|
expect(missingEmpty).toMatchObject({ classification: 'confirmed_configured_deviation',
|
|
baselineVariantAssessment: { decision: 'all-fail' }, comparator: { baseline: { kind: 'text', value: '' } } });
|
|
expect(policyComparisonDisposition(missingEmpty)).toBe('misconfigured');
|
|
expect(workStatus(missingEmptyEvaluation)).toBe('Fail');
|
|
expect(buildPolicyGuidance([missingEmptyEvaluation]).get(missingEmpty.id)?.remediation).toContain('Expected: Empty string');
|
|
});
|
|
|
|
it('creates a deviation when a recommended setting is missing from the customer backup', () => {
|
|
expect(evaluate(undefined)).toMatchObject({ run: { status: 'complete', deviationCount: 1 }, results: [{
|
|
aggregationStateId: undefined, customerState: 'missing', observationIds: [],
|
|
classification: 'confirmed_configured_deviation', comparator: { relation: 'different' }
|
|
}] });
|
|
});
|
|
|
|
it('does not emit actual-only settings without a baseline recommendation', () => {
|
|
const source = baseline('empty', 1);
|
|
source.analysis.analysis.settings = [];
|
|
expect(evaluate(2, [source])).toMatchObject({ run: { resultCount: 0, matchCount: 0, deviationCount: 0 }, results: [] });
|
|
});
|
|
|
|
it('does not emit PASS or FAIL for a structurally present baseline row without a Microsoft value', () => {
|
|
const source = baseline('blank', 1);
|
|
source.analysis.analysis.settings[0].observation.values = [];
|
|
expect(evaluate(undefined, [source])).toMatchObject({
|
|
run: { resultCount: 0, matchCount: 0, deviationCount: 0, reviewCount: 0 },
|
|
results: []
|
|
});
|
|
});
|
|
|
|
it('keeps an unsupported baseline value out of PASS and FAIL', () => {
|
|
const source = baseline('unsupported', 1);
|
|
source.analysis.analysis.settings[0].observation.values = [{
|
|
kind: 'service-preference', serviceName: 'Synthetic', serviceAction: 'start',
|
|
startupType: 'automatic', passwordAttributePresent: false
|
|
}];
|
|
expect(evaluate(undefined, [source])).toMatchObject({
|
|
run: { deviationCount: 0, matchCount: 0, reviewCount: 1 },
|
|
results: [{ classification: 'review_required', baselineState: 'unsupported-setting' }]
|
|
});
|
|
});
|
|
|
|
it('compares every baseline independently', () => {
|
|
const record = evaluate(1, [baseline('one', 1), baseline('two', 2)]);
|
|
expect(record.run).toMatchObject({ resultCount: 2, matchCount: 1, deviationCount: 1, reviewCount: 0 });
|
|
expect(new Set(record.results.map(result => result.baselineAnalysisId))).toEqual(
|
|
new Set(['baseline-analysis-one', 'baseline-analysis-two'])
|
|
);
|
|
});
|
|
|
|
it('keeps configured comparison usable for a selected-subset backup', () => {
|
|
expect(evaluate(2, undefined, { partial: true })).toMatchObject({
|
|
run: { status: 'complete', deviationCount: 1, reviewCount: 0 },
|
|
results: [{ classification: 'confirmed_configured_deviation' }]
|
|
});
|
|
});
|
|
|
|
it('rolls a proven failing member up to Fail while retaining the customer conflict', () => {
|
|
expect(evaluate(1, undefined, { conflicted: true })).toMatchObject({
|
|
run: { status: 'complete', deviationCount: 1, reviewCount: 0 }, results: [{ customerState: 'conflicted',
|
|
classification: 'confirmed_configured_deviation', comparator: { relation: 'different' },
|
|
baselineVariantAssessment: { decision: 'all-fail', actualValues: [value(1), value(2)] },
|
|
diagnosticCodes: expect.arrayContaining(['policy-evaluation-customer-conflict']) }]
|
|
});
|
|
expect(evaluate(1, undefined, { conflicted: true, unresolvedMember: true })).toMatchObject({
|
|
run: { deviationCount: 1, reviewCount: 0 }, results: [{ baselineState: 'explicit-recommendation',
|
|
classification: 'confirmed_configured_deviation', baselineVariantAssessment: { decision: 'all-fail' } }]
|
|
});
|
|
});
|
|
|
|
it('does not manufacture security findings from neutral comparison rows', () => {
|
|
const evaluation = evaluate(2);
|
|
const findings = buildPolicyFindingRun({ evaluation, aggregation: aggregation(2), profile,
|
|
startedAt: timestamp, completedAt: timestamp });
|
|
expect(findings).toMatchObject({ run: { status: 'complete', eligibleResultCount: 0, findingCount: 0 },
|
|
definitions: [], occurrences: [], rejections: [] });
|
|
});
|
|
|
|
it('fails every differing variant without inventory, stores individual evidence and never merges recommendations', () => {
|
|
const source = templates();
|
|
const before = JSON.stringify(source);
|
|
const output = evaluate(2, [source]);
|
|
const result = output.results[0];
|
|
expect(output.run).toMatchObject({ evaluator: { version: '1.9.0' }, deviationCount: 1, reviewCount: 0 });
|
|
expect(result).toMatchObject({ classification: 'confirmed_configured_deviation', effectiveState: 'unknown',
|
|
baselineTemplateSelection: { status: 'unresolved' }, comparator: { relation: 'different', baseline: undefined },
|
|
baselineVariantAssessment: { version: 1, scope: 'backup-configuration', decision: 'all-fail',
|
|
variants: [0, 0, 1].map((number, index) => ({ settingId: `role-setting-${index}`,
|
|
baselineValues: [value(number)], comparator: { baseline: { kind: 'integer', value: String(number) }, relation: 'different' } })) } });
|
|
expect(result.diagnosticCodes).not.toContain('policy-evaluation-template-context-required');
|
|
expect(result.diagnosticCodes).not.toContain('policy-evaluation-baseline-consensus-conflict');
|
|
expect(JSON.stringify(source)).toBe(before);
|
|
expect(storedPolicyEvaluationValidationErrors(JSON.parse(JSON.stringify(output)))).toEqual([]);
|
|
const invalid = structuredClone(output);
|
|
invalid.results[0].baselineVariantAssessment!.variants[0].comparator.relation = 'match';
|
|
expect(storedPolicyEvaluationValidationErrors(invalid)).not.toEqual([]);
|
|
});
|
|
|
|
it('does not lose missing, unsupported or ambiguous variants to manufacture unanimity', () => {
|
|
for (const values of [[], [value(0), value(1)], [{ kind: 'service-preference' as const, serviceName: 'Synthetic',
|
|
serviceAction: 'start' as const, startupType: 'automatic' as const, passwordAttributePresent: false }]]) {
|
|
const source = templates();
|
|
source.analysis.analysis.settings[0].observation.values = values;
|
|
const output = evaluate(2, [source]);
|
|
expect(output.results[0]).toMatchObject({ classification: 'review_required',
|
|
baselineVariantAssessment: { decision: 'unavailable' } });
|
|
expect(output.results[0].baselineVariantAssessment?.variants).toHaveLength(3);
|
|
}
|
|
});
|
|
|
|
it('shows absence in the analyzed backup scope as Not configured while retaining its scope limit', () => {
|
|
expect(evaluate(undefined, [templates()], { partial: true }).results[0]).toMatchObject({
|
|
customerState: 'missing', classification: 'confirmed_configured_deviation',
|
|
baselineVariantAssessment: { decision: 'all-fail', diagnosticCodes: [] },
|
|
diagnosticCodes: expect.arrayContaining(['policy-evaluation-customer-absence-scope-limited']) });
|
|
const source = templates();
|
|
source.analysis.analysis.status = 'partial';
|
|
expect(evaluate(2, [source]).results[0]).toMatchObject({ classification: 'review_required',
|
|
baselineVariantAssessment: { decision: 'unavailable' } });
|
|
source.analysis.analysis.diagnosticCodes = ['microsoft-baseline-admx-metadata-not-found', 'gpo-metadata-domain-missing',
|
|
'gpo-metadata-backup-time-missing', 'gpo-metadata-backup-time-zone-missing'];
|
|
source.analysis.analysis.admxCatalog.status = 'partial';
|
|
expect(evaluate(2, [source]).results[0]).toMatchObject({ classification: 'confirmed_configured_deviation',
|
|
baselineVariantAssessment: { decision: 'all-fail' } });
|
|
source.analysis.analysis.diagnosticCodes.push('gpo-metadata-field-shape-invalid');
|
|
expect(evaluate(2, [source]).results[0].classification).toBe('review_required');
|
|
expect(evaluate(undefined, [templates()]).results[0]).toMatchObject({ customerState: 'missing',
|
|
classification: 'confirmed_configured_deviation', baselineVariantAssessment: { decision: 'all-fail' } });
|
|
});
|
|
|
|
it('keeps a resolved registry comparison usable when only unrelated baseline sections are partial', () => {
|
|
const source = baseline('partial-unrelated-sections', 1);
|
|
source.analysis.analysis.status = 'partial';
|
|
source.analysis.analysis.diagnosticCodes = [
|
|
'gpo-metadata-backup-id-missing',
|
|
'gpo-security-template-entry-invalid',
|
|
'gpo-security-template-section-unsupported'
|
|
];
|
|
expect(evaluate(1, [source]).results[0]).toMatchObject({
|
|
classification: 'configured_match',
|
|
baselineVariantAssessment: { decision: 'all-pass', diagnosticCodes: [] }
|
|
});
|
|
expect(evaluate(2, [source]).results[0]).toMatchObject({
|
|
classification: 'confirmed_configured_deviation',
|
|
baselineVariantAssessment: { decision: 'all-fail', diagnosticCodes: [] }
|
|
});
|
|
});
|
|
|
|
it('treats account lists as independent exact sets, never as a union baseline', () => {
|
|
const source = templates();
|
|
const principal = (principals: string[]) => ({ kind: 'principal-set' as const, principals });
|
|
source.analysis.analysis.settings = source.analysis.analysis.settings.slice(0, 2);
|
|
source.analysis.analysis.settings.forEach((setting, index) => {
|
|
setting.observation.values = [principal(index ? ['*S-1-5-32-544', '*S-1-5-9'] : ['*S-1-5-32-544'])];
|
|
});
|
|
const check = (principals: string[]) => {
|
|
const customer = aggregation(1);
|
|
customer.states[0].values = [principal(principals)];
|
|
return buildPolicyEvaluation({ profile, aggregation: customer, baselineRecords: [source.record],
|
|
baselineAnalyses: [source.analysis], ruleCatalog, startedAt: timestamp, completedAt: timestamp });
|
|
};
|
|
expect(check(['*S-1-5-32-544', '*S-1-5-9', '*S-1-1-0']).results[0].baselineVariantAssessment?.decision).toBe('all-fail');
|
|
expect(check(['*S-1-5-9', '*S-1-5-32-544']).results[0].baselineVariantAssessment?.decision).toBe('mixed');
|
|
// Inside the union but equal to neither required set: still Fail for exact comparison.
|
|
expect(check(['*S-1-5-9']).results[0].baselineVariantAssessment?.decision).toBe('all-fail');
|
|
source.analysis.analysis.settings[0].observation.values = [principal(['*S-1-5-32-544', '*S-1-5-9'])];
|
|
expect(check(['*S-1-5-9', '*S-1-5-32-544']).results[0].baselineVariantAssessment?.decision).toBe('all-pass');
|
|
});
|
|
|
|
it('does not treat identical numeric payloads with different registry types as Passed', () => {
|
|
const source = baseline('qword', 1);
|
|
source.analysis.analysis.settings[0].observation.values = [{ ...value(1), typeCode: 11, data: { kind: 'uint64', value: '1' } }];
|
|
expect(evaluate(1, [source]).results[0].baselineVariantAssessment?.decision).toBe('all-fail');
|
|
});
|
|
|
|
it('projects current variant judgments consistently into Work filters, details and Result DB after serialization', () => {
|
|
for (const [actual, expected, decision, filter] of [
|
|
[2, 'Fail', 'all-fail', 'deviation'], [1, 'Review required', 'mixed', 'all'],
|
|
[undefined, 'Not configured', 'all-fail', 'not-configured'], [1, 'Pass', 'all-pass', 'passed']
|
|
] as const) {
|
|
const source = templates();
|
|
if (expected === 'Pass') source.analysis.analysis.settings.forEach(setting => { setting.observation.values = [value(1)]; });
|
|
const saved = JSON.parse(JSON.stringify(evaluate(actual, [source]))) as ReturnType<typeof evaluate>;
|
|
const observations = actual === undefined ? [] : [{ sourceKind: 'policy-observation', sourceResultId: 'synthetic-observation',
|
|
projectId, assessmentId: 'synthetic-slot', title: 'Mode', importedAt: timestamp, policyScope: 'computer',
|
|
policyDeliveryMechanism: 'registry-policy', policyIdentityStatus: 'resolved', policyIdentityKey: identity.id,
|
|
policyValues: [value(actual)], policyBackupInstanceId: 'synthetic-backup' } as unknown as UnifiedResultProjection];
|
|
const guidance = buildPolicyGuidance([saved], [source.analysis]);
|
|
const dataset = appendPolicyObservationsToDataset(null, 'Synthetic', observations, [saved], guidance)!;
|
|
const sheet = dataset.sheets[0];
|
|
const fields = Object.fromEntries(sheet.rows[0].map((header, index) => [header, sheet.rows[1][index]]));
|
|
expect(fields.Status).toBe(expected);
|
|
expect(fields.Comparison).toContain(decision === 'mixed' ? 'Review required' : 'every assessed baseline variant');
|
|
expect(fields.Description).toContain('not effective device security');
|
|
expect(fields.Description.match(/Value comparison:/g)).toHaveLength(3);
|
|
expect(fields.Conflict).toBe('');
|
|
const matching = (status: string) => filterAndSortRecords(sheet, { activeProfile: genericProfile, dataset,
|
|
reviews: {}, search: '', statusFilter: status, sortColumn: '', sortDirection: 'asc', actionOnly: false });
|
|
expect(matching(filter)).toHaveLength(1);
|
|
expect(matching('conflicts')).toHaveLength(0);
|
|
if (expected !== 'Fail') expect(matching('deviation')).toHaveLength(0);
|
|
const facets = selectWorkFacets(sheet, { activeProfile: genericProfile, dataset, reviews: {}, statusFilter: 'all',
|
|
facetFilters: {}, search: '', actionOnly: false });
|
|
expect(facets[0].values.map(item => item.label)).toEqual(['Deviation', 'Passed', 'Not configured', 'No baseline rule', 'Not comparable', 'Conflicts', 'Duplicates']);
|
|
const unified = createPolicyEvaluationUnifiedResult(saved.run, saved.results[0]);
|
|
expect(unified).toMatchObject({
|
|
outcomeNormalized: expected === 'Fail' ? 'fail' : expected === 'Pass' ? 'pass' : expected === 'Not configured' ? 'informational' : 'warning',
|
|
policyClassification: expected === 'Fail' ? 'misconfigured' : expected === 'Pass' ? 'match' : expected === 'Not configured' ? 'not-configured' : 'review-required',
|
|
policyBaselineVariantAssessment: saved.results[0].baselineVariantAssessment
|
|
});
|
|
const html = renderToStaticMarkup(createElement(ResultRow, { item: unified, expanded: true, onToggle() {} }));
|
|
expect(html.match(/Setting reference:/g)).toHaveLength(3);
|
|
expect(html).toContain('No effective device state');
|
|
// The saved per-variant values and verdicts remain available without loaded catalog metadata.
|
|
expect(buildPolicyGuidance([saved]).get(saved.results[0].id)?.description).toContain('Value comparison:');
|
|
}
|
|
});
|
|
|
|
it('keeps a setting absent from a selected backup scope filterable as Not configured', () => {
|
|
const source = templates();
|
|
const saved = evaluate(undefined, [source], { partial: true });
|
|
const dataset = appendPolicyObservationsToDataset(null, 'Synthetic', [], [saved], buildPolicyGuidance([saved], [source.analysis]))!;
|
|
const record = dataset.sheets[0].analysis.records[0];
|
|
expect(record.fields.find(field => field.label === 'Status')?.value).toBe('Not configured');
|
|
expect(record.fields.find(field => field.label === 'Diagnostics')?.value)
|
|
.toContain('policy-evaluation-customer-absence-scope-limited');
|
|
expect(genericProfile.matchesStatus(record, 'not-configured')).toBe(true);
|
|
expect(genericProfile.matchesStatus(record, 'deviation')).toBe(false);
|
|
});
|
|
|
|
it('keeps both previous engine versions read-only and prioritizes the new evaluation', () => {
|
|
const current = evaluate(2, [templates()]);
|
|
const older = structuredClone(current);
|
|
older.run.evaluator.version = '1.3.3'; older.run.id = 'older';
|
|
const previous = structuredClone(current);
|
|
previous.run.evaluator.version = '1.4.0'; previous.run.id = 'previous';
|
|
const history = JSON.stringify([previous, older]);
|
|
expect(selectCurrentPolicyEvaluations([previous, older])).toEqual([]);
|
|
expect(selectCurrentPolicyEvaluations([previous, older], { allowPreviousVersionForDisplay: true })).toEqual([previous]);
|
|
expect(selectCurrentPolicyEvaluations([previous, current, older], { allowPreviousVersionForDisplay: true })).toEqual([current]);
|
|
expect(JSON.stringify([previous, older])).toBe(history);
|
|
});
|
|
});
|