@sentriflow/core 0.3.2 → 0.4.1
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 +10 -4
- package/package.json +65 -65
- package/src/grx2-loader/GRX2ExtendedLoader.ts +2 -3
- package/src/grx2-loader/index.ts +2 -0
- package/src/grx2-loader/types.ts +9 -3
- package/src/helpers/cisco/helpers.ts +19 -0
- package/src/helpers/cisco/index.ts +1 -0
- package/src/helpers/common/helpers.ts +29 -0
- package/src/pack-provider/PackProvider.ts +1 -1
package/README.md
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
# @sentriflow/core
|
|
2
2
|
|
|
3
|
-
Core engine for SentriFlow - a network configuration
|
|
3
|
+
Core engine for SentriFlow - a network configuration validator.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
`@sentriflow/core` provides the fundamental building blocks for parsing and analyzing network device configurations across multiple vendors,
|
|
7
|
+
`@sentriflow/core` provides the fundamental building blocks for parsing and analyzing network device configurations across multiple vendors, validating them against policy rules—whether industry best practices or your organization's specific requirements.
|
|
8
|
+
|
|
9
|
+
SentriFlow is a validation tool that assesses configuration alignment with policies and standards.
|
|
8
10
|
|
|
9
11
|
## Installation
|
|
10
12
|
|
|
@@ -18,7 +20,7 @@ bun add @sentriflow/core
|
|
|
18
20
|
|
|
19
21
|
- **Multi-vendor support**: Cisco IOS/NX-OS, Juniper JunOS, Arista EOS, Fortinet FortiGate, Palo Alto PAN-OS, and more
|
|
20
22
|
- **AST-based parsing**: Converts configurations into a vendor-agnostic Abstract Syntax Tree
|
|
21
|
-
- **Extensible rule engine**: Define
|
|
23
|
+
- **Extensible rule engine**: Define validation rules for best practices or organization-specific policies
|
|
22
24
|
- **IP/Subnet Extraction**: Extract and deduplicate IP addresses and CIDR subnets from configurations
|
|
23
25
|
- **GRX2 Loader**: Load and decrypt extended encrypted rule packs for offline usage
|
|
24
26
|
- **TypeScript native**: Full type safety with comprehensive type definitions
|
|
@@ -173,9 +175,13 @@ try {
|
|
|
173
175
|
## Related Packages
|
|
174
176
|
|
|
175
177
|
- [`@sentriflow/cli`](https://github.com/sentriflow/sentriflow/tree/main/packages/cli) - Command-line interface
|
|
176
|
-
- [`@sentriflow/rules-default`](https://github.com/sentriflow/sentriflow/tree/main/packages/rules-default) - Default
|
|
178
|
+
- [`@sentriflow/rules-default`](https://github.com/sentriflow/sentriflow/tree/main/packages/rules-default) - Default validation rules
|
|
177
179
|
- [`@sentriflow/rule-helpers`](https://github.com/sentriflow/sentriflow/tree/main/packages/rule-helpers) - Helper functions for rule development
|
|
178
180
|
|
|
181
|
+
## Disclaimer
|
|
182
|
+
|
|
183
|
+
SentriFlow provides automated configuration validation. Validation results do not constitute compliance certification.
|
|
184
|
+
|
|
179
185
|
## License
|
|
180
186
|
|
|
181
187
|
Apache-2.0
|
package/package.json
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@sentriflow/core",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "SentriFlow core engine for network configuration validation",
|
|
5
|
-
"license": "Apache-2.0",
|
|
6
|
-
"module": "src/index.ts",
|
|
7
|
-
"type": "module",
|
|
8
|
-
"exports": {
|
|
9
|
-
".": "./src/index.ts",
|
|
10
|
-
"./grx2-loader": "./src/grx2-loader/index.ts",
|
|
11
|
-
"./helpers": "./src/helpers/index.ts",
|
|
12
|
-
"./helpers/common": "./src/helpers/common/index.ts",
|
|
13
|
-
"./helpers/arista": "./src/helpers/arista/index.ts",
|
|
14
|
-
"./helpers/aruba": "./src/helpers/aruba/index.ts",
|
|
15
|
-
"./helpers/cisco": "./src/helpers/cisco/index.ts",
|
|
16
|
-
"./helpers/cumulus": "./src/helpers/cumulus/index.ts",
|
|
17
|
-
"./helpers/extreme": "./src/helpers/extreme/index.ts",
|
|
18
|
-
"./helpers/fortinet": "./src/helpers/fortinet/index.ts",
|
|
19
|
-
"./helpers/huawei": "./src/helpers/huawei/index.ts",
|
|
20
|
-
"./helpers/juniper": "./src/helpers/juniper/index.ts",
|
|
21
|
-
"./helpers/mikrotik": "./src/helpers/mikrotik/index.ts",
|
|
22
|
-
"./helpers/nokia": "./src/helpers/nokia/index.ts",
|
|
23
|
-
"./helpers/paloalto": "./src/helpers/paloalto/index.ts",
|
|
24
|
-
"./helpers/vyos": "./src/helpers/vyos/index.ts"
|
|
25
|
-
},
|
|
26
|
-
"repository": {
|
|
27
|
-
"type": "git",
|
|
28
|
-
"url": "git+https://github.com/sentriflow/sentriflow.git",
|
|
29
|
-
"directory": "packages/core"
|
|
30
|
-
},
|
|
31
|
-
"homepage": "https://github.com/sentriflow/sentriflow#readme",
|
|
32
|
-
"bugs": {
|
|
33
|
-
"url": "https://github.com/sentriflow/sentriflow/issues"
|
|
34
|
-
},
|
|
35
|
-
"keywords": [
|
|
36
|
-
"network",
|
|
37
|
-
"configuration",
|
|
38
|
-
"validation",
|
|
39
|
-
"security",
|
|
40
|
-
"cisco",
|
|
41
|
-
"juniper",
|
|
42
|
-
"arista",
|
|
43
|
-
"firewall",
|
|
44
|
-
"linter",
|
|
45
|
-
"helpers"
|
|
46
|
-
],
|
|
47
|
-
"files": [
|
|
48
|
-
"src",
|
|
49
|
-
"LICENSE",
|
|
50
|
-
"README.md"
|
|
51
|
-
],
|
|
52
|
-
"publishConfig": {
|
|
53
|
-
"access": "public"
|
|
54
|
-
},
|
|
55
|
-
"dependencies": {
|
|
56
|
-
"node-machine-id": "^1.1.12"
|
|
57
|
-
},
|
|
58
|
-
"devDependencies": {
|
|
59
|
-
"bun-types": "latest",
|
|
60
|
-
"@types/node": "^20.0.0"
|
|
61
|
-
},
|
|
62
|
-
"peerDependencies": {
|
|
63
|
-
"typescript": "^5.0.0"
|
|
64
|
-
}
|
|
65
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@sentriflow/core",
|
|
3
|
+
"version": "0.4.1",
|
|
4
|
+
"description": "SentriFlow core engine for network configuration validation",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"module": "src/index.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": "./src/index.ts",
|
|
10
|
+
"./grx2-loader": "./src/grx2-loader/index.ts",
|
|
11
|
+
"./helpers": "./src/helpers/index.ts",
|
|
12
|
+
"./helpers/common": "./src/helpers/common/index.ts",
|
|
13
|
+
"./helpers/arista": "./src/helpers/arista/index.ts",
|
|
14
|
+
"./helpers/aruba": "./src/helpers/aruba/index.ts",
|
|
15
|
+
"./helpers/cisco": "./src/helpers/cisco/index.ts",
|
|
16
|
+
"./helpers/cumulus": "./src/helpers/cumulus/index.ts",
|
|
17
|
+
"./helpers/extreme": "./src/helpers/extreme/index.ts",
|
|
18
|
+
"./helpers/fortinet": "./src/helpers/fortinet/index.ts",
|
|
19
|
+
"./helpers/huawei": "./src/helpers/huawei/index.ts",
|
|
20
|
+
"./helpers/juniper": "./src/helpers/juniper/index.ts",
|
|
21
|
+
"./helpers/mikrotik": "./src/helpers/mikrotik/index.ts",
|
|
22
|
+
"./helpers/nokia": "./src/helpers/nokia/index.ts",
|
|
23
|
+
"./helpers/paloalto": "./src/helpers/paloalto/index.ts",
|
|
24
|
+
"./helpers/vyos": "./src/helpers/vyos/index.ts"
|
|
25
|
+
},
|
|
26
|
+
"repository": {
|
|
27
|
+
"type": "git",
|
|
28
|
+
"url": "git+https://github.com/sentriflow/sentriflow.git",
|
|
29
|
+
"directory": "packages/core"
|
|
30
|
+
},
|
|
31
|
+
"homepage": "https://github.com/sentriflow/sentriflow#readme",
|
|
32
|
+
"bugs": {
|
|
33
|
+
"url": "https://github.com/sentriflow/sentriflow/issues"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"network",
|
|
37
|
+
"configuration",
|
|
38
|
+
"validation",
|
|
39
|
+
"security",
|
|
40
|
+
"cisco",
|
|
41
|
+
"juniper",
|
|
42
|
+
"arista",
|
|
43
|
+
"firewall",
|
|
44
|
+
"linter",
|
|
45
|
+
"helpers"
|
|
46
|
+
],
|
|
47
|
+
"files": [
|
|
48
|
+
"src",
|
|
49
|
+
"LICENSE",
|
|
50
|
+
"README.md"
|
|
51
|
+
],
|
|
52
|
+
"publishConfig": {
|
|
53
|
+
"access": "public"
|
|
54
|
+
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"node-machine-id": "^1.1.12"
|
|
57
|
+
},
|
|
58
|
+
"devDependencies": {
|
|
59
|
+
"bun-types": "latest",
|
|
60
|
+
"@types/node": "^20.0.0"
|
|
61
|
+
},
|
|
62
|
+
"peerDependencies": {
|
|
63
|
+
"typescript": "^5.0.0"
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -358,9 +358,8 @@ export async function loadExtendedPack(
|
|
|
358
358
|
machineId: string,
|
|
359
359
|
debug?: (msg: string) => void
|
|
360
360
|
): Promise<RulePack> {
|
|
361
|
-
debug?.(`[GRX2Loader] Loading pack: ${filePath}`);
|
|
362
|
-
debug?.(`[GRX2Loader]
|
|
363
|
-
debug?.(`[GRX2Loader] Machine ID: "${machineId}" (length: ${machineId.length})`);
|
|
361
|
+
debug?.(`[GRX2Loader] Loading pack: ${filePath}`);
|
|
362
|
+
debug?.(`[GRX2Loader] Machine ID: "${machineId}" (length: ${machineId.length})`);
|
|
364
363
|
|
|
365
364
|
// Read pack file
|
|
366
365
|
const data = await readFile(filePath);
|
package/src/grx2-loader/index.ts
CHANGED
package/src/grx2-loader/types.ts
CHANGED
|
@@ -25,7 +25,7 @@ export interface LicensePayload {
|
|
|
25
25
|
sub: string;
|
|
26
26
|
|
|
27
27
|
/** Customer tier */
|
|
28
|
-
tier: '
|
|
28
|
+
tier: 'basic' | 'professional' | 'enterprise';
|
|
29
29
|
|
|
30
30
|
/** Entitled feed IDs */
|
|
31
31
|
feeds: string[];
|
|
@@ -274,8 +274,14 @@ export const GRX2_KEY_TYPE_TMK = 1;
|
|
|
274
274
|
/** CTMK key type */
|
|
275
275
|
export const GRX2_KEY_TYPE_CTMK = 2;
|
|
276
276
|
|
|
277
|
+
/** Base SentriFlow home directory (platform-aware: ~/.sentriflow or %USERPROFILE%\.sentriflow) */
|
|
278
|
+
export const SENTRIFLOW_HOME = join(homedir(), '.sentriflow');
|
|
279
|
+
|
|
277
280
|
/** Default packs directory (platform-aware) */
|
|
278
|
-
export const DEFAULT_PACKS_DIRECTORY = join(
|
|
281
|
+
export const DEFAULT_PACKS_DIRECTORY = join(SENTRIFLOW_HOME, 'packs');
|
|
282
|
+
|
|
283
|
+
/** Default custom rules directory (platform-aware) */
|
|
284
|
+
export const DEFAULT_RULES_DIRECTORY = join(SENTRIFLOW_HOME, 'rules');
|
|
279
285
|
|
|
280
286
|
/** Cache directory (for downloaded packs, platform-aware) */
|
|
281
|
-
export const CACHE_DIRECTORY = join(
|
|
287
|
+
export const CACHE_DIRECTORY = join(SENTRIFLOW_HOME, 'cache');
|
|
@@ -10,6 +10,7 @@ import {
|
|
|
10
10
|
includesIgnoreCase,
|
|
11
11
|
startsWithIgnoreCase,
|
|
12
12
|
parseInteger,
|
|
13
|
+
findParentSection,
|
|
13
14
|
} from '../common/helpers';
|
|
14
15
|
|
|
15
16
|
// Re-export common helpers for convenience
|
|
@@ -214,6 +215,24 @@ export const hasWeakUsernamePassword = (node: ConfigNode): boolean => {
|
|
|
214
215
|
return false;
|
|
215
216
|
};
|
|
216
217
|
|
|
218
|
+
/**
|
|
219
|
+
* Check if password is under a line configuration section (vty, console, aux).
|
|
220
|
+
* Line passwords cannot be encrypted in Cisco IOS - they only support plaintext.
|
|
221
|
+
* Security for these should be enforced via AAA authentication instead.
|
|
222
|
+
*
|
|
223
|
+
* @param ast The full AST (array of ConfigNode)
|
|
224
|
+
* @param node The password node to check
|
|
225
|
+
* @returns true if the password is under a line vty/console/aux section
|
|
226
|
+
*/
|
|
227
|
+
export const isLineConfigPassword = (ast: ConfigNode[], node: ConfigNode): boolean => {
|
|
228
|
+
const parent = findParentSection(ast, node);
|
|
229
|
+
if (!parent) return false;
|
|
230
|
+
const parentId = parent.id.toLowerCase();
|
|
231
|
+
return parentId.startsWith('line vty') ||
|
|
232
|
+
parentId.startsWith('line console') ||
|
|
233
|
+
parentId.startsWith('line aux');
|
|
234
|
+
};
|
|
235
|
+
|
|
217
236
|
/**
|
|
218
237
|
* Get SSH version from configuration
|
|
219
238
|
*/
|
|
@@ -202,6 +202,35 @@ export const isShutdown = (node: ConfigNode): boolean => {
|
|
|
202
202
|
});
|
|
203
203
|
};
|
|
204
204
|
|
|
205
|
+
/**
|
|
206
|
+
* Find the parent section of a node in the AST.
|
|
207
|
+
* Traverses the AST to locate the parent section containing the target node.
|
|
208
|
+
* Useful for context-aware rules that need to check parent context.
|
|
209
|
+
*
|
|
210
|
+
* @param ast The full AST (array of ConfigNode)
|
|
211
|
+
* @param targetNode The node to find the parent for
|
|
212
|
+
* @returns The parent section node, or undefined if not found
|
|
213
|
+
*/
|
|
214
|
+
export const findParentSection = (
|
|
215
|
+
ast: ConfigNode[],
|
|
216
|
+
targetNode: ConfigNode
|
|
217
|
+
): ConfigNode | undefined => {
|
|
218
|
+
for (const node of ast) {
|
|
219
|
+
if (node.type === 'section') {
|
|
220
|
+
// Check if target is a direct child (by line number match)
|
|
221
|
+
if (node.children.some(child =>
|
|
222
|
+
child.loc.startLine === targetNode.loc.startLine
|
|
223
|
+
)) {
|
|
224
|
+
return node;
|
|
225
|
+
}
|
|
226
|
+
// Recurse into children
|
|
227
|
+
const found = findParentSection(node.children, targetNode);
|
|
228
|
+
if (found) return found;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
return undefined;
|
|
232
|
+
};
|
|
233
|
+
|
|
205
234
|
/**
|
|
206
235
|
* Check if a node is an actual interface definition (not a reference or sub-command).
|
|
207
236
|
* Interface definitions are top-level sections that define physical/logical interfaces.
|
|
@@ -39,7 +39,7 @@ export interface PackProviderLicenseStatus {
|
|
|
39
39
|
isValid: boolean;
|
|
40
40
|
|
|
41
41
|
/** License tier */
|
|
42
|
-
tier: '
|
|
42
|
+
tier: 'basic' | 'professional' | 'enterprise' | string;
|
|
43
43
|
|
|
44
44
|
/** List of entitled feed/pack IDs */
|
|
45
45
|
entitledFeeds: string[];
|