@oneuptime/common 12.0.21 → 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.
Files changed (94) hide show
  1. package/Models/DatabaseModels/Index.ts +4 -0
  2. package/Models/DatabaseModels/NetworkDevice.ts +44 -0
  3. package/Models/DatabaseModels/NetworkDeviceAutoImportRule.ts +564 -0
  4. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +38 -0
  5. package/Models/DatabaseModels/UserTwoFactorBackupCode.ts +262 -0
  6. package/Server/API/UserTwoFactorBackupCodeAPI.ts +258 -0
  7. package/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddNetworkDeviceAutoImportRule.ts +60 -0
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddUserTwoFactorBackupCode.ts +63 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/1789200000000-AddSysObjectIdPatternToAutoImportRule.ts +26 -0
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/1789300000000-AddAutoApplyVendorHealthTemplate.ts +26 -0
  11. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  12. package/Server/Services/Index.ts +4 -0
  13. package/Server/Services/NetworkDeviceAutoImportRuleEngineService.ts +917 -0
  14. package/Server/Services/NetworkDeviceAutoImportRuleService.ts +181 -0
  15. package/Server/Services/UserService.ts +42 -0
  16. package/Server/Services/UserTwoFactorBackupCodeService.ts +355 -0
  17. package/Server/Utils/Monitor/NetworkInventoryUtil.ts +39 -1
  18. package/Server/Utils/TwoFactorBackupCode.ts +266 -0
  19. package/Tests/Server/API/UserAuthenticationAPI.test.ts +16 -3
  20. package/Tests/Server/API/UserTwoFactorAuthAdminAPI.test.ts +18 -2
  21. package/Tests/Server/API/UserTwoFactorBackupCodeAPI.test.ts +1390 -0
  22. package/Tests/Server/Services/AutoImportScanCredentialSelect.test.ts +205 -0
  23. package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +933 -0
  24. package/Tests/Server/Services/UserAuthenticationService.test.ts +23 -1
  25. package/Tests/Server/Services/UserTwoFactorAuthAdmin.test.ts +21 -0
  26. package/Tests/Server/Services/UserTwoFactorBackupCodeAdminSurface.test.ts +919 -0
  27. package/Tests/Server/Services/UserTwoFactorBackupCodeService.test.ts +862 -0
  28. package/Tests/Server/Utils/Monitor/NetworkInventoryUtil.test.ts +97 -1
  29. package/Tests/Server/Utils/TwoFactorBackupCode.test.ts +475 -0
  30. package/Tests/Utils/NetworkDiscovery/AutoImportRuleMatcher.test.ts +516 -0
  31. package/Tests/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.test.ts +272 -0
  32. package/Tests/Utils/NetworkDiscovery/ScanTargetUtil.test.ts +164 -0
  33. package/Types/Email/EmailTemplateType.ts +2 -0
  34. package/Types/NetworkAutomation/RuleRunResult.ts +84 -0
  35. package/Types/Permission.ts +47 -0
  36. package/Types/UserAuthenticationStatus.ts +16 -0
  37. package/Utils/NetworkDiscovery/AutoImportRuleMatcher.ts +257 -0
  38. package/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.ts +183 -0
  39. package/Utils/NetworkDiscovery/DiscoveredHostUtil.ts +95 -0
  40. package/Utils/NetworkDiscovery/DiscoveryImportEligibility.ts +66 -0
  41. package/Utils/NetworkDiscovery/ScanTargetUtil.ts +82 -0
  42. package/build/dist/Models/DatabaseModels/Index.js +4 -0
  43. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  44. package/build/dist/Models/DatabaseModels/NetworkDevice.js +45 -0
  45. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  46. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js +589 -0
  47. package/build/dist/Models/DatabaseModels/NetworkDeviceAutoImportRule.js.map +1 -0
  48. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +28 -0
  49. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  50. package/build/dist/Models/DatabaseModels/UserTwoFactorBackupCode.js +277 -0
  51. package/build/dist/Models/DatabaseModels/UserTwoFactorBackupCode.js.map +1 -0
  52. package/build/dist/Server/API/UserTwoFactorBackupCodeAPI.js +201 -0
  53. package/build/dist/Server/API/UserTwoFactorBackupCodeAPI.js.map +1 -0
  54. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddNetworkDeviceAutoImportRule.js +35 -0
  55. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddNetworkDeviceAutoImportRule.js.map +1 -0
  56. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddUserTwoFactorBackupCode.js +46 -0
  57. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789100000000-AddUserTwoFactorBackupCode.js.map +1 -0
  58. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789200000000-AddSysObjectIdPatternToAutoImportRule.js +19 -0
  59. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789200000000-AddSysObjectIdPatternToAutoImportRule.js.map +1 -0
  60. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789300000000-AddAutoApplyVendorHealthTemplate.js +19 -0
  61. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789300000000-AddAutoApplyVendorHealthTemplate.js.map +1 -0
  62. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  63. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  64. package/build/dist/Server/Services/Index.js +4 -0
  65. package/build/dist/Server/Services/Index.js.map +1 -1
  66. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js +711 -0
  67. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleEngineService.js.map +1 -0
  68. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js +155 -0
  69. package/build/dist/Server/Services/NetworkDeviceAutoImportRuleService.js.map +1 -0
  70. package/build/dist/Server/Services/UserService.js +39 -0
  71. package/build/dist/Server/Services/UserService.js.map +1 -1
  72. package/build/dist/Server/Services/UserTwoFactorBackupCodeService.js +327 -0
  73. package/build/dist/Server/Services/UserTwoFactorBackupCodeService.js.map +1 -0
  74. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js +26 -0
  75. package/build/dist/Server/Utils/Monitor/NetworkInventoryUtil.js.map +1 -1
  76. package/build/dist/Server/Utils/TwoFactorBackupCode.js +269 -0
  77. package/build/dist/Server/Utils/TwoFactorBackupCode.js.map +1 -0
  78. package/build/dist/Types/Email/EmailTemplateType.js +2 -0
  79. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  80. package/build/dist/Types/NetworkAutomation/RuleRunResult.js +24 -0
  81. package/build/dist/Types/NetworkAutomation/RuleRunResult.js.map +1 -1
  82. package/build/dist/Types/Permission.js +41 -0
  83. package/build/dist/Types/Permission.js.map +1 -1
  84. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js +149 -0
  85. package/build/dist/Utils/NetworkDiscovery/AutoImportRuleMatcher.js.map +1 -0
  86. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js +121 -0
  87. package/build/dist/Utils/NetworkDiscovery/DiscoveredDeviceBuilder.js.map +1 -0
  88. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js +75 -0
  89. package/build/dist/Utils/NetworkDiscovery/DiscoveredHostUtil.js.map +1 -0
  90. package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js +59 -0
  91. package/build/dist/Utils/NetworkDiscovery/DiscoveryImportEligibility.js.map +1 -0
  92. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js +60 -0
  93. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js.map +1 -1
  94. package/package.json +1 -1
@@ -0,0 +1,205 @@
1
+ /*
2
+ * The auto-import rule engine reads a completed scan's SNMP credentials
3
+ * through AUTO_IMPORT_SCAN_CREDENTIAL_SELECT and copies them onto every
4
+ * device it creates via DiscoveredDeviceBuilder. The probe claim endpoint
5
+ * (App/FeatureSet/Telemetry/API/ProbeIngest/DiscoveryScan.ts) selects the
6
+ * same credential columns for the same reason: an unselected column arrives
7
+ * undefined and is silently NOT copied/used — no error anywhere, just a
8
+ * device (or a sweep) that can never authenticate.
9
+ *
10
+ * That failure mode is exactly the kind that drifts in: someone adds a
11
+ * credential column to the scan model, wires it into ONE of the three
12
+ * consumers, and the other two quietly drop it. So this suite pins the list
13
+ * in BOTH directions against the claim endpoint's select and against the
14
+ * builder — read from source with fs, the
15
+ * DiscoveryScanClaimHookFreeSafety.test.ts technique, because the select
16
+ * literal in a route handler is not importable. If an assertion here fails,
17
+ * its variable name says which side is missing which key; add the key to
18
+ * that side rather than relaxing the pin.
19
+ */
20
+
21
+ /*
22
+ * The engine's import closure reaches DatabaseService (and through it
23
+ * PasswordHash) via the three collaborating services. None of them is called
24
+ * here — this suite only wants the exported select constant — so the service
25
+ * MODULES are stubbed out before the engine is imported, keeping the suite
26
+ * Postgres-free and immune to the local-only PasswordHash ts-jest compile
27
+ * failure.
28
+ */
29
+ jest.mock("../../../Server/Services/NetworkDeviceService", () => {
30
+ return {
31
+ __esModule: true,
32
+ default: {},
33
+ };
34
+ });
35
+
36
+ jest.mock("../../../Server/Services/NetworkDeviceDiscoveryScanService", () => {
37
+ return {
38
+ __esModule: true,
39
+ default: {},
40
+ };
41
+ });
42
+
43
+ jest.mock("../../../Server/Services/NetworkDeviceAutoImportRuleService", () => {
44
+ return {
45
+ __esModule: true,
46
+ default: {},
47
+ };
48
+ });
49
+
50
+ // The engine's sweep lock would otherwise pull the Redis client in.
51
+ jest.mock("../../../Server/Infrastructure/Semaphore", () => {
52
+ return {
53
+ __esModule: true,
54
+ default: {},
55
+ };
56
+ });
57
+
58
+ jest.mock("../../../Server/Utils/Logger", () => {
59
+ return {
60
+ __esModule: true,
61
+ default: {
62
+ debug: jest.fn(),
63
+ info: jest.fn(),
64
+ warn: jest.fn(),
65
+ error: jest.fn(),
66
+ trace: jest.fn(),
67
+ },
68
+ };
69
+ });
70
+
71
+ import { AUTO_IMPORT_SCAN_CREDENTIAL_SELECT } from "../../../Server/Services/NetworkDeviceAutoImportRuleEngineService";
72
+ import { describe, expect, test } from "@jest/globals";
73
+ import fs from "fs";
74
+ import path from "path";
75
+
76
+ const REPO_ROOT: string = path.join(__dirname, "..", "..", "..", "..");
77
+
78
+ const CLAIM_ENDPOINT_SOURCE: string = fs.readFileSync(
79
+ path.join(
80
+ REPO_ROOT,
81
+ "App",
82
+ "FeatureSet",
83
+ "Telemetry",
84
+ "API",
85
+ "ProbeIngest",
86
+ "DiscoveryScan.ts",
87
+ ),
88
+ "utf8",
89
+ );
90
+
91
+ const BUILDER_SOURCE: string = fs.readFileSync(
92
+ path.join(
93
+ REPO_ROOT,
94
+ "Common",
95
+ "Utils",
96
+ "NetworkDiscovery",
97
+ "DiscoveredDeviceBuilder.ts",
98
+ ),
99
+ "utf8",
100
+ );
101
+
102
+ /*
103
+ * Every `snmp*: true` in the claim endpoint is a select entry — the file's
104
+ * only other snmp mention is the `snmpReachable !== false` responder count,
105
+ * which this shape can never match.
106
+ */
107
+ function extractSelectedSnmpColumns(source: string): Array<string> {
108
+ return Array.from(source.matchAll(/\b(snmp\w+)\s*:\s*true\b/g)).map(
109
+ (match: RegExpMatchArray) => {
110
+ return match[1]!;
111
+ },
112
+ );
113
+ }
114
+
115
+ describe("AUTO_IMPORT_SCAN_CREDENTIAL_SELECT", () => {
116
+ test("carries exactly the credential columns an import copies", () => {
117
+ expect(Object.keys(AUTO_IMPORT_SCAN_CREDENTIAL_SELECT).sort()).toEqual(
118
+ [
119
+ "probeId",
120
+ "snmpVersion",
121
+ "snmpCommunityString",
122
+ "snmpPort",
123
+ "snmpV3SecurityLevel",
124
+ "snmpV3Username",
125
+ "snmpV3AuthProtocol",
126
+ "snmpV3AuthKey",
127
+ "snmpV3PrivProtocol",
128
+ "snmpV3PrivKey",
129
+ ].sort(),
130
+ );
131
+ });
132
+
133
+ // Guard against the extraction regex rotting into a vacuous pass.
134
+ test("the claim endpoint's select is extractable from its source", () => {
135
+ const selected: Array<string> = extractSelectedSnmpColumns(
136
+ CLAIM_ENDPOINT_SOURCE,
137
+ );
138
+
139
+ expect(selected).toContain("snmpVersion");
140
+ expect(selected).toContain("snmpV3PrivKey");
141
+ // The responder-count read is not a select entry and must not match.
142
+ expect(selected).not.toContain("snmpReachable");
143
+ });
144
+
145
+ /*
146
+ * Direction one: a credential column the probe sweeps WITH but the engine
147
+ * does not select would import devices that poll with less than the scan
148
+ * used — a v3 scan importing v2c-shaped devices, say. Any name listed in
149
+ * this failure is selected by the claim endpoint and missing from
150
+ * AUTO_IMPORT_SCAN_CREDENTIAL_SELECT.
151
+ */
152
+ test("every snmp column the probe claim endpoint selects is in the engine's select", () => {
153
+ const snmpColumnsSelectedByClaimEndpointButMissingFromEngineSelect: Array<string> =
154
+ extractSelectedSnmpColumns(CLAIM_ENDPOINT_SOURCE).filter(
155
+ (column: string) => {
156
+ return !(column in AUTO_IMPORT_SCAN_CREDENTIAL_SELECT);
157
+ },
158
+ );
159
+
160
+ expect(
161
+ snmpColumnsSelectedByClaimEndpointButMissingFromEngineSelect,
162
+ ).toEqual([]);
163
+ });
164
+
165
+ /*
166
+ * Direction two: a credential column the engine copies onto devices but
167
+ * the probe never receives would mean sweeps and imports disagree about
168
+ * what the credentials ARE. Any name listed in this failure is a key of
169
+ * AUTO_IMPORT_SCAN_CREDENTIAL_SELECT missing from the claim endpoint's
170
+ * select.
171
+ */
172
+ test("every snmp key of the engine's select is selected by the probe claim endpoint", () => {
173
+ const claimSelectedColumns: Array<string> = extractSelectedSnmpColumns(
174
+ CLAIM_ENDPOINT_SOURCE,
175
+ );
176
+
177
+ const engineSnmpKeysMissingFromClaimEndpointSelect: Array<string> =
178
+ Object.keys(AUTO_IMPORT_SCAN_CREDENTIAL_SELECT)
179
+ .filter((key: string) => {
180
+ return key.startsWith("snmp");
181
+ })
182
+ .filter((key: string) => {
183
+ return !claimSelectedColumns.includes(key);
184
+ });
185
+
186
+ expect(engineSnmpKeysMissingFromClaimEndpointSelect).toEqual([]);
187
+ });
188
+
189
+ /*
190
+ * And the last hop: selecting a credential the builder never copies is the
191
+ * same silent drop one module later. Every key of the select must appear
192
+ * in DiscoveredDeviceBuilder.ts — the copy is a same-named field access,
193
+ * so a plain occurrence check is a faithful pin. Any name listed in this
194
+ * failure is selected by the engine and never mentioned by the builder.
195
+ */
196
+ test("every key of the engine's select is copied by the device builder", () => {
197
+ const engineSelectKeysNeverMentionedByBuilder: Array<string> = Object.keys(
198
+ AUTO_IMPORT_SCAN_CREDENTIAL_SELECT,
199
+ ).filter((key: string) => {
200
+ return !BUILDER_SOURCE.includes(key);
201
+ });
202
+
203
+ expect(engineSelectKeysNeverMentionedByBuilder).toEqual([]);
204
+ });
205
+ });