@oneuptime/common 12.0.22 → 12.0.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/Models/DatabaseModels/Index.ts +2 -0
- package/Models/DatabaseModels/NetworkDevice.ts +44 -0
- package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +564 -0
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +38 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddNetworkDeviceAutoImportRule.ts +60 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789200000000-AddSysObjectIdPatternToAutoImportRule.ts +26 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1789300000000-AddAutoApplyVendorHealthTemplate.ts +26 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +917 -0
- package/Server/Services/NetworkDeviceAutoImportRuleService.ts +181 -0
- package/Server/Utils/Monitor/NetworkInventoryUtil.ts +39 -1
- package/Tests/Server/Services/AutoImportScanCredentialSelect.test.ts +205 -0
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +933 -0
- package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +97 -1
- package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +516 -0
- package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +272 -0
- package/Tests/Utils/NetworkDiscovery/ScanTargetUtil.test.ts +164 -0
- package/Types/NetworkAutomation/RuleRunResult.ts +84 -0
- package/Types/Permission.ts +47 -0
- package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +257 -0
- package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +183 -0
- package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +95 -0
- package/Utils/NetworkDiscovery/DiscoveryImportEligibility.ts +66 -0
- package/Utils/NetworkDiscovery/ScanTargetUtil.ts +82 -0
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDevice.js +45 -0
- package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +589 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +28 -0
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddNetworkDeviceAutoImportRule.js +35 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddNetworkDeviceAutoImportRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789200000000-AddSysObjectIdPatternToAutoImportRule.js +19 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789200000000-AddSysObjectIdPatternToAutoImportRule.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789300000000-AddAutoApplyVendorHealthTemplate.js +19 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789300000000-AddAutoApplyVendorHealthTemplate.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +711 -0
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -0
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +155 -0
- package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +26 -0
- package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
- package/build/dist/Types/NetworkAutomation/RuleRunResult.js +24 -0
- package/build/dist/Types/NetworkAutomation/RuleRunResult.js.map +1 -1
- package/build/dist/Types/Permission.js +41 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +149 -0
- package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +121 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +75 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js +59 -0
- package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js +60 -0
- package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
import NetworkDeviceMonitoringMethod from "../../Types/NetworkDevice/NetworkDeviceMonitoringMethod";
|
|
2
|
+
import CidrMatchUtil from "../NetworkSite/CidrMatchUtil";
|
|
3
|
+
import RulePatternMatchUtil from "../Rules/RulePatternMatchUtil";
|
|
4
|
+
import { monitoringMethodForDiscoveredHost } from "./DiscoveryImportEligibility";
|
|
5
|
+
import ScanTargetUtil from "./ScanTargetUtil";
|
|
6
|
+
/*
|
|
7
|
+
* Longest subject string a pattern is evaluated against. SNMP DisplayStrings
|
|
8
|
+
* top out at 255 octets, so anything longer only appears in a hostile or
|
|
9
|
+
* corrupt probe payload — and the jsonb these hosts come from is stored
|
|
10
|
+
* verbatim, unbounded. Patterns run through JavaScript's backtracking regex
|
|
11
|
+
* engine, whose worst case grows with subject length, so the subject is
|
|
12
|
+
* clamped before matching: a rule author writing a pathological pattern can
|
|
13
|
+
* only ever run it against a bounded string. (The same author already holds
|
|
14
|
+
* Edit permission on rules — this bounds the blast radius, it does not make
|
|
15
|
+
* hostile patterns free.)
|
|
16
|
+
*/
|
|
17
|
+
const MAX_PATTERN_SUBJECT_LENGTH = 500;
|
|
18
|
+
function clampSubject(value) {
|
|
19
|
+
if (typeof value !== "string") {
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
return value.length > MAX_PATTERN_SUBJECT_LENGTH
|
|
23
|
+
? value.substring(0, MAX_PATTERN_SUBJECT_LENGTH)
|
|
24
|
+
: value;
|
|
25
|
+
}
|
|
26
|
+
/*
|
|
27
|
+
* Strips the leading dot some agents prefix OIDs with (".1.3.6.1.4.1.9...")
|
|
28
|
+
* so a pattern and a value in the two spellings still line up.
|
|
29
|
+
*/
|
|
30
|
+
function normalizeOid(value) {
|
|
31
|
+
return value.startsWith(".") ? value.substring(1) : value;
|
|
32
|
+
}
|
|
33
|
+
/*
|
|
34
|
+
* OID-aware matching for the sysObjectID condition — deliberately NOT
|
|
35
|
+
* RulePatternMatchUtil, whose regex-FIRST semantics are systematically wrong
|
|
36
|
+
* for a dotted numeric arc: as a regex, "1.3.6.1.4.1.9.*" has every '.'
|
|
37
|
+
* matching any character and is unanchored, so it also matches enterprise
|
|
38
|
+
* 94, 990, 9148... — the exact vendors a "Cisco only" rule exists to keep
|
|
39
|
+
* out, in a pipeline that creates devices unattended. Here:
|
|
40
|
+
*
|
|
41
|
+
* - A pattern containing '*' is a whole-string glob with LITERAL dots
|
|
42
|
+
* (CidrMatchUtil's ReDoS-safe matcher): "1.3.6.1.4.1.9.*" matches the
|
|
43
|
+
* Cisco subtree and nothing else.
|
|
44
|
+
* - A pattern with no '*' is an arc-prefix test on sub-identifier
|
|
45
|
+
* boundaries: "1.3.6.1.4.1.9" matches itself and everything under it,
|
|
46
|
+
* and can never match "1.3.6.1.4.1.94" — the same comparison
|
|
47
|
+
* SnmpVendorTemplateUtil.getEnterpriseNumber makes.
|
|
48
|
+
*/
|
|
49
|
+
export function matchesOidPattern(value, pattern) {
|
|
50
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const oid = normalizeOid(value.trim());
|
|
54
|
+
const oidPattern = normalizeOid(pattern);
|
|
55
|
+
if (oidPattern.includes("*")) {
|
|
56
|
+
return CidrMatchUtil.hostnameMatchesWildcard(oid, oidPattern);
|
|
57
|
+
}
|
|
58
|
+
return oid === oidPattern || oid.startsWith(oidPattern + ".");
|
|
59
|
+
}
|
|
60
|
+
export class AutoImportRuleMatcher {
|
|
61
|
+
// True when the host answered ping but not SNMP.
|
|
62
|
+
static isPingOnlyHost(host) {
|
|
63
|
+
return (monitoringMethodForDiscoveredHost(host) ===
|
|
64
|
+
NetworkDeviceMonitoringMethod.Monitor);
|
|
65
|
+
}
|
|
66
|
+
/*
|
|
67
|
+
* True when this rule's populated conditions all match the host.
|
|
68
|
+
*
|
|
69
|
+
* The ping-only gate applies to IMPORT rules only: a host that never
|
|
70
|
+
* answered SNMP imports only through a rule that explicitly opted into
|
|
71
|
+
* ping-only hosts — an SNMP credential typo makes a whole subnet report as
|
|
72
|
+
* ping-only, and a rule silently importing hundreds of half-identified
|
|
73
|
+
* hosts on a typo is the failure mode this default exists to prevent. An
|
|
74
|
+
* EXCLUSION rule has no such gate: a veto is a veto whatever the host
|
|
75
|
+
* answered with.
|
|
76
|
+
*/
|
|
77
|
+
static ruleMatchesHost(rule, host) {
|
|
78
|
+
const ipMatchTarget = (rule.ipMatchTarget || "").trim();
|
|
79
|
+
const sysNamePattern = (rule.sysNamePattern || "").trim();
|
|
80
|
+
const sysDescrPattern = (rule.sysDescrPattern || "").trim();
|
|
81
|
+
const sysObjectIdPattern = (rule.sysObjectIdPattern || "").trim();
|
|
82
|
+
// A rule with no conditions matches nothing — the site-rule precedent.
|
|
83
|
+
if (!ipMatchTarget &&
|
|
84
|
+
!sysNamePattern &&
|
|
85
|
+
!sysDescrPattern &&
|
|
86
|
+
!sysObjectIdPattern) {
|
|
87
|
+
return false;
|
|
88
|
+
}
|
|
89
|
+
if (!rule.isExclusion &&
|
|
90
|
+
!rule.includePingOnlyHosts &&
|
|
91
|
+
AutoImportRuleMatcher.isPingOnlyHost(host)) {
|
|
92
|
+
return false;
|
|
93
|
+
}
|
|
94
|
+
if (ipMatchTarget) {
|
|
95
|
+
if (!host.ipAddress ||
|
|
96
|
+
!ScanTargetUtil.contains(ipMatchTarget, host.ipAddress)) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/*
|
|
101
|
+
* Pattern semantics are RulePatternMatchUtil's, identical to label/owner
|
|
102
|
+
* rules: case-insensitive unanchored regex first, '*' glob fallback —
|
|
103
|
+
* so "contains WB1678" is written the same way here as everywhere else.
|
|
104
|
+
* A host missing the field never matches a configured pattern.
|
|
105
|
+
*/
|
|
106
|
+
if (sysNamePattern &&
|
|
107
|
+
!RulePatternMatchUtil.matches(clampSubject(host.sysName), sysNamePattern)) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
if (sysDescrPattern &&
|
|
111
|
+
!RulePatternMatchUtil.matches(clampSubject(host.sysDescr), sysDescrPattern)) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
if (sysObjectIdPattern &&
|
|
115
|
+
!matchesOidPattern(clampSubject(host.sysObjectId), sysObjectIdPattern)) {
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* What the whole rule set says about one host: import, and through which
|
|
122
|
+
* rules — or vetoed, and by which exclusion.
|
|
123
|
+
*
|
|
124
|
+
* Exclusions are evaluated first so the evaluation can short-circuit into
|
|
125
|
+
* an explainable answer: "excluded by rule R" beats "matched rules A and B
|
|
126
|
+
* and was then excluded" for the operator reading a dry run.
|
|
127
|
+
*/
|
|
128
|
+
static evaluateHost(rules, host) {
|
|
129
|
+
for (const rule of rules) {
|
|
130
|
+
if (rule.isExclusion &&
|
|
131
|
+
AutoImportRuleMatcher.ruleMatchesHost(rule, host)) {
|
|
132
|
+
return {
|
|
133
|
+
shouldImport: false,
|
|
134
|
+
matchedRules: [],
|
|
135
|
+
excludedByRule: rule,
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
const matchedRules = rules.filter((rule) => {
|
|
140
|
+
return (!rule.isExclusion && AutoImportRuleMatcher.ruleMatchesHost(rule, host));
|
|
141
|
+
});
|
|
142
|
+
return {
|
|
143
|
+
shouldImport: matchedRules.length > 0,
|
|
144
|
+
matchedRules: matchedRules,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
export default AutoImportRuleMatcher;
|
|
149
|
+
//# sourceMappingURL=AutoImportRuleMatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AutoImportRuleMatcher.js","sourceRoot":"","sources":["../../../../Utils/NetworkDiscovery/AutoImportRuleMatcher.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import NetworkDevice from "../../Models/DatabaseModels/NetworkDevice";
|
|
2
|
+
import NetworkDeviceMonitoringMethod from "../../Types/NetworkDevice/NetworkDeviceMonitoringMethod";
|
|
3
|
+
import ObjectID from "../../Types/ObjectID";
|
|
4
|
+
import { monitoringMethodForDiscoveredHost } from "./DiscoveryImportEligibility";
|
|
5
|
+
/*
|
|
6
|
+
* One discovered host -> one NetworkDevice, the same way everywhere.
|
|
7
|
+
*
|
|
8
|
+
* This mapping used to live inline in the Dashboard's Discovery page import
|
|
9
|
+
* loop. The server-side auto-import rule engine needs the identical recipe —
|
|
10
|
+
* a host imported by a rule and the same host imported by hand must be the
|
|
11
|
+
* same device — so the recipe lives here and both callers use it. Anything
|
|
12
|
+
* added to one path by editing this file is automatically added to the other.
|
|
13
|
+
*/
|
|
14
|
+
/*
|
|
15
|
+
* Longest device name the builder will emit.
|
|
16
|
+
*
|
|
17
|
+
* The name column is varchar(100) and the create path THROWS on overflow (no
|
|
18
|
+
* truncation), but the real ceiling is the slug: it is slugify(name) plus a
|
|
19
|
+
* dash and ten random digits into its own varchar(100), so a name over ~88
|
|
20
|
+
* characters fails the create with a slug-length error even though the name
|
|
21
|
+
* itself fits. SNMP sysName is a DisplayString of up to 255 octets, so
|
|
22
|
+
* over-long names are routine on real gear, and the collision fallback below
|
|
23
|
+
* appends up to 18 more characters (" (255.255.255.255)"). 80 leaves headroom
|
|
24
|
+
* for both.
|
|
25
|
+
*/
|
|
26
|
+
export const MAX_DEVICE_NAME_LENGTH = 80;
|
|
27
|
+
// NetworkDevice.description is stored to 500 characters; sysDescr can be 255+.
|
|
28
|
+
export const MAX_DEVICE_DESCRIPTION_LENGTH = 500;
|
|
29
|
+
function truncate(value, maxLength) {
|
|
30
|
+
return value.length > maxLength ? value.substring(0, maxLength) : value;
|
|
31
|
+
}
|
|
32
|
+
/** The name a discovered host imports under: its sysName, or its address. */
|
|
33
|
+
export function buildDeviceName(host) {
|
|
34
|
+
return truncate((host.sysName || "").trim() || host.ipAddress, MAX_DEVICE_NAME_LENGTH);
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* The fallback name when `buildDeviceName`'s answer is already taken.
|
|
38
|
+
*
|
|
39
|
+
* Device names are unique per project, and two devices legitimately sharing a
|
|
40
|
+
* sysName (a factory default, a cloned config) is common on real estates. The
|
|
41
|
+
* address is what tells them apart, so it goes into the name — with the
|
|
42
|
+
* sysName cut down first so the composed string still fits under the same
|
|
43
|
+
* ceiling.
|
|
44
|
+
*/
|
|
45
|
+
export function buildFallbackDeviceName(host) {
|
|
46
|
+
const suffix = ` (${host.ipAddress})`;
|
|
47
|
+
const baseName = buildDeviceName(host);
|
|
48
|
+
return (truncate(baseName, Math.max(1, MAX_DEVICE_NAME_LENGTH - suffix.length)) +
|
|
49
|
+
suffix);
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* The NetworkDevice a discovered host imports as.
|
|
53
|
+
*
|
|
54
|
+
* An SNMP-reachable host becomes a polled device carrying the scan's probe
|
|
55
|
+
* and credentials. A ping-only host becomes a monitor-backed device with no
|
|
56
|
+
* probe, no credentials and polling off: it is recorded so it can belong to a
|
|
57
|
+
* site and appear on the topology map, and binding a monitor to it stays a
|
|
58
|
+
* separate, deliberate step.
|
|
59
|
+
*
|
|
60
|
+
* The caller supplies the name (normally `buildDeviceName(host)`) so the
|
|
61
|
+
* name-collision retry can rebuild the same device under
|
|
62
|
+
* `buildFallbackDeviceName(host)` without re-deciding anything else.
|
|
63
|
+
*/
|
|
64
|
+
export function buildNetworkDeviceFromDiscoveredHost(data) {
|
|
65
|
+
const host = data.host;
|
|
66
|
+
const device = new NetworkDevice();
|
|
67
|
+
device.projectId = data.projectId;
|
|
68
|
+
device.name = data.name || buildDeviceName(host);
|
|
69
|
+
// The address is the device's hostname AND the registered-host dedup key.
|
|
70
|
+
device.hostname = host.ipAddress;
|
|
71
|
+
if (host.sysDescr) {
|
|
72
|
+
device.description = truncate(host.sysDescr, MAX_DEVICE_DESCRIPTION_LENGTH);
|
|
73
|
+
}
|
|
74
|
+
const monitoringMethod = monitoringMethodForDiscoveredHost(host);
|
|
75
|
+
device.monitoringMethod = monitoringMethod;
|
|
76
|
+
if (monitoringMethod === NetworkDeviceMonitoringMethod.Monitor) {
|
|
77
|
+
/*
|
|
78
|
+
* A ping-only host is never SNMP-polled, so the vendor-template
|
|
79
|
+
* auto-apply (which keys off a polled sysObjectID) stays off too.
|
|
80
|
+
*/
|
|
81
|
+
device.isPollingEnabled = false;
|
|
82
|
+
return device;
|
|
83
|
+
}
|
|
84
|
+
if (data.autoApplyVendorHealthTemplate) {
|
|
85
|
+
device.autoApplyVendorHealthTemplate = true;
|
|
86
|
+
}
|
|
87
|
+
if (data.scan.probeId) {
|
|
88
|
+
// Re-wrapped: the scan may hold a serialized id rather than an ObjectID.
|
|
89
|
+
device.probeId = new ObjectID(data.scan.probeId.toString());
|
|
90
|
+
}
|
|
91
|
+
if (data.scan.snmpVersion) {
|
|
92
|
+
device.snmpVersion = data.scan.snmpVersion;
|
|
93
|
+
}
|
|
94
|
+
if (data.scan.snmpCommunityString) {
|
|
95
|
+
device.snmpCommunityString = data.scan.snmpCommunityString;
|
|
96
|
+
}
|
|
97
|
+
if (data.scan.snmpPort) {
|
|
98
|
+
device.snmpPort = data.scan.snmpPort;
|
|
99
|
+
}
|
|
100
|
+
// Carry the v3 credentials so a v3 scan imports as a v3 device.
|
|
101
|
+
if (data.scan.snmpV3SecurityLevel) {
|
|
102
|
+
device.snmpV3SecurityLevel = data.scan.snmpV3SecurityLevel;
|
|
103
|
+
}
|
|
104
|
+
if (data.scan.snmpV3Username) {
|
|
105
|
+
device.snmpV3Username = data.scan.snmpV3Username;
|
|
106
|
+
}
|
|
107
|
+
if (data.scan.snmpV3AuthProtocol) {
|
|
108
|
+
device.snmpV3AuthProtocol = data.scan.snmpV3AuthProtocol;
|
|
109
|
+
}
|
|
110
|
+
if (data.scan.snmpV3AuthKey) {
|
|
111
|
+
device.snmpV3AuthKey = data.scan.snmpV3AuthKey;
|
|
112
|
+
}
|
|
113
|
+
if (data.scan.snmpV3PrivProtocol) {
|
|
114
|
+
device.snmpV3PrivProtocol = data.scan.snmpV3PrivProtocol;
|
|
115
|
+
}
|
|
116
|
+
if (data.scan.snmpV3PrivKey) {
|
|
117
|
+
device.snmpV3PrivKey = data.scan.snmpV3PrivKey;
|
|
118
|
+
}
|
|
119
|
+
return device;
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=DiscoveredDeviceBuilder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscoveredDeviceBuilder.js","sourceRoot":"","sources":["../../../../Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Normalisation for a scan's stored results, shared by every reader of the
|
|
3
|
+
* `discoveredDevices` jsonb column: the dashboard's Review dialog and the
|
|
4
|
+
* server-side auto-import rule engine. It moved here from the Dashboard's
|
|
5
|
+
* DiscoveredHostFilter when the engine appeared, for the reason spelled out
|
|
6
|
+
* on normalizeDiscoveredHosts below — a server that matched raw jsonb would
|
|
7
|
+
* re-hit every landmine the dialog already fixed.
|
|
8
|
+
*/
|
|
9
|
+
/*
|
|
10
|
+
* What a nullish or non-object entry in the jsonb reads as: nothing. Written
|
|
11
|
+
* as a type guard so the normalisation below narrows properly.
|
|
12
|
+
*/
|
|
13
|
+
function isDiscoveredHostObject(host) {
|
|
14
|
+
return Boolean(host) && typeof host === "object";
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* The scan's rows, cleaned up so every rule downstream sees the same thing.
|
|
18
|
+
*
|
|
19
|
+
* `discoveredDevices` is jsonb written verbatim from the probe's payload, and
|
|
20
|
+
* the only guard on it checks that the VALUE is an array — never that its
|
|
21
|
+
* elements are shaped like hosts. Everything downstream keys off `ipAddress`,
|
|
22
|
+
* so three payload shapes that a probe should never send, but that nothing
|
|
23
|
+
* stops it sending, each broke something:
|
|
24
|
+
*
|
|
25
|
+
* - A `null` element. Every predicate dereferences the host, so one null row
|
|
26
|
+
* threw a TypeError the moment the operator clicked a filter button —
|
|
27
|
+
* inside the modal body, during render.
|
|
28
|
+
* - A non-string address. `10` is written into the selection record as the
|
|
29
|
+
* key "10" (object keys are strings) but matched out of the imported-set
|
|
30
|
+
* with `Set.has(10)`, which does not coerce — so the host imported and
|
|
31
|
+
* then could never be retired, and pressing Import again duplicated it.
|
|
32
|
+
* - The same address on two rows with different frozen `isAlreadyRegistered`
|
|
33
|
+
* values. One checkbox governs both rows, but only one of them refused to
|
|
34
|
+
* import, so whether a device already in the inventory got created a
|
|
35
|
+
* second time depended on which order the probe happened to list them in.
|
|
36
|
+
*
|
|
37
|
+
* All three are fixed here rather than at each call site, so the row the
|
|
38
|
+
* operator sees, the badge above it, the list Import walks, and the hosts an
|
|
39
|
+
* auto-import rule evaluates can never be working from different readings of
|
|
40
|
+
* the same payload.
|
|
41
|
+
*/
|
|
42
|
+
export function normalizeDiscoveredHosts(hosts) {
|
|
43
|
+
const cleaned = [];
|
|
44
|
+
for (const host of hosts) {
|
|
45
|
+
if (!isDiscoveredHostObject(host)) {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
/*
|
|
49
|
+
* Trimmed as well as stringified: " " is not an address, but it is
|
|
50
|
+
* truthy, so it used to pass selectability and import as a Network Device
|
|
51
|
+
* whose hostname was a single space.
|
|
52
|
+
*/
|
|
53
|
+
cleaned.push(Object.assign(Object.assign({}, host), { ipAddress: host.ipAddress === undefined || host.ipAddress === null
|
|
54
|
+
? ""
|
|
55
|
+
: String(host.ipAddress).trim() }));
|
|
56
|
+
}
|
|
57
|
+
// An address the scan reports as registered is registered on every row.
|
|
58
|
+
const registeredIpAddresses = new Set();
|
|
59
|
+
for (const host of cleaned) {
|
|
60
|
+
if (host.ipAddress && host.isAlreadyRegistered) {
|
|
61
|
+
registeredIpAddresses.add(host.ipAddress);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (registeredIpAddresses.size === 0) {
|
|
65
|
+
return cleaned;
|
|
66
|
+
}
|
|
67
|
+
return cleaned.map((host) => {
|
|
68
|
+
if (host.isAlreadyRegistered ||
|
|
69
|
+
!registeredIpAddresses.has(host.ipAddress)) {
|
|
70
|
+
return host;
|
|
71
|
+
}
|
|
72
|
+
return Object.assign(Object.assign({}, host), { isAlreadyRegistered: true });
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
//# sourceMappingURL=DiscoveredHostUtil.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscoveredHostUtil.js","sourceRoot":"","sources":["../../../../Utils/NetworkDiscovery/DiscoveredHostUtil.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AAEH;;;GAGG;AACH,SAAS,sBAAsB,CAC7B,IAAa;IAEb,OAAO,OAAO,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,KAAK,QAAQ,CAAC;AACnD,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,MAAM,UAAU,wBAAwB,CACtC,KAAqC;IAErC,MAAM,OAAO,GAAmC,EAAE,CAAC;IAEnD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,sBAAsB,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,SAAS;QACX,CAAC;QAED;;;;WAIG;QACH,OAAO,CAAC,IAAI,iCACP,IAAI,KACP,SAAS,EACP,IAAI,CAAC,SAAS,KAAK,SAAS,IAAI,IAAI,CAAC,SAAS,KAAK,IAAI;gBACrD,CAAC,CAAC,EAAE;gBACJ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,EAAE,IACnC,CAAC;IACL,CAAC;IAED,wEAAwE;IACxE,MAAM,qBAAqB,GAAgB,IAAI,GAAG,EAAU,CAAC;IAE7D,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC3B,IAAI,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,mBAAmB,EAAE,CAAC;YAC/C,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5C,CAAC;IACH,CAAC;IAED,IAAI,qBAAqB,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACrC,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,IAA6B,EAAE,EAAE;QACnD,IACE,IAAI,CAAC,mBAAmB;YACxB,CAAC,qBAAqB,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,EAC1C,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,uCAAY,IAAI,KAAE,mBAAmB,EAAE,IAAI,IAAG;IAChD,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import NetworkDeviceMonitoringMethod from "../../Types/NetworkDevice/NetworkDeviceMonitoringMethod";
|
|
2
|
+
/*
|
|
3
|
+
* Pure, react-free import rule for discovery scan results.
|
|
4
|
+
*
|
|
5
|
+
* Every host the sweep found alive is importable; what differs is HOW. A host
|
|
6
|
+
* that answered SNMP becomes a polled device with the scan's credentials. A
|
|
7
|
+
* host that answered only ping becomes a monitor-backed device: no probe, no
|
|
8
|
+
* credentials, health supplied later by a monitor the operator binds to it.
|
|
9
|
+
*
|
|
10
|
+
* Ping-only hosts used to be refused outright, on the reasoning that they
|
|
11
|
+
* would turn up as ARP/FDB endpoints once their switch was monitored. That is
|
|
12
|
+
* true only where a monitored switch sees them, and an endpoint is not a
|
|
13
|
+
* device — it cannot belong to a site, carry labels, own an owner rule, or be
|
|
14
|
+
* one end of a link. Issue #3023 is what that gap looks like from the outside:
|
|
15
|
+
* "devices I monitor manually don't appear in the topology at all".
|
|
16
|
+
*
|
|
17
|
+
* Lives in Common (it started life next to the Discovery page component)
|
|
18
|
+
* because the dashboard's Review dialog and the server-side auto-import rule
|
|
19
|
+
* engine both decide "how does this host import" through it, and the two must
|
|
20
|
+
* never disagree: the group a host is shown under in the dialog and the
|
|
21
|
+
* monitoring method a rule imports it with are the same decision.
|
|
22
|
+
*/
|
|
23
|
+
/**
|
|
24
|
+
* Which monitoring method a discovered host should be imported under.
|
|
25
|
+
*
|
|
26
|
+
* Only an EXPLICIT snmpReachable === false means ping-only: scans stored
|
|
27
|
+
* before the field existed carry undefined, and every host on those scans
|
|
28
|
+
* answered SNMP (ping-only sweeps did not exist yet), so legacy rows keep
|
|
29
|
+
* importing as SNMP devices.
|
|
30
|
+
*/
|
|
31
|
+
export function monitoringMethodForDiscoveredHost(host) {
|
|
32
|
+
/*
|
|
33
|
+
* Nullish hosts read as SNMP rather than throwing. `discoveredDevices` is
|
|
34
|
+
* jsonb written verbatim from the probe's payload and the only guard on it
|
|
35
|
+
* (DiscoveryScanOutcome.getDiscoveredHosts) checks that the VALUE is an
|
|
36
|
+
* array — never that its elements are objects. A single null element used
|
|
37
|
+
* to take the whole page down from inside a table cell or a modal body,
|
|
38
|
+
* where a thrown TypeError has nowhere useful to go. Every other kind of
|
|
39
|
+
* junk element (a number, a string, {}) already read as SNMP; null is now
|
|
40
|
+
* simply consistent with them.
|
|
41
|
+
*/
|
|
42
|
+
return (host === null || host === void 0 ? void 0 : host.snmpReachable) === false
|
|
43
|
+
? NetworkDeviceMonitoringMethod.Monitor
|
|
44
|
+
: NetworkDeviceMonitoringMethod.Snmp;
|
|
45
|
+
}
|
|
46
|
+
/** True when the discovered host can be imported as a Network Device. */
|
|
47
|
+
export function isImportableDiscoveredHost(_host) {
|
|
48
|
+
/*
|
|
49
|
+
* Every alive host now is. The predicate survives because the Discovery
|
|
50
|
+
* page filters and counts through it, and because it is the seam where a
|
|
51
|
+
* future "don't import X" rule for MANUAL review would belong. (The
|
|
52
|
+
* automatic path already has one: an auto-import exclusion rule vetoes
|
|
53
|
+
* hosts for the rule engine — deliberately without reaching into this
|
|
54
|
+
* dialog, where a human is looking at the list and unticking a host is
|
|
55
|
+
* the veto.)
|
|
56
|
+
*/
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=DiscoveryImportEligibility.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscoveryImportEligibility.js","sourceRoot":"","sources":["../../../../Utils/NetworkDiscovery/DiscoveryImportEligibility.ts"],"names":[],"mappings":"AACA,OAAO,6BAA6B,MAAM,yDAAyD,CAAC;AAEpG;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH;;;;;;;GAOG;AACH,MAAM,UAAU,iCAAiC,CAC/C,IAAgD;IAEhD;;;;;;;;;OASG;IACH,OAAO,CAAA,IAAI,aAAJ,IAAI,uBAAJ,IAAI,CAAE,aAAa,MAAK,KAAK;QAClC,CAAC,CAAC,6BAA6B,CAAC,OAAO;QACvC,CAAC,CAAC,6BAA6B,CAAC,IAAI,CAAC;AACzC,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,0BAA0B,CACxC,KAA8B;IAE9B;;;;;;;;OAQG;IACH,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -102,6 +102,42 @@ export class ScanTargetUtil {
|
|
|
102
102
|
}
|
|
103
103
|
return ScanTargetUtil.expandOctetRangeTarget(parsed);
|
|
104
104
|
}
|
|
105
|
+
/*
|
|
106
|
+
* True when `ip` falls inside `target`, in either notation. This is the
|
|
107
|
+
* matcher behind the auto-import rules' "Host IP is in" condition, sharing
|
|
108
|
+
* the exact parser scan targets are validated and expanded with — so a
|
|
109
|
+
* condition that saves is a condition that matches what its scan sweeps.
|
|
110
|
+
*
|
|
111
|
+
* Containment, not enumeration: a CIDR block is a mask comparison over the
|
|
112
|
+
* whole block (network and broadcast addresses INCLUDED — a rule asking
|
|
113
|
+
* "is this address in 10.0.0.0/24" means the subnet, not the sweep list),
|
|
114
|
+
* and an octet range is per-octet interval membership. The latter is NOT a
|
|
115
|
+
* single numeric interval: for `10.16-22.0-255.51-66`, the address
|
|
116
|
+
* 10.17.5.10 sits between the range's lowest and highest addresses but its
|
|
117
|
+
* fourth octet is outside 51-66, so it does not match.
|
|
118
|
+
*
|
|
119
|
+
* Malformed targets and malformed addresses match nothing.
|
|
120
|
+
*/
|
|
121
|
+
static contains(target, ip) {
|
|
122
|
+
const parsed = ScanTargetUtil.parse(target);
|
|
123
|
+
if (!parsed) {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
const octets = ScanTargetUtil.parseIpOctets(ip);
|
|
127
|
+
if (!octets) {
|
|
128
|
+
return false;
|
|
129
|
+
}
|
|
130
|
+
if (parsed.notation === ScanTargetNotation.Cidr) {
|
|
131
|
+
const ipLong = (((octets[0] * 256 + octets[1]) * 256 + octets[2]) * 256 +
|
|
132
|
+
octets[3]) >>>
|
|
133
|
+
0;
|
|
134
|
+
return (ipLong >= parsed.networkLong &&
|
|
135
|
+
ipLong < parsed.networkLong + parsed.blockSize);
|
|
136
|
+
}
|
|
137
|
+
return parsed.octetRanges.every((range, index) => {
|
|
138
|
+
return octets[index] >= range.start && octets[index] <= range.end;
|
|
139
|
+
});
|
|
140
|
+
}
|
|
105
141
|
/*
|
|
106
142
|
* Both notations in one sentence, for form hints and error messages. Kept
|
|
107
143
|
* here so the UI, the server-side validator and the probe all describe the
|
|
@@ -278,6 +314,28 @@ export class ScanTargetUtil {
|
|
|
278
314
|
}
|
|
279
315
|
return hosts;
|
|
280
316
|
}
|
|
317
|
+
// '10.0.0.1' -> [10, 0, 0, 1]; anything malformed -> null.
|
|
318
|
+
static parseIpOctets(ip) {
|
|
319
|
+
if (typeof ip !== "string") {
|
|
320
|
+
return null;
|
|
321
|
+
}
|
|
322
|
+
const terms = ip.trim().split(".");
|
|
323
|
+
if (terms.length !== 4) {
|
|
324
|
+
return null;
|
|
325
|
+
}
|
|
326
|
+
const octets = [];
|
|
327
|
+
for (const term of terms) {
|
|
328
|
+
if (!ScanTargetUtil.IP_OCTET_PATTERN.test(term)) {
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
const octet = parseInt(term, 10);
|
|
332
|
+
if (octet > 255) {
|
|
333
|
+
return null;
|
|
334
|
+
}
|
|
335
|
+
octets.push(octet);
|
|
336
|
+
}
|
|
337
|
+
return octets;
|
|
338
|
+
}
|
|
281
339
|
static getMalformedTargetMessage(target) {
|
|
282
340
|
const shown = typeof target === "string" ? target.trim() : String(target);
|
|
283
341
|
return (`"${shown}" is not a valid scan target. ` + ScanTargetUtil.getSyntaxHint());
|
|
@@ -326,6 +384,8 @@ ScanTargetUtil.MAX_TARGET_LENGTH = 64;
|
|
|
326
384
|
ScanTargetUtil.CIDR_PATTERN = /^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\/(\d{1,3})$/;
|
|
327
385
|
// A single octet term: `42` or `16-22`. Bounds are validated after parsing.
|
|
328
386
|
ScanTargetUtil.OCTET_TERM_PATTERN = /^(\d{1,3})(?:-(\d{1,3}))?$/;
|
|
387
|
+
// One octet of a bare address. Bounds are validated after parsing.
|
|
388
|
+
ScanTargetUtil.IP_OCTET_PATTERN = /^\d{1,3}$/;
|
|
329
389
|
ScanTargetUtil.EXAMPLE_CIDR = "192.168.1.0/24";
|
|
330
390
|
ScanTargetUtil.EXAMPLE_OCTET_RANGE = "10.16-22.0-255.51-66";
|
|
331
391
|
export default ScanTargetUtil;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ScanTargetUtil.js","sourceRoot":"","sources":["../../../../Utils/NetworkDiscovery/ScanTargetUtil.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,4DAA4D;AAC5D,MAAM,CAAN,IAAY,kBAGX;AAHD,WAAY,kBAAkB;IAC5B,mCAAa,CAAA;IACb,+CAAyB,CAAA;AAC3B,CAAC,EAHW,kBAAkB,KAAlB,kBAAkB,QAG7B;AAgCD,MAAM,OAAO,cAAc;
|
|
1
|
+
{"version":3,"file":"ScanTargetUtil.js","sourceRoot":"","sources":["../../../../Utils/NetworkDiscovery/ScanTargetUtil.ts"],"names":[],"mappings":"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"}
|