@sentriflow/core 0.2.0 → 0.3.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.
- package/README.md +66 -0
- package/package.json +7 -2
- package/src/constants.ts +4 -1
- package/src/engine/RuleExecutor.ts +7 -1
- package/src/grx2-loader/GRX2ExtendedLoader.ts +645 -0
- package/src/grx2-loader/MachineId.ts +51 -0
- package/src/grx2-loader/index.ts +47 -0
- package/src/grx2-loader/types.ts +280 -0
- package/src/helpers/arista/helpers.ts +165 -95
- package/src/helpers/aruba/helpers.ts +11 -5
- package/src/helpers/cisco/helpers.ts +16 -8
- package/src/helpers/common/helpers.ts +19 -13
- package/src/helpers/common/validation.ts +6 -6
- package/src/helpers/cumulus/helpers.ts +11 -7
- package/src/helpers/extreme/helpers.ts +8 -5
- package/src/helpers/fortinet/helpers.ts +16 -6
- package/src/helpers/huawei/helpers.ts +112 -61
- package/src/helpers/juniper/helpers.ts +36 -20
- package/src/helpers/mikrotik/helpers.ts +10 -3
- package/src/helpers/nokia/helpers.ts +71 -42
- package/src/helpers/paloalto/helpers.ts +51 -41
- package/src/helpers/vyos/helpers.ts +58 -31
- package/src/index.ts +6 -0
- package/src/pack-loader/PackLoader.ts +29 -4
- package/src/pack-loader/format-detector.ts +113 -0
- package/src/pack-loader/index.ts +7 -0
- package/src/parser/SchemaAwareParser.ts +84 -0
- package/src/parser/vendors/cisco-ios.ts +19 -5
- package/src/parser/vendors/cisco-nxos.ts +10 -2
- package/src/validation/index.ts +12 -0
- package/src/validation/rule-validation.ts +209 -0
|
@@ -12,15 +12,16 @@ export { hasChildCommand, getChildCommand, getChildCommands } from '../common/he
|
|
|
12
12
|
* In Huawei, interfaces are shutdown by default; 'undo shutdown' enables them
|
|
13
13
|
*/
|
|
14
14
|
export const isShutdown = (node: ConfigNode): boolean => {
|
|
15
|
+
if (!node?.children) return true; // Default to shutdown if no children
|
|
15
16
|
// Check if there's a 'shutdown' command
|
|
16
17
|
const hasShutdown = node.children.some((child) => {
|
|
17
|
-
const id = child
|
|
18
|
+
const id = child?.id?.toLowerCase().trim();
|
|
18
19
|
return id === 'shutdown';
|
|
19
20
|
});
|
|
20
21
|
|
|
21
22
|
// Check if there's an 'undo shutdown' command
|
|
22
23
|
const hasUndoShutdown = node.children.some((child) => {
|
|
23
|
-
const rawText = child
|
|
24
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
24
25
|
return rawText === 'undo shutdown';
|
|
25
26
|
});
|
|
26
27
|
|
|
@@ -32,8 +33,9 @@ export const isShutdown = (node: ConfigNode): boolean => {
|
|
|
32
33
|
* Check if interface is explicitly enabled (has 'undo shutdown')
|
|
33
34
|
*/
|
|
34
35
|
export const isEnabled = (node: ConfigNode): boolean => {
|
|
36
|
+
if (!node?.children) return false;
|
|
35
37
|
return node.children.some((child) => {
|
|
36
|
-
const rawText = child
|
|
38
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
37
39
|
return rawText === 'undo shutdown';
|
|
38
40
|
});
|
|
39
41
|
};
|
|
@@ -79,8 +81,9 @@ export const isEthTrunk = (interfaceName: string): boolean => {
|
|
|
79
81
|
* Check if interface is configured as trunk port
|
|
80
82
|
*/
|
|
81
83
|
export const isTrunkPort = (node: ConfigNode): boolean => {
|
|
84
|
+
if (!node?.children) return false;
|
|
82
85
|
return node.children.some((child) => {
|
|
83
|
-
const rawText = child
|
|
86
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
84
87
|
return rawText?.includes('port link-type trunk') ?? false;
|
|
85
88
|
});
|
|
86
89
|
};
|
|
@@ -89,8 +92,9 @@ export const isTrunkPort = (node: ConfigNode): boolean => {
|
|
|
89
92
|
* Check if interface is configured as access port
|
|
90
93
|
*/
|
|
91
94
|
export const isAccessPort = (node: ConfigNode): boolean => {
|
|
95
|
+
if (!node?.children) return false;
|
|
92
96
|
return node.children.some((child) => {
|
|
93
|
-
const rawText = child
|
|
97
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
94
98
|
return rawText?.includes('port link-type access') ?? false;
|
|
95
99
|
});
|
|
96
100
|
};
|
|
@@ -99,8 +103,9 @@ export const isAccessPort = (node: ConfigNode): boolean => {
|
|
|
99
103
|
* Check if interface is configured as hybrid port
|
|
100
104
|
*/
|
|
101
105
|
export const isHybridPort = (node: ConfigNode): boolean => {
|
|
106
|
+
if (!node?.children) return false;
|
|
102
107
|
return node.children.some((child) => {
|
|
103
|
-
const rawText = child
|
|
108
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
104
109
|
return rawText?.includes('port link-type hybrid') ?? false;
|
|
105
110
|
});
|
|
106
111
|
};
|
|
@@ -109,8 +114,9 @@ export const isHybridPort = (node: ConfigNode): boolean => {
|
|
|
109
114
|
* Get the default VLAN for an access port
|
|
110
115
|
*/
|
|
111
116
|
export const getDefaultVlan = (node: ConfigNode): string | undefined => {
|
|
117
|
+
if (!node?.children) return undefined;
|
|
112
118
|
const vlanCmd = node.children.find((child) => {
|
|
113
|
-
const rawText = child
|
|
119
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
114
120
|
return rawText?.startsWith('port default vlan') ?? false;
|
|
115
121
|
});
|
|
116
122
|
|
|
@@ -128,8 +134,9 @@ export const getDefaultVlan = (node: ConfigNode): string | undefined => {
|
|
|
128
134
|
* Get allowed VLANs for trunk port
|
|
129
135
|
*/
|
|
130
136
|
export const getTrunkAllowedVlans = (node: ConfigNode): string | undefined => {
|
|
137
|
+
if (!node?.children) return undefined;
|
|
131
138
|
const vlanCmd = node.children.find((child) => {
|
|
132
|
-
const rawText = child
|
|
139
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
133
140
|
return rawText?.startsWith('port trunk allow-pass vlan') ?? false;
|
|
134
141
|
});
|
|
135
142
|
|
|
@@ -169,8 +176,9 @@ export const getDescription = (node: ConfigNode): string | undefined => {
|
|
|
169
176
|
* Check if STP edge port is enabled (stp edged-port enable)
|
|
170
177
|
*/
|
|
171
178
|
export const hasStpEdgedPort = (node: ConfigNode): boolean => {
|
|
179
|
+
if (!node?.children) return false;
|
|
172
180
|
return node.children.some((child) => {
|
|
173
|
-
const rawText = child
|
|
181
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
174
182
|
return rawText?.includes('stp edged-port enable') ?? false;
|
|
175
183
|
});
|
|
176
184
|
};
|
|
@@ -179,8 +187,9 @@ export const hasStpEdgedPort = (node: ConfigNode): boolean => {
|
|
|
179
187
|
* Check if port security is enabled
|
|
180
188
|
*/
|
|
181
189
|
export const hasPortSecurity = (node: ConfigNode): boolean => {
|
|
190
|
+
if (!node?.children) return false;
|
|
182
191
|
return node.children.some((child) => {
|
|
183
|
-
const rawText = child
|
|
192
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
184
193
|
return rawText?.includes('port-security enable') ?? false;
|
|
185
194
|
});
|
|
186
195
|
};
|
|
@@ -189,8 +198,9 @@ export const hasPortSecurity = (node: ConfigNode): boolean => {
|
|
|
189
198
|
* Check if BPDU protection is enabled
|
|
190
199
|
*/
|
|
191
200
|
export const hasBpduProtection = (node: ConfigNode): boolean => {
|
|
201
|
+
if (!node?.children) return false;
|
|
192
202
|
return node.children.some((child) => {
|
|
193
|
-
const rawText = child
|
|
203
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
194
204
|
if (!rawText) {
|
|
195
205
|
return false;
|
|
196
206
|
}
|
|
@@ -202,8 +212,9 @@ export const hasBpduProtection = (node: ConfigNode): boolean => {
|
|
|
202
212
|
* Get child command value for 'set <key> <value>' style commands
|
|
203
213
|
*/
|
|
204
214
|
export const getCommandValue = (node: ConfigNode, command: string): string | undefined => {
|
|
215
|
+
if (!node?.children) return undefined;
|
|
205
216
|
const cmd = node.children.find((child) => {
|
|
206
|
-
const text = child
|
|
217
|
+
const text = child?.rawText?.toLowerCase().trim();
|
|
207
218
|
return text?.startsWith(command.toLowerCase()) ?? false;
|
|
208
219
|
});
|
|
209
220
|
|
|
@@ -218,9 +229,10 @@ export const getCommandValue = (node: ConfigNode, command: string): string | und
|
|
|
218
229
|
* Check if SSH is enabled
|
|
219
230
|
*/
|
|
220
231
|
export const isSshEnabled = (node: ConfigNode): boolean => {
|
|
232
|
+
if (!node?.id || !node?.children) return false;
|
|
221
233
|
if (node.id.toLowerCase().includes('user-interface')) {
|
|
222
234
|
return node.children.some((child) => {
|
|
223
|
-
const rawText = child
|
|
235
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
224
236
|
return rawText?.includes('protocol inbound ssh') || rawText === 'protocol inbound all';
|
|
225
237
|
});
|
|
226
238
|
}
|
|
@@ -231,9 +243,11 @@ export const isSshEnabled = (node: ConfigNode): boolean => {
|
|
|
231
243
|
* Check if Telnet is enabled (security concern)
|
|
232
244
|
*/
|
|
233
245
|
export const isTelnetEnabled = (node: ConfigNode): boolean => {
|
|
246
|
+
if (!node?.id || !node?.children) return false;
|
|
234
247
|
if (node.id.toLowerCase().includes('user-interface')) {
|
|
235
248
|
return node.children.some((child) => {
|
|
236
|
-
const rawText = child
|
|
249
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
250
|
+
if (!rawText) return false;
|
|
237
251
|
return (
|
|
238
252
|
rawText.includes('protocol inbound telnet') ||
|
|
239
253
|
rawText === 'protocol inbound all' ||
|
|
@@ -249,9 +263,10 @@ export const isTelnetEnabled = (node: ConfigNode): boolean => {
|
|
|
249
263
|
* Check if authentication mode AAA is configured
|
|
250
264
|
*/
|
|
251
265
|
export const hasAaaAuthentication = (node: ConfigNode): boolean => {
|
|
266
|
+
if (!node?.children) return false;
|
|
252
267
|
return node.children.some((child) => {
|
|
253
|
-
const rawText = child
|
|
254
|
-
return rawText
|
|
268
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
269
|
+
return rawText?.includes('authentication-mode aaa') ?? false;
|
|
255
270
|
});
|
|
256
271
|
};
|
|
257
272
|
|
|
@@ -259,9 +274,10 @@ export const hasAaaAuthentication = (node: ConfigNode): boolean => {
|
|
|
259
274
|
* Check if password authentication is configured (less secure)
|
|
260
275
|
*/
|
|
261
276
|
export const hasPasswordAuthentication = (node: ConfigNode): boolean => {
|
|
277
|
+
if (!node?.children) return false;
|
|
262
278
|
return node.children.some((child) => {
|
|
263
|
-
const rawText = child
|
|
264
|
-
return rawText
|
|
279
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
280
|
+
return rawText?.includes('authentication-mode password') ?? false;
|
|
265
281
|
});
|
|
266
282
|
};
|
|
267
283
|
|
|
@@ -291,9 +307,10 @@ export const getIdleTimeout = (node: ConfigNode): number | undefined => {
|
|
|
291
307
|
* Check if ACL is applied inbound on user-interface
|
|
292
308
|
*/
|
|
293
309
|
export const hasAclInbound = (node: ConfigNode): boolean => {
|
|
310
|
+
if (!node?.children) return false;
|
|
294
311
|
return node.children.some((child) => {
|
|
295
|
-
const rawText = child
|
|
296
|
-
return rawText
|
|
312
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
313
|
+
return rawText?.match(/acl\s+\d+\s+inbound/) ?? false;
|
|
297
314
|
});
|
|
298
315
|
};
|
|
299
316
|
|
|
@@ -301,9 +318,11 @@ export const hasAclInbound = (node: ConfigNode): boolean => {
|
|
|
301
318
|
* Find a stanza by name in the configuration tree
|
|
302
319
|
*/
|
|
303
320
|
export const findStanza = (node: ConfigNode, stanzaName: string): ConfigNode | undefined => {
|
|
321
|
+
if (!node?.id) return undefined;
|
|
304
322
|
if (node.id.toLowerCase().startsWith(stanzaName.toLowerCase())) {
|
|
305
323
|
return node;
|
|
306
324
|
}
|
|
325
|
+
if (!node?.children) return undefined;
|
|
307
326
|
for (const child of node.children) {
|
|
308
327
|
const found = findStanza(child, stanzaName);
|
|
309
328
|
if (found) return found;
|
|
@@ -316,9 +335,11 @@ export const findStanza = (node: ConfigNode, stanzaName: string): ConfigNode | u
|
|
|
316
335
|
*/
|
|
317
336
|
export const findStanzas = (node: ConfigNode, stanzaName: string): ConfigNode[] => {
|
|
318
337
|
const results: ConfigNode[] = [];
|
|
338
|
+
if (!node?.id) return results;
|
|
319
339
|
if (node.id.toLowerCase().startsWith(stanzaName.toLowerCase())) {
|
|
320
340
|
results.push(node);
|
|
321
341
|
}
|
|
342
|
+
if (!node?.children) return results;
|
|
322
343
|
for (const child of node.children) {
|
|
323
344
|
results.push(...findStanzas(child, stanzaName));
|
|
324
345
|
}
|
|
@@ -329,8 +350,10 @@ export const findStanzas = (node: ConfigNode, stanzaName: string): ConfigNode[]
|
|
|
329
350
|
* Check if local-user has password configured with cipher (encrypted)
|
|
330
351
|
*/
|
|
331
352
|
export const hasEncryptedPassword = (node: ConfigNode): boolean => {
|
|
353
|
+
if (!node?.children) return false;
|
|
332
354
|
return node.children.some((child) => {
|
|
333
|
-
const rawText = child
|
|
355
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
356
|
+
if (!rawText) return false;
|
|
334
357
|
return (
|
|
335
358
|
rawText.includes('password cipher') ||
|
|
336
359
|
rawText.includes('password irreversible-cipher')
|
|
@@ -342,9 +365,10 @@ export const hasEncryptedPassword = (node: ConfigNode): boolean => {
|
|
|
342
365
|
* Check if local-user has plaintext password (security concern)
|
|
343
366
|
*/
|
|
344
367
|
export const hasPlaintextPassword = (node: ConfigNode): boolean => {
|
|
368
|
+
if (!node?.children) return false;
|
|
345
369
|
return node.children.some((child) => {
|
|
346
|
-
const rawText = child
|
|
347
|
-
return rawText
|
|
370
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
371
|
+
return rawText?.includes('password simple') ?? false;
|
|
348
372
|
});
|
|
349
373
|
};
|
|
350
374
|
|
|
@@ -352,9 +376,10 @@ export const hasPlaintextPassword = (node: ConfigNode): boolean => {
|
|
|
352
376
|
* Get privilege level for local-user
|
|
353
377
|
*/
|
|
354
378
|
export const getPrivilegeLevel = (node: ConfigNode): number | undefined => {
|
|
379
|
+
if (!node?.children) return undefined;
|
|
355
380
|
const privCmd = node.children.find((child) => {
|
|
356
|
-
const rawText = child
|
|
357
|
-
return rawText?.includes('privilege level');
|
|
381
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
382
|
+
return rawText?.includes('privilege level') ?? false;
|
|
358
383
|
});
|
|
359
384
|
|
|
360
385
|
if (privCmd?.rawText) {
|
|
@@ -375,8 +400,9 @@ export const getPrivilegeLevel = (node: ConfigNode): number | undefined => {
|
|
|
375
400
|
* Check if BGP peer has password authentication configured
|
|
376
401
|
*/
|
|
377
402
|
export const hasBgpPeerPassword = (node: ConfigNode, peerIp: string): boolean => {
|
|
403
|
+
if (!node?.children) return false;
|
|
378
404
|
return node.children.some((child) => {
|
|
379
|
-
const rawText = child
|
|
405
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
380
406
|
return rawText?.includes(`peer ${peerIp.toLowerCase()}`) && rawText?.includes('password');
|
|
381
407
|
});
|
|
382
408
|
};
|
|
@@ -385,8 +411,9 @@ export const hasBgpPeerPassword = (node: ConfigNode, peerIp: string): boolean =>
|
|
|
385
411
|
* Check if BGP peer has keychain authentication configured
|
|
386
412
|
*/
|
|
387
413
|
export const hasBgpPeerKeychain = (node: ConfigNode, peerIp: string): boolean => {
|
|
414
|
+
if (!node?.children) return false;
|
|
388
415
|
return node.children.some((child) => {
|
|
389
|
-
const rawText = child
|
|
416
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
390
417
|
return rawText?.includes(`peer ${peerIp.toLowerCase()}`) && rawText?.includes('keychain');
|
|
391
418
|
});
|
|
392
419
|
};
|
|
@@ -395,8 +422,9 @@ export const hasBgpPeerKeychain = (node: ConfigNode, peerIp: string): boolean =>
|
|
|
395
422
|
* Check if BGP peer has GTSM (valid-ttl-hops) configured
|
|
396
423
|
*/
|
|
397
424
|
export const hasBgpPeerGtsm = (node: ConfigNode, peerIp: string): boolean => {
|
|
425
|
+
if (!node?.children) return false;
|
|
398
426
|
return node.children.some((child) => {
|
|
399
|
-
const rawText = child
|
|
427
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
400
428
|
return rawText?.includes(`peer ${peerIp.toLowerCase()}`) && rawText?.includes('valid-ttl-hops');
|
|
401
429
|
});
|
|
402
430
|
};
|
|
@@ -405,8 +433,9 @@ export const hasBgpPeerGtsm = (node: ConfigNode, peerIp: string): boolean => {
|
|
|
405
433
|
* Check if BGP peer has route-limit (maximum prefix) configured
|
|
406
434
|
*/
|
|
407
435
|
export const hasBgpPeerRouteLimit = (node: ConfigNode, peerIp: string): boolean => {
|
|
436
|
+
if (!node?.children) return false;
|
|
408
437
|
return node.children.some((child) => {
|
|
409
|
-
const rawText = child
|
|
438
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
410
439
|
return rawText?.includes(`peer ${peerIp.toLowerCase()}`) && rawText?.includes('route-limit');
|
|
411
440
|
});
|
|
412
441
|
};
|
|
@@ -415,8 +444,9 @@ export const hasBgpPeerRouteLimit = (node: ConfigNode, peerIp: string): boolean
|
|
|
415
444
|
* Check if BGP peer has prefix filtering configured (ip-prefix or route-policy)
|
|
416
445
|
*/
|
|
417
446
|
export const hasBgpPeerPrefixFilter = (node: ConfigNode, peerIp: string): boolean => {
|
|
447
|
+
if (!node?.children) return false;
|
|
418
448
|
return node.children.some((child) => {
|
|
419
|
-
const rawText = child
|
|
449
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
420
450
|
return (
|
|
421
451
|
rawText?.includes(`peer ${peerIp.toLowerCase()}`) &&
|
|
422
452
|
(rawText?.includes('ip-prefix') || rawText?.includes('route-policy') || rawText?.includes('filter-policy'))
|
|
@@ -429,8 +459,9 @@ export const hasBgpPeerPrefixFilter = (node: ConfigNode, peerIp: string): boolea
|
|
|
429
459
|
*/
|
|
430
460
|
export const getBgpPeers = (node: ConfigNode): string[] => {
|
|
431
461
|
const peers: string[] = [];
|
|
462
|
+
if (!node?.children) return peers;
|
|
432
463
|
for (const child of node.children) {
|
|
433
|
-
if (child
|
|
464
|
+
if (child?.rawText) {
|
|
434
465
|
const match = child.rawText.match(/peer\s+([\d.]+)\s+as-number/i);
|
|
435
466
|
if (match?.[1]) {
|
|
436
467
|
peers.push(match[1]);
|
|
@@ -444,8 +475,9 @@ export const getBgpPeers = (node: ConfigNode): string[] => {
|
|
|
444
475
|
* Check if BGP has graceful-restart enabled
|
|
445
476
|
*/
|
|
446
477
|
export const hasBgpGracefulRestart = (node: ConfigNode): boolean => {
|
|
478
|
+
if (!node?.children) return false;
|
|
447
479
|
return node.children.some((child) => {
|
|
448
|
-
const rawText = child
|
|
480
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
449
481
|
return rawText === 'graceful-restart' || rawText?.startsWith('graceful-restart ');
|
|
450
482
|
});
|
|
451
483
|
};
|
|
@@ -458,9 +490,10 @@ export const hasBgpGracefulRestart = (node: ConfigNode): boolean => {
|
|
|
458
490
|
* Check if OSPF area has authentication configured
|
|
459
491
|
*/
|
|
460
492
|
export const hasOspfAreaAuthentication = (node: ConfigNode): boolean => {
|
|
493
|
+
if (!node?.children) return false;
|
|
461
494
|
return node.children.some((child) => {
|
|
462
|
-
const rawText = child
|
|
463
|
-
return rawText?.includes('authentication-mode');
|
|
495
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
496
|
+
return rawText?.includes('authentication-mode') ?? false;
|
|
464
497
|
});
|
|
465
498
|
};
|
|
466
499
|
|
|
@@ -468,9 +501,10 @@ export const hasOspfAreaAuthentication = (node: ConfigNode): boolean => {
|
|
|
468
501
|
* Check if interface has OSPF authentication configured
|
|
469
502
|
*/
|
|
470
503
|
export const hasInterfaceOspfAuth = (node: ConfigNode): boolean => {
|
|
504
|
+
if (!node?.children) return false;
|
|
471
505
|
return node.children.some((child) => {
|
|
472
|
-
const rawText = child
|
|
473
|
-
return rawText?.includes('ospf authentication-mode');
|
|
506
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
507
|
+
return rawText?.includes('ospf authentication-mode') ?? false;
|
|
474
508
|
});
|
|
475
509
|
};
|
|
476
510
|
|
|
@@ -478,9 +512,10 @@ export const hasInterfaceOspfAuth = (node: ConfigNode): boolean => {
|
|
|
478
512
|
* Check if IS-IS has area authentication configured
|
|
479
513
|
*/
|
|
480
514
|
export const hasIsisAreaAuth = (node: ConfigNode): boolean => {
|
|
515
|
+
if (!node?.children) return false;
|
|
481
516
|
return node.children.some((child) => {
|
|
482
|
-
const rawText = child
|
|
483
|
-
return rawText?.includes('area-authentication-mode');
|
|
517
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
518
|
+
return rawText?.includes('area-authentication-mode') ?? false;
|
|
484
519
|
});
|
|
485
520
|
};
|
|
486
521
|
|
|
@@ -488,9 +523,10 @@ export const hasIsisAreaAuth = (node: ConfigNode): boolean => {
|
|
|
488
523
|
* Check if IS-IS has domain authentication configured
|
|
489
524
|
*/
|
|
490
525
|
export const hasIsisDomainAuth = (node: ConfigNode): boolean => {
|
|
526
|
+
if (!node?.children) return false;
|
|
491
527
|
return node.children.some((child) => {
|
|
492
|
-
const rawText = child
|
|
493
|
-
return rawText?.includes('domain-authentication-mode');
|
|
528
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
529
|
+
return rawText?.includes('domain-authentication-mode') ?? false;
|
|
494
530
|
});
|
|
495
531
|
};
|
|
496
532
|
|
|
@@ -498,9 +534,10 @@ export const hasIsisDomainAuth = (node: ConfigNode): boolean => {
|
|
|
498
534
|
* Check if interface has IS-IS authentication configured
|
|
499
535
|
*/
|
|
500
536
|
export const hasInterfaceIsisAuth = (node: ConfigNode): boolean => {
|
|
537
|
+
if (!node?.children) return false;
|
|
501
538
|
return node.children.some((child) => {
|
|
502
|
-
const rawText = child
|
|
503
|
-
return rawText?.includes('isis authentication-mode');
|
|
539
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
540
|
+
return rawText?.includes('isis authentication-mode') ?? false;
|
|
504
541
|
});
|
|
505
542
|
};
|
|
506
543
|
|
|
@@ -512,9 +549,10 @@ export const hasInterfaceIsisAuth = (node: ConfigNode): boolean => {
|
|
|
512
549
|
* Check if interface has VRRP configured
|
|
513
550
|
*/
|
|
514
551
|
export const hasVrrp = (node: ConfigNode): boolean => {
|
|
552
|
+
if (!node?.children) return false;
|
|
515
553
|
return node.children.some((child) => {
|
|
516
|
-
const rawText = child
|
|
517
|
-
return rawText?.includes('vrrp vrid');
|
|
554
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
555
|
+
return rawText?.includes('vrrp vrid') ?? false;
|
|
518
556
|
});
|
|
519
557
|
};
|
|
520
558
|
|
|
@@ -523,8 +561,9 @@ export const hasVrrp = (node: ConfigNode): boolean => {
|
|
|
523
561
|
* In Huawei VRP, authentication can be on a single line: "vrrp vrid 1 authentication-mode md5 <key>"
|
|
524
562
|
*/
|
|
525
563
|
export const hasVrrpAuthentication = (node: ConfigNode): boolean => {
|
|
564
|
+
if (!node?.children) return false;
|
|
526
565
|
return node.children.some((child) => {
|
|
527
|
-
const rawText = child
|
|
566
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
528
567
|
// Check if line contains both vrrp vrid and authentication-mode
|
|
529
568
|
return rawText?.includes('vrrp vrid') && rawText?.includes('authentication-mode');
|
|
530
569
|
});
|
|
@@ -534,8 +573,9 @@ export const hasVrrpAuthentication = (node: ConfigNode): boolean => {
|
|
|
534
573
|
* Get VRRP VRID from interface
|
|
535
574
|
*/
|
|
536
575
|
export const getVrrpVrid = (node: ConfigNode): string | undefined => {
|
|
576
|
+
if (!node?.children) return undefined;
|
|
537
577
|
const vrrpCmd = node.children.find((child) => {
|
|
538
|
-
return child
|
|
578
|
+
return child?.rawText?.toLowerCase().includes('vrrp vrid') ?? false;
|
|
539
579
|
});
|
|
540
580
|
|
|
541
581
|
if (vrrpCmd?.rawText) {
|
|
@@ -555,8 +595,9 @@ export const getVrrpVrid = (node: ConfigNode): string | undefined => {
|
|
|
555
595
|
* Check if ICMP redirect is disabled on interface
|
|
556
596
|
*/
|
|
557
597
|
export const hasIcmpRedirectDisabled = (node: ConfigNode): boolean => {
|
|
598
|
+
if (!node?.children) return false;
|
|
558
599
|
return node.children.some((child) => {
|
|
559
|
-
const rawText = child
|
|
600
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
560
601
|
return rawText === 'undo icmp redirect send';
|
|
561
602
|
});
|
|
562
603
|
};
|
|
@@ -565,8 +606,9 @@ export const hasIcmpRedirectDisabled = (node: ConfigNode): boolean => {
|
|
|
565
606
|
* Check if directed broadcast is disabled on interface
|
|
566
607
|
*/
|
|
567
608
|
export const hasDirectedBroadcastDisabled = (node: ConfigNode): boolean => {
|
|
609
|
+
if (!node?.children) return false;
|
|
568
610
|
return node.children.some((child) => {
|
|
569
|
-
const rawText = child
|
|
611
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
570
612
|
return rawText === 'undo ip directed-broadcast enable' || rawText === 'undo ip directed-broadcast';
|
|
571
613
|
});
|
|
572
614
|
};
|
|
@@ -575,8 +617,9 @@ export const hasDirectedBroadcastDisabled = (node: ConfigNode): boolean => {
|
|
|
575
617
|
* Check if ARP proxy is disabled on interface
|
|
576
618
|
*/
|
|
577
619
|
export const hasArpProxyDisabled = (node: ConfigNode): boolean => {
|
|
620
|
+
if (!node?.children) return false;
|
|
578
621
|
return node.children.some((child) => {
|
|
579
|
-
const rawText = child
|
|
622
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
580
623
|
return rawText === 'undo arp proxy enable' || rawText === 'undo proxy-arp';
|
|
581
624
|
});
|
|
582
625
|
};
|
|
@@ -585,8 +628,9 @@ export const hasArpProxyDisabled = (node: ConfigNode): boolean => {
|
|
|
585
628
|
* Check if uRPF is enabled on interface
|
|
586
629
|
*/
|
|
587
630
|
export const hasUrpf = (node: ConfigNode): boolean => {
|
|
631
|
+
if (!node?.children) return false;
|
|
588
632
|
return node.children.some((child) => {
|
|
589
|
-
const rawText = child
|
|
633
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
590
634
|
return rawText?.includes('urpf strict') || rawText?.includes('urpf loose');
|
|
591
635
|
});
|
|
592
636
|
};
|
|
@@ -595,9 +639,10 @@ export const hasUrpf = (node: ConfigNode): boolean => {
|
|
|
595
639
|
* Get uRPF mode (strict or loose)
|
|
596
640
|
*/
|
|
597
641
|
export const getUrpfMode = (node: ConfigNode): 'strict' | 'loose' | undefined => {
|
|
642
|
+
if (!node?.children) return undefined;
|
|
598
643
|
const urpfCmd = node.children.find((child) => {
|
|
599
|
-
const rawText = child
|
|
600
|
-
return rawText?.includes('urpf');
|
|
644
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
645
|
+
return rawText?.includes('urpf') ?? false;
|
|
601
646
|
});
|
|
602
647
|
|
|
603
648
|
if (urpfCmd?.rawText) {
|
|
@@ -612,8 +657,9 @@ export const getUrpfMode = (node: ConfigNode): 'strict' | 'loose' | undefined =>
|
|
|
612
657
|
* Check if LLDP is disabled on interface
|
|
613
658
|
*/
|
|
614
659
|
export const hasLldpDisabled = (node: ConfigNode): boolean => {
|
|
660
|
+
if (!node?.children) return false;
|
|
615
661
|
return node.children.some((child) => {
|
|
616
|
-
const rawText = child
|
|
662
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
617
663
|
return rawText === 'undo lldp enable';
|
|
618
664
|
});
|
|
619
665
|
};
|
|
@@ -626,8 +672,9 @@ export const hasLldpDisabled = (node: ConfigNode): boolean => {
|
|
|
626
672
|
* Check if NTP authentication is enabled
|
|
627
673
|
*/
|
|
628
674
|
export const hasNtpAuthentication = (node: ConfigNode): boolean => {
|
|
675
|
+
if (!node?.children) return false;
|
|
629
676
|
return node.children.some((child) => {
|
|
630
|
-
const rawText = child
|
|
677
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
631
678
|
return rawText === 'authentication enable';
|
|
632
679
|
});
|
|
633
680
|
};
|
|
@@ -636,9 +683,10 @@ export const hasNtpAuthentication = (node: ConfigNode): boolean => {
|
|
|
636
683
|
* Check if NTP has authentication key configured
|
|
637
684
|
*/
|
|
638
685
|
export const hasNtpAuthKey = (node: ConfigNode): boolean => {
|
|
686
|
+
if (!node?.children) return false;
|
|
639
687
|
return node.children.some((child) => {
|
|
640
|
-
const rawText = child
|
|
641
|
-
return rawText?.includes('authentication-keyid');
|
|
688
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
689
|
+
return rawText?.includes('authentication-keyid') ?? false;
|
|
642
690
|
});
|
|
643
691
|
};
|
|
644
692
|
|
|
@@ -709,8 +757,9 @@ export const hasCpuDefendPolicy = (node: ConfigNode): boolean => {
|
|
|
709
757
|
* Check if CPU-defend policy has auto-defend enabled
|
|
710
758
|
*/
|
|
711
759
|
export const hasCpuDefendAutoDefend = (node: ConfigNode): boolean => {
|
|
760
|
+
if (!node?.children) return false;
|
|
712
761
|
return node.children.some((child) => {
|
|
713
|
-
const rawText = child
|
|
762
|
+
const rawText = child?.rawText?.toLowerCase().trim();
|
|
714
763
|
return rawText === 'auto-defend enable';
|
|
715
764
|
});
|
|
716
765
|
};
|
|
@@ -773,9 +822,10 @@ export const isIpSourceRouteDisabled = (rawText: string): boolean => {
|
|
|
773
822
|
* Check if HWTACACS server template has shared-key configured
|
|
774
823
|
*/
|
|
775
824
|
export const hasHwtacacsSharedKey = (node: ConfigNode): boolean => {
|
|
825
|
+
if (!node?.children) return false;
|
|
776
826
|
return node.children.some((child) => {
|
|
777
|
-
const rawText = child
|
|
778
|
-
return rawText?.includes('shared-key cipher');
|
|
827
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
828
|
+
return rawText?.includes('shared-key cipher') ?? false;
|
|
779
829
|
});
|
|
780
830
|
};
|
|
781
831
|
|
|
@@ -783,8 +833,9 @@ export const hasHwtacacsSharedKey = (node: ConfigNode): boolean => {
|
|
|
783
833
|
* Check if HWTACACS has secondary server configured
|
|
784
834
|
*/
|
|
785
835
|
export const hasHwtacacsSecondary = (node: ConfigNode): boolean => {
|
|
836
|
+
if (!node?.children) return false;
|
|
786
837
|
return node.children.some((child) => {
|
|
787
|
-
const rawText = child
|
|
788
|
-
return rawText?.includes('secondary');
|
|
838
|
+
const rawText = child?.rawText?.toLowerCase();
|
|
839
|
+
return rawText?.includes('secondary') ?? false;
|
|
789
840
|
});
|
|
790
841
|
};
|