import { createHash } from 'node:crypto'; import { describe, expect, it } from 'vitest'; import { parseGroupPolicyPreferenceXml, reduceGroupPolicyPreferences } from '../../server/gpo/group-policy-preference-parser'; import type { VerifiedZipFile } from '../../server/gpo/zip-inventory'; import { gpoPolicyObservationValidationErrors } from '../../src/domain/gpo-policy'; const rootClsid = '{2CFB484A-4E96-4b5d-A0B6-093D2F91E6AE}'; const itemClsid = '{AB6F0B67-341F-4e51-92F9-005FBFBA1A43}'; function verifiedFile(content: string): VerifiedZipFile { const bytes = new TextEncoder().encode(content); return { entry: { index: 1, relativePath: 'synthetic/DomainSysvol/GPO/Machine/Preferences/Services/Services.xml', kind: 'file', compressionMethod: 8, compressedBytes: bytes.byteLength, uncompressedBytes: bytes.byteLength, crc32: '00000000', sha256: createHash('sha256').update(bytes).digest('hex') }, bytes }; } const context = { backupInstanceId: 'backup-synthetic', sourceArtifactId: 'source-synthetic', artifactId: 'entry-synthetic' }; describe('Services preference CSE', () => { it('preserves service, startup, failure and targeting semantics without retaining cPassword', () => { const secret = 'synthetic-service-secret-never-return'; const document = parseGroupPolicyPreferenceXml(verifiedFile([ ``, ` `, ` `, ' ', ' ', '' ].join('\r\n')), 'computer'); expect(document).toMatchObject({ preferenceType: 'services', status: 'complete', secretIndicatorStatus: 'present' }); expect(JSON.stringify(document)).not.toContain(secret); const observations = reduceGroupPolicyPreferences(document, context); expect(JSON.stringify(observations)).not.toContain(secret); expect(observations).toEqual([expect.objectContaining({ identity: { status: 'unresolved', namespace: 'group-policy-preference', section: 'service', key: 'syntheticservice' }, state: 'instruction', values: [{ kind: 'service-preference', serviceName: 'SyntheticService', serviceAction: 'restart-if-required', startupType: 'automatic', timeout: 30, accountName: 'Synthetic\\Service', passwordAttributePresent: true, interact: false, firstFailure: 'no-action', secondFailure: 'start', thirdFailure: 'restart', resetFailCountDelay: 0, restartServiceDelay: 900000, restartComputerDelay: 120, restartMessage: '', program: 'C:\\Synthetic\\recover.exe', args: '--safe', append: '' }], preference: expect.objectContaining({ cse: 'services', operation: 'configure', sequence: 0, removePolicy: true, applyOnce: true, targeting: expect.objectContaining({ status: 'present', evaluability: 'unknown' }) }), sourceLines: [2], effectiveState: 'unknown', diagnosticCodes: ['gpo-preference-targeting-unevaluated', 'gpo-secret-indicator-present'] })]); }); it('defaults an omitted serviceAction to no-change as in the Microsoft example', () => { const document = parseGroupPolicyPreferenceXml(verifiedFile( `` ), 'computer'); expect(document).toMatchObject({ status: 'complete', instructions: [{ value: { serviceAction: 'no-change', startupType: 'no-change' } }] }); }); it('fails closed for malformed supported enums, numbers and booleans', () => { const document = parseGroupPolicyPreferenceXml(verifiedFile( `` ), 'computer'); expect(document).toMatchObject({ status: 'invalid', instructions: [] }); expect(document.diagnosticCodes).toEqual(expect.arrayContaining([ 'gpo-preference-boolean-invalid', 'gpo-preference-service-enum-invalid', 'gpo-preference-service-number-invalid' ])); expect(reduceGroupPolicyPreferences(document, context)).toEqual([]); }); it('rejects malformed persisted Services observations at the runtime contract', () => { const document = parseGroupPolicyPreferenceXml(verifiedFile( `` ), 'computer'); const observation = structuredClone(reduceGroupPolicyPreferences(document, context)[0]) as any; observation.scope = 'user'; observation.preference.operation = 'update'; observation.values[0].passwordAttributePresent = 'yes'; expect(gpoPolicyObservationValidationErrors(observation)).toContain('Eine Service-Preference ist ungültig.'); }); it('keeps unknown supported-CSE properties and user scope partial without inventing semantics', () => { const unknown = parseGroupPolicyPreferenceXml(verifiedFile( `` ), 'computer'); expect(unknown).toMatchObject({ status: 'partial', instructions: [], diagnosticCodes: ['gpo-preference-service-item-unsupported'] }); const userScoped = parseGroupPolicyPreferenceXml(verifiedFile( `` ), 'user'); expect(userScoped).toMatchObject({ status: 'partial' }); expect(userScoped.diagnosticCodes).toContain('gpo-preference-services-scope-unsupported'); expect(reduceGroupPolicyPreferences(userScoped, context)).toEqual([]); }); });