emilsoftware-utilities 2.0.0-dev.66 → 2.0.0-dev.68
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/dist/EmilsoftwareModule.d.ts +11 -3
- package/dist/EmilsoftwareModule.js +1 -1
- package/dist/EmilsoftwareModule.js.map +1 -1
- package/dist/accessi/client/index.d.ts +26 -0
- package/dist/accessi/client/index.js +49 -0
- package/dist/accessi/client/index.js.map +1 -0
- package/dist/accessi/console/index.d.ts +15 -0
- package/dist/accessi/console/index.js +25 -0
- package/dist/accessi/console/index.js.map +1 -0
- package/dist/accessi/contracts/dtos.d.ts +8 -0
- package/dist/accessi/contracts/dtos.js +25 -0
- package/dist/accessi/contracts/dtos.js.map +1 -0
- package/dist/accessi/contracts/index.d.ts +25 -0
- package/dist/accessi/contracts/index.js +28 -0
- package/dist/accessi/contracts/index.js.map +1 -0
- package/dist/accessi/openapi/index.d.ts +2 -0
- package/dist/accessi/openapi/index.js +19 -0
- package/dist/accessi/openapi/index.js.map +1 -0
- package/dist/accessi/resource-server/core.d.ts +6 -0
- package/dist/accessi/resource-server/core.js +23 -0
- package/dist/accessi/resource-server/core.js.map +1 -0
- package/dist/accessi/resource-server/errors.d.ts +10 -0
- package/dist/accessi/resource-server/errors.js +19 -0
- package/dist/accessi/resource-server/errors.js.map +1 -0
- package/dist/accessi/resource-server/express.d.ts +17 -0
- package/dist/accessi/resource-server/express.js +66 -0
- package/dist/accessi/resource-server/express.js.map +1 -0
- package/dist/accessi/resource-server/index.d.ts +3 -0
- package/dist/accessi/resource-server/index.js +20 -0
- package/dist/accessi/resource-server/index.js.map +1 -0
- package/dist/accessi/resource-server/introspection.d.ts +16 -0
- package/dist/accessi/resource-server/introspection.js +115 -0
- package/dist/accessi/resource-server/introspection.js.map +1 -0
- package/dist/accessi/resource-server/keys.d.ts +11 -0
- package/dist/accessi/resource-server/keys.js +22 -0
- package/dist/accessi/resource-server/keys.js.map +1 -0
- package/dist/accessi/resource-server/nest.d.ts +9 -0
- package/dist/accessi/resource-server/nest.js +62 -0
- package/dist/accessi/resource-server/nest.js.map +1 -0
- package/dist/accessi/resource-server/runtime.d.ts +27 -0
- package/dist/accessi/resource-server/runtime.js +128 -0
- package/dist/accessi/resource-server/runtime.js.map +1 -0
- package/dist/accessi/resource-server/token.d.ts +23 -0
- package/dist/accessi/resource-server/token.js +230 -0
- package/dist/accessi/resource-server/token.js.map +1 -0
- package/dist/accessi/resource-server/types.d.ts +78 -0
- package/dist/accessi/resource-server/types.js +3 -0
- package/dist/accessi/resource-server/types.js.map +1 -0
- package/dist/accessi/server/index.d.ts +10 -0
- package/dist/accessi/server/index.js +29 -0
- package/dist/accessi/server/index.js.map +1 -0
- package/dist/accessi/ui/index.d.ts +13 -0
- package/dist/accessi/ui/index.js +19 -0
- package/dist/accessi/ui/index.js.map +1 -0
- package/dist/accessi-module/AccessiModule.d.ts +52 -2
- package/dist/accessi-module/AccessiModule.js +2 -0
- package/dist/accessi-module/AccessiModule.js.map +1 -1
- package/dist/accessi-module/Console/accessiFetch.d.ts +4 -0
- package/dist/accessi-module/Console/accessiFetch.js +18 -4
- package/dist/accessi-module/Console/accessiFetch.js.map +1 -1
- package/dist/accessi-module/Console/console.js +122 -11
- package/dist/accessi-module/Console/console.js.map +1 -1
- package/dist/accessi-module/Console/generated/{accessiApi.d.ts → emilsoftware-utilities.d.ts} +11 -1
- package/dist/accessi-module/Console/generated/{accessiApi.js → emilsoftware-utilities.js} +10 -2
- package/dist/accessi-module/Console/generated/emilsoftware-utilities.js.map +1 -0
- package/dist/accessi-module/Console/generated/model/accessiIntrospectionResultDto.d.ts +16 -0
- package/dist/accessi-module/Console/generated/model/accessiIntrospectionResultDto.js +3 -0
- package/dist/accessi-module/Console/generated/model/accessiIntrospectionResultDto.js.map +1 -0
- package/dist/accessi-module/Console/generated/model/index.d.ts +3 -0
- package/dist/accessi-module/Console/generated/model/index.js +3 -0
- package/dist/accessi-module/Console/generated/model/index.js.map +1 -1
- package/dist/accessi-module/Console/generated/model/introspectAccessiTokenRequest.d.ts +10 -0
- package/dist/accessi-module/Console/generated/model/introspectAccessiTokenRequest.js +9 -0
- package/dist/accessi-module/Console/generated/model/introspectAccessiTokenRequest.js.map +1 -0
- package/dist/accessi-module/Console/generated/model/introspectAccessiTokenResponse.d.ts +14 -0
- package/dist/accessi-module/Console/generated/model/introspectAccessiTokenResponse.js +3 -0
- package/dist/accessi-module/Console/generated/model/introspectAccessiTokenResponse.js.map +1 -0
- package/dist/accessi-module/Console/wiki.js +106 -5
- package/dist/accessi-module/Console/wiki.js.map +1 -1
- package/dist/accessi-module/Controllers/AccessiIntrospectionController.d.ts +17 -0
- package/dist/accessi-module/Controllers/AccessiIntrospectionController.js +93 -0
- package/dist/accessi-module/Controllers/AccessiIntrospectionController.js.map +1 -0
- package/dist/accessi-module/Controllers/AuthController.js +6 -6
- package/dist/accessi-module/Controllers/AuthController.js.map +1 -1
- package/dist/accessi-module/Controllers/ConsoleEntryController.d.ts +2 -0
- package/dist/accessi-module/Controllers/ConsoleEntryController.js +11 -3
- package/dist/accessi-module/Controllers/ConsoleEntryController.js.map +1 -1
- package/dist/accessi-module/Controllers/EmailController.js +1 -1
- package/dist/accessi-module/Controllers/EmailController.js.map +1 -1
- package/dist/accessi-module/Controllers/UserController.js +1 -1
- package/dist/accessi-module/Controllers/UserController.js.map +1 -1
- package/dist/accessi-module/Dtos/IntrospectionDtos.d.ts +16 -0
- package/dist/accessi-module/Dtos/IntrospectionDtos.js +59 -0
- package/dist/accessi-module/Dtos/IntrospectionDtos.js.map +1 -0
- package/dist/accessi-module/Dtos/index.d.ts +1 -0
- package/dist/accessi-module/Dtos/index.js +1 -0
- package/dist/accessi-module/Dtos/index.js.map +1 -1
- package/dist/accessi-module/Services/AuthService/AuthService.d.ts +13 -0
- package/dist/accessi-module/Services/AuthService/AuthService.js +42 -10
- package/dist/accessi-module/Services/AuthService/AuthService.js.map +1 -1
- package/dist/accessi-module/database-updates/accessiOptionsFromEnv.js +18 -19
- package/dist/accessi-module/database-updates/accessiOptionsFromEnv.js.map +1 -1
- package/dist/accessi-module/database-updates/menuScopeSeed.d.ts +2 -2
- package/dist/accessi-module/database-updates/menuScopeSeed.js +101 -53
- package/dist/accessi-module/database-updates/menuScopeSeed.js.map +1 -1
- package/dist/accessi-module/database-updates/menuScopeSeeder.js +1 -1
- package/dist/accessi-module/database-updates/menuScopeSeeder.js.map +1 -1
- package/dist/accessi-module/index.d.ts +25 -4
- package/dist/accessi-module/index.js +47 -21
- package/dist/accessi-module/index.js.map +1 -1
- package/dist/accessi-module/jwt/jwt.strategy.js +5 -5
- package/dist/accessi-module/jwt/jwt.strategy.js.map +1 -1
- package/dist/accessi-module/middleware/authenticateGen.js +5 -5
- package/dist/accessi-module/middleware/authenticateGen.js.map +1 -1
- package/dist/accessi-module/security/consoleEntry.d.ts +56 -11
- package/dist/accessi-module/security/consoleEntry.js +165 -31
- package/dist/accessi-module/security/consoleEntry.js.map +1 -1
- package/dist/accessi-module/security/edgeRateLimit.d.ts +31 -0
- package/dist/accessi-module/security/edgeRateLimit.js +70 -0
- package/dist/accessi-module/security/edgeRateLimit.js.map +1 -0
- package/dist/accessi-module/security/jwks.d.ts +33 -0
- package/dist/accessi-module/security/jwks.js +83 -0
- package/dist/accessi-module/security/jwks.js.map +1 -0
- package/dist/accessi-module/security/jwtTokenOptions.d.ts +15 -0
- package/dist/accessi-module/security/jwtTokenOptions.js +44 -0
- package/dist/accessi-module/security/jwtTokenOptions.js.map +1 -0
- package/dist/accessi-module/security/publicAuthRateLimit.d.ts +8 -6
- package/dist/accessi-module/security/publicAuthRateLimit.js +54 -78
- package/dist/accessi-module/security/publicAuthRateLimit.js.map +1 -1
- package/dist/accessi-module/security/rateLimitStore.d.ts +32 -0
- package/dist/accessi-module/security/rateLimitStore.js +129 -0
- package/dist/accessi-module/security/rateLimitStore.js.map +1 -0
- package/dist/accessi-module/security/serviceTokenGuard.d.ts +3 -1
- package/dist/accessi-module/security/serviceTokenGuard.js +11 -6
- package/dist/accessi-module/security/serviceTokenGuard.js.map +1 -1
- package/dist/accessi-module/security/serviceTokenRateLimit.d.ts +5 -4
- package/dist/accessi-module/security/serviceTokenRateLimit.js +33 -29
- package/dist/accessi-module/security/serviceTokenRateLimit.js.map +1 -1
- package/dist/accessi-module/startupLog.d.ts +3 -2
- package/dist/accessi-module/startupLog.js +8 -4
- package/dist/accessi-module/startupLog.js.map +1 -1
- package/dist/allegati-module/index.js +2 -2
- package/dist/allegati-module/index.js.map +1 -1
- package/dist/angular-components/aree-disponibili/demo.html +4 -4
- package/dist/emilsoftware-utilities-2.0.0-dev.68.tgz +0 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/initEmilsoftwareModule.d.ts +11 -1
- package/dist/initEmilsoftwareModule.js +29 -23
- package/dist/initEmilsoftwareModule.js.map +1 -1
- package/dist/openapi/OpenApiConfig.d.ts +68 -0
- package/dist/openapi/OpenApiConfig.js +157 -0
- package/dist/openapi/OpenApiConfig.js.map +1 -0
- package/dist/openapi/OpenApiMerge.d.ts +15 -0
- package/dist/openapi/OpenApiMerge.js +119 -0
- package/dist/openapi/OpenApiMerge.js.map +1 -0
- package/docs/gateway-rate-limit.md +98 -0
- package/integration-prompt.md +612 -0
- package/package.json +89 -5
- package/dist/accessi-module/Console/generated/accessiApi.js.map +0 -1
- package/dist/emilsoftware-utilities-2.0.0-dev.66.tgz +0 -0
- package/dist/swagger/SwaggerConfig.d.ts +0 -8
- package/dist/swagger/SwaggerConfig.js +0 -41
- package/dist/swagger/SwaggerConfig.js.map +0 -1
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.mergeOpenApiDocuments = mergeOpenApiDocuments;
|
|
4
|
+
function isRecord(value) {
|
|
5
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6
|
+
}
|
|
7
|
+
function cloneDocument(document) {
|
|
8
|
+
return JSON.parse(JSON.stringify(document));
|
|
9
|
+
}
|
|
10
|
+
function sameValue(left, right) {
|
|
11
|
+
return JSON.stringify(left) === JSON.stringify(right);
|
|
12
|
+
}
|
|
13
|
+
function mergeRecord(target, source, policy, section) {
|
|
14
|
+
if (!source)
|
|
15
|
+
return target;
|
|
16
|
+
const merged = Object.assign({}, (target !== null && target !== void 0 ? target : {}));
|
|
17
|
+
for (const [key, value] of Object.entries(source)) {
|
|
18
|
+
if (!(key in merged)) {
|
|
19
|
+
merged[key] = value;
|
|
20
|
+
continue;
|
|
21
|
+
}
|
|
22
|
+
if (sameValue(merged[key], value))
|
|
23
|
+
continue;
|
|
24
|
+
if (policy === "keep")
|
|
25
|
+
continue;
|
|
26
|
+
if (policy === "overwrite") {
|
|
27
|
+
merged[key] = value;
|
|
28
|
+
continue;
|
|
29
|
+
}
|
|
30
|
+
throw new Error(`Conflitto OpenAPI in ${section}.${key}.`);
|
|
31
|
+
}
|
|
32
|
+
return merged;
|
|
33
|
+
}
|
|
34
|
+
function mergeTags(target, source, policy) {
|
|
35
|
+
if (!Array.isArray(target) || !Array.isArray(source))
|
|
36
|
+
return target !== null && target !== void 0 ? target : source;
|
|
37
|
+
const merged = [...target];
|
|
38
|
+
for (const tag of source) {
|
|
39
|
+
if (!isRecord(tag) || typeof tag.name !== "string") {
|
|
40
|
+
merged.push(tag);
|
|
41
|
+
continue;
|
|
42
|
+
}
|
|
43
|
+
const existingIndex = merged.findIndex((candidate) => isRecord(candidate) && candidate.name === tag.name);
|
|
44
|
+
if (existingIndex < 0) {
|
|
45
|
+
merged.push(tag);
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
const existing = merged[existingIndex];
|
|
49
|
+
if (sameValue(existing, tag))
|
|
50
|
+
continue;
|
|
51
|
+
if (policy === "keep")
|
|
52
|
+
continue;
|
|
53
|
+
if (policy === "overwrite") {
|
|
54
|
+
merged[existingIndex] = tag;
|
|
55
|
+
continue;
|
|
56
|
+
}
|
|
57
|
+
throw new Error(`Conflitto OpenAPI nel tag "${tag.name}".`);
|
|
58
|
+
}
|
|
59
|
+
return merged;
|
|
60
|
+
}
|
|
61
|
+
function mergeServers(target, source, policy) {
|
|
62
|
+
if (!Array.isArray(target) || !Array.isArray(source))
|
|
63
|
+
return target !== null && target !== void 0 ? target : source;
|
|
64
|
+
const merged = [...target];
|
|
65
|
+
for (const server of source) {
|
|
66
|
+
if (!isRecord(server) || typeof server.url !== "string") {
|
|
67
|
+
merged.push(server);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const existingIndex = merged.findIndex((candidate) => isRecord(candidate) && candidate.url === server.url);
|
|
71
|
+
if (existingIndex < 0) {
|
|
72
|
+
merged.push(server);
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const existing = merged[existingIndex];
|
|
76
|
+
if (sameValue(existing, server))
|
|
77
|
+
continue;
|
|
78
|
+
if (policy === "keep")
|
|
79
|
+
continue;
|
|
80
|
+
if (policy === "overwrite") {
|
|
81
|
+
merged[existingIndex] = server;
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
throw new Error(`Conflitto OpenAPI nel server "${server.url}".`);
|
|
85
|
+
}
|
|
86
|
+
return merged;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Unisce il documento Accessi nel documento OpenAPI dell'host.
|
|
90
|
+
*
|
|
91
|
+
* Per default un conflitto su path, schema o security scheme produce errore:
|
|
92
|
+
* e meglio accorgersi subito di due contratti incompatibili. Usare
|
|
93
|
+
* `conflict: "overwrite"` solo quando il documento host deve vincere.
|
|
94
|
+
*/
|
|
95
|
+
function mergeOpenApiDocuments(target, source, options = {}) {
|
|
96
|
+
var _a;
|
|
97
|
+
if (!target || !source) {
|
|
98
|
+
throw new Error("mergeOpenApiDocuments richiede due documenti OpenAPI validi.");
|
|
99
|
+
}
|
|
100
|
+
const policy = (_a = options.conflict) !== null && _a !== void 0 ? _a : "error";
|
|
101
|
+
const result = cloneDocument(target);
|
|
102
|
+
const sourceDocument = source;
|
|
103
|
+
result.paths = mergeRecord(isRecord(result.paths) ? result.paths : undefined, isRecord(sourceDocument.paths) ? sourceDocument.paths : undefined, policy, "paths");
|
|
104
|
+
const targetComponents = isRecord(result.components) ? result.components : {};
|
|
105
|
+
const sourceComponents = isRecord(sourceDocument.components) ? sourceDocument.components : {};
|
|
106
|
+
const componentSections = new Set([
|
|
107
|
+
...Object.keys(targetComponents),
|
|
108
|
+
...Object.keys(sourceComponents),
|
|
109
|
+
]);
|
|
110
|
+
const mergedComponents = Object.assign({}, targetComponents);
|
|
111
|
+
for (const section of componentSections) {
|
|
112
|
+
mergedComponents[section] = mergeRecord(isRecord(targetComponents[section]) ? targetComponents[section] : undefined, isRecord(sourceComponents[section]) ? sourceComponents[section] : undefined, policy, `components.${section}`);
|
|
113
|
+
}
|
|
114
|
+
result.components = mergedComponents;
|
|
115
|
+
result.tags = mergeTags(result.tags, sourceDocument.tags, policy);
|
|
116
|
+
result.servers = mergeServers(result.servers, sourceDocument.servers, policy);
|
|
117
|
+
return result;
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=OpenApiMerge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"OpenApiMerge.js","sourceRoot":"","sources":["../../src/openapi/OpenApiMerge.ts"],"names":[],"mappings":"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","sourcesContent":["import type { OpenAPIObject } from \"@nestjs/swagger\";\n\n/** Politica di risoluzione quando due documenti definiscono la stessa chiave. */\nexport type OpenApiMergeConflictPolicy = \"error\" | \"keep\" | \"overwrite\";\n\nexport interface MergeOpenApiOptions {\n /** Default: `error`. */\n conflict?: OpenApiMergeConflictPolicy;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction cloneDocument(document: OpenAPIObject): Record<string, unknown> {\n return JSON.parse(JSON.stringify(document)) as Record<string, unknown>;\n}\n\nfunction sameValue(left: unknown, right: unknown): boolean {\n return JSON.stringify(left) === JSON.stringify(right);\n}\n\nfunction mergeRecord(\n target: Record<string, unknown> | undefined,\n source: Record<string, unknown> | undefined,\n policy: OpenApiMergeConflictPolicy,\n section: string,\n): Record<string, unknown> | undefined {\n if (!source) return target;\n const merged: Record<string, unknown> = { ...(target ?? {}) };\n\n for (const [key, value] of Object.entries(source)) {\n if (!(key in merged)) {\n merged[key] = value;\n continue;\n }\n if (sameValue(merged[key], value)) continue;\n if (policy === \"keep\") continue;\n if (policy === \"overwrite\") {\n merged[key] = value;\n continue;\n }\n throw new Error(`Conflitto OpenAPI in ${section}.${key}.`);\n }\n\n return merged;\n}\n\nfunction mergeTags(\n target: unknown,\n source: unknown,\n policy: OpenApiMergeConflictPolicy,\n): unknown {\n if (!Array.isArray(target) || !Array.isArray(source)) return target ?? source;\n const merged = [...target];\n for (const tag of source) {\n if (!isRecord(tag) || typeof tag.name !== \"string\") {\n merged.push(tag);\n continue;\n }\n const existingIndex = merged.findIndex(\n (candidate) => isRecord(candidate) && candidate.name === tag.name,\n );\n if (existingIndex < 0) {\n merged.push(tag);\n continue;\n }\n const existing = merged[existingIndex];\n if (sameValue(existing, tag)) continue;\n if (policy === \"keep\") continue;\n if (policy === \"overwrite\") {\n merged[existingIndex] = tag;\n continue;\n }\n throw new Error(`Conflitto OpenAPI nel tag \"${tag.name}\".`);\n }\n return merged;\n}\n\nfunction mergeServers(\n target: unknown,\n source: unknown,\n policy: OpenApiMergeConflictPolicy,\n): unknown {\n if (!Array.isArray(target) || !Array.isArray(source)) return target ?? source;\n const merged = [...target];\n for (const server of source) {\n if (!isRecord(server) || typeof server.url !== \"string\") {\n merged.push(server);\n continue;\n }\n const existingIndex = merged.findIndex(\n (candidate) => isRecord(candidate) && candidate.url === server.url,\n );\n if (existingIndex < 0) {\n merged.push(server);\n continue;\n }\n const existing = merged[existingIndex];\n if (sameValue(existing, server)) continue;\n if (policy === \"keep\") continue;\n if (policy === \"overwrite\") {\n merged[existingIndex] = server;\n continue;\n }\n throw new Error(`Conflitto OpenAPI nel server \"${server.url}\".`);\n }\n return merged;\n}\n\n/**\n * Unisce il documento Accessi nel documento OpenAPI dell'host.\n *\n * Per default un conflitto su path, schema o security scheme produce errore:\n * e meglio accorgersi subito di due contratti incompatibili. Usare\n * `conflict: \"overwrite\"` solo quando il documento host deve vincere.\n */\nexport function mergeOpenApiDocuments(\n target: OpenAPIObject,\n source: OpenAPIObject,\n options: MergeOpenApiOptions = {},\n): OpenAPIObject {\n if (!target || !source) {\n throw new Error(\"mergeOpenApiDocuments richiede due documenti OpenAPI validi.\");\n }\n\n const policy = options.conflict ?? \"error\";\n const result = cloneDocument(target);\n const sourceDocument = source as unknown as Record<string, unknown>;\n\n result.paths = mergeRecord(\n isRecord(result.paths) ? result.paths : undefined,\n isRecord(sourceDocument.paths) ? sourceDocument.paths : undefined,\n policy,\n \"paths\",\n );\n\n const targetComponents = isRecord(result.components) ? result.components : {};\n const sourceComponents = isRecord(sourceDocument.components) ? sourceDocument.components : {};\n const componentSections = new Set([\n ...Object.keys(targetComponents),\n ...Object.keys(sourceComponents),\n ]);\n const mergedComponents: Record<string, unknown> = { ...targetComponents };\n for (const section of componentSections) {\n mergedComponents[section] = mergeRecord(\n isRecord(targetComponents[section]) ? targetComponents[section] : undefined,\n isRecord(sourceComponents[section]) ? sourceComponents[section] : undefined,\n policy,\n `components.${section}`,\n );\n }\n result.components = mergedComponents;\n\n result.tags = mergeTags(result.tags, sourceDocument.tags, policy);\n result.servers = mergeServers(result.servers, sourceDocument.servers, policy);\n\n return result as unknown as OpenAPIObject;\n}\n"]}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# Gateway rate limit per Accessi Service
|
|
2
|
+
|
|
3
|
+
Il rate limit applicativo di Accessi protegge login, 2FA, reset password, console entry e service token. Il gateway/API gateway resta utile per una protezione per IP, connessioni e bot prima che la richiesta raggiunga Node.
|
|
4
|
+
|
|
5
|
+
Regole consigliate:
|
|
6
|
+
|
|
7
|
+
- `/api/accessi/auth/*`: soglia bassa, burst contenuto
|
|
8
|
+
- `/api/accessi/console/entry/exchange`: soglia bassa
|
|
9
|
+
- `/api/accessi/*`: soglia media
|
|
10
|
+
- `/accessi/openapi*` e `/accessi/.well-known/jwks.json`: soglia alta o cache CDN
|
|
11
|
+
|
|
12
|
+
## Nginx
|
|
13
|
+
|
|
14
|
+
```nginx
|
|
15
|
+
limit_req_zone $binary_remote_addr zone=accessi_auth:10m rate=2r/s;
|
|
16
|
+
limit_req_zone $binary_remote_addr zone=accessi_api:10m rate=10r/s;
|
|
17
|
+
limit_conn_zone $binary_remote_addr zone=accessi_conn:10m;
|
|
18
|
+
|
|
19
|
+
server {
|
|
20
|
+
# Se Accessi e dietro un proxy/load balancer, configura real_ip
|
|
21
|
+
# prima di usare $binary_remote_addr.
|
|
22
|
+
|
|
23
|
+
location /api/accessi/auth/ {
|
|
24
|
+
limit_req zone=accessi_auth burst=10 nodelay;
|
|
25
|
+
limit_conn accessi_conn 20;
|
|
26
|
+
proxy_pass http://accessi_service;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
location /api/accessi/ {
|
|
30
|
+
limit_req zone=accessi_api burst=50 nodelay;
|
|
31
|
+
limit_conn accessi_conn 20;
|
|
32
|
+
proxy_pass http://accessi_service;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
location /accessi/ {
|
|
36
|
+
limit_req zone=accessi_api burst=50 nodelay;
|
|
37
|
+
proxy_pass http://accessi_service;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Traefik
|
|
43
|
+
|
|
44
|
+
```yaml
|
|
45
|
+
http:
|
|
46
|
+
middlewares:
|
|
47
|
+
accessi-auth-ratelimit:
|
|
48
|
+
rateLimit:
|
|
49
|
+
average: 2
|
|
50
|
+
burst: 10
|
|
51
|
+
period: 1s
|
|
52
|
+
accessi-api-ratelimit:
|
|
53
|
+
rateLimit:
|
|
54
|
+
average: 10
|
|
55
|
+
burst: 50
|
|
56
|
+
period: 1s
|
|
57
|
+
routers:
|
|
58
|
+
accessi-auth:
|
|
59
|
+
rule: PathPrefix(`/api/accessi/auth/`)
|
|
60
|
+
middlewares: [accessi-auth-ratelimit]
|
|
61
|
+
service: accessi
|
|
62
|
+
accessi-api:
|
|
63
|
+
rule: PathPrefix(`/api/accessi/`) || PathPrefix(`/accessi/`)
|
|
64
|
+
middlewares: [accessi-api-ratelimit]
|
|
65
|
+
service: accessi
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Cloudflare
|
|
69
|
+
|
|
70
|
+
Regole di rate limiting:
|
|
71
|
+
|
|
72
|
+
- path `/api/accessi/auth/*`: 10 richieste/minuto per IP, azione `managed challenge`
|
|
73
|
+
- path `/api/accessi/console/entry/exchange`: 30 richieste/5 minuti per IP
|
|
74
|
+
- path `/api/accessi/*`: 300 richieste/minuto per IP, azione `block`
|
|
75
|
+
- path `/accessi/.well-known/jwks.json`: cache CDN, limite alto
|
|
76
|
+
|
|
77
|
+
Aggiungere bot fight mode/WAF secondo il piano disponibile.
|
|
78
|
+
|
|
79
|
+
## AWS WAF / API Gateway
|
|
80
|
+
|
|
81
|
+
- rate-based rule: 300 richieste/5 minuti per IP
|
|
82
|
+
- scope-down statement: `URI starts with /api/accessi`
|
|
83
|
+
- regola più severa su `/api/accessi/auth/*`
|
|
84
|
+
- AWS Shield/WAF Bot Control se disponibile
|
|
85
|
+
|
|
86
|
+
## Rapporto con `edgeRateLimit` della libreria
|
|
87
|
+
|
|
88
|
+
`edgeRateLimit` e un ultimo livello applicativo:
|
|
89
|
+
|
|
90
|
+
- usa lo stesso `RateLimitStore` Redis dei rate limit per account;
|
|
91
|
+
- copre Accessi anche se il gateway non ha regole specifiche;
|
|
92
|
+
- non sostituisce WAF, bot protection, limiti di connessione o protezione DDoS.
|
|
93
|
+
|
|
94
|
+
In produzione usare entrambi:
|
|
95
|
+
|
|
96
|
+
```text
|
|
97
|
+
Client -> CDN/WAF -> API gateway -> edgeRateLimit Accessi -> rate limit per account
|
|
98
|
+
```
|