Assessor_2.0/tests/domain/gpo-ingestion.test.ts

164 lines
7.4 KiB
TypeScript

import { describe, expect, it } from 'vitest';
import { artifactPathCollisionKey, normalizeArtifactRelativePath } from '../../src/domain/artifact-path';
import type { GpoBackupInstance } from '../../src/domain/gpo-ingestion';
import {
gpoArtifactInventoryValidationErrors,
gpoBackupCompleteness,
gpoBackupInstanceValidationErrors
} from '../../src/domain/gpo-ingestion';
import { buildGpoAnalysisSnapshots } from '../../src/gpo/snapshot-builder';
const timestamp = '2026-07-20T12:00:00.000Z';
function instance(
id: string,
gpoId: string,
backupSetId: string,
overrides: Partial<GpoBackupInstance> = {}
): GpoBackupInstance {
return {
version: 1,
id,
projectId: 'project-synthetic',
sourceArtifactId: `artifact-${id}`,
identity: {
status: 'resolved',
gpoId,
backupId: `${id.length.toString(16).padStart(8, '0')}-1111-4111-8111-111111111111`,
evidence: 'backup-metadata'
},
domain: { status: 'resolved', key: 'domain-synthetic', evidence: 'backup-metadata' },
collection: { status: 'observed', collectedAt: timestamp, evidence: 'collection-manifest' },
backupSet: { id: backupSetId, scope: 'complete-domain-export', evidence: 'collection-manifest', expectedGpoCount: 1 },
metadataStatus: 'complete',
sections: { computer: 'empty', user: 'disabled' },
inventory: {
version: 1,
status: 'complete',
entries: [{
version: 1,
artifactId: `metadata-${id}`,
relativePath: `${id}/Backup.xml`,
role: 'backup-metadata',
scope: 'shared',
disposition: 'supported',
secretIndicatorStatus: 'not-inspected'
}],
diagnosticCodes: []
},
discoveredAt: timestamp,
...overrides
};
}
describe('GPO ingestion contracts', () => {
it('normalizes safe archive paths and rejects traversal, aliases and Windows special paths', () => {
expect(normalizeArtifactRelativePath('Domain\\Policies\\Machine\\Registry.pol'))
.toBe('Domain/Policies/Machine/Registry.pol');
expect(artifactPathCollisionKey('Domain/Backup.XML')).toBe('domain/backup.xml');
for (const unsafe of [
'../escape.xml', '/absolute.xml', '\\server\\share.xml', 'C:\\drive.xml', 'safe/../escape.xml',
'safe/file.xml:stream', 'safe/CON.txt', 'safe/name. ', 'safe//double.xml', 'safe/fi\u202ele.xml'
]) expect(normalizeArtifactRelativePath(unsafe)).toBeNull();
});
it('blocks case-colliding inventory paths and executable script treatment', () => {
const value = instance('one', '11111111-1111-4111-8111-111111111111', 'set-one');
value.inventory.entries.push({
version: 1,
artifactId: 'script-one',
relativePath: 'ONE/backup.xml',
role: 'script',
scope: 'computer',
disposition: 'supported',
secretIndicatorStatus: 'not-inspected'
});
expect(gpoArtifactInventoryValidationErrors(value.inventory)).toEqual(expect.arrayContaining([
expect.stringContaining('kollidiert'),
expect.stringContaining('Skript')
]));
});
it('keeps inventory-only scripts from authorizing set-absence conclusions', () => {
const value = instance('scripted', '55555555-5555-4555-8555-555555555555', 'set-scripted');
value.inventory.entries.push({
version: 1,
artifactId: 'script-file',
relativePath: 'scripted/Machine/Scripts/startup.ps1',
role: 'script',
scope: 'computer',
disposition: 'inventory-only',
secretIndicatorStatus: 'not-inspected'
});
expect(gpoBackupInstanceValidationErrors(value)).toEqual([]);
expect(gpoBackupCompleteness(value)).toBe('partial');
expect(buildGpoAnalysisSnapshots([value], { createdAt: timestamp })[0])
.toMatchObject({ status: 'indeterminate', permitsSetAbsenceConclusions: false });
});
it('forms a complete manifest-backed snapshot without inventing scope or effectiveness', () => {
const first = instance('first', '11111111-1111-4111-8111-111111111111', 'set-complete', {
backupSet: { id: 'set-complete', scope: 'complete-domain-export', evidence: 'collection-manifest', expectedGpoCount: 2 }
});
const second = instance('second', '22222222-2222-4222-8222-222222222222', 'set-complete', {
backupSet: { id: 'set-complete', scope: 'complete-domain-export', evidence: 'collection-manifest', expectedGpoCount: 2 }
});
const snapshots = buildGpoAnalysisSnapshots([second, first], { createdAt: timestamp });
expect(snapshots).toEqual([expect.objectContaining({
instanceIds: ['first', 'second'],
status: 'consistent',
completeness: 'complete',
permitsSetAbsenceConclusions: true,
diagnosticCodes: []
})]);
});
it('separates historical sets and blocks duplicate GPO identities inside one snapshot', () => {
const historical = buildGpoAnalysisSnapshots([
instance('old', '11111111-1111-4111-8111-111111111111', 'set-old'),
instance('new', '11111111-1111-4111-8111-111111111111', 'set-new')
], { createdAt: timestamp });
expect(historical).toHaveLength(2);
expect(historical.every(snapshot => snapshot.status === 'consistent')).toBe(true);
const duplicated = buildGpoAnalysisSnapshots([
instance('copy-a', '11111111-1111-4111-8111-111111111111', 'set-duplicate', {
backupSet: { id: 'set-duplicate', scope: 'complete-domain-export', evidence: 'collection-manifest', expectedGpoCount: 2 }
}),
instance('copy-b', '11111111-1111-4111-8111-111111111111', 'set-duplicate', {
backupSet: { id: 'set-duplicate', scope: 'complete-domain-export', evidence: 'collection-manifest', expectedGpoCount: 2 }
})
], { createdAt: timestamp });
expect(duplicated[0]).toMatchObject({ status: 'inconsistent', completeness: 'inconsistent', permitsSetAbsenceConclusions: false });
expect(duplicated[0].diagnosticCodes).toContain('gpo-duplicate-identity-in-snapshot');
});
it('splits mixed domains and keeps partial or selected sets from negative conclusions', () => {
const otherDomain = instance('other', '22222222-2222-4222-8222-222222222222', 'set-domain');
otherDomain.domain = { status: 'resolved', key: 'other-domain', evidence: 'backup-metadata' };
const split = buildGpoAnalysisSnapshots([
instance('primary', '11111111-1111-4111-8111-111111111111', 'set-domain'),
otherDomain
], { createdAt: timestamp });
expect(split).toHaveLength(2);
expect(split.every(snapshot => snapshot.status === 'inconsistent'
&& snapshot.diagnosticCodes.includes('gpo-backup-set-domain-split'))).toBe(true);
const selected = instance('selected', '33333333-3333-4333-8333-333333333333', 'set-selected', {
backupSet: { id: 'set-selected', scope: 'selected-gpos', evidence: 'user-selection' }
});
const selectedSnapshot = buildGpoAnalysisSnapshots([selected], { createdAt: timestamp })[0];
expect(selectedSnapshot).toMatchObject({ status: 'consistent', completeness: 'selected-subset', permitsSetAbsenceConclusions: false });
const incomplete = instance('incomplete', '44444444-4444-4444-8444-444444444444', 'set-incomplete', {
sections: { computer: 'missing', user: 'disabled' }
});
expect(gpoBackupCompleteness(incomplete)).toBe('partial');
expect(gpoBackupInstanceValidationErrors(incomplete)).toEqual([]);
expect(buildGpoAnalysisSnapshots([incomplete], { createdAt: timestamp })[0]).toMatchObject({
status: 'indeterminate', permitsSetAbsenceConclusions: false,
diagnosticCodes: expect.arrayContaining(['gpo-backup-instance-incomplete'])
});
});
});