@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
package/README.md
CHANGED
|
@@ -20,6 +20,7 @@ bun add @sentriflow/core
|
|
|
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
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
|
|
23
24
|
- **TypeScript native**: Full type safety with comprehensive type definitions
|
|
24
25
|
|
|
25
26
|
## Supported Vendors
|
|
@@ -104,6 +105,71 @@ const summary = extractIPSummary(config);
|
|
|
104
105
|
- `includeSubnetNetworks`: Include subnet network addresses in address lists
|
|
105
106
|
- `skipIPv4`, `skipIPv6`, `skipSubnets`: Skip specific extraction types
|
|
106
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
|
+
|
|
107
173
|
## Related Packages
|
|
108
174
|
|
|
109
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.
|
|
3
|
+
"version": "0.3.0",
|
|
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 {
|