zuplo 6.70.69 → 6.70.71
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/docs/ai-gateway/getting-started.mdx +14 -9
- package/docs/ai-gateway/integrations/ai-sdk.mdx +17 -0
- package/docs/ai-gateway/introduction.mdx +12 -10
- package/docs/ai-gateway/providers.mdx +2 -0
- package/docs/analytics/access-and-entitlements.md +71 -0
- package/docs/analytics/overview.md +63 -0
- package/docs/analytics/reference/metrics-glossary.md +105 -0
- package/docs/analytics/reference/url-parameters.md +66 -0
- package/docs/analytics/shared-controls.md +121 -0
- package/docs/analytics/tabs/agents.md +88 -0
- package/docs/analytics/tabs/consumers.md +73 -0
- package/docs/analytics/tabs/graphql.md +77 -0
- package/docs/analytics/tabs/mcp.md +80 -0
- package/docs/analytics/tabs/origins.md +82 -0
- package/docs/analytics/tabs/requests.md +96 -0
- package/docs/articles/api-key-buckets.mdx +4 -2
- package/docs/articles/archiving-requests-to-storage.mdx +4 -4
- package/docs/articles/branch-based-deployments.mdx +10 -8
- package/docs/articles/ci-cd-github/basic-deployment.mdx +10 -1
- package/docs/articles/ci-cd-github/cleanup-on-branch-delete.mdx +52 -31
- package/docs/articles/ci-cd-github/deploy-and-test.mdx +14 -1
- package/docs/articles/ci-cd-github/local-testing.mdx +3 -1
- package/docs/articles/ci-cd-github/pr-preview-environments.mdx +53 -10
- package/docs/articles/custom-ci-cd-azure.mdx +1 -1
- package/docs/articles/custom-ci-cd-bitbucket.mdx +1 -1
- package/docs/articles/custom-ci-cd-circleci.mdx +1 -1
- package/docs/articles/custom-ci-cd-github.mdx +12 -3
- package/docs/articles/custom-ci-cd-gitlab.mdx +1 -1
- package/docs/articles/graphql.mdx +276 -0
- package/docs/articles/monetization/api-access.mdx +184 -0
- package/docs/articles/monetization/meters.mdx +4 -4
- package/docs/articles/monetization/monetization-policy.md +4 -1
- package/docs/articles/monetization/private-plans.md +3 -4
- package/docs/articles/monetization/stripe-integration.md +9 -0
- package/docs/articles/monetization/subscription-lifecycle.md +12 -11
- package/docs/articles/monorepo-deployment.mdx +37 -5
- package/docs/articles/opentelemetry.mdx +5 -2
- package/docs/articles/securing-the-gateway-with-client-mtls.mdx +68 -43
- package/docs/articles/step-1-setup-basic-gateway.mdx +1 -3
- package/docs/articles/step-2-add-rate-limiting.mdx +1 -1
- package/docs/articles/testing.mdx +1 -1
- package/docs/articles/troubleshooting.md +7 -3
- package/docs/articles/waf-ddos-akamai.md +35 -16
- package/docs/articles/waf-ddos-aws-waf-shield.mdx +35 -16
- package/docs/articles/waf-ddos-fastly.mdx +10 -7
- package/docs/cli/deploy.mdx +44 -9
- package/docs/cli/deploy.partial.mdx +44 -9
- package/docs/concepts/api-keys.md +2 -2
- package/docs/dev-portal/zudoku/components/callout.mdx +11 -18
- package/docs/dev-portal/zudoku/components/sidecar-box.mdx +131 -0
- package/docs/dev-portal/zudoku/configuration/api-catalog.md +62 -42
- package/docs/dev-portal/zudoku/configuration/api-reference.md +5 -4
- package/docs/dev-portal/zudoku/configuration/navigation.mdx +70 -7
- package/docs/dev-portal/zudoku/configuration/search.md +36 -0
- package/docs/dev-portal/zudoku/configuration/site.md +38 -0
- package/docs/dev-portal/zudoku/customization/colors-theme.mdx +51 -40
- package/docs/errors/rate-limit-exceeded.mdx +30 -3
- package/docs/guides/canary-routing-for-employees.mdx +103 -39
- package/docs/guides/modify-openapi-paths.mdx +3 -3
- package/docs/handlers/legacy-dev-portal-handler.mdx +1 -1
- package/docs/handlers/mcp-server.mdx +13 -11
- package/docs/handlers/url-forward.mdx +5 -1
- package/docs/handlers/url-rewrite.mdx +7 -2
- package/docs/handlers/websocket-handler.mdx +5 -1
- package/docs/mcp-gateway/observability/logging.mdx +19 -12
- package/docs/mcp-server/resources.mdx +27 -15
- package/docs/mcp-server/testing.mdx +0 -2
- package/docs/policies/_index.md +2 -0
- package/docs/policies/archive-request-azure-storage-inbound/doc.md +1 -1
- package/docs/policies/archive-response-azure-storage-outbound/doc.md +1 -1
- package/docs/policies/data-loss-prevention-inbound/doc.md +116 -0
- package/docs/policies/data-loss-prevention-inbound/intro.md +15 -0
- package/docs/policies/data-loss-prevention-inbound/schema.json +220 -0
- package/docs/policies/data-loss-prevention-outbound/doc.md +116 -0
- package/docs/policies/data-loss-prevention-outbound/intro.md +18 -0
- package/docs/policies/data-loss-prevention-outbound/schema.json +220 -0
- package/docs/policies/ip-restriction-inbound/policy.ts +1 -1
- package/docs/programmable-api/background-dispatcher.mdx +6 -8
- package/docs/programmable-api/http-problems.mdx +0 -18
- package/docs/programmable-api/jwt-service-plugin.mdx +131 -109
- package/docs/programmable-api/runtime-behaviors.mdx +4 -2
- package/docs/programmable-api/streaming-zone-cache.mdx +4 -6
- package/docs/programmable-api/web-crypto-apis.mdx +10 -6
- package/docs/programmable-api/zone-cache.mdx +1 -1
- package/docs/rate-limiting/combining-policies.mdx +293 -0
- package/docs/rate-limiting/dynamic-rate-limiting.mdx +240 -0
- package/docs/rate-limiting/getting-started.mdx +339 -0
- package/docs/rate-limiting/how-it-works.md +225 -0
- package/docs/rate-limiting/monitoring-and-troubleshooting.mdx +243 -0
- package/docs/{articles → rate-limiting}/per-user-rate-limits-using-db.mdx +39 -28
- package/package.json +4 -4
- package/docs/concepts/rate-limiting.md +0 -246
- package/docs/errors/get-head-body-error.mdx +0 -41
|
@@ -141,33 +141,40 @@ structured entries described above with their `event` field preserved.
|
|
|
141
141
|
Registering both plugins is a small addition to `modules/zuplo.runtime.ts`:
|
|
142
142
|
|
|
143
143
|
```ts title="modules/zuplo.runtime.ts"
|
|
144
|
-
import {
|
|
144
|
+
import { OpenTelemetryPlugin } from "@zuplo/otel";
|
|
145
|
+
import { environment, RuntimeExtensions } from "@zuplo/runtime";
|
|
145
146
|
import { McpGatewayPlugin } from "@zuplo/runtime/mcp-gateway";
|
|
146
|
-
import { OpenTelemetryPlugin } from "@zuplo/runtime";
|
|
147
147
|
|
|
148
148
|
export function runtimeInit(runtime: RuntimeExtensions) {
|
|
149
149
|
runtime.addPlugin(new McpGatewayPlugin());
|
|
150
150
|
runtime.addPlugin(
|
|
151
151
|
new OpenTelemetryPlugin({
|
|
152
|
-
|
|
153
|
-
logUrl:
|
|
154
|
-
|
|
152
|
+
traceUrl: environment.OTLP_TRACES_ENDPOINT,
|
|
153
|
+
logUrl: environment.OTLP_LOGS_ENDPOINT,
|
|
154
|
+
headers: {
|
|
155
|
+
Authorization: environment.OTLP_AUTHORIZATION,
|
|
156
|
+
},
|
|
157
|
+
service: {
|
|
158
|
+
name: "mcp-gateway",
|
|
159
|
+
},
|
|
155
160
|
}),
|
|
156
161
|
);
|
|
157
162
|
}
|
|
158
163
|
```
|
|
159
164
|
|
|
160
|
-
|
|
161
|
-
|
|
165
|
+
Logs are only exported when `logUrl` is set alongside `traceUrl` — configuring
|
|
166
|
+
only `exporter.url` exports traces alone. Grafana Cloud is one common
|
|
167
|
+
destination — define the endpoints and credentials as
|
|
168
|
+
[environment variables](../../articles/environment-variables.mdx):
|
|
162
169
|
|
|
163
170
|
```bash
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
171
|
+
OTLP_TRACES_ENDPOINT=https://otlp-gateway-prod-<region>.grafana.net/otlp/v1/traces
|
|
172
|
+
OTLP_LOGS_ENDPOINT=https://otlp-gateway-prod-<region>.grafana.net/otlp/v1/logs
|
|
173
|
+
OTLP_AUTHORIZATION=Basic <base64 of instance-id:api-token>
|
|
167
174
|
```
|
|
168
175
|
|
|
169
|
-
|
|
170
|
-
`/v1/traces` and `/v1/logs`
|
|
176
|
+
The plugin sends OTLP data to the configured URLs exactly as given, so include
|
|
177
|
+
the full `/v1/traces` and `/v1/logs` paths. Other OTLP-compatible destinations
|
|
171
178
|
(Honeycomb, Dynatrace, New Relic, Tempo, self-hosted Jaeger) work the same way;
|
|
172
179
|
substitute the endpoint and credential headers.
|
|
173
180
|
|
|
@@ -191,27 +191,36 @@ Response:
|
|
|
191
191
|
"result": {
|
|
192
192
|
"resources": [
|
|
193
193
|
{
|
|
194
|
-
"name": "
|
|
195
|
-
"uri": "
|
|
196
|
-
"title": "
|
|
197
|
-
"description": "
|
|
198
|
-
"mimeType": "text/
|
|
194
|
+
"name": "html_doc",
|
|
195
|
+
"uri": "ui://html",
|
|
196
|
+
"title": "html_doc",
|
|
197
|
+
"description": "The HTML document for the AI applet",
|
|
198
|
+
"mimeType": "text/html"
|
|
199
199
|
},
|
|
200
200
|
{
|
|
201
|
-
"name": "
|
|
202
|
-
"uri": "
|
|
203
|
-
"title": "
|
|
204
|
-
"description": "
|
|
205
|
-
"mimeType": "text/
|
|
201
|
+
"name": "css",
|
|
202
|
+
"uri": "mcp://resources/css",
|
|
203
|
+
"title": "css",
|
|
204
|
+
"description": "Returns the AI applet's CSS",
|
|
205
|
+
"mimeType": "text/plain"
|
|
206
206
|
}
|
|
207
207
|
]
|
|
208
208
|
}
|
|
209
209
|
}
|
|
210
210
|
```
|
|
211
211
|
|
|
212
|
+
The `html_doc` resource uses the custom `name`, `uri`, `description`, and
|
|
213
|
+
`mimeType` from the route configuration shown earlier. The `css` resource sets
|
|
214
|
+
only `"mcp": { "type": "resource" }`, so the defaults apply: the name comes from
|
|
215
|
+
the `operationId`, the URI defaults to `mcp://resources/{name}`, the description
|
|
216
|
+
falls back to the operation's `description`, and the MIME type defaults to
|
|
217
|
+
`text/plain`.
|
|
218
|
+
|
|
212
219
|
### Read a Resource
|
|
213
220
|
|
|
214
|
-
Use the MCP `resources/read` method to read a resource by its URI
|
|
221
|
+
Use the MCP `resources/read` method to read a resource by its URI. Resources
|
|
222
|
+
configured without a custom `uri` use the default `mcp://resources/{name}`
|
|
223
|
+
format:
|
|
215
224
|
|
|
216
225
|
```bash
|
|
217
226
|
curl https://my-gateway.zuplo.dev/mcp \
|
|
@@ -222,7 +231,7 @@ curl https://my-gateway.zuplo.dev/mcp \
|
|
|
222
231
|
"id": "0",
|
|
223
232
|
"method": "resources/read",
|
|
224
233
|
"params": {
|
|
225
|
-
"uri": "mcp://resources/
|
|
234
|
+
"uri": "mcp://resources/css"
|
|
226
235
|
}
|
|
227
236
|
}'
|
|
228
237
|
```
|
|
@@ -236,9 +245,9 @@ Response:
|
|
|
236
245
|
"result": {
|
|
237
246
|
"contents": [
|
|
238
247
|
{
|
|
239
|
-
"uri": "mcp://resources/
|
|
248
|
+
"uri": "mcp://resources/css",
|
|
240
249
|
"mimeType": "text/plain",
|
|
241
|
-
"text": "
|
|
250
|
+
"text": "div { color: blue; }"
|
|
242
251
|
}
|
|
243
252
|
]
|
|
244
253
|
}
|
|
@@ -247,6 +256,9 @@ Response:
|
|
|
247
256
|
|
|
248
257
|
### Read a Resource with Custom URI
|
|
249
258
|
|
|
259
|
+
Resources configured with a custom `uri`, like the `html_doc` resource above,
|
|
260
|
+
are read using that URI:
|
|
261
|
+
|
|
250
262
|
```bash
|
|
251
263
|
curl https://my-gateway.zuplo.dev/mcp \
|
|
252
264
|
-X POST \
|
|
@@ -256,7 +268,7 @@ curl https://my-gateway.zuplo.dev/mcp \
|
|
|
256
268
|
"id": "0",
|
|
257
269
|
"method": "resources/read",
|
|
258
270
|
"params": {
|
|
259
|
-
"uri": "ui://
|
|
271
|
+
"uri": "ui://html"
|
|
260
272
|
}
|
|
261
273
|
}'
|
|
262
274
|
```
|
package/docs/policies/_index.md
CHANGED
|
@@ -37,6 +37,8 @@
|
|
|
37
37
|
| curity-phantom-token-inbound | Curity Phantom Token Auth | Authenticate users using the Curity Phantom Token Pattern. | api-gateway |
|
|
38
38
|
| custom-code-inbound | Custom Code Inbound | Enables a custom code policy written in TypeScript. Change YOUR_MODULE to the name of your module (without .ts extension) | api-gateway |
|
|
39
39
|
| custom-code-outbound | Custom Code Outbound | A custom outbound response policy. | api-gateway |
|
|
40
|
+
| data-loss-prevention-outbound | Data Loss Prevention | Scans the upstream response body for sensitive data — PII, secrets, and financial identifiers — using an extensible catalog of built-in recognizers plus any custom patterns, and takes a configurable action when a match is found. The action is one of `mask` (redact matches before returning the response), `block` (replace the response with a `422` listing the detected entity names only), or `log` (record a warning and return unchanged). Only text content types are inspected; binary bodies pass through untouched, and the body is read from a clone so the client still receives the original stream. | api-gateway |
|
|
41
|
+
| data-loss-prevention-inbound | Data Loss Prevention | Scans the incoming request body for sensitive data — PII, secrets, and financial identifiers — using an extensible catalog of built-in recognizers plus any custom patterns, and takes a configurable action when a match is found. The action is one of `mask` (redact matches before forwarding the request), `block` (reject with a `422` listing the detected entity names only), or `log` (record a warning and forward unchanged). Only text content types are inspected; binary bodies pass through untouched, and the body is read from a clone so the upstream still receives the original stream. | api-gateway |
|
|
40
42
|
| firebase-jwt-inbound | Firebase JWT Auth | Authenticate users using Firebase issued JWT tokens. | api-gateway |
|
|
41
43
|
| formdata-to-json-inbound | Form Data to JSON | Converts form data in the incoming request to JSON. | api-gateway |
|
|
42
44
|
| galileo-tracing-inbound | Galileo Tracing | Galileo Tracing Inbound Policy | ai-gateway |
|
|
@@ -20,7 +20,7 @@ can generate one of these on the `Shared access tokens` tab.
|
|
|
20
20
|
Note, you should minimize the permissions - and select only the `Create`
|
|
21
21
|
permission. Choose a sensible start and expiration time for your token. Note, we
|
|
22
22
|
don't recommend restricting IP addresses because Zuplo runs at the edge in over
|
|
23
|
-
|
|
23
|
+
300 data centers worldwide.
|
|
24
24
|
|
|
25
25
|

|
|
26
26
|
|
|
@@ -20,7 +20,7 @@ can generate one of these on the `Shared access tokens` tab.
|
|
|
20
20
|
Note, you should minimize the permissions - and select only the `Create`
|
|
21
21
|
permission. Choose a sensible start and expiration time for your token. Note, we
|
|
22
22
|
don't recommend restricting IP addresses because Zuplo runs at the edge in over
|
|
23
|
-
|
|
23
|
+
300 data centers worldwide.
|
|
24
24
|
|
|
25
25
|

|
|
26
26
|
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
This policy inspects the body of each incoming request for sensitive data and
|
|
2
|
+
applies a configurable action. It is the inbound counterpart to the
|
|
3
|
+
[Data Loss Prevention - Outbound](/docs/policies/data-loss-prevention-outbound)
|
|
4
|
+
policy, which inspects upstream responses.
|
|
5
|
+
|
|
6
|
+
Detection happens entirely inside the gateway isolate — request bodies are never
|
|
7
|
+
sent to a third-party service.
|
|
8
|
+
|
|
9
|
+
## Actions
|
|
10
|
+
|
|
11
|
+
- **`mask`** (default) — every detected value is replaced with the `mask` string
|
|
12
|
+
and the modified body is forwarded upstream. Overlapping matches are merged
|
|
13
|
+
and masked once.
|
|
14
|
+
- **`block`** — the request is rejected with a `422 Unprocessable Content`. The
|
|
15
|
+
problem detail lists only the names of the detected entities, never the
|
|
16
|
+
matched values, so the policy never leaks the data it caught.
|
|
17
|
+
- **`log`** — a structured warning is written (entity ids and counts only) and
|
|
18
|
+
the request is forwarded unchanged.
|
|
19
|
+
|
|
20
|
+
## Built-in recognizers
|
|
21
|
+
|
|
22
|
+
Enable entities individually or by **group selector** in the `entities`
|
|
23
|
+
option, or omit it to use the full catalog. Entity ids follow a
|
|
24
|
+
`{category}-{scope}-{name}` taxonomy, and any dash-aligned prefix of an id is a
|
|
25
|
+
valid selector: `secret` enables every secret, `id-au` enables Australia's
|
|
26
|
+
identifiers, `secret-aws` enables both AWS entities. Two named groups (`pii`,
|
|
27
|
+
`region-eu`) bundle entities across categories.
|
|
28
|
+
|
|
29
|
+
| Group | Entities |
|
|
30
|
+
| ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
31
|
+
| `secret` | `secret-private-key`, `secret-jwt`, `secret-aws-access-key`, `secret-aws-bedrock`, `secret-github`, `secret-gitlab`, `secret-zuplo`, `secret-openai`, `secret-anthropic`, `secret-google-api-key`, `secret-stripe`, `secret-slack`, `secret-discord-webhook`, `secret-npm`, `secret-pypi`, `secret-sendgrid`, `secret-twilio`, `secret-hugging-face`, `secret-databricks`, `secret-shopify`, `secret-square`, `secret-mailchimp`, `secret-mailgun`, `secret-postman`, `secret-terraform`, `secret-sentry`, `secret-digitalocean`, `secret-heroku`, `secret-perplexity`, `secret-azure-client`, `secret-telegram-bot` |
|
|
32
|
+
| `finance` | `finance-credit-card` (Luhn), `finance-iban` (per-country length + mod-97), `finance-crypto-wallet`, `finance-us-aba-routing` (checksum), `finance-swift-bic`, `finance-us-bank-account`, `finance-cvv` |
|
|
33
|
+
| `id` | `id-us-ssn`, `id-us-itin`, `id-us-passport`, `id-uk-nino`, `id-uk-nhs` (mod-11), `id-ca-sin` (Luhn), `id-au-abn`, `id-au-acn`, `id-au-tfn`, `id-au-medicare` (all checksummed), `id-in-aadhaar` (Verhoeff), `id-in-pan`, `id-sg-nric` (checksum), `id-es-nif` (checksum), `id-it-fiscal-code` (checksum), `id-pl-pesel` (checksum), `id-nl-bsn` (11-proef), `id-br-cpf` (checksum), `id-fr-nir` (mod-97) |
|
|
34
|
+
| `contact` | `contact-email`, `contact-phone` |
|
|
35
|
+
| `network` | `network-ipv4`, `network-ipv6`, `network-mac` |
|
|
36
|
+
| `pii` | `contact` + `id` |
|
|
37
|
+
| Prefixes | `id-us`, `id-uk`, `id-au`, `id-ca`, `id-in`, `id-sg`, `id-es`, `id-it`, `id-pl`, `id-nl`, `id-br`, `id-fr`, `finance-us`, `secret-aws` — everything whose id starts with that prefix |
|
|
38
|
+
| `region-eu` | `id-es-nif`, `id-it-fiscal-code`, `id-pl-pesel`, `id-nl-bsn`, `id-fr-nir`, `finance-iban` |
|
|
39
|
+
|
|
40
|
+
## Context-word scoring
|
|
41
|
+
|
|
42
|
+
Every match gets a confidence score. Recognizers whose raw pattern is just "a
|
|
43
|
+
run of digits" (bank accounts, routing numbers, NHS numbers, …) carry a low
|
|
44
|
+
base confidence and a list of **context words**; when one of those words
|
|
45
|
+
appears near the match — in prose, or in a JSON key, form field, or header-like
|
|
46
|
+
label (`nhsNumber`, `routing_number`, `cvv:`) — the confidence is boosted above
|
|
47
|
+
the detection threshold.
|
|
48
|
+
|
|
49
|
+
For example, with the `id-uk-nhs` entity enabled, `{"nhsNumber": "9434765919"}` is
|
|
50
|
+
masked while the same digits in `{"orderId": "9434765919"}` pass through
|
|
51
|
+
untouched.
|
|
52
|
+
|
|
53
|
+
The threshold is configurable via `minConfidence` (default `0.5`): lower it to
|
|
54
|
+
detect context-dependent entities everywhere, raise it to keep only prefix- and
|
|
55
|
+
checksum-validated matches.
|
|
56
|
+
|
|
57
|
+
## Custom patterns
|
|
58
|
+
|
|
59
|
+
Add your own recognizers with `customPatterns`. Each entry has a `name`, a
|
|
60
|
+
JavaScript regular expression `pattern`, and optionally a `confidence` and
|
|
61
|
+
`context` words to participate in context scoring. Invalid patterns are logged
|
|
62
|
+
and skipped rather than failing the request. Remember to escape backslashes for
|
|
63
|
+
JSON (for example `\\d` to match a digit).
|
|
64
|
+
|
|
65
|
+
## Content types
|
|
66
|
+
|
|
67
|
+
Only text-based bodies (JSON, XML, form-encoded, and `text/*`) are scanned;
|
|
68
|
+
binary bodies pass through untouched. Override the allow-list with the
|
|
69
|
+
`contentTypes` option if you need to scan a different set of content types.
|
|
70
|
+
|
|
71
|
+
## Configuration
|
|
72
|
+
|
|
73
|
+
- `engine`: The detection engine. Only `builtin` is available today. **Default:**
|
|
74
|
+
`builtin`
|
|
75
|
+
- `entities`: Recognizer ids and/or group selectors (prefixes, `pii`,
|
|
76
|
+
`region-eu`) to enable. **Default:** all
|
|
77
|
+
recognizers
|
|
78
|
+
- `customPatterns`: Additional `{ name, pattern, confidence?, context? }` regex
|
|
79
|
+
recognizers
|
|
80
|
+
- `action`: `mask`, `block`, or `log`. **Default:** `mask`
|
|
81
|
+
- `mask`: Replacement string used when `action` is `mask`. **Default:**
|
|
82
|
+
`[REDACTED]`
|
|
83
|
+
- `minConfidence`: Detection threshold (0-1). **Default:** `0.5`
|
|
84
|
+
- `contentTypes`: Override the scannable content-type allow-list
|
|
85
|
+
|
|
86
|
+
## Usage
|
|
87
|
+
|
|
88
|
+
Apply this policy to inbound requests in your route configuration:
|
|
89
|
+
|
|
90
|
+
```json
|
|
91
|
+
{
|
|
92
|
+
"policies": [
|
|
93
|
+
{
|
|
94
|
+
"name": "data-loss-prevention-inbound",
|
|
95
|
+
"policyType": "data-loss-prevention-inbound",
|
|
96
|
+
"handler": {
|
|
97
|
+
"export": "DataLossPreventionInboundPolicy",
|
|
98
|
+
"module": "$import(@zuplo/runtime)",
|
|
99
|
+
"options": {
|
|
100
|
+
"action": "mask",
|
|
101
|
+
"entities": ["secret", "finance", "id-us", "contact-email"],
|
|
102
|
+
"mask": "[REDACTED]",
|
|
103
|
+
"customPatterns": [
|
|
104
|
+
{
|
|
105
|
+
"name": "employee-id",
|
|
106
|
+
"pattern": "EMP-\\d{6}",
|
|
107
|
+
"confidence": 0.3,
|
|
108
|
+
"context": ["employee"]
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
The Data Loss Prevention (DLP) policy scans incoming request bodies for
|
|
2
|
+
sensitive data — personally identifiable information (PII), secrets and API
|
|
3
|
+
keys for dozens of vendors, payment and bank identifiers, and national IDs for
|
|
4
|
+
many countries — using a catalog of 60+ built-in recognizers plus any custom
|
|
5
|
+
patterns you add. When a match is found it takes a configurable action: mask
|
|
6
|
+
the matches, block the request, or log a warning and let it through.
|
|
7
|
+
|
|
8
|
+
Recognizers are selected individually or via entity groups (`secret`,
|
|
9
|
+
`finance`, `pii`, `id-us`, `id-uk`, `region-eu`, …). Detection runs entirely in the
|
|
10
|
+
gateway isolate using regular expressions, checksums (Luhn, mod-97, Verhoeff,
|
|
11
|
+
and friends), and context-word scoring — no request data leaves the gateway.
|
|
12
|
+
|
|
13
|
+
Pair with the
|
|
14
|
+
[Data Loss Prevention - Outbound](/docs/policies/data-loss-prevention-outbound)
|
|
15
|
+
policy to also scan upstream responses before they're returned to the client.
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft-07/schema",
|
|
3
|
+
"$id": "https://cdn.zuplo.com/policies/runtime/schemas/data-loss-prevention-inbound.json",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"title": "Data Loss Prevention",
|
|
6
|
+
"isDeprecated": false,
|
|
7
|
+
"isPaidAddOn": false,
|
|
8
|
+
"isEnterprise": false,
|
|
9
|
+
"isInternal": false,
|
|
10
|
+
"isBeta": false,
|
|
11
|
+
"isHidden": false,
|
|
12
|
+
"requiresAI": false,
|
|
13
|
+
"products": ["api-gateway"],
|
|
14
|
+
"description": "Scans the incoming request body for sensitive data — PII, secrets, and financial identifiers — using an extensible catalog of built-in recognizers plus any custom patterns, and takes a configurable action when a match is found.\n\nThe action is one of `mask` (redact matches before forwarding the request), `block` (reject with a `422` listing the detected entity names only), or `log` (record a warning and forward unchanged). Only text content types are inspected; binary bodies pass through untouched, and the body is read from a clone so the upstream still receives the original stream.",
|
|
15
|
+
"deprecatedMessage": "",
|
|
16
|
+
"required": ["handler"],
|
|
17
|
+
"properties": {
|
|
18
|
+
"handler": {
|
|
19
|
+
"type": "object",
|
|
20
|
+
"default": {},
|
|
21
|
+
"required": ["export", "module", "options"],
|
|
22
|
+
"properties": {
|
|
23
|
+
"export": {
|
|
24
|
+
"const": "DataLossPreventionInboundPolicy",
|
|
25
|
+
"description": "The name of the exported type"
|
|
26
|
+
},
|
|
27
|
+
"module": {
|
|
28
|
+
"const": "$import(@zuplo/runtime)",
|
|
29
|
+
"description": "The module containing the policy"
|
|
30
|
+
},
|
|
31
|
+
"options": {
|
|
32
|
+
"title": "DataLossPreventionInboundPolicyOptions",
|
|
33
|
+
"type": "object",
|
|
34
|
+
"description": "The options for the Data Loss Prevention inbound policy. Scans the incoming request body for sensitive data and applies the configured action (mask, block, or log).",
|
|
35
|
+
"additionalProperties": false,
|
|
36
|
+
"required": [],
|
|
37
|
+
"examples": [
|
|
38
|
+
{
|
|
39
|
+
"action": "mask",
|
|
40
|
+
"entities": ["secret", "finance", "contact-email", "id-us-ssn"],
|
|
41
|
+
"mask": "[REDACTED]"
|
|
42
|
+
}
|
|
43
|
+
],
|
|
44
|
+
"properties": {
|
|
45
|
+
"engine": {
|
|
46
|
+
"type": "string",
|
|
47
|
+
"enum": ["builtin"],
|
|
48
|
+
"default": "builtin",
|
|
49
|
+
"description": "The detection engine. Only `builtin` (in-isolate regex + checksum detection with context-word scoring) is available today. This is the extension point for a future hosted `presidio-service` mode; declaring it now keeps adding that mode an additive, non-breaking change."
|
|
50
|
+
},
|
|
51
|
+
"entities": {
|
|
52
|
+
"type": "array",
|
|
53
|
+
"description": "Built-in recognizer ids and/or group selectors to enable. Entity ids follow a {category}-{scope}-{name} taxonomy, and any dash-aligned id prefix acts as a selector (for example `secret` is every secret, `id-au` is Australia's identifiers, `secret-aws` is both AWS entities), plus the named groups `pii` and `region-eu`. Available selectors: `contact`, `finance`, `finance-us`, `id`, `id-au`, `id-br`, `id-ca`, `id-es`, `id-fr`, `id-in`, `id-it`, `id-nl`, `id-pl`, `id-sg`, `id-uk`, `id-us`, `network`, `pii`, `region-eu`, `secret`, `secret-aws`. When omitted, the full built-in catalog is used.",
|
|
54
|
+
"items": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"enum": [
|
|
57
|
+
"contact",
|
|
58
|
+
"finance",
|
|
59
|
+
"finance-us",
|
|
60
|
+
"id",
|
|
61
|
+
"id-au",
|
|
62
|
+
"id-br",
|
|
63
|
+
"id-ca",
|
|
64
|
+
"id-es",
|
|
65
|
+
"id-fr",
|
|
66
|
+
"id-in",
|
|
67
|
+
"id-it",
|
|
68
|
+
"id-nl",
|
|
69
|
+
"id-pl",
|
|
70
|
+
"id-sg",
|
|
71
|
+
"id-uk",
|
|
72
|
+
"id-us",
|
|
73
|
+
"network",
|
|
74
|
+
"pii",
|
|
75
|
+
"region-eu",
|
|
76
|
+
"secret",
|
|
77
|
+
"secret-aws",
|
|
78
|
+
"contact-email",
|
|
79
|
+
"contact-phone",
|
|
80
|
+
"finance-credit-card",
|
|
81
|
+
"finance-crypto-wallet",
|
|
82
|
+
"finance-cvv",
|
|
83
|
+
"finance-iban",
|
|
84
|
+
"finance-swift-bic",
|
|
85
|
+
"finance-us-aba-routing",
|
|
86
|
+
"finance-us-bank-account",
|
|
87
|
+
"id-au-abn",
|
|
88
|
+
"id-au-acn",
|
|
89
|
+
"id-au-medicare",
|
|
90
|
+
"id-au-tfn",
|
|
91
|
+
"id-br-cpf",
|
|
92
|
+
"id-ca-sin",
|
|
93
|
+
"id-es-nif",
|
|
94
|
+
"id-fr-nir",
|
|
95
|
+
"id-in-aadhaar",
|
|
96
|
+
"id-in-pan",
|
|
97
|
+
"id-it-fiscal-code",
|
|
98
|
+
"id-nl-bsn",
|
|
99
|
+
"id-pl-pesel",
|
|
100
|
+
"id-sg-nric",
|
|
101
|
+
"id-uk-nhs",
|
|
102
|
+
"id-uk-nino",
|
|
103
|
+
"id-us-itin",
|
|
104
|
+
"id-us-passport",
|
|
105
|
+
"id-us-ssn",
|
|
106
|
+
"network-ipv4",
|
|
107
|
+
"network-ipv6",
|
|
108
|
+
"network-mac",
|
|
109
|
+
"secret-anthropic",
|
|
110
|
+
"secret-aws-access-key",
|
|
111
|
+
"secret-aws-bedrock",
|
|
112
|
+
"secret-azure-client",
|
|
113
|
+
"secret-databricks",
|
|
114
|
+
"secret-digitalocean",
|
|
115
|
+
"secret-discord-webhook",
|
|
116
|
+
"secret-github",
|
|
117
|
+
"secret-gitlab",
|
|
118
|
+
"secret-google-api-key",
|
|
119
|
+
"secret-heroku",
|
|
120
|
+
"secret-hugging-face",
|
|
121
|
+
"secret-jwt",
|
|
122
|
+
"secret-mailchimp",
|
|
123
|
+
"secret-mailgun",
|
|
124
|
+
"secret-npm",
|
|
125
|
+
"secret-openai",
|
|
126
|
+
"secret-perplexity",
|
|
127
|
+
"secret-postman",
|
|
128
|
+
"secret-private-key",
|
|
129
|
+
"secret-pypi",
|
|
130
|
+
"secret-sendgrid",
|
|
131
|
+
"secret-sentry",
|
|
132
|
+
"secret-shopify",
|
|
133
|
+
"secret-slack",
|
|
134
|
+
"secret-square",
|
|
135
|
+
"secret-stripe",
|
|
136
|
+
"secret-telegram-bot",
|
|
137
|
+
"secret-terraform",
|
|
138
|
+
"secret-twilio",
|
|
139
|
+
"secret-zuplo"
|
|
140
|
+
]
|
|
141
|
+
}
|
|
142
|
+
},
|
|
143
|
+
"customPatterns": {
|
|
144
|
+
"type": "array",
|
|
145
|
+
"description": "Additional customer-defined regex recognizers. Invalid patterns are logged and skipped rather than failing the request.",
|
|
146
|
+
"items": {
|
|
147
|
+
"type": "object",
|
|
148
|
+
"title": "DlpCustomPattern",
|
|
149
|
+
"additionalProperties": false,
|
|
150
|
+
"required": ["name", "pattern"],
|
|
151
|
+
"properties": {
|
|
152
|
+
"name": {
|
|
153
|
+
"type": "string",
|
|
154
|
+
"description": "Identifier reported in findings and block details for this pattern."
|
|
155
|
+
},
|
|
156
|
+
"pattern": {
|
|
157
|
+
"type": "string",
|
|
158
|
+
"description": "A JavaScript regular expression source string. Remember to escape backslashes for JSON (for example `\\\\d` for a digit)."
|
|
159
|
+
},
|
|
160
|
+
"confidence": {
|
|
161
|
+
"type": "number",
|
|
162
|
+
"minimum": 0,
|
|
163
|
+
"maximum": 1,
|
|
164
|
+
"default": 0.85,
|
|
165
|
+
"description": "Base confidence (0-1) for matches of this pattern. The default of 0.85 is above the default detection threshold; combine a low value with `context` words for patterns that are only sensitive in context."
|
|
166
|
+
},
|
|
167
|
+
"context": {
|
|
168
|
+
"type": "array",
|
|
169
|
+
"items": {
|
|
170
|
+
"type": "string"
|
|
171
|
+
},
|
|
172
|
+
"description": "Context words that boost a match's confidence by 0.45 when one appears near the match (in the surrounding field, label, or key)."
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
},
|
|
177
|
+
"action": {
|
|
178
|
+
"type": "string",
|
|
179
|
+
"enum": ["mask", "block", "log"],
|
|
180
|
+
"default": "mask",
|
|
181
|
+
"description": "What to do when sensitive data is detected. `mask` redacts matches before forwarding the request, `block` rejects with a 422 listing only the detected entity names, and `log` records a warning and forwards the request unchanged."
|
|
182
|
+
},
|
|
183
|
+
"mask": {
|
|
184
|
+
"type": "string",
|
|
185
|
+
"default": "[REDACTED]",
|
|
186
|
+
"examples": ["[REDACTED]"],
|
|
187
|
+
"description": "The string that replaces detected values when `action` is `mask`."
|
|
188
|
+
},
|
|
189
|
+
"minConfidence": {
|
|
190
|
+
"type": "number",
|
|
191
|
+
"minimum": 0,
|
|
192
|
+
"maximum": 1,
|
|
193
|
+
"default": 0.5,
|
|
194
|
+
"x-show-example": false,
|
|
195
|
+
"description": "Minimum confidence (0-1) a match must reach to count as a finding. Context-dependent recognizers (for example `finance-us-bank-account` or `finance-us-aba-routing`) sit below the default threshold of 0.5 until a context word near the match boosts them above it. Lower the threshold to surface them everywhere; raise it to keep only prefix- or checksum-validated matches."
|
|
196
|
+
},
|
|
197
|
+
"contentTypes": {
|
|
198
|
+
"type": "array",
|
|
199
|
+
"description": "Override the set of scannable content-type prefixes. When omitted, the built-in text content-type allow-list (JSON, XML, form-encoded, text/\\*) is used.",
|
|
200
|
+
"items": {
|
|
201
|
+
"type": "string"
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
},
|
|
207
|
+
"examples": [
|
|
208
|
+
{
|
|
209
|
+
"export": "DataLossPreventionInboundPolicy",
|
|
210
|
+
"module": "$import(@zuplo/runtime)",
|
|
211
|
+
"options": {
|
|
212
|
+
"action": "mask",
|
|
213
|
+
"entities": ["secret", "finance", "contact-email", "id-us-ssn"],
|
|
214
|
+
"mask": "[REDACTED]"
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
]
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
}
|