zuplo 6.72.1 → 6.72.3
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/articles/accounts/audit-logs.mdx +4 -4
- package/docs/articles/audit-logging.mdx +65 -0
- package/docs/articles/audit-logs.mdx +222 -0
- package/docs/articles/{custom-audit-log-policy.mdx → custom-audit-logs.mdx} +26 -22
- package/docs/policies/_index.md +1 -0
- package/docs/policies/audit-log-inbound/doc.md +16 -11
- package/docs/policies/authzen-inbound/schema.json +1 -1
- package/docs/policies/axiomatics-authz-inbound/schema.json +1 -1
- package/docs/policies/mtls-auth-inbound/intro.md +52 -5
- package/docs/policies/okta-fga-authz-inbound/schema.json +1 -1
- package/docs/policies/openfga-authz-inbound/schema.json +1 -1
- package/docs/policies/require-user-claims-inbound/doc.md +120 -0
- package/docs/policies/require-user-claims-inbound/intro.md +9 -0
- package/docs/policies/require-user-claims-inbound/schema.json +1323 -0
- package/docs/policies/semantic-cache-inbound/schema.json +1 -1
- package/docs/policies/upstream-gcp-federated-auth-inbound/schema.json +1 -1
- package/docs/programmable-api/overview.mdx +0 -7
- package/package.json +4 -4
- package/docs/programmable-api/audit-log.mdx +0 -74
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: Audit Logs
|
|
2
|
+
title: Account Audit Logs
|
|
3
3
|
sidebar_label: Audit Logs
|
|
4
4
|
---
|
|
5
5
|
|
|
@@ -211,8 +211,8 @@ exceed 30 days. The start date must be before the end date.
|
|
|
211
211
|
|
|
212
212
|
:::tip
|
|
213
213
|
|
|
214
|
-
Account audit logs track administrative activities
|
|
215
|
-
|
|
216
|
-
[Audit
|
|
214
|
+
Account audit logs track administrative activities in your Zuplo account. To
|
|
215
|
+
record an audit trail of the requests flowing through your gateway, see
|
|
216
|
+
[Audit Logging](../audit-logging.mdx).
|
|
217
217
|
|
|
218
218
|
:::
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Audit Logging
|
|
3
|
+
sidebar_label: Overview
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Audit logs answer the question "who did what through your API, and when?" —
|
|
7
|
+
providing a structured, searchable record of every request and business event
|
|
8
|
+
that flows through your gateway. This page explains why audit logging matters
|
|
9
|
+
and the options Zuplo gives you for capturing an audit trail.
|
|
10
|
+
|
|
11
|
+
## Why audit logging?
|
|
12
|
+
|
|
13
|
+
Audit logging plays a critical role in API security: it lets you detect and
|
|
14
|
+
investigate issues such as unauthorized access or permission elevation, and
|
|
15
|
+
reconstruct exactly what happened to a resource after the fact. It's also a hard
|
|
16
|
+
requirement for many compliance certifications (SOC 2, ISO 27001, HIPAA, PCI
|
|
17
|
+
DSS) and a common buying criterion for enterprise customers of your API.
|
|
18
|
+
|
|
19
|
+
Unlike request logs — which are optimized for debugging and operational
|
|
20
|
+
visibility — audit logs are structured business records: each event identifies
|
|
21
|
+
an actor, an action, and the resources affected, in a stable format you can
|
|
22
|
+
retain, search, and hand to an auditor.
|
|
23
|
+
|
|
24
|
+
## Options for audit logging
|
|
25
|
+
|
|
26
|
+
Zuplo supports two approaches, depending on where you want your audit trail to
|
|
27
|
+
live:
|
|
28
|
+
|
|
29
|
+
1. **[Zuplo Audit Logs](./audit-logs.mdx)** — the recommended approach for most
|
|
30
|
+
APIs. Add a single policy and Zuplo records, stores, and indexes a structured
|
|
31
|
+
audit event for every request. You can search the events in the Zuplo Portal,
|
|
32
|
+
query them through the Zuplo API, and export them to a SIEM. No code or
|
|
33
|
+
infrastructure required.
|
|
34
|
+
2. **[Custom audit logs](./custom-audit-logs.mdx)** — write a small custom
|
|
35
|
+
policy that sends audit events to any external audit provider (for example,
|
|
36
|
+
WorkOS Audit Logs). Full control over the event format and destination.
|
|
37
|
+
|
|
38
|
+
| | Zuplo Audit Logs | Custom audit logs |
|
|
39
|
+
| ------------ | ------------------------- | --------------------- |
|
|
40
|
+
| Setup | Add a policy | Write policy code |
|
|
41
|
+
| Storage | Managed by Zuplo | Your provider |
|
|
42
|
+
| Viewing | Zuplo Portal + Zuplo API | Your provider's tools |
|
|
43
|
+
| Availability | Enterprise (free to test) | All plans |
|
|
44
|
+
|
|
45
|
+
Zuplo Audit Logs is an enterprise feature, but anyone can use it for free for
|
|
46
|
+
development and testing purposes.
|
|
47
|
+
|
|
48
|
+
## Gateway audit logs versus account audit logs
|
|
49
|
+
|
|
50
|
+
Zuplo has two separate audit trails — the options above all concern the first:
|
|
51
|
+
|
|
52
|
+
- **Gateway audit logs** record traffic through _your API_: requests from your
|
|
53
|
+
API's consumers and custom events emitted by your gateway code.
|
|
54
|
+
- **[Account audit logs](./accounts/audit-logs.mdx)** record administrative
|
|
55
|
+
activity in _your Zuplo account_: project changes, team member management,
|
|
56
|
+
deployments, and other portal and API operations.
|
|
57
|
+
|
|
58
|
+
## Next steps
|
|
59
|
+
|
|
60
|
+
- [Zuplo Audit Logs](./audit-logs.mdx) — enable the built-in feature and start
|
|
61
|
+
recording events
|
|
62
|
+
- [Custom audit logs](./custom-audit-logs.mdx) — send audit events to an
|
|
63
|
+
external provider
|
|
64
|
+
- [Audit Logs policy reference](../policies/audit-log-inbound.mdx) — all
|
|
65
|
+
configuration options and the full event shape
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Zuplo Audit Logs
|
|
3
|
+
sidebar_label: Zuplo Audit Logs
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
Zuplo's Audit Logs feature gives you a complete
|
|
7
|
+
[audit trail](./audit-logging.mdx) of your API with a single policy: the gateway
|
|
8
|
+
records a structured event for every request, stores the events for you, and
|
|
9
|
+
makes them available in the Zuplo Portal and through the Zuplo API.
|
|
10
|
+
|
|
11
|
+
<EnterpriseFeature name="Audit Logs" />
|
|
12
|
+
|
|
13
|
+
## How it works
|
|
14
|
+
|
|
15
|
+
<Diagram height="h-56">
|
|
16
|
+
<DiagramNode id="client">Client</DiagramNode>
|
|
17
|
+
<DiagramGroup id="zuplo" label="Zuplo">
|
|
18
|
+
<DiagramNode id="gateway" variant="zuplo">
|
|
19
|
+
Gateway (Audit Logs policy)
|
|
20
|
+
</DiagramNode>
|
|
21
|
+
<DiagramNode id="store">Audit log storage</DiagramNode>
|
|
22
|
+
</DiagramGroup>
|
|
23
|
+
<DiagramNode id="consumers">Portal / API / SIEM</DiagramNode>
|
|
24
|
+
<DiagramEdge from="client" to="gateway" />
|
|
25
|
+
<DiagramEdge from="gateway" to="store" label="events" />
|
|
26
|
+
<DiagramEdge from="store" to="consumers" />
|
|
27
|
+
</Diagram>
|
|
28
|
+
|
|
29
|
+
Add the [Audit Logs policy](../policies/audit-log-inbound.mdx) to any route and
|
|
30
|
+
the gateway records one structured audit event per request — who made the
|
|
31
|
+
request, what they called, and the outcome. You can also emit your own custom
|
|
32
|
+
events (for example, "account deleted") from handlers and custom policies. Every
|
|
33
|
+
event follows the [CloudEvents](https://cloudevents.io/) 1.0 format.
|
|
34
|
+
|
|
35
|
+
Zuplo stores the events for you, grouped by environment — production, preview,
|
|
36
|
+
and working copy environments each write to their own bucket. You don't need a
|
|
37
|
+
database, logging service, or any other infrastructure of your own.
|
|
38
|
+
|
|
39
|
+
## Recording audit events
|
|
40
|
+
|
|
41
|
+
### Automatic request events
|
|
42
|
+
|
|
43
|
+
Add the policy to the routes you want audited. Typically that's any route that
|
|
44
|
+
modifies data, though depending on your API you may want it on sensitive read
|
|
45
|
+
operations as well (for example, retrieving a secret).
|
|
46
|
+
|
|
47
|
+
```json title="config/policies.json"
|
|
48
|
+
{
|
|
49
|
+
"name": "audit-logs",
|
|
50
|
+
"policyType": "audit-log-inbound",
|
|
51
|
+
"handler": {
|
|
52
|
+
"export": "AuditLogInboundPolicy",
|
|
53
|
+
"module": "$import(@zuplo/runtime)"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Each request through the policy produces an event of type
|
|
59
|
+
`com.zuplo.api.request` capturing the actor, HTTP method and path, response
|
|
60
|
+
status, caller IP address, and geolocation.
|
|
61
|
+
|
|
62
|
+
Audit events can contain personal or sensitive data. The policy's `include`
|
|
63
|
+
options let you turn off individual fields (query parameters, user identity, IP
|
|
64
|
+
address, geolocation) to satisfy your own data-handling and personally
|
|
65
|
+
identifiable information (PII) policies, and `samplingRate` lets you capture
|
|
66
|
+
only a fraction of requests on high-volume routes. See the
|
|
67
|
+
[policy reference](../policies/audit-log-inbound.mdx) for all options.
|
|
68
|
+
|
|
69
|
+
### Custom events
|
|
70
|
+
|
|
71
|
+
Beyond the automatic per-request event, record your own domain events from a
|
|
72
|
+
handler or custom policy with the static `AuditLogInboundPolicy.log()` method.
|
|
73
|
+
Only `type` is required — Zuplo fills in the actor, timestamp, request ID, and
|
|
74
|
+
other context fields automatically from the request:
|
|
75
|
+
|
|
76
|
+
```ts title="modules/handlers.ts"
|
|
77
|
+
import {
|
|
78
|
+
AuditLogInboundPolicy,
|
|
79
|
+
ZuploContext,
|
|
80
|
+
ZuploRequest,
|
|
81
|
+
} from "@zuplo/runtime";
|
|
82
|
+
|
|
83
|
+
export async function deleteAccount(
|
|
84
|
+
request: ZuploRequest,
|
|
85
|
+
context: ZuploContext,
|
|
86
|
+
) {
|
|
87
|
+
const accountId = request.params.accountId;
|
|
88
|
+
|
|
89
|
+
// ...perform the delete...
|
|
90
|
+
|
|
91
|
+
AuditLogInboundPolicy.log(context, {
|
|
92
|
+
type: "com.acme.account.deleted",
|
|
93
|
+
subject: `account|${accountId}`,
|
|
94
|
+
resources: [{ type: "account", id: accountId }],
|
|
95
|
+
success: true,
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
return new Response(null, { status: 204 });
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Audit logging is best-effort by design: `log()` never throws and never blocks or
|
|
103
|
+
fails the request, even if an event can't be recorded.
|
|
104
|
+
|
|
105
|
+
## Viewing audit logs in the portal
|
|
106
|
+
|
|
107
|
+
To browse and search your audit logs, open your project's
|
|
108
|
+
[**Services**](https://portal.zuplo.com/+/account/project/services) page in the
|
|
109
|
+
Zuplo Portal and select the **Audit Logs** tile for the environment you want to
|
|
110
|
+
inspect.
|
|
111
|
+
|
|
112
|
+
The events view lets you:
|
|
113
|
+
|
|
114
|
+
- Filter events by time range, event type, actor, and subject
|
|
115
|
+
- See the top event types and most active actors for the selected window
|
|
116
|
+
- Select any event to inspect the full event payload
|
|
117
|
+
|
|
118
|
+
## Querying audit logs with the API
|
|
119
|
+
|
|
120
|
+
Everything in the portal is backed by the Zuplo API, so you can query audit logs
|
|
121
|
+
programmatically — for scripting, custom dashboards, or exporting to other
|
|
122
|
+
systems. Authenticate with a [Zuplo API key](./accounts/zuplo-api-keys.mdx) and
|
|
123
|
+
query events by bucket name. Your bucket name is shown on the **Services** page
|
|
124
|
+
in the portal (it's the same bucket used by the API Key Service).
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
curl "https://dev.zuplo.com/v1/audit-logs/$BUCKET_NAME/events?type=com.zuplo.api.request&startDate=2026-07-01T00:00:00Z&endDate=2026-07-07T00:00:00Z" \
|
|
128
|
+
-H "Authorization: Bearer $ZUPLO_API_KEY"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
"data": [
|
|
134
|
+
{
|
|
135
|
+
"specversion": "1.0",
|
|
136
|
+
"id": "e6c8b1f2-2c3d-4a5b-9e10-1f2a3b4c5d6e",
|
|
137
|
+
"type": "com.zuplo.api.request",
|
|
138
|
+
"time": "2026-07-05T18:12:04.123Z",
|
|
139
|
+
"actorsub": "user|12356",
|
|
140
|
+
"actortype": "user",
|
|
141
|
+
"requestid": "b1a2c3d4-e5f6-7890-abcd-ef1234567890",
|
|
142
|
+
"httpmethod": "GET",
|
|
143
|
+
"httpurl": "/customers/12345?expand=orders",
|
|
144
|
+
"httpstatus": 200,
|
|
145
|
+
"success": true,
|
|
146
|
+
"ipaddress": "203.0.113.7",
|
|
147
|
+
"useragent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) ...",
|
|
148
|
+
"country": "US",
|
|
149
|
+
"region": "Washington",
|
|
150
|
+
"city": "Seattle"
|
|
151
|
+
}
|
|
152
|
+
],
|
|
153
|
+
"pagination": { "limit": 20, "offset": 0, "total": 1, "hasMore": false }
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Two endpoints are available:
|
|
158
|
+
|
|
159
|
+
- **Query events** — `GET /v1/audit-logs/{bucketId}/events` returns matching
|
|
160
|
+
events, filterable by `type`, `actorSub`, `subject`, and time range.
|
|
161
|
+
- **Aggregated stats** — `GET /v1/audit-logs/{bucketId}/stats` returns top-N
|
|
162
|
+
event counts grouped by event type or actor.
|
|
163
|
+
|
|
164
|
+
The `bucketId` path parameter accepts either the bucket ID or the bucket name.
|
|
165
|
+
Each query is limited to a 30-day window between `startDate` and `endDate`. See
|
|
166
|
+
the [Audit Logs API reference](../api/audit-logs) for all parameters and
|
|
167
|
+
response schemas.
|
|
168
|
+
|
|
169
|
+
## Exporting audit logs to a SIEM
|
|
170
|
+
|
|
171
|
+
Many organizations centralize audit trails in a SIEM (Splunk, Microsoft
|
|
172
|
+
Sentinel, Datadog Cloud SIEM, and so on) to correlate API activity with other
|
|
173
|
+
security signals, drive alerting, and meet long-term retention requirements. The
|
|
174
|
+
events API is designed for this: run a scheduled job that pulls new events since
|
|
175
|
+
its last checkpoint and forwards them to your SIEM.
|
|
176
|
+
|
|
177
|
+
```ts
|
|
178
|
+
const BASE_URL = "https://dev.zuplo.com/v1/audit-logs";
|
|
179
|
+
|
|
180
|
+
// Run on a schedule (e.g. every 5 minutes). `startDate` is the checkpoint
|
|
181
|
+
// saved by the previous run; `endDate` is the current time.
|
|
182
|
+
async function exportAuditLogs(
|
|
183
|
+
bucketName: string,
|
|
184
|
+
startDate: string,
|
|
185
|
+
endDate: string,
|
|
186
|
+
) {
|
|
187
|
+
let offset = 0;
|
|
188
|
+
let hasMore = true;
|
|
189
|
+
while (hasMore) {
|
|
190
|
+
const url = new URL(`${BASE_URL}/${bucketName}/events`);
|
|
191
|
+
url.searchParams.set("startDate", startDate);
|
|
192
|
+
url.searchParams.set("endDate", endDate);
|
|
193
|
+
url.searchParams.set("limit", "100");
|
|
194
|
+
url.searchParams.set("offset", String(offset));
|
|
195
|
+
const response = await fetch(url, {
|
|
196
|
+
headers: { Authorization: `Bearer ${process.env.ZUPLO_API_KEY}` },
|
|
197
|
+
});
|
|
198
|
+
const { data, pagination } = await response.json();
|
|
199
|
+
await sendToSiem(data); // e.g. Splunk HEC, Datadog Logs API, S3
|
|
200
|
+
offset += data.length;
|
|
201
|
+
hasMore = pagination.hasMore;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Because every event is a CloudEvents document, most SIEMs can ingest the payload
|
|
207
|
+
directly without transformation.
|
|
208
|
+
|
|
209
|
+
Alternatively, if you'd rather send audit events to an external audit provider
|
|
210
|
+
directly from the gateway instead of storing them in Zuplo, see
|
|
211
|
+
[Custom Audit Logs](./custom-audit-logs.mdx).
|
|
212
|
+
|
|
213
|
+
## Related resources
|
|
214
|
+
|
|
215
|
+
- [Audit logging overview](./audit-logging.mdx) — why audit logging matters and
|
|
216
|
+
how the options compare
|
|
217
|
+
- [Audit Logs policy reference](../policies/audit-log-inbound.mdx) — all
|
|
218
|
+
configuration options, custom event fields, and the full event shape
|
|
219
|
+
- [Audit Logs API reference](../api/audit-logs) — query events and stats
|
|
220
|
+
programmatically
|
|
221
|
+
- [Account audit logs](./accounts/audit-logs.mdx) — the audit trail of your
|
|
222
|
+
Zuplo account itself
|
|
@@ -1,29 +1,22 @@
|
|
|
1
1
|
---
|
|
2
|
-
title: Custom Audit
|
|
3
|
-
sidebar_label: Audit
|
|
2
|
+
title: Custom Audit Logs
|
|
3
|
+
sidebar_label: Custom Audit Logs
|
|
4
4
|
---
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
[Zuplo Audit Logs](./audit-logs.mdx) stores your audit trail in Zuplo and gives
|
|
7
|
+
you a portal viewer and query API out of the box. If your organization uses an
|
|
8
|
+
external audit logging service instead, you can send events to it directly from
|
|
9
|
+
the gateway with a [custom policy](../policies/custom-code-inbound.mdx) that
|
|
10
|
+
uses [runtime hooks](../programmable-api/runtime-extensions.mdx). This approach
|
|
11
|
+
works on any plan — it's just custom code — and gives you full control over
|
|
12
|
+
which events are recorded, the event format, and the destination.
|
|
8
13
|
|
|
9
|
-
|
|
10
|
-
detecting and correcting issues such as unauthorized access or permission
|
|
11
|
-
elevations within your system. Audit logging is also a requirement for many
|
|
12
|
-
compliance certifications as well as part of the buying criteria for larger
|
|
13
|
-
enterprises.
|
|
14
|
-
|
|
15
|
-
Adding Audit Logging to your APIs that are secured with Zuplo is as easy as
|
|
16
|
-
adding a custom policy. Typically you want to add audit logs to any API that
|
|
17
|
-
modifies data, however depending on the API you may want it on read operations
|
|
18
|
-
as well (for example retrieve a secret key, etc.)
|
|
19
|
-
|
|
20
|
-
## Example Policy: WorkOS Audit Logs
|
|
14
|
+
## Example: WorkOS Audit Logs
|
|
21
15
|
|
|
22
16
|
[WorkOS](https://workos.com/) provides various services that help enable
|
|
23
|
-
enterprise features on your service such as SSO and Audit Logs.
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
using their API.
|
|
17
|
+
enterprise features on your service such as SSO and Audit Logs. The following
|
|
18
|
+
custom policy logs API calls to the WorkOS Audit Logs API after each response is
|
|
19
|
+
sent:
|
|
27
20
|
|
|
28
21
|
```ts
|
|
29
22
|
import { ZuploContext, ZuploRequest, environment } from "@zuplo/runtime";
|
|
@@ -34,7 +27,7 @@ export async function auditLogPlugin(
|
|
|
34
27
|
policyName: string,
|
|
35
28
|
) {
|
|
36
29
|
// Clone the request so the body can be read in the hook
|
|
37
|
-
// note: remove this
|
|
30
|
+
// note: remove this if you don't need content from the body
|
|
38
31
|
const cloned = request.clone();
|
|
39
32
|
context.addResponseSendingFinalHook(async (response) => {
|
|
40
33
|
const incomingBody = await cloned.json();
|
|
@@ -48,7 +41,7 @@ export async function auditLogPlugin(
|
|
|
48
41
|
version: 1,
|
|
49
42
|
actor: {
|
|
50
43
|
type: "user",
|
|
51
|
-
//
|
|
44
|
+
// Use the user sub for authenticated users
|
|
52
45
|
id: request.user.sub,
|
|
53
46
|
metadata: {
|
|
54
47
|
role: "user",
|
|
@@ -93,3 +86,14 @@ export async function auditLogPlugin(
|
|
|
93
86
|
return request;
|
|
94
87
|
}
|
|
95
88
|
```
|
|
89
|
+
|
|
90
|
+
The same pattern works for any provider with an HTTP API — swap the event shape
|
|
91
|
+
and endpoint for your provider's, and store credentials in
|
|
92
|
+
[environment variables](./environment-variables.mdx).
|
|
93
|
+
|
|
94
|
+
## Related resources
|
|
95
|
+
|
|
96
|
+
- [Audit logging overview](./audit-logging.mdx) — why audit logging matters and
|
|
97
|
+
how the options compare
|
|
98
|
+
- [Zuplo Audit Logs](./audit-logs.mdx) — the built-in feature with portal
|
|
99
|
+
viewing and a query API
|
package/docs/policies/_index.md
CHANGED
|
@@ -91,6 +91,7 @@
|
|
|
91
91
|
| request-size-limit-inbound | Request Size Limit | Enforces a maximum size in bytes of the incoming request. | api-gateway |
|
|
92
92
|
| request-validation-inbound | Request Validation | Validates incoming requests against your OpenAPI specification. Checks query parameters, path parameters, headers, and request body to ensure they match the defined schema before processing. | api-gateway |
|
|
93
93
|
| require-origin-inbound | Require Origin | Sets an allow-list for an origin header | api-gateway |
|
|
94
|
+
| require-user-claims-inbound | Require User Claims | Authorizes requests by validating claims on the authenticated user (`request.user`) against a configurable rule of `and`/`or` combinators and per-claim `eq`, `in`, and `startsWith` checks. Run it after any authentication policy that populates `request.user` — a JWT auth policy, API key auth, mTLS, and so on — to allow only specific callers (service accounts, OAuth clients, tenants, groups) without writing custom code. Every check fails closed: a missing or non-primitive claim never matches, comparisons are strict and type-sensitive, and requests without an authenticated user receive a 401 response. Denied requests receive a 403 response that does not echo claim values or expected values; the failing checks are written to the request log instead. Validation of the options runs lazily inside the policy constructor, which the runtime caches per policy name. Misconfigured options therefore fail on first use with a customer-facing `ConfigurationError` instead of failing at module load. | api-gateway |
|
|
94
95
|
| secret-masking-outbound | Secret Masking | Masks common secrets like Zuplo API keys, GitHub tokens, or SSH private key in the response body. | api-gateway |
|
|
95
96
|
| semantic-cache-inbound | Semantic Cache | Respond to matched incoming requests with semantically cached content The Semantic Cache Inbound policy caches responses based on semantic similarity of cache keys rather than exact matches. This allows for more flexible caching where similar requests can return cached responses even if the cache key is not exactly the same. The policy uses Large Language Model (LLM) embeddings to determine semantic similarity between cache keys based on a configurable similarity tolerance. Options: - semanticTolerance: The semantic similarity threshold for semantic cache matches (0-1, default: 0.2). Values closer to 0 require higher similarity. Can be overridden by custom functions. - expirationSecondsTtl: The timeout of the cache in seconds (default: 3600, 1 hour). Can be overridden by custom functions. - namespace: Optional namespace to isolate cache entries (default: "default"). Useful for multi-tenant scenarios or different cache contexts. - cacheBy: Determines how cache keys are generated: 'function' for custom logic or 'propertyPath' to extract from JSON body. | ai-gateway |
|
|
96
97
|
| set-body-inbound | Set Body | Sets the body of the request in the inbound pipeline - make sure to convert a GET/HEAD request to another method when using this policy. | api-gateway |
|
|
@@ -16,14 +16,14 @@ requests).
|
|
|
16
16
|
## Controlling What's Logged
|
|
17
17
|
|
|
18
18
|
Audit events can contain personal or sensitive data. To keep audit logging
|
|
19
|
-
compliant with your own data-handling and PII policies, use the `include`
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
compliant with your own data-handling and PII policies, use the `include` option
|
|
20
|
+
to turn individual fields off. Everything is captured by default; set a flag to
|
|
21
|
+
`false` to omit it:
|
|
22
22
|
|
|
23
23
|
- `queryParams` — the request's query-string parameters (in the logged URL).
|
|
24
|
-
- `user` — the authenticated user / actor identity (subject, email,
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
- `user` — the authenticated user / actor identity (subject, email, connection).
|
|
25
|
+
The `user` vs `anonymous` classification is always kept, but the identifying
|
|
26
|
+
values are omitted when disabled.
|
|
27
27
|
- `ipAddress` — the caller's IP address.
|
|
28
28
|
- `geolocation` — the caller's country, region, and city.
|
|
29
29
|
|
|
@@ -87,7 +87,8 @@ export async function deleteAccount(
|
|
|
87
87
|
The event object passed to `log()` supports the following fields. Only `type` is
|
|
88
88
|
required.
|
|
89
89
|
|
|
90
|
-
- `type` — the event type, in reverse-DNS form (e.g.
|
|
90
|
+
- `type` — the event type, in reverse-DNS form (e.g.
|
|
91
|
+
`com.acme.account.deleted`).
|
|
91
92
|
- `subject` — the primary entity the event is about.
|
|
92
93
|
- `resources` — an array of `{ type, id, metadata? }` describing the resources
|
|
93
94
|
the event affected.
|
|
@@ -95,9 +96,8 @@ required.
|
|
|
95
96
|
- `data` — any additional structured data to attach to the event.
|
|
96
97
|
- `actor` — override the automatically-derived actor
|
|
97
98
|
(`{ sub, type, email, connection }`).
|
|
98
|
-
- `country`, `region`, `city` — override the caller's geolocation. These
|
|
99
|
-
|
|
100
|
-
them.
|
|
99
|
+
- `country`, `region`, `city` — override the caller's geolocation. These default
|
|
100
|
+
to the current request's location, so you normally don't need to set them.
|
|
101
101
|
|
|
102
102
|
Audit logging is best-effort: `log()` never throws and never blocks or fails the
|
|
103
103
|
request, even if an event cannot be recorded.
|
|
@@ -134,4 +134,9 @@ pass, and the remaining fields are populated from the request context.
|
|
|
134
134
|
|
|
135
135
|
## Viewing Audit Logs
|
|
136
136
|
|
|
137
|
-
|
|
137
|
+
Audit logs are available in the [Zuplo portal](https://portal.zuplo.com) under
|
|
138
|
+
your project's Audit Log service, where you can browse and search the events
|
|
139
|
+
recorded by this policy.
|
|
140
|
+
|
|
141
|
+
You can also query audit logs programmatically using the
|
|
142
|
+
[Zuplo API](https://zuplo.com/docs/api).
|
|
@@ -1,7 +1,44 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
1
|
+
The `mtls-auth-inbound` policy is the enforcement step of client mutual TLS
|
|
2
|
+
(mTLS). It reads the verification result that Zuplo's edge proxy attaches to
|
|
3
|
+
each request and, when enforcement is enabled, rejects requests that don't
|
|
4
|
+
present a valid client certificate signed by a CA you trust. It is one part of a
|
|
5
|
+
complete client mTLS setup: you first upload the signing CA to your account,
|
|
6
|
+
then add this policy to the routes you want to protect.
|
|
7
|
+
|
|
8
|
+
For the full walkthrough — CA upload, configuration, testing with `curl`,
|
|
9
|
+
rotation, and troubleshooting (including the common
|
|
10
|
+
`FAILED to get issuer certificate` error) — see the
|
|
11
|
+
[Client mTLS authentication guide](https://zuplo.com/docs/articles/securing-the-gateway-with-client-mtls).
|
|
12
|
+
|
|
13
|
+
## Setting up client mTLS
|
|
14
|
+
|
|
15
|
+
This policy only enforces a result; it does not, on its own, make Zuplo verify
|
|
16
|
+
client certificates. The end-to-end setup is:
|
|
17
|
+
|
|
18
|
+
1. **Upload your CA certificate** to your account with the
|
|
19
|
+
[Zuplo CLI](https://zuplo.com/docs/cli/ca-certificate-create):
|
|
20
|
+
`zuplo ca-certificate create --name my_ca --cert ./ca.pem --account your-account`.
|
|
21
|
+
Upload the self-signed **root** CA that anchors the chain, not an
|
|
22
|
+
intermediate. CA certificates are scoped to your **account**, so once
|
|
23
|
+
uploaded, every gateway domain on the account verifies presented client
|
|
24
|
+
certificates against it.
|
|
25
|
+
2. **Add this policy** (`mtls-auth-inbound`) to each route that should require a
|
|
26
|
+
verified client certificate, and set `certIssuerDN` to pin the issuer (see
|
|
27
|
+
the options described below).
|
|
28
|
+
3. **Read the certificate** in your request handler or downstream policies from
|
|
29
|
+
`request.user.data.mtlsAuth`.
|
|
30
|
+
4. **Test** with a client certificate issued by (or chained to) your CA:
|
|
31
|
+
`curl --cert ./client.pem --key ./client.key https://your-gateway.zuplo.app/v1/example`.
|
|
32
|
+
|
|
33
|
+
See the
|
|
34
|
+
[full guide](https://zuplo.com/docs/articles/securing-the-gateway-with-client-mtls)
|
|
35
|
+
for CA management, custom domains, rotation, and troubleshooting.
|
|
36
|
+
|
|
37
|
+
## How the policy behaves
|
|
38
|
+
|
|
39
|
+
When enforcement is enabled, the policy rejects requests where no client
|
|
40
|
+
certificate was presented, certificate verification failed, or the certificate
|
|
41
|
+
metadata cannot be parsed.
|
|
5
42
|
|
|
6
43
|
When verification passes, the policy parses the client certificate metadata and
|
|
7
44
|
sets it on `request.user.data.mtlsAuth`. The metadata includes `subject`,
|
|
@@ -30,5 +67,15 @@ inspect `request.user.data.mtlsAuth.issuer` from a request signed by the desired
|
|
|
30
67
|
CA.
|
|
31
68
|
|
|
32
69
|
Note: this policy does not work with local development since it relies on
|
|
33
|
-
metadata from the upstream reverse proxy
|
|
70
|
+
metadata from the upstream reverse proxy. It is recommended to test this using a
|
|
34
71
|
working-copy or preview environment.
|
|
72
|
+
|
|
73
|
+
## Learn more
|
|
74
|
+
|
|
75
|
+
- [Client mTLS authentication guide](https://zuplo.com/docs/articles/securing-the-gateway-with-client-mtls)
|
|
76
|
+
— full end-to-end setup, CA management, and troubleshooting
|
|
77
|
+
- [`ca-certificate` CLI reference](https://zuplo.com/docs/cli/ca-certificate-create)
|
|
78
|
+
— upload, list, describe, rename, and delete account CA certificates
|
|
79
|
+
- [Gateway to Origin mTLS](https://zuplo.com/docs/articles/securing-backend-mtls)
|
|
80
|
+
— the reverse direction, where Zuplo authenticates to your backend with a
|
|
81
|
+
client certificate
|