Assessor_2.0/server/gpo/gpo-environment-context.ts

31 lines
1.8 KiB
TypeScript

import { createHash } from 'node:crypto';
import type { EnvironmentObservation } from '../../src/domain/environment-context';
import type { EnvironmentProfileContext } from '../../src/domain/gpo-snapshot-aggregation';
/** Observed platform inventory is evidence for candidate contexts, not GPO applicability. */
export function inferGpoEnvironmentContexts(observations: EnvironmentObservation[]): Array<Omit<EnvironmentProfileContext, 'version'>> {
const contexts = new Map<string, Omit<EnvironmentProfileContext, 'version'>>();
for (const observation of observations) {
if (observation.state !== 'observed' || observation.property !== 'operating_system.name') continue;
const value = observation.normalizedValue ?? observation.originalValue;
if (typeof value !== 'string') continue;
const isDc = observation.subject.type === 'computer-information.domain-controllers';
const server = /^Windows(?: Server)? (2008(?: R2)?|2012(?: R2)?|2016|2019|2022|2025)(?:\b|$)/i.exec(value.trim());
// A generic server inventory row does not prove member-server role.
if (!isDc || !server) continue;
const productVersion = server[1].toUpperCase();
const key = `Windows Server:${productVersion}:Domain Controller`;
const existing = contexts.get(key);
if (existing) {
existing.sourceObservationIds = [...new Set([...(existing.sourceObservationIds ?? []), observation.id])].sort();
continue;
}
contexts.set(key, {
id: 'detected-context-' + createHash('sha256').update(key).digest('hex').slice(0, 24),
kind: 'operating-system', productFamily: 'Windows Server', productVersion,
role: 'Domain Controller', scope: 'computer', sourceObservationIds: [observation.id]
});
}
return [...contexts.values()].sort((a, b) => a.id.localeCompare(b.id));
}