@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
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GRX2 Extended Loader Module
|
|
3
|
+
*
|
|
4
|
+
* Provides functionality for loading and decrypting extended GRX2 encrypted rule packs.
|
|
5
|
+
* This module is used by both the CLI and VS Code extension.
|
|
6
|
+
*
|
|
7
|
+
* @module @sentriflow/core/grx2-loader
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Types
|
|
11
|
+
export type {
|
|
12
|
+
LicensePayload,
|
|
13
|
+
GRX2ExtendedHeader,
|
|
14
|
+
WrappedTMK,
|
|
15
|
+
SerializedWrappedTMK,
|
|
16
|
+
EncryptedPackInfo,
|
|
17
|
+
GRX2PackLoadResult,
|
|
18
|
+
EncryptedPackErrorCode,
|
|
19
|
+
} from './types';
|
|
20
|
+
|
|
21
|
+
// Error class
|
|
22
|
+
export { EncryptedPackError } from './types';
|
|
23
|
+
|
|
24
|
+
// Constants
|
|
25
|
+
export {
|
|
26
|
+
GRX2_HEADER_SIZE,
|
|
27
|
+
GRX2_EXTENDED_VERSION,
|
|
28
|
+
GRX2_EXTENDED_FLAG,
|
|
29
|
+
GRX2_PORTABLE_FLAG,
|
|
30
|
+
GRX2_ALGORITHM_AES_256_GCM,
|
|
31
|
+
GRX2_KDF_PBKDF2,
|
|
32
|
+
GRX2_KEY_TYPE_TMK,
|
|
33
|
+
GRX2_KEY_TYPE_CTMK,
|
|
34
|
+
DEFAULT_PACKS_DIRECTORY,
|
|
35
|
+
CACHE_DIRECTORY,
|
|
36
|
+
} from './types';
|
|
37
|
+
|
|
38
|
+
// Machine ID functions
|
|
39
|
+
export { getMachineId, getMachineIdSync } from './MachineId';
|
|
40
|
+
|
|
41
|
+
// Loader functions
|
|
42
|
+
export {
|
|
43
|
+
isExtendedGRX2,
|
|
44
|
+
loadExtendedPack,
|
|
45
|
+
loadAllPacks,
|
|
46
|
+
getPackInfo,
|
|
47
|
+
} from './GRX2ExtendedLoader';
|
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* GRX2 Extended Loader Types
|
|
3
|
+
*
|
|
4
|
+
* Types for encrypted GRX2 rule pack loading.
|
|
5
|
+
* Used by both CLI and VS Code extension.
|
|
6
|
+
*
|
|
7
|
+
* @module @sentriflow/core/grx2-loader/types
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import { homedir } from 'node:os';
|
|
11
|
+
import { join } from 'node:path';
|
|
12
|
+
|
|
13
|
+
// =============================================================================
|
|
14
|
+
// License Types
|
|
15
|
+
// =============================================================================
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* JWT License payload structure
|
|
19
|
+
*
|
|
20
|
+
* The license key is a JWT containing this payload.
|
|
21
|
+
* It can be decoded offline to get entitlements.
|
|
22
|
+
*/
|
|
23
|
+
export interface LicensePayload {
|
|
24
|
+
/** Customer ID (JWT subject) */
|
|
25
|
+
sub: string;
|
|
26
|
+
|
|
27
|
+
/** Customer tier */
|
|
28
|
+
tier: 'community' | 'professional' | 'enterprise';
|
|
29
|
+
|
|
30
|
+
/** Entitled feed IDs */
|
|
31
|
+
feeds: string[];
|
|
32
|
+
|
|
33
|
+
/** API URL for cloud updates */
|
|
34
|
+
api: string;
|
|
35
|
+
|
|
36
|
+
/** Expiration timestamp (Unix seconds) */
|
|
37
|
+
exp: number;
|
|
38
|
+
|
|
39
|
+
/** Issued at timestamp (Unix seconds) */
|
|
40
|
+
iat: number;
|
|
41
|
+
|
|
42
|
+
/** Optional machine ID binding */
|
|
43
|
+
mid?: string;
|
|
44
|
+
|
|
45
|
+
/** Optional customer name */
|
|
46
|
+
name?: string;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// =============================================================================
|
|
50
|
+
// GRX2 Extended Format Types
|
|
51
|
+
// =============================================================================
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Extended GRX2 header structure (96 bytes)
|
|
55
|
+
*
|
|
56
|
+
* The extended format uses version=3 and includes a wrapped TMK block
|
|
57
|
+
* after the standard header.
|
|
58
|
+
*/
|
|
59
|
+
export interface GRX2ExtendedHeader {
|
|
60
|
+
/** Magic bytes ("GRX2") */
|
|
61
|
+
magic: Buffer;
|
|
62
|
+
|
|
63
|
+
/** Format version (3 for extended) */
|
|
64
|
+
version: number;
|
|
65
|
+
|
|
66
|
+
/** Encryption algorithm (1 = AES-256-GCM) */
|
|
67
|
+
algorithm: number;
|
|
68
|
+
|
|
69
|
+
/** Key derivation function (1 = PBKDF2) */
|
|
70
|
+
kdf: number;
|
|
71
|
+
|
|
72
|
+
/** Key type (1 = TMK, 2 = CTMK) */
|
|
73
|
+
keyType: number;
|
|
74
|
+
|
|
75
|
+
/** Tier ID */
|
|
76
|
+
tierId: number;
|
|
77
|
+
|
|
78
|
+
/** TMK version */
|
|
79
|
+
tmkVersion: number;
|
|
80
|
+
|
|
81
|
+
/** Initialization vector (12 bytes) */
|
|
82
|
+
iv: Buffer;
|
|
83
|
+
|
|
84
|
+
/** Authentication tag (16 bytes) */
|
|
85
|
+
authTag: Buffer;
|
|
86
|
+
|
|
87
|
+
/** PBKDF2 salt (32 bytes, zeros for TMK mode) */
|
|
88
|
+
salt: Buffer;
|
|
89
|
+
|
|
90
|
+
/** Encrypted payload length */
|
|
91
|
+
payloadLength: number;
|
|
92
|
+
|
|
93
|
+
/** Pack hash (16 bytes, truncated SHA-256) */
|
|
94
|
+
packHash: Buffer;
|
|
95
|
+
|
|
96
|
+
/** Reserved bytes */
|
|
97
|
+
reserved: Buffer;
|
|
98
|
+
|
|
99
|
+
/** Indicates extended format */
|
|
100
|
+
isExtended: true;
|
|
101
|
+
|
|
102
|
+
/** Indicates portable pack (no machine binding required) */
|
|
103
|
+
isPortable: boolean;
|
|
104
|
+
|
|
105
|
+
/** Wrapped TMK embedded in pack */
|
|
106
|
+
wrappedTMK: WrappedTMK;
|
|
107
|
+
|
|
108
|
+
/** Total header size (96 + 4 + wrapped TMK length) */
|
|
109
|
+
totalHeaderSize: number;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Wrapped TMK structure
|
|
114
|
+
*
|
|
115
|
+
* TMK encrypted with LDK (derived from license key + salt).
|
|
116
|
+
* Embedded in extended GRX2 packs.
|
|
117
|
+
*
|
|
118
|
+
* SECURITY: Uses random salt for PBKDF2 key derivation.
|
|
119
|
+
* The salt is stored with the wrapped TMK, not derived from predictable values.
|
|
120
|
+
*/
|
|
121
|
+
export interface WrappedTMK {
|
|
122
|
+
/** Encrypted TMK (32 bytes encrypted) */
|
|
123
|
+
encryptedKey: Buffer;
|
|
124
|
+
|
|
125
|
+
/** IV used for TMK encryption (12 bytes) */
|
|
126
|
+
iv: Buffer;
|
|
127
|
+
|
|
128
|
+
/** Auth tag for TMK (16 bytes) */
|
|
129
|
+
authTag: Buffer;
|
|
130
|
+
|
|
131
|
+
/** TMK version that was wrapped */
|
|
132
|
+
tmkVersion: number;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Random salt for LDK derivation (32 bytes)
|
|
136
|
+
* SECURITY: This is a cryptographically random value, NOT derived from machineId.
|
|
137
|
+
* The machineId is used as additional input to the KDF, not as the sole salt.
|
|
138
|
+
*/
|
|
139
|
+
ldkSalt: Buffer;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Serialized wrapped TMK (for JSON storage)
|
|
144
|
+
*/
|
|
145
|
+
export interface SerializedWrappedTMK {
|
|
146
|
+
/** Base64-encoded encrypted key */
|
|
147
|
+
k: string;
|
|
148
|
+
/** Base64-encoded IV */
|
|
149
|
+
i: string;
|
|
150
|
+
/** Base64-encoded auth tag */
|
|
151
|
+
t: string;
|
|
152
|
+
/** TMK version */
|
|
153
|
+
v: number;
|
|
154
|
+
/** Base64-encoded LDK salt (32 bytes random) */
|
|
155
|
+
s: string;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// =============================================================================
|
|
159
|
+
// Pack Types
|
|
160
|
+
// =============================================================================
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Information about a loaded encrypted pack
|
|
164
|
+
*/
|
|
165
|
+
export interface EncryptedPackInfo {
|
|
166
|
+
/** Feed ID */
|
|
167
|
+
feedId: string;
|
|
168
|
+
|
|
169
|
+
/** Pack name */
|
|
170
|
+
name: string;
|
|
171
|
+
|
|
172
|
+
/** Pack version */
|
|
173
|
+
version: string;
|
|
174
|
+
|
|
175
|
+
/** Publisher */
|
|
176
|
+
publisher: string;
|
|
177
|
+
|
|
178
|
+
/** Number of rules in pack */
|
|
179
|
+
ruleCount: number;
|
|
180
|
+
|
|
181
|
+
/** File path of the pack */
|
|
182
|
+
filePath: string;
|
|
183
|
+
|
|
184
|
+
/** Whether pack was loaded successfully */
|
|
185
|
+
loaded: boolean;
|
|
186
|
+
|
|
187
|
+
/** Error message if loading failed */
|
|
188
|
+
error?: string;
|
|
189
|
+
|
|
190
|
+
/** Source: local directory or cloud cache */
|
|
191
|
+
source: 'local' | 'cache';
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* GRX2 Pack loading result
|
|
196
|
+
* Named GRX2PackLoadResult to avoid collision with pack-provider's PackLoadResult
|
|
197
|
+
*/
|
|
198
|
+
export interface GRX2PackLoadResult {
|
|
199
|
+
/** Whether loading was successful */
|
|
200
|
+
success: boolean;
|
|
201
|
+
|
|
202
|
+
/** Loaded packs */
|
|
203
|
+
packs: EncryptedPackInfo[];
|
|
204
|
+
|
|
205
|
+
/** Total rules loaded */
|
|
206
|
+
totalRules: number;
|
|
207
|
+
|
|
208
|
+
/** Errors encountered */
|
|
209
|
+
errors: string[];
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// =============================================================================
|
|
213
|
+
// Error Types
|
|
214
|
+
// =============================================================================
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Encrypted pack error codes
|
|
218
|
+
*/
|
|
219
|
+
export type EncryptedPackErrorCode =
|
|
220
|
+
| 'LICENSE_MISSING'
|
|
221
|
+
| 'LICENSE_EXPIRED'
|
|
222
|
+
| 'LICENSE_INVALID'
|
|
223
|
+
| 'NOT_ENTITLED'
|
|
224
|
+
| 'PACK_NOT_FOUND'
|
|
225
|
+
| 'PACK_CORRUPTED'
|
|
226
|
+
| 'DECRYPTION_FAILED'
|
|
227
|
+
| 'MACHINE_MISMATCH'
|
|
228
|
+
| 'NETWORK_ERROR'
|
|
229
|
+
| 'API_ERROR';
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Encrypted pack error
|
|
233
|
+
*/
|
|
234
|
+
export class EncryptedPackError extends Error {
|
|
235
|
+
constructor(
|
|
236
|
+
message: string,
|
|
237
|
+
public readonly code: EncryptedPackErrorCode,
|
|
238
|
+
public readonly details?: unknown
|
|
239
|
+
) {
|
|
240
|
+
super(message);
|
|
241
|
+
this.name = 'EncryptedPackError';
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// =============================================================================
|
|
246
|
+
// Constants
|
|
247
|
+
// =============================================================================
|
|
248
|
+
|
|
249
|
+
/** Standard GRX2 header size */
|
|
250
|
+
export const GRX2_HEADER_SIZE = 96;
|
|
251
|
+
|
|
252
|
+
/** Extended format version */
|
|
253
|
+
export const GRX2_EXTENDED_VERSION = 3;
|
|
254
|
+
|
|
255
|
+
/** Extended format flag in reserved byte (bit 0) */
|
|
256
|
+
export const GRX2_EXTENDED_FLAG = 0x01;
|
|
257
|
+
|
|
258
|
+
/** Portable pack flag in reserved byte (bit 1) - no machine binding */
|
|
259
|
+
export const GRX2_PORTABLE_FLAG = 0x02;
|
|
260
|
+
|
|
261
|
+
/** AES-256-GCM algorithm ID */
|
|
262
|
+
export const GRX2_ALGORITHM_AES_256_GCM = 1;
|
|
263
|
+
|
|
264
|
+
/** PBKDF2 KDF ID */
|
|
265
|
+
export const GRX2_KDF_PBKDF2 = 1;
|
|
266
|
+
|
|
267
|
+
/** TMK key type */
|
|
268
|
+
export const GRX2_KEY_TYPE_TMK = 1;
|
|
269
|
+
|
|
270
|
+
/** CTMK key type */
|
|
271
|
+
export const GRX2_KEY_TYPE_CTMK = 2;
|
|
272
|
+
|
|
273
|
+
/** Default packs directory (platform-aware) */
|
|
274
|
+
export const DEFAULT_PACKS_DIRECTORY = join(homedir(), '.sentriflow', 'packs');
|
|
275
|
+
|
|
276
|
+
/** Cache directory (for downloaded packs, platform-aware) */
|
|
277
|
+
export const CACHE_DIRECTORY = join(homedir(), '.sentriflow', 'cache');
|