@sentriflow/core 0.3.2 → 0.4.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/package.json CHANGED
@@ -1,65 +1,65 @@
1
- {
2
- "name": "@sentriflow/core",
3
- "version": "0.3.2",
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.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
+ }
@@ -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] License key length: ${licenseKey.length}, first 20 chars: ${licenseKey.substring(0, 20)}...`);
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);
@@ -31,7 +31,9 @@ export {
31
31
  GRX2_KDF_PBKDF2,
32
32
  GRX2_KEY_TYPE_TMK,
33
33
  GRX2_KEY_TYPE_CTMK,
34
+ SENTRIFLOW_HOME,
34
35
  DEFAULT_PACKS_DIRECTORY,
36
+ DEFAULT_RULES_DIRECTORY,
35
37
  CACHE_DIRECTORY,
36
38
  } from './types';
37
39
 
@@ -25,7 +25,7 @@ export interface LicensePayload {
25
25
  sub: string;
26
26
 
27
27
  /** Customer tier */
28
- tier: 'community' | 'professional' | 'enterprise';
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(homedir(), '.sentriflow', 'packs');
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(homedir(), '.sentriflow', 'cache');
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
  */
@@ -8,4 +8,5 @@ export {
8
8
  hasChildCommand,
9
9
  getChildCommand,
10
10
  getChildCommands,
11
+ findParentSection,
11
12
  } from '../common/helpers';
@@ -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: 'community' | 'professional' | 'enterprise' | string;
42
+ tier: 'basic' | 'professional' | 'enterprise' | string;
43
43
 
44
44
  /** List of entitled feed/pack IDs */
45
45
  entitledFeeds: string[];