@serve.zone/dcrouter 13.41.2 → 13.42.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/deno.json +1 -1
- package/dist_serve/bundle.js +1025 -983
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/config/classes.db-seeder.js +29 -2
- package/dist_ts/config/classes.reference-resolver.d.ts +5 -0
- package/dist_ts/config/classes.reference-resolver.js +79 -15
- package/dist_ts/config/classes.route-config-manager.d.ts +5 -1
- package/dist_ts/config/classes.route-config-manager.js +136 -6
- package/dist_ts/config/classes.source-policy-compiler.d.ts +35 -0
- package/dist_ts/config/classes.source-policy-compiler.js +497 -0
- package/dist_ts/config/index.d.ts +1 -0
- package/dist_ts/config/index.js +2 -1
- package/dist_ts_interfaces/data/route-management.d.ts +39 -0
- package/dist_ts_interfaces/data/route-management.js +65 -1
- package/dist_ts_migrations/index.js +67 -1
- package/dist_ts_web/00_commitinfo_data.js +1 -1
- package/dist_ts_web/elements/network/ops-view-routes.d.ts +2 -0
- package/dist_ts_web/elements/network/ops-view-routes.js +237 -11
- package/dist_ts_web/elements/network/ops-view-sourceprofiles.js +42 -5
- package/package.json +4 -4
- package/readme.md +74 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/config/classes.db-seeder.ts +28 -1
- package/ts/config/classes.reference-resolver.ts +94 -14
- package/ts/config/classes.route-config-manager.ts +162 -5
- package/ts/config/classes.source-policy-compiler.ts +614 -0
- package/ts/config/index.ts +1 -0
- package/ts/readme.md +1 -1
- package/ts_web/00_commitinfo_data.ts +1 -1
- package/ts_web/elements/network/ops-view-routes.ts +257 -10
- package/ts_web/elements/network/ops-view-sourceprofiles.ts +41 -4
|
@@ -0,0 +1,497 @@
|
|
|
1
|
+
import * as plugins from '../plugins.js';
|
|
2
|
+
import { giteaRoutePathClassLabels, giteaRoutePathClassPatterns, routePathClasses, } from '../../dist_ts_interfaces/data/route-management.js';
|
|
3
|
+
const MIN_ROUTE_PRIORITY = 0;
|
|
4
|
+
const MAX_ROUTE_PRIORITY = 10000;
|
|
5
|
+
const SOURCE_PRIORITY_BAND = 0.0008;
|
|
6
|
+
const PATH_PRIORITY_BAND = 0.0001;
|
|
7
|
+
export const sourcePolicyLimits = {
|
|
8
|
+
maxBindings: 16,
|
|
9
|
+
maxPathPoliciesPerBinding: 12,
|
|
10
|
+
maxPathPatternsPerPolicy: 64,
|
|
11
|
+
maxPathPatternLength: 256,
|
|
12
|
+
maxPathPatternWildcards: 8,
|
|
13
|
+
maxSourceProfileRefLength: 256,
|
|
14
|
+
maxIdLength: 128,
|
|
15
|
+
maxExceededMessageLength: 512,
|
|
16
|
+
maxCompiledVariantsPerRoute: 512,
|
|
17
|
+
};
|
|
18
|
+
export class SourcePolicyCompiler {
|
|
19
|
+
static compileRoute(route, metadata, referenceResolver, routeId) {
|
|
20
|
+
const bindings = metadata?.sourcePolicy?.bindings || [];
|
|
21
|
+
if (bindings.length === 0) {
|
|
22
|
+
return [route];
|
|
23
|
+
}
|
|
24
|
+
if (this.validateSourcePolicyShape(metadata?.sourcePolicy, route)) {
|
|
25
|
+
return [];
|
|
26
|
+
}
|
|
27
|
+
if (!referenceResolver) {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
if (this.validateResolvedSourcePolicy(metadata?.sourcePolicy, referenceResolver)) {
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
const compiledRoutes = [];
|
|
34
|
+
const basePriority = route.priority ?? 0;
|
|
35
|
+
bindings.forEach((binding, index) => {
|
|
36
|
+
const profile = referenceResolver.getProfile(binding.sourceProfileRef);
|
|
37
|
+
const profileSecurity = referenceResolver.resolveSourceProfileSecurity(binding.sourceProfileRef);
|
|
38
|
+
if (!profile || !profileSecurity) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
const sourceMatches = this.getSourceMatchEntries(profileSecurity);
|
|
42
|
+
if (sourceMatches.length === 0) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const sourcePriority = this.calculateSourcePriority(basePriority, index, bindings.length);
|
|
46
|
+
const sourceMatch = this.matchesAllSources(sourceMatches)
|
|
47
|
+
? { ...route.match }
|
|
48
|
+
: { ...route.match, clientIp: sourceMatches };
|
|
49
|
+
const pathPolicies = binding.pathPolicies || [];
|
|
50
|
+
if (pathPolicies.length === 0) {
|
|
51
|
+
compiledRoutes.push(this.buildCompiledRoute({
|
|
52
|
+
route,
|
|
53
|
+
sourceMatch,
|
|
54
|
+
profileName: profile.name,
|
|
55
|
+
profileSecurity,
|
|
56
|
+
binding,
|
|
57
|
+
sourcePriority,
|
|
58
|
+
routeId,
|
|
59
|
+
sourceIndex: index,
|
|
60
|
+
}));
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
let hasSourceFallback = false;
|
|
64
|
+
pathPolicies.forEach((pathPolicy, pathIndex) => {
|
|
65
|
+
const pathPatterns = this.getPathPatterns(pathPolicy);
|
|
66
|
+
if (pathPatterns.length === 0) {
|
|
67
|
+
hasSourceFallback = true;
|
|
68
|
+
compiledRoutes.push(this.buildCompiledRoute({
|
|
69
|
+
route,
|
|
70
|
+
sourceMatch,
|
|
71
|
+
profileName: profile.name,
|
|
72
|
+
profileSecurity,
|
|
73
|
+
binding,
|
|
74
|
+
pathPolicy,
|
|
75
|
+
sourcePriority,
|
|
76
|
+
routeId,
|
|
77
|
+
sourceIndex: index,
|
|
78
|
+
pathIndex,
|
|
79
|
+
pathPolicyCount: pathPolicies.length,
|
|
80
|
+
}));
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
pathPatterns.forEach((pathPattern, pathPatternIndex) => {
|
|
84
|
+
compiledRoutes.push(this.buildCompiledRoute({
|
|
85
|
+
route,
|
|
86
|
+
sourceMatch,
|
|
87
|
+
profileName: profile.name,
|
|
88
|
+
profileSecurity,
|
|
89
|
+
binding,
|
|
90
|
+
pathPolicy,
|
|
91
|
+
pathPattern,
|
|
92
|
+
sourcePriority,
|
|
93
|
+
routeId,
|
|
94
|
+
sourceIndex: index,
|
|
95
|
+
pathIndex,
|
|
96
|
+
pathPolicyCount: pathPolicies.length,
|
|
97
|
+
pathPatternIndex,
|
|
98
|
+
pathPatternCount: pathPatterns.length,
|
|
99
|
+
}));
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
if (!hasSourceFallback) {
|
|
103
|
+
compiledRoutes.push(this.buildCompiledRoute({
|
|
104
|
+
route,
|
|
105
|
+
sourceMatch,
|
|
106
|
+
profileName: profile.name,
|
|
107
|
+
profileSecurity,
|
|
108
|
+
binding,
|
|
109
|
+
sourcePriority,
|
|
110
|
+
routeId,
|
|
111
|
+
sourceIndex: index,
|
|
112
|
+
}));
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
return compiledRoutes;
|
|
116
|
+
}
|
|
117
|
+
static validateSourcePolicyPayload(sourcePolicy) {
|
|
118
|
+
if (!sourcePolicy) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
if (!Array.isArray(sourcePolicy.bindings)) {
|
|
122
|
+
return 'Source policy bindings must be an array';
|
|
123
|
+
}
|
|
124
|
+
if (sourcePolicy.bindings.length === 0) {
|
|
125
|
+
return undefined;
|
|
126
|
+
}
|
|
127
|
+
if (sourcePolicy.bindings.length > sourcePolicyLimits.maxBindings) {
|
|
128
|
+
return `Source policy exceeds ${sourcePolicyLimits.maxBindings} bindings`;
|
|
129
|
+
}
|
|
130
|
+
const validClasses = new Set(routePathClasses);
|
|
131
|
+
for (const binding of sourcePolicy.bindings) {
|
|
132
|
+
if (!binding || typeof binding !== 'object') {
|
|
133
|
+
return 'Source policy binding must be an object';
|
|
134
|
+
}
|
|
135
|
+
if (typeof binding.sourceProfileRef !== 'string') {
|
|
136
|
+
return 'Source policy binding requires a source profile';
|
|
137
|
+
}
|
|
138
|
+
if (binding.sourceProfileRef.length > sourcePolicyLimits.maxSourceProfileRefLength) {
|
|
139
|
+
return `Source policy source profile ref exceeds ${sourcePolicyLimits.maxSourceProfileRefLength} characters`;
|
|
140
|
+
}
|
|
141
|
+
if (binding.sourceProfileRef.trim().length === 0) {
|
|
142
|
+
return 'Source policy binding requires a source profile';
|
|
143
|
+
}
|
|
144
|
+
if (typeof binding.id === 'string' && binding.id.length > sourcePolicyLimits.maxIdLength) {
|
|
145
|
+
return `Source policy binding id exceeds ${sourcePolicyLimits.maxIdLength} characters`;
|
|
146
|
+
}
|
|
147
|
+
if (typeof binding.maxConnections === 'number' && binding.maxConnections < 0) {
|
|
148
|
+
return 'Source policy maxConnections must be non-negative';
|
|
149
|
+
}
|
|
150
|
+
const bindingRateLimitError = this.validateRateLimitPayload(binding.rateLimit);
|
|
151
|
+
if (bindingRateLimitError) {
|
|
152
|
+
return bindingRateLimitError;
|
|
153
|
+
}
|
|
154
|
+
const bindingMessage = binding.onExceeded?.errorMessage;
|
|
155
|
+
if (typeof bindingMessage === 'string' && bindingMessage.length > sourcePolicyLimits.maxExceededMessageLength) {
|
|
156
|
+
return `Source policy exceeded message exceeds ${sourcePolicyLimits.maxExceededMessageLength} characters`;
|
|
157
|
+
}
|
|
158
|
+
const pathPolicies = binding.pathPolicies;
|
|
159
|
+
if (pathPolicies === undefined) {
|
|
160
|
+
continue;
|
|
161
|
+
}
|
|
162
|
+
if (!Array.isArray(pathPolicies)) {
|
|
163
|
+
return 'Source policy path policies must be an array';
|
|
164
|
+
}
|
|
165
|
+
if (pathPolicies.length > sourcePolicyLimits.maxPathPoliciesPerBinding) {
|
|
166
|
+
return `Source policy binding exceeds ${sourcePolicyLimits.maxPathPoliciesPerBinding} path policies`;
|
|
167
|
+
}
|
|
168
|
+
for (const pathPolicy of pathPolicies) {
|
|
169
|
+
if (!pathPolicy || typeof pathPolicy !== 'object') {
|
|
170
|
+
return 'Source policy path policy must be an object';
|
|
171
|
+
}
|
|
172
|
+
if (!validClasses.has(pathPolicy.pathClass)) {
|
|
173
|
+
return 'Source policy path policy uses an unsupported path class';
|
|
174
|
+
}
|
|
175
|
+
if (typeof pathPolicy.id === 'string' && pathPolicy.id.length > sourcePolicyLimits.maxIdLength) {
|
|
176
|
+
return `Source policy path policy id exceeds ${sourcePolicyLimits.maxIdLength} characters`;
|
|
177
|
+
}
|
|
178
|
+
if (typeof pathPolicy.maxConnections === 'number' && pathPolicy.maxConnections < 0) {
|
|
179
|
+
return 'Source policy path policy maxConnections must be non-negative';
|
|
180
|
+
}
|
|
181
|
+
const pathRateLimitError = this.validateRateLimitPayload(pathPolicy.rateLimit);
|
|
182
|
+
if (pathRateLimitError) {
|
|
183
|
+
return pathRateLimitError;
|
|
184
|
+
}
|
|
185
|
+
const pathMessage = pathPolicy.onExceeded?.errorMessage;
|
|
186
|
+
if (typeof pathMessage === 'string' && pathMessage.length > sourcePolicyLimits.maxExceededMessageLength) {
|
|
187
|
+
return `Source policy exceeded message exceeds ${sourcePolicyLimits.maxExceededMessageLength} characters`;
|
|
188
|
+
}
|
|
189
|
+
const pathPatterns = pathPolicy.pathPatterns;
|
|
190
|
+
if (pathPatterns === undefined) {
|
|
191
|
+
continue;
|
|
192
|
+
}
|
|
193
|
+
if (!Array.isArray(pathPatterns)) {
|
|
194
|
+
return 'Source policy path patterns must be an array';
|
|
195
|
+
}
|
|
196
|
+
if (pathPatterns.length > sourcePolicyLimits.maxPathPatternsPerPolicy) {
|
|
197
|
+
return `Source policy path class exceeds ${sourcePolicyLimits.maxPathPatternsPerPolicy} path patterns`;
|
|
198
|
+
}
|
|
199
|
+
for (const pattern of pathPatterns) {
|
|
200
|
+
if (typeof pattern !== 'string') {
|
|
201
|
+
return 'Source policy path pattern must be a string';
|
|
202
|
+
}
|
|
203
|
+
if (pattern.length > sourcePolicyLimits.maxPathPatternLength) {
|
|
204
|
+
return `Source policy path pattern exceeds ${sourcePolicyLimits.maxPathPatternLength} characters`;
|
|
205
|
+
}
|
|
206
|
+
const wildcardCount = pattern.split('*').length - 1;
|
|
207
|
+
if (wildcardCount > sourcePolicyLimits.maxPathPatternWildcards) {
|
|
208
|
+
return `Source policy path pattern exceeds ${sourcePolicyLimits.maxPathPatternWildcards} wildcards`;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
return undefined;
|
|
214
|
+
}
|
|
215
|
+
static validateRateLimitPayload(rateLimit) {
|
|
216
|
+
if (!rateLimit || typeof rateLimit !== 'object') {
|
|
217
|
+
return undefined;
|
|
218
|
+
}
|
|
219
|
+
const rawRateLimit = rateLimit;
|
|
220
|
+
for (const key of ['maxRequests', 'window']) {
|
|
221
|
+
const value = rawRateLimit[key];
|
|
222
|
+
if (typeof value === 'string' && value.length > 32) {
|
|
223
|
+
return `Source policy rate limit ${key} exceeds 32 characters`;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
if (typeof rateLimit.errorMessage === 'string'
|
|
227
|
+
&& rateLimit.errorMessage.length > sourcePolicyLimits.maxExceededMessageLength) {
|
|
228
|
+
return `Source policy rate limit error message exceeds ${sourcePolicyLimits.maxExceededMessageLength} characters`;
|
|
229
|
+
}
|
|
230
|
+
return undefined;
|
|
231
|
+
}
|
|
232
|
+
static validateSourcePolicyShape(sourcePolicy, route) {
|
|
233
|
+
const payloadError = this.validateSourcePolicyPayload(sourcePolicy);
|
|
234
|
+
if (payloadError) {
|
|
235
|
+
return payloadError;
|
|
236
|
+
}
|
|
237
|
+
const bindings = sourcePolicy?.bindings || [];
|
|
238
|
+
if (bindings.length === 0) {
|
|
239
|
+
return undefined;
|
|
240
|
+
}
|
|
241
|
+
let estimatedCompiledRoutes = 0;
|
|
242
|
+
for (const binding of bindings) {
|
|
243
|
+
const pathPolicies = binding.pathPolicies || [];
|
|
244
|
+
if (pathPolicies.length === 0) {
|
|
245
|
+
estimatedCompiledRoutes++;
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
let hasSourceFallback = false;
|
|
249
|
+
for (const pathPolicy of pathPolicies) {
|
|
250
|
+
const pathPatterns = this.getPathPatterns(pathPolicy);
|
|
251
|
+
if (pathPatterns.length > sourcePolicyLimits.maxPathPatternsPerPolicy) {
|
|
252
|
+
return `Source policy path class expands beyond ${sourcePolicyLimits.maxPathPatternsPerPolicy} path patterns`;
|
|
253
|
+
}
|
|
254
|
+
if (pathPatterns.length === 0) {
|
|
255
|
+
hasSourceFallback = true;
|
|
256
|
+
estimatedCompiledRoutes++;
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
estimatedCompiledRoutes += pathPatterns.length;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
if (!hasSourceFallback) {
|
|
263
|
+
estimatedCompiledRoutes++;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
if (estimatedCompiledRoutes > sourcePolicyLimits.maxCompiledVariantsPerRoute) {
|
|
267
|
+
return `Source policy exceeds ${sourcePolicyLimits.maxCompiledVariantsPerRoute} compiled route variants`;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
const expandedPortCount = route ? this.getExpandedPortCount(route.match?.ports) : 1;
|
|
271
|
+
if (estimatedCompiledRoutes * expandedPortCount > sourcePolicyLimits.maxCompiledVariantsPerRoute) {
|
|
272
|
+
return `Source policy exceeds ${sourcePolicyLimits.maxCompiledVariantsPerRoute} compiled route-port variants`;
|
|
273
|
+
}
|
|
274
|
+
return undefined;
|
|
275
|
+
}
|
|
276
|
+
static validateResolvedSourcePolicy(sourcePolicy, referenceResolver) {
|
|
277
|
+
const bindings = sourcePolicy?.bindings || [];
|
|
278
|
+
if (bindings.length === 0) {
|
|
279
|
+
return undefined;
|
|
280
|
+
}
|
|
281
|
+
if (!referenceResolver) {
|
|
282
|
+
return 'Source policy requires source profile resolution';
|
|
283
|
+
}
|
|
284
|
+
for (let index = 0; index < bindings.length; index++) {
|
|
285
|
+
const binding = bindings[index];
|
|
286
|
+
const profile = referenceResolver.getProfile(binding.sourceProfileRef);
|
|
287
|
+
if (!profile) {
|
|
288
|
+
return `Source profile '${binding.sourceProfileRef}' not found`;
|
|
289
|
+
}
|
|
290
|
+
const profileSecurity = referenceResolver.resolveSourceProfileSecurity(binding.sourceProfileRef);
|
|
291
|
+
if (!profileSecurity) {
|
|
292
|
+
return `Source profile '${profile.name}' could not be resolved`;
|
|
293
|
+
}
|
|
294
|
+
const sourceMatches = this.getSourceMatchEntries(profileSecurity);
|
|
295
|
+
if (sourceMatches.length === 0) {
|
|
296
|
+
return `Source profile '${profile.name}' has no source matches`;
|
|
297
|
+
}
|
|
298
|
+
const matchesAllSources = this.matchesAllSources(sourceMatches);
|
|
299
|
+
if (matchesAllSources && index < bindings.length - 1) {
|
|
300
|
+
return 'Wildcard source profile bindings must be last in a source policy';
|
|
301
|
+
}
|
|
302
|
+
if (index === bindings.length - 1 && !matchesAllSources) {
|
|
303
|
+
return 'Source policy must end with an all-source fallback profile';
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return undefined;
|
|
307
|
+
}
|
|
308
|
+
static buildCompiledRoute(options) {
|
|
309
|
+
const routeKey = options.route.id || options.routeId || options.route.name || 'route';
|
|
310
|
+
const bindingKey = options.binding.id || options.binding.sourceProfileRef || String(options.sourceIndex + 1);
|
|
311
|
+
const pathPolicyKey = options.pathPolicy
|
|
312
|
+
? options.pathPolicy.id || options.pathPolicy.pathClass
|
|
313
|
+
: undefined;
|
|
314
|
+
const pathLabel = options.pathPolicy
|
|
315
|
+
? giteaRoutePathClassLabels[options.pathPolicy.pathClass]
|
|
316
|
+
: undefined;
|
|
317
|
+
const pathPatternSuffix = options.pathPatternCount && options.pathPatternCount > 1
|
|
318
|
+
? `:${(options.pathPatternIndex || 0) + 1}`
|
|
319
|
+
: '';
|
|
320
|
+
const pathPriority = options.pathPolicy
|
|
321
|
+
? this.calculatePathPriorityOffset(options.pathPattern, options.pathIndex || 0, options.pathPolicyCount || 1, options.pathPatternIndex || 0, options.pathPatternCount || 1)
|
|
322
|
+
: 0;
|
|
323
|
+
return {
|
|
324
|
+
...options.route,
|
|
325
|
+
id: pathPolicyKey
|
|
326
|
+
? `${routeKey}:source:${bindingKey}:path:${pathPolicyKey}${pathPatternSuffix}`
|
|
327
|
+
: `${routeKey}:source:${bindingKey}`,
|
|
328
|
+
name: pathLabel
|
|
329
|
+
? `${options.route.name || routeKey}:source:${options.profileName}:path:${pathLabel}${pathPatternSuffix}`
|
|
330
|
+
: `${options.route.name || routeKey}:source:${options.profileName}`,
|
|
331
|
+
match: options.pathPattern
|
|
332
|
+
? { ...options.sourceMatch, path: options.pathPattern }
|
|
333
|
+
: { ...options.sourceMatch },
|
|
334
|
+
priority: this.clampPriority(options.sourcePriority + pathPriority),
|
|
335
|
+
security: this.buildBindingSecurity(options.route.security, options.profileSecurity, options.binding, options.pathPolicy),
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
static getPathPatterns(pathPolicy) {
|
|
339
|
+
const patterns = pathPolicy.pathPatterns?.length
|
|
340
|
+
? pathPolicy.pathPatterns
|
|
341
|
+
: giteaRoutePathClassPatterns[pathPolicy.pathClass];
|
|
342
|
+
return [...new Set(patterns.map((pattern) => pattern.trim()).filter(Boolean))];
|
|
343
|
+
}
|
|
344
|
+
static calculatePathPriorityOffset(pathPattern, pathIndex, pathPolicyCount, pathPatternIndex, pathPatternCount) {
|
|
345
|
+
if (!pathPattern) {
|
|
346
|
+
return 0;
|
|
347
|
+
}
|
|
348
|
+
const pathPolicyOffset = ((pathPolicyCount - pathIndex) / (pathPolicyCount + 1))
|
|
349
|
+
* (PATH_PRIORITY_BAND * 0.9);
|
|
350
|
+
const pathPatternOffset = ((pathPatternCount - pathPatternIndex) / (pathPatternCount + 1))
|
|
351
|
+
* (PATH_PRIORITY_BAND * 0.1 / (pathPolicyCount + 1));
|
|
352
|
+
return pathPolicyOffset + pathPatternOffset;
|
|
353
|
+
}
|
|
354
|
+
static calculateSourcePriority(basePriority, sourceIndex, sourceCount) {
|
|
355
|
+
const safeBasePriority = this.clampPriority(basePriority, MIN_ROUTE_PRIORITY, MAX_ROUTE_PRIORITY - SOURCE_PRIORITY_BAND - PATH_PRIORITY_BAND);
|
|
356
|
+
const sourceStep = SOURCE_PRIORITY_BAND / (sourceCount + 1);
|
|
357
|
+
return safeBasePriority + ((sourceCount - sourceIndex) * sourceStep);
|
|
358
|
+
}
|
|
359
|
+
static clampPriority(priority, min = MIN_ROUTE_PRIORITY, max = MAX_ROUTE_PRIORITY) {
|
|
360
|
+
if (!Number.isFinite(priority)) {
|
|
361
|
+
return min;
|
|
362
|
+
}
|
|
363
|
+
return Math.min(max, Math.max(min, priority));
|
|
364
|
+
}
|
|
365
|
+
static getExpandedPortCount(portRange) {
|
|
366
|
+
if (portRange === undefined) {
|
|
367
|
+
return 1;
|
|
368
|
+
}
|
|
369
|
+
if (typeof portRange === 'number') {
|
|
370
|
+
return Number.isFinite(portRange) ? 1 : sourcePolicyLimits.maxCompiledVariantsPerRoute + 1;
|
|
371
|
+
}
|
|
372
|
+
if (!Array.isArray(portRange)) {
|
|
373
|
+
return sourcePolicyLimits.maxCompiledVariantsPerRoute + 1;
|
|
374
|
+
}
|
|
375
|
+
let count = 0;
|
|
376
|
+
for (const portEntry of portRange) {
|
|
377
|
+
if (typeof portEntry === 'number') {
|
|
378
|
+
if (!Number.isFinite(portEntry)) {
|
|
379
|
+
return sourcePolicyLimits.maxCompiledVariantsPerRoute + 1;
|
|
380
|
+
}
|
|
381
|
+
count++;
|
|
382
|
+
}
|
|
383
|
+
else if (portEntry
|
|
384
|
+
&& typeof portEntry === 'object'
|
|
385
|
+
&& Number.isFinite(portEntry.from)
|
|
386
|
+
&& Number.isFinite(portEntry.to)
|
|
387
|
+
&& portEntry.from <= portEntry.to) {
|
|
388
|
+
count += Math.floor(portEntry.to) - Math.floor(portEntry.from) + 1;
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
return sourcePolicyLimits.maxCompiledVariantsPerRoute + 1;
|
|
392
|
+
}
|
|
393
|
+
if (count > sourcePolicyLimits.maxCompiledVariantsPerRoute) {
|
|
394
|
+
return count;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
return Math.max(1, count);
|
|
398
|
+
}
|
|
399
|
+
static normalizeMaxConnections(value) {
|
|
400
|
+
return typeof value === 'number' && Number.isFinite(value) && value >= 0 ? value : undefined;
|
|
401
|
+
}
|
|
402
|
+
static forceIpRateLimit(rateLimit) {
|
|
403
|
+
if (!rateLimit) {
|
|
404
|
+
return undefined;
|
|
405
|
+
}
|
|
406
|
+
const { headerName: _headerName, ...rest } = structuredClone(rateLimit);
|
|
407
|
+
return {
|
|
408
|
+
...rest,
|
|
409
|
+
keyBy: 'ip',
|
|
410
|
+
};
|
|
411
|
+
}
|
|
412
|
+
static sanitizeSourcePolicySecurity(security) {
|
|
413
|
+
const sanitized = structuredClone(security);
|
|
414
|
+
const maxConnections = this.normalizeMaxConnections(sanitized.maxConnections);
|
|
415
|
+
if (maxConnections === undefined) {
|
|
416
|
+
delete sanitized.maxConnections;
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
sanitized.maxConnections = maxConnections;
|
|
420
|
+
}
|
|
421
|
+
if (sanitized.rateLimit) {
|
|
422
|
+
sanitized.rateLimit = this.forceIpRateLimit(sanitized.rateLimit);
|
|
423
|
+
}
|
|
424
|
+
return sanitized;
|
|
425
|
+
}
|
|
426
|
+
static isEmptySecurity(security) {
|
|
427
|
+
return Object.keys(security).length === 0;
|
|
428
|
+
}
|
|
429
|
+
static getSourceMatchEntries(security) {
|
|
430
|
+
const entries = security.ipAllowList || [];
|
|
431
|
+
const normalizedEntries = [];
|
|
432
|
+
for (const entry of entries) {
|
|
433
|
+
const rawEntry = typeof entry === 'string' ? entry : entry.ip;
|
|
434
|
+
if (typeof rawEntry !== 'string')
|
|
435
|
+
continue;
|
|
436
|
+
const normalizedEntry = rawEntry.trim();
|
|
437
|
+
if (normalizedEntry) {
|
|
438
|
+
normalizedEntries.push(normalizedEntry);
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return [...new Set(normalizedEntries)];
|
|
442
|
+
}
|
|
443
|
+
static matchesAllSources(sourceMatches) {
|
|
444
|
+
return sourceMatches.includes('*')
|
|
445
|
+
|| (sourceMatches.includes('0.0.0.0/0') && sourceMatches.includes('::/0'));
|
|
446
|
+
}
|
|
447
|
+
static buildBindingSecurity(routeSecurity, profileSecurity, binding, pathPolicy) {
|
|
448
|
+
const baseSecurity = this.omitSourceMatchFields(routeSecurity || {});
|
|
449
|
+
const sourceSecurity = this.omitSourceMatchFields(profileSecurity);
|
|
450
|
+
if (binding.rateLimit !== undefined) {
|
|
451
|
+
sourceSecurity.rateLimit = this.forceIpRateLimit(binding.rateLimit);
|
|
452
|
+
}
|
|
453
|
+
if (binding.maxConnections !== undefined) {
|
|
454
|
+
const maxConnections = this.normalizeMaxConnections(binding.maxConnections);
|
|
455
|
+
if (maxConnections === undefined) {
|
|
456
|
+
delete sourceSecurity.maxConnections;
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
sourceSecurity.maxConnections = maxConnections;
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
if (binding.onExceeded?.errorMessage && sourceSecurity.rateLimit) {
|
|
463
|
+
sourceSecurity.rateLimit = {
|
|
464
|
+
...sourceSecurity.rateLimit,
|
|
465
|
+
errorMessage: binding.onExceeded.errorMessage,
|
|
466
|
+
};
|
|
467
|
+
}
|
|
468
|
+
if (pathPolicy?.rateLimit !== undefined) {
|
|
469
|
+
sourceSecurity.rateLimit = this.forceIpRateLimit(pathPolicy.rateLimit);
|
|
470
|
+
}
|
|
471
|
+
if (pathPolicy?.maxConnections !== undefined) {
|
|
472
|
+
const maxConnections = this.normalizeMaxConnections(pathPolicy.maxConnections);
|
|
473
|
+
if (maxConnections === undefined) {
|
|
474
|
+
delete sourceSecurity.maxConnections;
|
|
475
|
+
}
|
|
476
|
+
else {
|
|
477
|
+
sourceSecurity.maxConnections = maxConnections;
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
if (pathPolicy?.onExceeded?.errorMessage && sourceSecurity.rateLimit) {
|
|
481
|
+
sourceSecurity.rateLimit = {
|
|
482
|
+
...sourceSecurity.rateLimit,
|
|
483
|
+
errorMessage: pathPolicy.onExceeded.errorMessage,
|
|
484
|
+
};
|
|
485
|
+
}
|
|
486
|
+
const mergedSecurity = this.sanitizeSourcePolicySecurity({
|
|
487
|
+
...baseSecurity,
|
|
488
|
+
...sourceSecurity,
|
|
489
|
+
});
|
|
490
|
+
return this.isEmptySecurity(mergedSecurity) ? undefined : mergedSecurity;
|
|
491
|
+
}
|
|
492
|
+
static omitSourceMatchFields(security) {
|
|
493
|
+
const { ipAllowList: _ipAllowList, ...controls } = security;
|
|
494
|
+
return this.sanitizeSourcePolicySecurity(controls);
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zb3VyY2UtcG9saWN5LWNvbXBpbGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vdHMvY29uZmlnL2NsYXNzZXMuc291cmNlLXBvbGljeS1jb21waWxlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEtBQUssT0FBTyxNQUFNLGVBQWUsQ0FBQztBQUN6QyxPQUFPLEVBQ0wseUJBQXlCLEVBQ3pCLDJCQUEyQixFQUMzQixnQkFBZ0IsR0FDakIsTUFBTSw4Q0FBOEMsQ0FBQztBQVV0RCxNQUFNLGtCQUFrQixHQUFHLENBQUMsQ0FBQztBQUM3QixNQUFNLGtCQUFrQixHQUFHLEtBQUssQ0FBQztBQUNqQyxNQUFNLG9CQUFvQixHQUFHLE1BQU0sQ0FBQztBQUNwQyxNQUFNLGtCQUFrQixHQUFHLE1BQU0sQ0FBQztBQUVsQyxNQUFNLENBQUMsTUFBTSxrQkFBa0IsR0FBRztJQUNoQyxXQUFXLEVBQUUsRUFBRTtJQUNmLHlCQUF5QixFQUFFLEVBQUU7SUFDN0Isd0JBQXdCLEVBQUUsRUFBRTtJQUM1QixvQkFBb0IsRUFBRSxHQUFHO0lBQ3pCLHVCQUF1QixFQUFFLENBQUM7SUFDMUIseUJBQXlCLEVBQUUsR0FBRztJQUM5QixXQUFXLEVBQUUsR0FBRztJQUNoQix3QkFBd0IsRUFBRSxHQUFHO0lBQzdCLDJCQUEyQixFQUFFLEdBQUc7Q0FDeEIsQ0FBQztBQUVYLE1BQU0sT0FBTyxvQkFBb0I7SUFDeEIsTUFBTSxDQUFDLFlBQVksQ0FDeEIsS0FBc0MsRUFDdEMsUUFBb0MsRUFDcEMsaUJBQWdELEVBQ2hELE9BQWdCO1FBRWhCLE1BQU0sUUFBUSxHQUFHLFFBQVEsRUFBRSxZQUFZLEVBQUUsUUFBUSxJQUFJLEVBQUUsQ0FBQztRQUN4RCxJQUFJLFFBQVEsQ0FBQyxNQUFNLEtBQUssQ0FBQyxFQUFFLENBQUM7WUFDMUIsT0FBTyxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2pCLENBQUM7UUFDRCxJQUFJLElB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
|
|
@@ -3,5 +3,6 @@ export { RouteConfigManager } from './classes.route-config-manager.js';
|
|
|
3
3
|
export { ApiTokenManager } from './classes.api-token-manager.js';
|
|
4
4
|
export { GatewayClientManager } from './classes.gateway-client-manager.js';
|
|
5
5
|
export { ReferenceResolver } from './classes.reference-resolver.js';
|
|
6
|
+
export { SourcePolicyCompiler } from './classes.source-policy-compiler.js';
|
|
6
7
|
export { DbSeeder } from './classes.db-seeder.js';
|
|
7
8
|
export { TargetProfileManager } from './classes.target-profile-manager.js';
|
package/dist_ts/config/index.js
CHANGED
|
@@ -4,6 +4,7 @@ export { RouteConfigManager } from './classes.route-config-manager.js';
|
|
|
4
4
|
export { ApiTokenManager } from './classes.api-token-manager.js';
|
|
5
5
|
export { GatewayClientManager } from './classes.gateway-client-manager.js';
|
|
6
6
|
export { ReferenceResolver } from './classes.reference-resolver.js';
|
|
7
|
+
export { SourcePolicyCompiler } from './classes.source-policy-compiler.js';
|
|
7
8
|
export { DbSeeder } from './classes.db-seeder.js';
|
|
8
9
|
export { TargetProfileManager } from './classes.target-profile-manager.js';
|
|
9
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
10
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90cy9jb25maWcvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsK0JBQStCO0FBQy9CLGNBQWMsZ0JBQWdCLENBQUM7QUFDL0IsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDdkUsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ2pFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQzNFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3BFLE9BQU8sRUFBRSxvQkFBb0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQzNFLE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUNsRCxPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQyJ9
|
|
@@ -45,6 +45,43 @@ export interface ISourceProfile {
|
|
|
45
45
|
updatedAt: number;
|
|
46
46
|
createdBy: string;
|
|
47
47
|
}
|
|
48
|
+
export interface IRouteSourcePolicyExceededAction {
|
|
49
|
+
type: '429';
|
|
50
|
+
errorMessage?: string;
|
|
51
|
+
}
|
|
52
|
+
export declare const routePathClasses: readonly ["git-smart-http", "static", "normal-html", "expensive-html", "raw", "archive"];
|
|
53
|
+
export type TRoutePathClass = typeof routePathClasses[number];
|
|
54
|
+
export declare const giteaRoutePathClassLabels: Record<TRoutePathClass, string>;
|
|
55
|
+
export declare const giteaRoutePathClassPatterns: Record<TRoutePathClass, string[]>;
|
|
56
|
+
export interface IRoutePathPolicyBinding {
|
|
57
|
+
id?: string;
|
|
58
|
+
pathClass: TRoutePathClass;
|
|
59
|
+
/** Optional custom patterns. When omitted, the Gitea defaults for the class are used. */
|
|
60
|
+
pathPatterns?: string[];
|
|
61
|
+
/** Optional path-class override for the source binding's rate limit. */
|
|
62
|
+
rateLimit?: IRouteSecurity['rateLimit'];
|
|
63
|
+
/** Optional path-class override for the source binding's connection limit. */
|
|
64
|
+
maxConnections?: IRouteSecurity['maxConnections'];
|
|
65
|
+
onExceeded?: IRouteSourcePolicyExceededAction;
|
|
66
|
+
}
|
|
67
|
+
export interface IRouteSourcePolicyBinding {
|
|
68
|
+
id?: string;
|
|
69
|
+
sourceProfileRef: string;
|
|
70
|
+
/** Snapshot of the profile name at resolution time, for display. */
|
|
71
|
+
sourceProfileName?: string;
|
|
72
|
+
/** Optional route-level override for the referenced profile's rate limit. */
|
|
73
|
+
rateLimit?: IRouteSecurity['rateLimit'];
|
|
74
|
+
/** Optional route-level override for the referenced profile's connection limit. */
|
|
75
|
+
maxConnections?: IRouteSecurity['maxConnections'];
|
|
76
|
+
/** Initial source-policy slice only supports explicit 429 behavior. */
|
|
77
|
+
onExceeded?: IRouteSourcePolicyExceededAction;
|
|
78
|
+
/** Optional path-class variants inside this source binding. Path-specific variants win over fallback variants. */
|
|
79
|
+
pathPolicies?: IRoutePathPolicyBinding[];
|
|
80
|
+
}
|
|
81
|
+
export interface IRouteSourcePolicy {
|
|
82
|
+
/** Ordered source profile bindings. The first matching binding wins. */
|
|
83
|
+
bindings: IRouteSourcePolicyBinding[];
|
|
84
|
+
}
|
|
48
85
|
/**
|
|
49
86
|
* A reusable, named network target (host + port) that can be referenced by routes.
|
|
50
87
|
*/
|
|
@@ -64,6 +101,8 @@ export interface INetworkTarget {
|
|
|
64
101
|
export interface IRouteMetadata {
|
|
65
102
|
/** ID of the SourceProfileDoc used to resolve this route's security. */
|
|
66
103
|
sourceProfileRef?: string;
|
|
104
|
+
/** Ordered source policy. When present, it supersedes sourceProfileRef. */
|
|
105
|
+
sourcePolicy?: IRouteSourcePolicy;
|
|
67
106
|
/** ID of the NetworkTargetDoc used to resolve this route's targets. */
|
|
68
107
|
networkTargetRef?: string;
|
|
69
108
|
/** Snapshot of the profile name at resolution time, for display. */
|