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';
const rootClsid = '{3125E937-EB16-4b4c-9934-544FC6D24D26}';
const userClsid = '{DF5F1855-51E5-4d24-8B1A-D9BDE98BA1D1}';
const groupClsid = '{6D4A79E4-529C-4481-ABD0-F5BD7EA93BA7}';
function verifiedFile(content: string): VerifiedZipFile {
const bytes = new TextEncoder().encode(content);
return {
entry: {
index: 1,
relativePath: 'synthetic/DomainSysvol/GPO/Machine/Preferences/Groups/Groups.xml',
kind: 'file',
compressionMethod: 8,
compressedBytes: bytes.byteLength,
uncompressedBytes: bytes.byteLength,
crc32: '00000000',
sha256: createHash('sha256').update(bytes).digest('hex')
},
bytes
};
}
function context() {
return { backupInstanceId: 'backup-synthetic', sourceArtifactId: 'source-synthetic', artifactId: 'entry-synthetic' };
}
describe('Local Users and Groups preference CSE', () => {
it('keeps user, group and ordered membership semantics without retaining cpassword', () => {
const secret = 'synthetic-secret-never-return';
const document = parseGroupPolicyPreferenceXml(verifiedFile([
``,
` `,
` `,
' ',
' ',
` `,
' ',
' ',
' ',
' ',
' ',
' ',
' ',
''
].join('\r\n')), 'computer');
expect(document).toMatchObject({
preferenceType: 'local-users-groups', 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({
state: 'instruction',
identity: expect.objectContaining({ section: 'local user', key: 'syntheticadmin' }),
preference: expect.objectContaining({ cse: 'local-users-groups', operation: 'update', sequence: 0, applyOnce: true }),
values: [{
kind: 'local-user-preference', userName: 'SyntheticAdmin', newName: 'SyntheticOperator',
fullName: 'Synthetic Operator', passwordAttributePresent: true, changePasswordAtLogon: true,
accountDisabled: false, passwordNeverExpires: true, passwordChangeAllowed: false
}],
sourceLines: [2],
effectiveState: 'unknown',
diagnosticCodes: ['gpo-preference-targeting-unevaluated', 'gpo-secret-indicator-present']
}),
expect.objectContaining({
identity: expect.objectContaining({ section: 'local group', key: 'S-1-5-32-544' }),
preference: expect.objectContaining({ cse: 'local-users-groups', operation: 'update', sequence: 1 }),
values: [{
kind: 'local-group-preference', groupName: 'Administrators', groupSid: 'S-1-5-32-544',
suppressCurrentUserOperation: false, deleteAllUsers: true, deleteAllGroups: false,
members: [
{ sequence: 0, operation: 'remove', selector: { kind: 'name', value: 'Synthetic\\Old' } },
{ sequence: 1, operation: 'add', selector: { kind: 'sid', value: 'S-1-5-21-1-2-3-1001' } }
]
}],
sourceLines: [6],
effectiveState: 'unknown'
})
]);
});
it('fails closed for malformed supported member and boolean semantics', () => {
const document = parseGroupPolicyPreferenceXml(verifiedFile(
``
), 'computer');
expect(document).toMatchObject({ status: 'invalid', instructions: [] });
expect(document.diagnosticCodes).toEqual(expect.arrayContaining([
'gpo-preference-boolean-invalid', 'gpo-preference-local-group-member-invalid'
]));
expect(reduceGroupPolicyPreferences(document, context())).toEqual([]);
});
it('keeps unknown supported-CSE item shapes partial without salvaging those items', () => {
const document = parseGroupPolicyPreferenceXml(verifiedFile(
``
), 'user');
expect(document).toMatchObject({
preferenceType: 'local-users-groups', status: 'partial', instructions: [],
diagnosticCodes: ['gpo-preference-local-user-item-unsupported']
});
expect(reduceGroupPolicyPreferences(document, context())).toEqual([]);
});
});