@sentriflow/core 0.1.0

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 (71) hide show
  1. package/LICENSE +190 -0
  2. package/README.md +86 -0
  3. package/package.json +60 -0
  4. package/src/constants.ts +77 -0
  5. package/src/engine/RuleExecutor.ts +256 -0
  6. package/src/engine/Runner.ts +312 -0
  7. package/src/engine/SandboxedExecutor.ts +208 -0
  8. package/src/errors.ts +88 -0
  9. package/src/helpers/arista/helpers.ts +1220 -0
  10. package/src/helpers/arista/index.ts +12 -0
  11. package/src/helpers/aruba/helpers.ts +637 -0
  12. package/src/helpers/aruba/index.ts +13 -0
  13. package/src/helpers/cisco/helpers.ts +534 -0
  14. package/src/helpers/cisco/index.ts +11 -0
  15. package/src/helpers/common/helpers.ts +265 -0
  16. package/src/helpers/common/index.ts +5 -0
  17. package/src/helpers/common/validation.ts +280 -0
  18. package/src/helpers/cumulus/helpers.ts +676 -0
  19. package/src/helpers/cumulus/index.ts +12 -0
  20. package/src/helpers/extreme/helpers.ts +422 -0
  21. package/src/helpers/extreme/index.ts +12 -0
  22. package/src/helpers/fortinet/helpers.ts +892 -0
  23. package/src/helpers/fortinet/index.ts +12 -0
  24. package/src/helpers/huawei/helpers.ts +790 -0
  25. package/src/helpers/huawei/index.ts +11 -0
  26. package/src/helpers/index.ts +53 -0
  27. package/src/helpers/juniper/helpers.ts +756 -0
  28. package/src/helpers/juniper/index.ts +12 -0
  29. package/src/helpers/mikrotik/helpers.ts +722 -0
  30. package/src/helpers/mikrotik/index.ts +12 -0
  31. package/src/helpers/nokia/helpers.ts +856 -0
  32. package/src/helpers/nokia/index.ts +11 -0
  33. package/src/helpers/paloalto/helpers.ts +939 -0
  34. package/src/helpers/paloalto/index.ts +12 -0
  35. package/src/helpers/vyos/helpers.ts +429 -0
  36. package/src/helpers/vyos/index.ts +12 -0
  37. package/src/index.ts +30 -0
  38. package/src/json-rules/ExpressionEvaluator.ts +292 -0
  39. package/src/json-rules/HelperRegistry.ts +177 -0
  40. package/src/json-rules/JsonRuleCompiler.ts +339 -0
  41. package/src/json-rules/JsonRuleValidator.ts +371 -0
  42. package/src/json-rules/index.ts +97 -0
  43. package/src/json-rules/schema.json +350 -0
  44. package/src/json-rules/types.ts +303 -0
  45. package/src/pack-loader/PackLoader.ts +332 -0
  46. package/src/pack-loader/index.ts +17 -0
  47. package/src/pack-loader/types.ts +135 -0
  48. package/src/parser/IncrementalParser.ts +527 -0
  49. package/src/parser/Sanitizer.ts +104 -0
  50. package/src/parser/SchemaAwareParser.ts +504 -0
  51. package/src/parser/VendorSchema.ts +72 -0
  52. package/src/parser/vendors/arista-eos.ts +206 -0
  53. package/src/parser/vendors/aruba-aoscx.ts +123 -0
  54. package/src/parser/vendors/aruba-aosswitch.ts +113 -0
  55. package/src/parser/vendors/aruba-wlc.ts +173 -0
  56. package/src/parser/vendors/cisco-ios.ts +110 -0
  57. package/src/parser/vendors/cisco-nxos.ts +107 -0
  58. package/src/parser/vendors/cumulus-linux.ts +161 -0
  59. package/src/parser/vendors/extreme-exos.ts +154 -0
  60. package/src/parser/vendors/extreme-voss.ts +167 -0
  61. package/src/parser/vendors/fortinet-fortigate.ts +217 -0
  62. package/src/parser/vendors/huawei-vrp.ts +192 -0
  63. package/src/parser/vendors/index.ts +1521 -0
  64. package/src/parser/vendors/juniper-junos.ts +230 -0
  65. package/src/parser/vendors/mikrotik-routeros.ts +274 -0
  66. package/src/parser/vendors/nokia-sros.ts +251 -0
  67. package/src/parser/vendors/paloalto-panos.ts +264 -0
  68. package/src/parser/vendors/vyos-vyos.ts +454 -0
  69. package/src/types/ConfigNode.ts +72 -0
  70. package/src/types/DeclarativeRule.ts +158 -0
  71. package/src/types/IRule.ts +270 -0
@@ -0,0 +1,422 @@
1
+ // packages/rule-helpers/src/extreme/helpers.ts
2
+ // Extreme Networks (EXOS and VOSS) specific helper functions
3
+
4
+ import type { ConfigNode } from '../../types/ConfigNode';
5
+ import { hasChildCommand } from '../common/helpers';
6
+
7
+ // =============================================================================
8
+ // EXOS-specific helpers
9
+ // =============================================================================
10
+
11
+ /**
12
+ * Check if node is an EXOS VLAN creation command
13
+ * @param node The ConfigNode to check
14
+ * @returns true if it's a "create vlan" command
15
+ */
16
+ export const isExosVlanCreate = (node: ConfigNode): boolean => {
17
+ return /^create\s+vlan\s+/i.test(node.id);
18
+ };
19
+
20
+ /**
21
+ * Extract VLAN name from EXOS VLAN command
22
+ * @param node The ConfigNode
23
+ * @returns The VLAN name or undefined
24
+ */
25
+ export const getExosVlanName = (node: ConfigNode): string | undefined => {
26
+ const match = node.id.match(/^(?:create|configure)\s+vlan\s+["']?(\w+)["']?/i);
27
+ const vlanName = match?.[1];
28
+ return vlanName?.trim();
29
+ };
30
+
31
+ /**
32
+ * Extract VLAN tag from EXOS VLAN command
33
+ * @param node The ConfigNode
34
+ * @returns The VLAN tag number or undefined
35
+ */
36
+ export const getExosVlanTag = (node: ConfigNode): number | undefined => {
37
+ const match = node.id.match(/tag\s+(\d+)/i);
38
+ const vlanTag = match?.[1];
39
+ return vlanTag ? parseInt(vlanTag, 10) : undefined;
40
+ };
41
+
42
+ /**
43
+ * Check if EXOS command is a configure command
44
+ * @param node The ConfigNode
45
+ * @returns true if it's a configure command
46
+ */
47
+ export const isExosConfigureCommand = (node: ConfigNode): boolean => {
48
+ return /^configure\s+/i.test(node.id);
49
+ };
50
+
51
+ /**
52
+ * Check if EXOS has SNMP sysname configured
53
+ * @param ast The full AST array
54
+ * @returns true if snmp sysname is configured
55
+ */
56
+ export const hasExosSysname = (ast: ConfigNode[]): boolean => {
57
+ return ast.some((node) =>
58
+ /^configure\s+snmp\s+sysname\s+/i.test(node.id)
59
+ );
60
+ };
61
+
62
+ /**
63
+ * Get EXOS sysname value
64
+ * @param ast The full AST array
65
+ * @returns The sysname or undefined
66
+ */
67
+ export const getExosSysname = (ast: ConfigNode[]): string | undefined => {
68
+ const node = ast.find((n) => /^configure\s+snmp\s+sysname\s+/i.test(n.id));
69
+ if (!node) return undefined;
70
+ const match = node.id.match(/sysname\s+["']?([^"'\s]+)["']?/i);
71
+ const sysname = match?.[1];
72
+ return sysname?.trim();
73
+ };
74
+
75
+ /**
76
+ * Check if EXOS has SNTP configured
77
+ * @param ast The full AST array
78
+ * @returns true if SNTP is configured
79
+ */
80
+ export const hasExosSntp = (ast: ConfigNode[]): boolean => {
81
+ return ast.some((node) =>
82
+ /^configure\s+sntp-client\s+/i.test(node.id)
83
+ );
84
+ };
85
+
86
+ /**
87
+ * Check if EXOS SNTP is enabled
88
+ * @param ast The full AST array
89
+ * @returns true if SNTP is enabled
90
+ */
91
+ export const isExosSntpEnabled = (ast: ConfigNode[]): boolean => {
92
+ return ast.some((node) =>
93
+ /^enable\s+sntp-client/i.test(node.id)
94
+ );
95
+ };
96
+
97
+ /**
98
+ * Check if EXOS has syslog configured
99
+ * @param ast The full AST array
100
+ * @returns true if syslog is configured
101
+ */
102
+ export const hasExosSyslog = (ast: ConfigNode[]): boolean => {
103
+ return ast.some((node) =>
104
+ /^configure\s+syslog\s+/i.test(node.id) ||
105
+ /^configure\s+log\s+target\s+/i.test(node.id)
106
+ );
107
+ };
108
+
109
+ /**
110
+ * Check if EXOS has SSH2 enabled
111
+ * @param ast The full AST array
112
+ * @returns true if SSH2 is configured
113
+ */
114
+ export const hasExosSsh2 = (ast: ConfigNode[]): boolean => {
115
+ return ast.some((node) =>
116
+ /^enable\s+ssh2/i.test(node.id) ||
117
+ /^configure\s+ssh2\s+/i.test(node.id)
118
+ );
119
+ };
120
+
121
+ /**
122
+ * Check if EXOS has RADIUS configured
123
+ * @param ast The full AST array
124
+ * @returns true if RADIUS is configured
125
+ */
126
+ export const hasExosRadius = (ast: ConfigNode[]): boolean => {
127
+ return ast.some((node) =>
128
+ /^configure\s+radius\s+/i.test(node.id)
129
+ );
130
+ };
131
+
132
+ /**
133
+ * Check if EXOS has TACACS configured
134
+ * @param ast The full AST array
135
+ * @returns true if TACACS is configured
136
+ */
137
+ export const hasExosTacacs = (ast: ConfigNode[]): boolean => {
138
+ return ast.some((node) =>
139
+ /^configure\s+tacacs\s+/i.test(node.id)
140
+ );
141
+ };
142
+
143
+ /**
144
+ * Check if EXOS LAG (sharing) is configured
145
+ * @param node The ConfigNode
146
+ * @returns true if it's an enable sharing command
147
+ */
148
+ export const isExosLag = (node: ConfigNode): boolean => {
149
+ return /^enable\s+sharing\s+/i.test(node.id);
150
+ };
151
+
152
+ /**
153
+ * Extract LAG master port from EXOS sharing command
154
+ * @param node The ConfigNode
155
+ * @returns The master port (e.g., "1:1") or undefined
156
+ */
157
+ export const getExosLagMasterPort = (node: ConfigNode): string | undefined => {
158
+ const match = node.id.match(/^enable\s+sharing\s+(\d+:\d+)/i);
159
+ const masterPort = match?.[1];
160
+ return masterPort?.trim();
161
+ };
162
+
163
+ /**
164
+ * Check if EXOS EAPS is configured
165
+ * @param ast The full AST array
166
+ * @returns true if EAPS is configured
167
+ */
168
+ export const hasExosEaps = (ast: ConfigNode[]): boolean => {
169
+ return ast.some((node) =>
170
+ /^create\s+eaps\s+/i.test(node.id) ||
171
+ /^configure\s+eaps\s+/i.test(node.id)
172
+ );
173
+ };
174
+
175
+ /**
176
+ * Check if EXOS stacking is enabled
177
+ * @param ast The full AST array
178
+ * @returns true if stacking is enabled
179
+ */
180
+ export const hasExosStacking = (ast: ConfigNode[]): boolean => {
181
+ return ast.some((node) =>
182
+ /^enable\s+stacking$/i.test(node.id) ||
183
+ /^configure\s+stacking\s+/i.test(node.id)
184
+ );
185
+ };
186
+
187
+ /**
188
+ * Check if EXOS MLAG is configured
189
+ * @param ast The full AST array
190
+ * @returns true if MLAG is configured
191
+ */
192
+ export const hasExosMlag = (ast: ConfigNode[]): boolean => {
193
+ return ast.some((node) =>
194
+ /^create\s+mlag\s+peer\s+/i.test(node.id) ||
195
+ /^configure\s+mlag\s+peer\s+/i.test(node.id)
196
+ );
197
+ };
198
+
199
+ // =============================================================================
200
+ // VOSS-specific helpers
201
+ // =============================================================================
202
+
203
+ /**
204
+ * Check if node is a VOSS VLAN creation command
205
+ * @param node The ConfigNode
206
+ * @returns true if it's a "vlan create" command
207
+ */
208
+ export const isVossVlanCreate = (node: ConfigNode): boolean => {
209
+ return /^vlan\s+create\s+\d+/i.test(node.id);
210
+ };
211
+
212
+ /**
213
+ * Extract VLAN ID from VOSS VLAN command
214
+ * @param node The ConfigNode
215
+ * @returns The VLAN ID or undefined
216
+ */
217
+ export const getVossVlanId = (node: ConfigNode): number | undefined => {
218
+ const match = node.id.match(/^vlan\s+(?:create|members|i-sid)\s+(\d+)/i);
219
+ const vlanId = match?.[1];
220
+ return vlanId ? parseInt(vlanId, 10) : undefined;
221
+ };
222
+
223
+ /**
224
+ * Check if VOSS has SPBM configured
225
+ * @param ast The full AST array
226
+ * @returns true if SPBM is configured
227
+ */
228
+ export const hasVossSpbm = (ast: ConfigNode[]): boolean => {
229
+ return ast.some((node) =>
230
+ /^spbm\s+\d+/i.test(node.id) ||
231
+ /^router\s+isis[\s\S]*spbm/i.test(node.id)
232
+ );
233
+ };
234
+
235
+ /**
236
+ * Check if VOSS has ISIS configured
237
+ * @param ast The full AST array
238
+ * @returns true if ISIS is configured
239
+ */
240
+ export const hasVossIsis = (ast: ConfigNode[]): boolean => {
241
+ return ast.some((node) =>
242
+ /^router\s+isis/i.test(node.id)
243
+ );
244
+ };
245
+
246
+ /**
247
+ * Check if VOSS has I-SID configured for VLAN
248
+ * @param ast The full AST array
249
+ * @param vlanId The VLAN ID to check
250
+ * @returns true if I-SID is configured for the VLAN
251
+ */
252
+ export const hasVossVlanIsid = (ast: ConfigNode[], vlanId: number): boolean => {
253
+ return ast.some((node) =>
254
+ new RegExp(`^vlan\\s+i-sid\\s+${vlanId}\\s+\\d+`, 'i').test(node.id)
255
+ );
256
+ };
257
+
258
+ /**
259
+ * Get I-SID for a VOSS VLAN
260
+ * @param ast The full AST array
261
+ * @param vlanId The VLAN ID
262
+ * @returns The I-SID or undefined
263
+ */
264
+ export const getVossVlanIsid = (ast: ConfigNode[], vlanId: number): number | undefined => {
265
+ const node = ast.find((n) =>
266
+ new RegExp(`^vlan\\s+i-sid\\s+${vlanId}\\s+\\d+`, 'i').test(n.id)
267
+ );
268
+ if (!node) return undefined;
269
+ const match = node.id.match(/i-sid\s+\d+\s+(\d+)/i);
270
+ const isid = match?.[1];
271
+ return isid ? parseInt(isid, 10) : undefined;
272
+ };
273
+
274
+ /**
275
+ * Check if VOSS interface is a GigabitEthernet
276
+ * @param node The ConfigNode
277
+ * @returns true if it's a GigabitEthernet interface
278
+ */
279
+ export const isVossGigabitEthernet = (node: ConfigNode): boolean => {
280
+ return /^interface\s+GigabitEthernet\s+\d+\/\d+/i.test(node.id);
281
+ };
282
+
283
+ /**
284
+ * Check if VOSS interface is an MLT (Multi-Link Trunk)
285
+ * @param node The ConfigNode
286
+ * @returns true if it's an MLT interface
287
+ */
288
+ export const isVossMlt = (node: ConfigNode): boolean => {
289
+ return /^interface\s+mlt\s+\d+/i.test(node.id) ||
290
+ /^mlt\s+\d+/i.test(node.id);
291
+ };
292
+
293
+ /**
294
+ * Get VOSS MLT ID
295
+ * @param node The ConfigNode
296
+ * @returns The MLT ID or undefined
297
+ */
298
+ export const getVossMltId = (node: ConfigNode): number | undefined => {
299
+ const match = node.id.match(/(?:interface\s+)?mlt\s+(\d+)/i);
300
+ const mltId = match?.[1];
301
+ return mltId ? parseInt(mltId, 10) : undefined;
302
+ };
303
+
304
+ /**
305
+ * Check if VOSS interface is shutdown
306
+ * @param node The interface ConfigNode
307
+ * @returns true if interface is shutdown
308
+ */
309
+ export const isVossShutdown = (node: ConfigNode): boolean => {
310
+ const hasShutdown = node.children.some((child) =>
311
+ child.id.toLowerCase() === 'shutdown'
312
+ );
313
+ const hasNoShutdown = node.children.some((child) =>
314
+ child.id.toLowerCase() === 'no shutdown'
315
+ );
316
+ return hasShutdown && !hasNoShutdown;
317
+ };
318
+
319
+ /**
320
+ * Check if VOSS has snmp-server name configured
321
+ * @param ast The full AST array
322
+ * @returns true if snmp-server name is configured
323
+ */
324
+ export const hasVossSnmpName = (ast: ConfigNode[]): boolean => {
325
+ return ast.some((node) =>
326
+ /^snmp-server\s+name\s+/i.test(node.id)
327
+ );
328
+ };
329
+
330
+ /**
331
+ * Get VOSS snmp-server name
332
+ * @param ast The full AST array
333
+ * @returns The name or undefined
334
+ */
335
+ export const getVossSnmpName = (ast: ConfigNode[]): string | undefined => {
336
+ const node = ast.find((n) => /^snmp-server\s+name\s+/i.test(n.id));
337
+ if (!node) return undefined;
338
+ const match = node.id.match(/name\s+["']?([^"'\s]+)["']?/i);
339
+ const name = match?.[1];
340
+ return name?.trim();
341
+ };
342
+
343
+ /**
344
+ * Check if VOSS has NTP configured
345
+ * @param ast The full AST array
346
+ * @returns true if NTP is configured
347
+ */
348
+ export const hasVossNtp = (ast: ConfigNode[]): boolean => {
349
+ return ast.some((node) =>
350
+ /^ntp\s+server\s+/i.test(node.id)
351
+ );
352
+ };
353
+
354
+ /**
355
+ * Check if VOSS has logging configured
356
+ * @param ast The full AST array
357
+ * @returns true if logging is configured
358
+ */
359
+ export const hasVossLogging = (ast: ConfigNode[]): boolean => {
360
+ return ast.some((node) =>
361
+ /^logging\s+(host|server)\s+/i.test(node.id)
362
+ );
363
+ };
364
+
365
+ /**
366
+ * Check if VOSS has SSH enabled
367
+ * @param ast The full AST array
368
+ * @returns true if SSH is configured
369
+ */
370
+ export const hasVossSsh = (ast: ConfigNode[]): boolean => {
371
+ return ast.some((node) =>
372
+ /^ssh\s+/i.test(node.id)
373
+ );
374
+ };
375
+
376
+ /**
377
+ * Check if VOSS has LACP configured on interface
378
+ * @param node The interface ConfigNode
379
+ * @returns true if LACP is configured
380
+ */
381
+ export const hasVossLacp = (node: ConfigNode): boolean => {
382
+ return node.children.some((child) =>
383
+ /^lacp\s+(enable|key)/i.test(child.id)
384
+ );
385
+ };
386
+
387
+ /**
388
+ * Check if VOSS has DVR (Distributed Virtual Routing) configured
389
+ * @param ast The full AST array
390
+ * @returns true if DVR is configured
391
+ */
392
+ export const hasVossDvr = (ast: ConfigNode[]): boolean => {
393
+ return ast.some((node) =>
394
+ /^dvr\s+(leaf|controller)/i.test(node.id)
395
+ );
396
+ };
397
+
398
+ /**
399
+ * Check if VOSS has CFM (Connectivity Fault Management) configured
400
+ * @param ast The full AST array
401
+ * @returns true if CFM is configured
402
+ */
403
+ export const hasVossCfm = (ast: ConfigNode[]): boolean => {
404
+ return ast.some((node) =>
405
+ /^cfm\s+/i.test(node.id)
406
+ );
407
+ };
408
+
409
+ /**
410
+ * Get VOSS interface default VLAN
411
+ * @param node The interface ConfigNode
412
+ * @returns The default VLAN ID or undefined
413
+ */
414
+ export const getVossDefaultVlan = (node: ConfigNode): number | undefined => {
415
+ const defaultVlan = node.children.find((child) =>
416
+ /^default-vlan-id\s+\d+/i.test(child.id)
417
+ );
418
+ if (!defaultVlan) return undefined;
419
+ const match = defaultVlan.id.match(/default-vlan-id\s+(\d+)/i);
420
+ const vlanId = match?.[1];
421
+ return vlanId ? parseInt(vlanId, 10) : undefined;
422
+ };
@@ -0,0 +1,12 @@
1
+ // packages/rule-helpers/src/extreme/index.ts
2
+ // Re-export all Extreme Networks helpers
3
+
4
+ export * from './helpers';
5
+
6
+ // Also re-export commonly used common helpers for convenience
7
+ export {
8
+ hasChildCommand,
9
+ getChildCommand,
10
+ getChildCommands,
11
+ parseIp,
12
+ } from '../common/helpers';