@sentriflow/core 0.1.9 → 0.2.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 +95 -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 +277 -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 +3 -0
- package/src/ip/extractor.ts +151 -61
- package/src/ip/index.ts +3 -0
- package/src/ip/types.ts +51 -0
- package/src/pack-loader/PackLoader.ts +29 -4
- 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/README.md
CHANGED
|
@@ -19,6 +19,8 @@ bun add @sentriflow/core
|
|
|
19
19
|
- **Multi-vendor support**: Cisco IOS/NX-OS, Juniper JunOS, Arista EOS, Fortinet FortiGate, Palo Alto PAN-OS, and more
|
|
20
20
|
- **AST-based parsing**: Converts configurations into a vendor-agnostic Abstract Syntax Tree
|
|
21
21
|
- **Extensible rule engine**: Define compliance rules for best practices or organization-specific policies
|
|
22
|
+
- **IP/Subnet Extraction**: Extract and deduplicate IP addresses and CIDR subnets from configurations
|
|
23
|
+
- **GRX2 Loader**: Load and decrypt extended encrypted rule packs for offline usage
|
|
22
24
|
- **TypeScript native**: Full type safety with comprehensive type definitions
|
|
23
25
|
|
|
24
26
|
## Supported Vendors
|
|
@@ -75,6 +77,99 @@ Checks an AST for compliance against a set of rules.
|
|
|
75
77
|
|
|
76
78
|
Auto-detects the vendor/platform from configuration content.
|
|
77
79
|
|
|
80
|
+
### `extractIPSummary(content: string, options?: ExtractOptions): IPSummary`
|
|
81
|
+
|
|
82
|
+
Extracts all IP addresses and subnets from configuration text.
|
|
83
|
+
|
|
84
|
+
```typescript
|
|
85
|
+
import { extractIPSummary } from '@sentriflow/core';
|
|
86
|
+
|
|
87
|
+
const config = `
|
|
88
|
+
interface GigabitEthernet0/1
|
|
89
|
+
ip address 192.168.1.1 255.255.255.0
|
|
90
|
+
ip route 10.0.0.0/24 via 192.168.1.254
|
|
91
|
+
`;
|
|
92
|
+
|
|
93
|
+
const summary = extractIPSummary(config);
|
|
94
|
+
// {
|
|
95
|
+
// ipv4Addresses: ['192.168.1.1', '192.168.1.254'],
|
|
96
|
+
// ipv6Addresses: [],
|
|
97
|
+
// ipv4Subnets: ['10.0.0.0/24'],
|
|
98
|
+
// ipv6Subnets: [],
|
|
99
|
+
// counts: { total: 3, ipv4: 2, ipv6: 0, ipv4Subnets: 1, ipv6Subnets: 0 }
|
|
100
|
+
// }
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Options:**
|
|
104
|
+
- `maxContentSize`: Maximum input size in bytes (default: 50MB) - prevents DoS
|
|
105
|
+
- `includeSubnetNetworks`: Include subnet network addresses in address lists
|
|
106
|
+
- `skipIPv4`, `skipIPv6`, `skipSubnets`: Skip specific extraction types
|
|
107
|
+
|
|
108
|
+
## GRX2 Loader Module
|
|
109
|
+
|
|
110
|
+
The `grx2-loader` module provides functionality for loading extended encrypted rule packs (.grx2). These packs embed wrapped encryption keys, enabling offline scanning without network access.
|
|
111
|
+
|
|
112
|
+
### Exported Functions
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import {
|
|
116
|
+
loadExtendedPack,
|
|
117
|
+
loadAllPacks,
|
|
118
|
+
getPackInfo,
|
|
119
|
+
getMachineId,
|
|
120
|
+
getMachineIdSync,
|
|
121
|
+
isExtendedGRX2,
|
|
122
|
+
} from '@sentriflow/core/grx2-loader';
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
| Function | Description |
|
|
126
|
+
|----------|-------------|
|
|
127
|
+
| `loadExtendedPack(filePath, licenseKey, machineId?)` | Load and decrypt a single GRX2 pack |
|
|
128
|
+
| `loadAllPacks(directory, licenseKey, machineId?)` | Load all GRX2 packs from a directory |
|
|
129
|
+
| `getPackInfo(filePath)` | Get metadata from a pack without decrypting |
|
|
130
|
+
| `getMachineId()` | Get the current machine identifier (async) |
|
|
131
|
+
| `getMachineIdSync()` | Get the current machine identifier (sync) |
|
|
132
|
+
| `isExtendedGRX2(buffer)` | Check if a buffer contains an extended GRX2 pack |
|
|
133
|
+
|
|
134
|
+
### Types
|
|
135
|
+
|
|
136
|
+
```typescript
|
|
137
|
+
import type {
|
|
138
|
+
GRX2ExtendedHeader,
|
|
139
|
+
GRX2PackLoadResult,
|
|
140
|
+
EncryptedPackInfo,
|
|
141
|
+
EncryptedPackErrorCode,
|
|
142
|
+
LicensePayload,
|
|
143
|
+
} from '@sentriflow/core/grx2-loader';
|
|
144
|
+
|
|
145
|
+
import { EncryptedPackError } from '@sentriflow/core/grx2-loader';
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### Example Usage
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
import { loadExtendedPack, getMachineId } from '@sentriflow/core/grx2-loader';
|
|
152
|
+
|
|
153
|
+
const licenseKey = process.env.SENTRIFLOW_LICENSE_KEY;
|
|
154
|
+
const machineId = await getMachineId();
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
const result = await loadExtendedPack('./rules.grx2', licenseKey, machineId);
|
|
158
|
+
if (result.success) {
|
|
159
|
+
console.log(`Loaded ${result.totalRules} rules`);
|
|
160
|
+
}
|
|
161
|
+
} catch (error) {
|
|
162
|
+
if (error instanceof EncryptedPackError) {
|
|
163
|
+
console.error(`Pack error: ${error.code} - ${error.message}`);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Machine-Bound vs Portable Packs
|
|
169
|
+
|
|
170
|
+
- **Portable packs**: Pass empty string for `machineId` parameter
|
|
171
|
+
- **Machine-bound packs**: Pass the result of `getMachineId()` for device-specific binding
|
|
172
|
+
|
|
78
173
|
## Related Packages
|
|
79
174
|
|
|
80
175
|
- [`@sentriflow/cli`](https://github.com/sentriflow/sentriflow/tree/main/packages/cli) - Command-line interface
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentriflow/core",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "SentriFlow core engine for network configuration validation",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"module": "src/index.ts",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"exports": {
|
|
9
9
|
".": "./src/index.ts",
|
|
10
|
+
"./grx2-loader": "./src/grx2-loader/index.ts",
|
|
10
11
|
"./helpers": "./src/helpers/index.ts",
|
|
11
12
|
"./helpers/common": "./src/helpers/common/index.ts",
|
|
12
13
|
"./helpers/arista": "./src/helpers/arista/index.ts",
|
|
@@ -51,8 +52,12 @@
|
|
|
51
52
|
"publishConfig": {
|
|
52
53
|
"access": "public"
|
|
53
54
|
},
|
|
55
|
+
"dependencies": {
|
|
56
|
+
"node-machine-id": "^1.1.12"
|
|
57
|
+
},
|
|
54
58
|
"devDependencies": {
|
|
55
|
-
"bun-types": "latest"
|
|
59
|
+
"bun-types": "latest",
|
|
60
|
+
"@types/node": "^20.0.0"
|
|
56
61
|
},
|
|
57
62
|
"peerDependencies": {
|
|
58
63
|
"typescript": "^5.0.0"
|
package/src/constants.ts
CHANGED
|
@@ -23,9 +23,12 @@ export const MAX_TRAVERSAL_DEPTH = 20;
|
|
|
23
23
|
/** Allowed extensions for config/rules files */
|
|
24
24
|
export const ALLOWED_CONFIG_EXTENSIONS = ['.js', '.ts', '.mjs', '.cjs'];
|
|
25
25
|
|
|
26
|
-
/** SEC-012: Allowed extensions for encrypted rule packs */
|
|
26
|
+
/** SEC-012: Allowed extensions for encrypted rule packs (.grpx legacy format) */
|
|
27
27
|
export const ALLOWED_ENCRYPTED_PACK_EXTENSIONS = ['.grpx'];
|
|
28
28
|
|
|
29
|
+
/** Allowed extensions for GRX2 extended encrypted rule packs */
|
|
30
|
+
export const ALLOWED_GRX2_PACK_EXTENSIONS = ['.grx2'];
|
|
31
|
+
|
|
29
32
|
/** Allowed extensions for JSON rule files */
|
|
30
33
|
export const ALLOWED_JSON_RULES_EXTENSIONS = ['.json'];
|
|
31
34
|
|
|
@@ -16,6 +16,8 @@ export interface ExecutionOptions {
|
|
|
16
16
|
onTimeout?: (ruleId: string, nodeId: string, elapsedMs: number) => void;
|
|
17
17
|
/** Callback when a rule is auto-disabled */
|
|
18
18
|
onRuleDisabled?: (ruleId: string, reason: string) => void;
|
|
19
|
+
/** Callback when a rule throws an error during execution */
|
|
20
|
+
onError?: (ruleId: string, nodeId: string, error: unknown) => void;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
/**
|
|
@@ -55,7 +57,7 @@ export class RuleExecutor {
|
|
|
55
57
|
private timeoutCounts = new Map<string, number>();
|
|
56
58
|
private executionTimes = new Map<string, { count: number; totalMs: number }>();
|
|
57
59
|
private disabledRules = new Set<string>();
|
|
58
|
-
private options: Required<ExecutionOptions>;
|
|
60
|
+
private options: Required<Omit<ExecutionOptions, 'onError'>> & Pick<ExecutionOptions, 'onError'>;
|
|
59
61
|
|
|
60
62
|
constructor(options: ExecutionOptions = {}) {
|
|
61
63
|
this.options = {
|
|
@@ -63,6 +65,7 @@ export class RuleExecutor {
|
|
|
63
65
|
maxTimeouts: options.maxTimeouts ?? 3,
|
|
64
66
|
onTimeout: options.onTimeout ?? (() => {}),
|
|
65
67
|
onRuleDisabled: options.onRuleDisabled ?? (() => {}),
|
|
68
|
+
onError: options.onError,
|
|
66
69
|
};
|
|
67
70
|
}
|
|
68
71
|
|
|
@@ -103,6 +106,9 @@ export class RuleExecutor {
|
|
|
103
106
|
const elapsed = performance.now() - startTime;
|
|
104
107
|
this.trackExecutionTime(rule.id, elapsed);
|
|
105
108
|
|
|
109
|
+
// Call error callback if provided (for debugging)
|
|
110
|
+
this.options.onError?.(rule.id, node.id, error);
|
|
111
|
+
|
|
106
112
|
// SEC-005: Sanitize error message to prevent information disclosure
|
|
107
113
|
// Don't expose internal error details which could reveal file paths or sensitive data
|
|
108
114
|
return {
|