diff --git a/src/openhound_sccm/collectors/registry.py b/src/openhound_sccm/collectors/registry.py index 180353f..af2e399 100644 --- a/src/openhound_sccm/collectors/registry.py +++ b/src/openhound_sccm/collectors/registry.py @@ -465,9 +465,10 @@ def collect_registry(target: str, ctx: "SourceContext") -> Iterable[tuple[str, d # server name only when AD resolution failed (ad_object # is None or lacks a name). logger.info("Found %s, this target is a site server", SCCM_REG_KEYS["component_servers"]) - target_entry = ctx.target_hosts_by_hostname[target] + target_entry = ctx.target_hosts_by_hostname.get(target.lower()) + ad_object = target_entry.ad_object if target_entry else None row = { - **(target_entry.ad_object or {}), + **(ad_object or {}), "source": "RemoteRegistry-ComponentServers", "sccm_infra": True, "sccm_site_system_roles": _roles(["SMS Site Server"], site_code), @@ -529,9 +530,11 @@ def collect_registry(target: str, ctx: "SourceContext") -> Iterable[tuple[str, d "database lives elsewhere. Emitting the SQL Server role as assumed " "pending corroboration in preprocess.", target, ) - target_entry = ctx.target_hosts_by_hostname[target] + target_entry = ctx.target_hosts_by_hostname.get(target.lower()) + ad_object = target_entry.ad_object if target_entry else None + row = { - **(target_entry.ad_object or {}), + **(ad_object or {}), "source": "RemoteRegistry-MultisiteComponentServers", "sccm_infra": True, "sccm_site_system_roles": _roles(["SMS SQL Server", "SMS Site Server"], site_code), @@ -600,7 +603,7 @@ def get_current_user(probe: _RegistryProbe, ctx: SourceContext) -> Iterable[tupl current_user_ad_object = ctx.resolve_principal(current_user_sid) if current_user_ad_object: logger.info("Found current user: %s (%s)", current_user_ad_object.get("sam_account_name"), current_user_sid) - target_entry = ctx.target_hosts_by_hostname.get(probe.hostname) + target_entry = ctx.target_hosts_by_hostname.get(probe.hostname.lower()) host_sid = target_entry.ad_object.get("object_sid") if (target_entry and target_entry.ad_object) else None if host_sid is None: # No resolved host AD object — HasSession can't be built for this row downstream; keep the row but log. @@ -663,16 +666,17 @@ def get_ntlm_settings(probe: _RegistryProbe, ctx: SourceContext) -> Iterable[tup disable_loopback_check = disable_loopback_reg == 1 logger.verbose(f"DisableLoopbackCheck is {'enabled' if disable_loopback_check else 'disabled'}") - target_entry = ctx.target_hosts_by_hostname[probe.hostname] + target_entry = ctx.target_hosts_by_hostname.get(probe.hostname.lower()) + ad_object = target_entry.ad_object if target_entry else None row = { - **(target_entry.ad_object or {}), + **(ad_object or {}), "source": "RemoteRegistry-NTLMSettings", "smb_signing_required": signing_required, "smb_signing_source": signing_source, "restrict_receiving_ntlm_traffic": restrict_receiving_ntlm_traffic, "disable_loopback_check": disable_loopback_check, } - row.setdefault("name", target_entry.ad_object.get("name") if target_entry.ad_object else probe.hostname) + row.setdefault("name", ad_object.get("name") if ad_object else probe.hostname) yield "remoteregistry_computers", row @@ -869,14 +873,15 @@ def get_mssql_settings(probe: _RegistryProbe, ctx: SourceContext) -> Iterable[tu probe, instance_names ) - target_entry = ctx.target_hosts_by_hostname[probe.hostname] + target_entry = ctx.target_hosts_by_hostname.get(probe.hostname.lower()) + ad_object = target_entry.ad_object if target_entry else None yield "remoteregistry_mssql_servers", { "source": "RemoteRegistry-MSSQL", "force_encryption": force_encryption if force_encryption is not None else None, "extended_protection": extended_protection if extended_protection is not None else None, - "name": target_entry.ad_object.get("name") if target_entry.ad_object else probe.hostname, - "domain_computer_sid": target_entry.ad_object.get("object_sid") if target_entry.ad_object else None, + "name": ad_object.get("name") if ad_object else probe.hostname, + "domain_computer_sid": ad_object.get("object_sid") if ad_object else None, "port": port if port else None, "instance_names": instance_names if instance_names else None, "service_start_type": service_start_type, diff --git a/tests/registry_collect_test.py b/tests/registry_collect_test.py index bb708a7..c202be9 100644 --- a/tests/registry_collect_test.py +++ b/tests/registry_collect_test.py @@ -16,7 +16,7 @@ from openhound_sccm.collectors import registry -TARGET = "ps1-pss.mayyhem.com" +TARGET = "PS1-PSS.mayyhem.com" TRIGGERS = registry.SCCM_REG_KEYS["triggers"] COMPONENTS = registry.SCCM_REG_KEYS["component_servers"] MULTISITE = registry.SCCM_REG_KEYS["multisite_component_servers"] @@ -95,7 +95,7 @@ def __init__(self, resolve_result=None, register_result="auto"): self._register_result = register_result self.resolved = [] self.registered = [] - self.target_hosts_by_hostname = {TARGET: _Entry(ad_object=None)} + self.target_hosts_by_hostname = {TARGET.lower(): _Entry(ad_object=None)} def method_enabled(self, name): return True @@ -193,7 +193,7 @@ def test_none_result_does_not_crash(monkeypatch): def test_multisite_empty_key_marks_local_site_database(monkeypatch): """Empty key -> the site database is local; this host gets both roles.""" ctx = FakeCtx() - ctx.target_hosts_by_hostname[TARGET] = _Entry(ad_object={"name": "PS1-PSS"}) + ctx.target_hosts_by_hostname[TARGET.lower()] = _Entry(ad_object={"name": "PS1-PSS"}) _, rows = _run( monkeypatch, enum_results=_site_server(**{MULTISITE: []}), read_values_result=[], ctx=ctx, @@ -251,7 +251,7 @@ def test_multisite_absent_key_emits_no_database_row(monkeypatch): def test_multisite_empty_key_marks_the_sql_role_as_assumed(monkeypatch): """The local-site-database inference flags itself as unverified.""" ctx = FakeCtx() - ctx.target_hosts_by_hostname[TARGET] = _Entry(ad_object={"name": "PS1-PSS"}) + ctx.target_hosts_by_hostname[TARGET.lower()] = _Entry(ad_object={"name": "PS1-PSS"}) _, rows = _run( monkeypatch, enum_results=_site_server(**{MULTISITE: []}), read_values_result=[], ctx=ctx, @@ -320,7 +320,7 @@ def _mssql_probe(instance="MSSQLSERVER", start=None, object_name=None): def _mssql_row(probe): ctx = FakeCtx() - ctx.target_hosts_by_hostname[TARGET] = _Entry(ad_object={"name": "PS1-PSV"}) + ctx.target_hosts_by_hostname[TARGET.lower()] = _Entry(ad_object={"name": "PS1-PSV"}) probe.hostname = TARGET rows = list(registry.get_mssql_settings(probe, ctx)) return next(r for t, r in rows if t == "remoteregistry_mssql_servers") diff --git a/tests/registry_current_user_test.py b/tests/registry_current_user_test.py index 938414c..7a1727f 100644 --- a/tests/registry_current_user_test.py +++ b/tests/registry_current_user_test.py @@ -4,13 +4,13 @@ class _FakeProbe: - hostname = "host1.lab" + hostname = "HOST1.lab" def read_values(self, _key): return [("UserSID", "S-1-5-21-1-2-3-1106"), ("Session", 1)] def _fake_ctx(): - host_obj = {"name": "HOST1", "object_sid": "S-1-5-21-1-2-3-1104"} + host_obj = {"name": "host1", "object_sid": "S-1-5-21-1-2-3-1104"} user_obj = {"sam_account_name": "alice", "object_sid": "S-1-5-21-1-2-3-1106"} ctx = types.SimpleNamespace() ctx.resolve_principal = lambda sid: dict(user_obj)