Part of epic: nudgebee/nudgebee-enterprise#35404. Start after the P1+P2 end-to-end demo.
What we're building, in one sentence
Two new ways for the forager to find machines it doesn't know about yet: probing its own network segment, and asking Active Directory for its computer list.
These only find machines (IP, name, a few facts). Collecting what's installed stays with discovery_inventory (#113).
Action 1: discovery_sweep
Request:
{"action": "discovery_sweep",
"params": {"cidrs": ["10.0.1.0/24"], "ports": [22, 3389, 5985],
"rate_pps": 100, "timeout_ms": 1000,
"exclusions": ["10.0.1.250/32"]}}
What it does per CIDR:
- If the CIDR is the forager's own L2: read the ARP/neighbor table after probing — gives MAC addresses for free.
- ICMP echo to each address (is anything there?).
- TCP connect to the given ports (22 = Linux/SSH, 3389/5985 = Windows — fingerprint only, we don't inventory Windows yet).
- Reverse-DNS lookup for responders.
Response per live host: {"ip": "10.0.1.15", "mac": "aa:bb:...", "rdns": "web-01.corp.local", "open_ports": [22]}.
Safety is part of the spec, not polish:
- Hard rate cap enforced in the forager (default ≤100 packets/sec) — the server asks, the forager still refuses to exceed it.
- Exclusion list honored before any packet is sent.
- Plain well-formed connects only — no raw crafted packets (malformed nmap-style probes crash embedded/OT gear).
- Open decision inside this ticket: plain
net.Dial loop vs a scanning library (e.g. naabu). Try plain first; a /24 at 100 pps is trivial.
Action 2: discovery_ldap
Uses an ldap datasource (unprivileged read-only bind account, credentials via pkg/secrets, configured like the db proxies).
Search: base DN from config, filter (objectCategory=computer), attributes name, dNSHostName, operatingSystem, lastLogonTimestamp, objectGUID.
Skip machines whose lastLogonTimestamp is older than active_within (param, e.g. 90 days) — AD is full of tombstones of machines that died years ago.
Response per computer: {"name": "WEB-01", "dns_name": "web-01.corp.local", "os": "Ubuntu", "last_logon": "...", "object_guid": "..."}. The objectGUID matters: it's a STRONG identity the server can merge on.
Acceptance criteria (each is a test)
Design: docs/design/vm-discovery-phase0.md §5, §9 (PR #117).
Part of epic: nudgebee/nudgebee-enterprise#35404. Start after the P1+P2 end-to-end demo.
What we're building, in one sentence
Two new ways for the forager to find machines it doesn't know about yet: probing its own network segment, and asking Active Directory for its computer list.
These only find machines (IP, name, a few facts). Collecting what's installed stays with
discovery_inventory(#113).Action 1:
discovery_sweepRequest:
{"action": "discovery_sweep", "params": {"cidrs": ["10.0.1.0/24"], "ports": [22, 3389, 5985], "rate_pps": 100, "timeout_ms": 1000, "exclusions": ["10.0.1.250/32"]}}What it does per CIDR:
Response per live host:
{"ip": "10.0.1.15", "mac": "aa:bb:...", "rdns": "web-01.corp.local", "open_ports": [22]}.Safety is part of the spec, not polish:
net.Dialloop vs a scanning library (e.g. naabu). Try plain first; a /24 at 100 pps is trivial.Action 2:
discovery_ldapUses an
ldapdatasource (unprivileged read-only bind account, credentials viapkg/secrets, configured like the db proxies).Search: base DN from config, filter
(objectCategory=computer), attributesname,dNSHostName,operatingSystem,lastLogonTimestamp,objectGUID.Skip machines whose
lastLogonTimestampis older thanactive_within(param, e.g. 90 days) — AD is full of tombstones of machines that died years ago.Response per computer:
{"name": "WEB-01", "dns_name": "web-01.corp.local", "os": "Ubuntu", "last_logon": "...", "object_guid": "..."}. The objectGUID matters: it's a STRONG identity the server can merge on.Acceptance criteria (each is a test)
rate_pps.lastLogonTimestampis filtered out.Design:
docs/design/vm-discovery-phase0.md§5, §9 (PR #117).