zuplo 6.72.13 → 6.72.14
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/migrate-from-apigee.md +1 -1
- package/docs/articles/migrate-from-azure-apim.md +1 -1
- package/docs/articles/migrate-from-kong.md +4 -4
- package/docs/articles/waf-ddos-akamai.md +6 -6
- package/docs/articles/waf-ddos-aws-waf-shield.mdx +6 -6
- package/docs/articles/waf-ddos-fastly.mdx +6 -6
- package/docs/articles/waf-ddos.mdx +1 -1
- package/docs/concepts/authentication.mdx +2 -1
- package/docs/concepts/request-lifecycle.mdx +1 -1
- package/docs/policies/_index.md +1 -13
- package/docs/policies/ai-gateway-model-routing-v2-inbound/doc.md +162 -0
- package/docs/policies/ai-gateway-model-routing-v2-inbound/intro.md +19 -0
- package/docs/policies/ai-gateway-model-routing-v2-inbound/schema.json +263 -0
- package/docs/policies/graphql-cache-inbound/doc.md +1 -1
- package/package.json +4 -4
- package/docs/policies/ab-test-inbound/intro.md +0 -8
- package/docs/policies/ab-test-inbound/policy.ts +0 -14
- package/docs/policies/ab-test-inbound/schema.json +0 -27
- package/docs/policies/ab-test-outbound/intro.md +0 -8
- package/docs/policies/ab-test-outbound/policy.ts +0 -26
- package/docs/policies/ab-test-outbound/schema.json +0 -27
- package/docs/policies/acl-policy-inbound/intro.md +0 -5
- package/docs/policies/acl-policy-inbound/policy.ts +0 -32
- package/docs/policies/acl-policy-inbound/schema.json +0 -52
- package/docs/policies/archive-request-aws-s3-inbound/intro.md +0 -4
- package/docs/policies/archive-request-aws-s3-inbound/policy.ts +0 -58
- package/docs/policies/archive-request-aws-s3-inbound/schema.json +0 -68
- package/docs/policies/archive-request-azure-storage-inbound/doc.md +0 -31
- package/docs/policies/archive-request-azure-storage-inbound/intro.md +0 -4
- package/docs/policies/archive-request-azure-storage-inbound/policy.ts +0 -54
- package/docs/policies/archive-request-azure-storage-inbound/schema.json +0 -53
- package/docs/policies/archive-request-gcp-storage-inbound/doc.md +0 -63
- package/docs/policies/archive-request-gcp-storage-inbound/intro.md +0 -4
- package/docs/policies/archive-request-gcp-storage-inbound/policy.ts +0 -68
- package/docs/policies/archive-request-gcp-storage-inbound/schema.json +0 -47
- package/docs/policies/archive-response-aws-s3-outbound/intro.md +0 -2
- package/docs/policies/archive-response-aws-s3-outbound/policy.ts +0 -59
- package/docs/policies/archive-response-aws-s3-outbound/schema.json +0 -68
- package/docs/policies/archive-response-azure-storage-outbound/doc.md +0 -31
- package/docs/policies/archive-response-azure-storage-outbound/intro.md +0 -3
- package/docs/policies/archive-response-azure-storage-outbound/policy.ts +0 -54
- package/docs/policies/archive-response-azure-storage-outbound/schema.json +0 -53
- package/docs/policies/hmac-auth-inbound/doc.md +0 -30
- package/docs/policies/hmac-auth-inbound/intro.md +0 -10
- package/docs/policies/hmac-auth-inbound/policy.ts +0 -70
- package/docs/policies/hmac-auth-inbound/schema.json +0 -53
- package/docs/policies/ip-restriction-inbound/intro.md +0 -8
- package/docs/policies/ip-restriction-inbound/policy.ts +0 -40
- package/docs/policies/ip-restriction-inbound/schema.json +0 -58
- package/docs/policies/rbac-policy-inbound/intro.md +0 -3
- package/docs/policies/rbac-policy-inbound/policy.ts +0 -42
- package/docs/policies/rbac-policy-inbound/schema.json +0 -52
- package/docs/policies/transform-body-inbound/intro.md +0 -8
- package/docs/policies/transform-body-inbound/policy.ts +0 -16
- package/docs/policies/transform-body-inbound/schema.json +0 -27
- package/docs/policies/transform-body-outbound/intro.md +0 -8
- package/docs/policies/transform-body-outbound/policy.ts +0 -19
- package/docs/policies/transform-body-outbound/schema.json +0 -27
|
@@ -0,0 +1,263 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft-07/schema",
|
|
3
|
+
"$id": "https://cdn.zuplo.com/policies/runtime/schemas/ai-gateway-model-routing-v2-inbound.json",
|
|
4
|
+
"type": "object",
|
|
5
|
+
"title": "AI Gateway Model Routing (v2)",
|
|
6
|
+
"isDeprecated": false,
|
|
7
|
+
"isPaidAddOn": false,
|
|
8
|
+
"isEnterprise": false,
|
|
9
|
+
"isInternal": false,
|
|
10
|
+
"isBeta": true,
|
|
11
|
+
"isHidden": false,
|
|
12
|
+
"requiresAI": true,
|
|
13
|
+
"products": ["ai-gateway"],
|
|
14
|
+
"description": "Matches AI Gateway requests against curated allow lists or open block lists, then stores the winning `AIGatewayRouteTarget` for the route handler.",
|
|
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": "AIGatewayModelRoutingV2InboundPolicy",
|
|
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
|
+
"type": "object",
|
|
33
|
+
"title": "AIGatewayModelRoutingV2InboundPolicyOptions",
|
|
34
|
+
"description": "Options for allowing or blocking provider/model routes for each AI Gateway capability.",
|
|
35
|
+
"additionalProperties": false,
|
|
36
|
+
"required": ["models"],
|
|
37
|
+
"properties": {
|
|
38
|
+
"models": {
|
|
39
|
+
"type": "object",
|
|
40
|
+
"title": "Models",
|
|
41
|
+
"description": "Declarative model-routing rules, grouped by AI Gateway capability.",
|
|
42
|
+
"additionalProperties": false,
|
|
43
|
+
"minProperties": 1,
|
|
44
|
+
"properties": {
|
|
45
|
+
"completions": {
|
|
46
|
+
"title": "Completions Models",
|
|
47
|
+
"description": "Rules for chat completions, Responses, and Anthropic Messages requests.",
|
|
48
|
+
"allOf": [
|
|
49
|
+
{
|
|
50
|
+
"title": "Capability Model Rules",
|
|
51
|
+
"description": "Choose curated allow-list mode or open-but-filtered block-list mode.",
|
|
52
|
+
"oneOf": [
|
|
53
|
+
{
|
|
54
|
+
"type": "object",
|
|
55
|
+
"title": "Curated Model Rules",
|
|
56
|
+
"description": "Allow only listed targets and use entry zero as the default.",
|
|
57
|
+
"additionalProperties": false,
|
|
58
|
+
"required": ["allowList"],
|
|
59
|
+
"not": {
|
|
60
|
+
"required": ["blockList"]
|
|
61
|
+
},
|
|
62
|
+
"properties": {
|
|
63
|
+
"allowList": {
|
|
64
|
+
"type": "array",
|
|
65
|
+
"title": "Allowed Models",
|
|
66
|
+
"description": "Curated targets clients may select; the first entry is the default when model is omitted.",
|
|
67
|
+
"minItems": 1,
|
|
68
|
+
"items": {
|
|
69
|
+
"title": "Route Target",
|
|
70
|
+
"description": "A provider/model string shorthand or a full model route target.",
|
|
71
|
+
"oneOf": [
|
|
72
|
+
{
|
|
73
|
+
"type": "string",
|
|
74
|
+
"title": "Provider and Model",
|
|
75
|
+
"description": "A model reference in provider/model form, split on the first slash.",
|
|
76
|
+
"pattern": "^[^/\\s]+/.+$"
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
"type": "object",
|
|
80
|
+
"title": "Model Route Target",
|
|
81
|
+
"description": "A primary model and optional failure or quota fallbacks.",
|
|
82
|
+
"additionalProperties": false,
|
|
83
|
+
"required": ["main"],
|
|
84
|
+
"properties": {
|
|
85
|
+
"main": {
|
|
86
|
+
"type": "string",
|
|
87
|
+
"title": "Provider and Model",
|
|
88
|
+
"description": "A model reference in provider/model form, split on the first slash.",
|
|
89
|
+
"pattern": "^[^/\\s]+/.+$"
|
|
90
|
+
},
|
|
91
|
+
"backup": {
|
|
92
|
+
"type": "string",
|
|
93
|
+
"title": "Provider and Model",
|
|
94
|
+
"description": "A model reference in provider/model form, split on the first slash.",
|
|
95
|
+
"pattern": "^[^/\\s]+/.+$"
|
|
96
|
+
},
|
|
97
|
+
"fallbackTimeoutSeconds": {
|
|
98
|
+
"type": "number",
|
|
99
|
+
"title": "Fallback Timeout Seconds",
|
|
100
|
+
"description": "How long the main model may take before the backup is attempted.",
|
|
101
|
+
"minimum": 1,
|
|
102
|
+
"maximum": 300,
|
|
103
|
+
"default": 60
|
|
104
|
+
},
|
|
105
|
+
"quotaFallback": {
|
|
106
|
+
"type": "string",
|
|
107
|
+
"title": "Provider and Model",
|
|
108
|
+
"description": "A model reference in provider/model form, split on the first slash.",
|
|
109
|
+
"pattern": "^[^/\\s]+/.+$"
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
]
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
"type": "object",
|
|
120
|
+
"title": "Open-but-Filtered Model Rules",
|
|
121
|
+
"description": "Allow any requested target except those explicitly blocked.",
|
|
122
|
+
"additionalProperties": false,
|
|
123
|
+
"required": ["blockList"],
|
|
124
|
+
"not": {
|
|
125
|
+
"required": ["allowList"]
|
|
126
|
+
},
|
|
127
|
+
"properties": {
|
|
128
|
+
"blockList": {
|
|
129
|
+
"type": "array",
|
|
130
|
+
"title": "Blocked Models",
|
|
131
|
+
"description": "Configured provider/model targets rejected in open-but-filtered mode; requests may use a bare model name or provider/model.",
|
|
132
|
+
"minItems": 1,
|
|
133
|
+
"items": {
|
|
134
|
+
"type": "string",
|
|
135
|
+
"title": "Provider and Model",
|
|
136
|
+
"description": "A model reference in provider/model form, split on the first slash.",
|
|
137
|
+
"pattern": "^[^/\\s]+/.+$"
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
},
|
|
146
|
+
"embeddings": {
|
|
147
|
+
"title": "Embeddings Models",
|
|
148
|
+
"description": "Rules for embedding requests.",
|
|
149
|
+
"allOf": [
|
|
150
|
+
{
|
|
151
|
+
"title": "Capability Model Rules",
|
|
152
|
+
"description": "Choose curated allow-list mode or open-but-filtered block-list mode.",
|
|
153
|
+
"oneOf": [
|
|
154
|
+
{
|
|
155
|
+
"type": "object",
|
|
156
|
+
"title": "Curated Model Rules",
|
|
157
|
+
"description": "Allow only listed targets and use entry zero as the default.",
|
|
158
|
+
"additionalProperties": false,
|
|
159
|
+
"required": ["allowList"],
|
|
160
|
+
"not": {
|
|
161
|
+
"required": ["blockList"]
|
|
162
|
+
},
|
|
163
|
+
"properties": {
|
|
164
|
+
"allowList": {
|
|
165
|
+
"type": "array",
|
|
166
|
+
"title": "Allowed Models",
|
|
167
|
+
"description": "Curated targets clients may select; the first entry is the default when model is omitted.",
|
|
168
|
+
"minItems": 1,
|
|
169
|
+
"items": {
|
|
170
|
+
"title": "Route Target",
|
|
171
|
+
"description": "A provider/model string shorthand or a full model route target.",
|
|
172
|
+
"oneOf": [
|
|
173
|
+
{
|
|
174
|
+
"type": "string",
|
|
175
|
+
"title": "Provider and Model",
|
|
176
|
+
"description": "A model reference in provider/model form, split on the first slash.",
|
|
177
|
+
"pattern": "^[^/\\s]+/.+$"
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"type": "object",
|
|
181
|
+
"title": "Model Route Target",
|
|
182
|
+
"description": "A primary model and optional failure or quota fallbacks.",
|
|
183
|
+
"additionalProperties": false,
|
|
184
|
+
"required": ["main"],
|
|
185
|
+
"properties": {
|
|
186
|
+
"main": {
|
|
187
|
+
"type": "string",
|
|
188
|
+
"title": "Provider and Model",
|
|
189
|
+
"description": "A model reference in provider/model form, split on the first slash.",
|
|
190
|
+
"pattern": "^[^/\\s]+/.+$"
|
|
191
|
+
},
|
|
192
|
+
"backup": {
|
|
193
|
+
"type": "string",
|
|
194
|
+
"title": "Provider and Model",
|
|
195
|
+
"description": "A model reference in provider/model form, split on the first slash.",
|
|
196
|
+
"pattern": "^[^/\\s]+/.+$"
|
|
197
|
+
},
|
|
198
|
+
"fallbackTimeoutSeconds": {
|
|
199
|
+
"type": "number",
|
|
200
|
+
"title": "Fallback Timeout Seconds",
|
|
201
|
+
"description": "How long the main model may take before the backup is attempted.",
|
|
202
|
+
"minimum": 1,
|
|
203
|
+
"maximum": 300,
|
|
204
|
+
"default": 60
|
|
205
|
+
},
|
|
206
|
+
"quotaFallback": {
|
|
207
|
+
"type": "string",
|
|
208
|
+
"title": "Provider and Model",
|
|
209
|
+
"description": "A model reference in provider/model form, split on the first slash.",
|
|
210
|
+
"pattern": "^[^/\\s]+/.+$"
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
]
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
"type": "object",
|
|
221
|
+
"title": "Open-but-Filtered Model Rules",
|
|
222
|
+
"description": "Allow any requested target except those explicitly blocked.",
|
|
223
|
+
"additionalProperties": false,
|
|
224
|
+
"required": ["blockList"],
|
|
225
|
+
"not": {
|
|
226
|
+
"required": ["allowList"]
|
|
227
|
+
},
|
|
228
|
+
"properties": {
|
|
229
|
+
"blockList": {
|
|
230
|
+
"type": "array",
|
|
231
|
+
"title": "Blocked Models",
|
|
232
|
+
"description": "Configured provider/model targets rejected in open-but-filtered mode; requests may use a bare model name or provider/model.",
|
|
233
|
+
"minItems": 1,
|
|
234
|
+
"items": {
|
|
235
|
+
"type": "string",
|
|
236
|
+
"title": "Provider and Model",
|
|
237
|
+
"description": "A model reference in provider/model form, split on the first slash.",
|
|
238
|
+
"pattern": "^[^/\\s]+/.+$"
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
]
|
|
244
|
+
}
|
|
245
|
+
]
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
},
|
|
252
|
+
"examples": [
|
|
253
|
+
{
|
|
254
|
+
"export": "AIGatewayModelRoutingV2InboundPolicy",
|
|
255
|
+
"module": "$import(@zuplo/runtime)",
|
|
256
|
+
"options": {
|
|
257
|
+
"models": {}
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
]
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
The GraphQL Cache policy stores successful GraphQL query responses in a
|
|
2
|
-
[ZoneCache](https://zuplo.com/docs/
|
|
2
|
+
[ZoneCache](https://zuplo.com/docs/programmable-api/zone-cache) and serves later,
|
|
3
3
|
identical queries directly from the edge.
|
|
4
4
|
|
|
5
5
|
### How caching works
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zuplo",
|
|
3
|
-
"version": "6.72.
|
|
3
|
+
"version": "6.72.14",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The programmable API Gateway",
|
|
6
6
|
"author": "Zuplo, Inc.",
|
|
@@ -19,9 +19,9 @@
|
|
|
19
19
|
"zuplo": "zuplo.js"
|
|
20
20
|
},
|
|
21
21
|
"dependencies": {
|
|
22
|
-
"@zuplo/cli": "6.72.
|
|
23
|
-
"@zuplo/core": "6.72.
|
|
24
|
-
"@zuplo/runtime": "6.72.
|
|
22
|
+
"@zuplo/cli": "6.72.14",
|
|
23
|
+
"@zuplo/core": "6.72.14",
|
|
24
|
+
"@zuplo/runtime": "6.72.14",
|
|
25
25
|
"@zuplo/test": "1.4.0"
|
|
26
26
|
}
|
|
27
27
|
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
This example shows how to perform an action on incoming requests based on the
|
|
2
|
-
result of a randomly generated number. A/B tests could also be performed on
|
|
3
|
-
properties such as the `request.user`.
|
|
4
|
-
|
|
5
|
-
A/B tests can also be combined with other policies by passing data to downstream
|
|
6
|
-
policies. For example, you could save a value in `ContextData` based on the
|
|
7
|
-
results of the A/B test and use that value in a later policy to modify the
|
|
8
|
-
request.
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { ZuploContext, ZuploRequest } from "@zuplo/runtime";
|
|
2
|
-
|
|
3
|
-
export default async function (request: ZuploRequest, context: ZuploContext) {
|
|
4
|
-
// Generate a random number to segment the test groups
|
|
5
|
-
const score = Math.random();
|
|
6
|
-
|
|
7
|
-
if (score < 0.5) {
|
|
8
|
-
// Do something for half the requests
|
|
9
|
-
} else {
|
|
10
|
-
// Do something else for the other half
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
return request;
|
|
14
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft-07/schema",
|
|
3
|
-
"$id": "http://zuplo.com/schemas/policies/ab-test-inbound.json",
|
|
4
|
-
"type": "object",
|
|
5
|
-
"title": "A/B Test Inbound",
|
|
6
|
-
"isCustom": true,
|
|
7
|
-
"products": ["api-gateway"],
|
|
8
|
-
"description": "An A/B test policy is used to handle requests differently based on parameters such as user, ip, etc.",
|
|
9
|
-
"required": ["handler"],
|
|
10
|
-
"properties": {
|
|
11
|
-
"handler": {
|
|
12
|
-
"type": "object",
|
|
13
|
-
"default": {},
|
|
14
|
-
"required": ["export", "module"],
|
|
15
|
-
"properties": {
|
|
16
|
-
"export": {
|
|
17
|
-
"const": "default",
|
|
18
|
-
"description": "The export from the custom policy"
|
|
19
|
-
},
|
|
20
|
-
"module": {
|
|
21
|
-
"const": "$import(./modules/YOUR_MODULE)",
|
|
22
|
-
"description": "The module containing the policy"
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
This example shows how to perform an action on incoming requests based on the
|
|
2
|
-
result of a randomly generated number. A/B tests could also be performed on
|
|
3
|
-
properties such as the `request.user`.
|
|
4
|
-
|
|
5
|
-
A/B tests can also be combined with other policies by passing data to downstream
|
|
6
|
-
policies. For example, you could save a value in `ContextData` based on the
|
|
7
|
-
results of the A/B test and use that value in a later policy to modify the
|
|
8
|
-
request.
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { ZuploContext, ZuploRequest } from "@zuplo/runtime";
|
|
2
|
-
|
|
3
|
-
export default async function (
|
|
4
|
-
response: Response,
|
|
5
|
-
request: ZuploRequest,
|
|
6
|
-
context: ZuploContext,
|
|
7
|
-
) {
|
|
8
|
-
// Generate a random number to segment the test groups
|
|
9
|
-
const score = Math.random();
|
|
10
|
-
|
|
11
|
-
// Get the outgoing response body
|
|
12
|
-
const data = await response.json();
|
|
13
|
-
|
|
14
|
-
// Modify the body based on the random value
|
|
15
|
-
if (score < 0.5) {
|
|
16
|
-
data.testEnabled = true;
|
|
17
|
-
} else {
|
|
18
|
-
data.testEnabled = false;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Stringify the data object
|
|
22
|
-
const body = JSON.stringify(data);
|
|
23
|
-
|
|
24
|
-
// Return a new response with the updated body
|
|
25
|
-
return new Response(body, response);
|
|
26
|
-
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft-07/schema",
|
|
3
|
-
"$id": "http://zuplo.com/schemas/policies/ab-test-outbound.json",
|
|
4
|
-
"type": "object",
|
|
5
|
-
"title": "A/B Test Outbound",
|
|
6
|
-
"isCustom": true,
|
|
7
|
-
"products": ["api-gateway"],
|
|
8
|
-
"description": "An A/B test policy is used to handle responses differently based on parameters such as user, ip, etc.",
|
|
9
|
-
"required": ["handler"],
|
|
10
|
-
"properties": {
|
|
11
|
-
"handler": {
|
|
12
|
-
"type": "object",
|
|
13
|
-
"default": {},
|
|
14
|
-
"required": ["export", "module"],
|
|
15
|
-
"properties": {
|
|
16
|
-
"export": {
|
|
17
|
-
"const": "default",
|
|
18
|
-
"description": "The export from the custom policy"
|
|
19
|
-
},
|
|
20
|
-
"module": {
|
|
21
|
-
"const": "$import(./modules/YOUR_MODULE)",
|
|
22
|
-
"description": "The module containing the policy"
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
}
|
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
ACL policies can be built many ways depending on your requirements. This example
|
|
2
|
-
shows how to perform an authorization check on a hard-coded list of users.
|
|
3
|
-
|
|
4
|
-
This policy could be extended to fetch data from external sources or even use an
|
|
5
|
-
authorization service such as [OpenFGA](https://openfga.dev/).
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { HttpProblems, ZuploContext, ZuploRequest } from "@zuplo/runtime";
|
|
2
|
-
|
|
3
|
-
interface PolicyOptions {
|
|
4
|
-
users: string[];
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
export default async function (
|
|
8
|
-
request: ZuploRequest,
|
|
9
|
-
context: ZuploContext,
|
|
10
|
-
options: PolicyOptions,
|
|
11
|
-
policyName: string,
|
|
12
|
-
) {
|
|
13
|
-
// Check that an authenticated user is set
|
|
14
|
-
// NOTE: This policy requires an authentication policy to run before
|
|
15
|
-
if (!request.user) {
|
|
16
|
-
context.log.error(
|
|
17
|
-
"User isn't authenticated. A authorization policy must come before the ACL policy.",
|
|
18
|
-
);
|
|
19
|
-
return HttpProblems.unauthorized(request, context);
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
// Check that the user has one of the allowed roles
|
|
23
|
-
if (!options.users.includes(request.user.sub)) {
|
|
24
|
-
context.log.error(
|
|
25
|
-
`The user '${request.user.sub}' isn't authorized to perform this action.`,
|
|
26
|
-
);
|
|
27
|
-
return HttpProblems.forbidden(request, context);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// If they made it here, they are authorized
|
|
31
|
-
return request;
|
|
32
|
-
}
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft-07/schema",
|
|
3
|
-
"$id": "http://zuplo.com/schemas/policies/acl-policy-inbound.json",
|
|
4
|
-
"type": "object",
|
|
5
|
-
"title": "Access Control List",
|
|
6
|
-
"isCustom": true,
|
|
7
|
-
"products": ["api-gateway"],
|
|
8
|
-
"description": "The access control list inbound policy limits access to resources based on parameters on the authenticated user.",
|
|
9
|
-
"required": ["handler"],
|
|
10
|
-
"properties": {
|
|
11
|
-
"handler": {
|
|
12
|
-
"type": "object",
|
|
13
|
-
"default": {},
|
|
14
|
-
"required": ["export", "module", "options"],
|
|
15
|
-
"properties": {
|
|
16
|
-
"export": {
|
|
17
|
-
"const": "default",
|
|
18
|
-
"description": "The name of the exported type"
|
|
19
|
-
},
|
|
20
|
-
"module": {
|
|
21
|
-
"const": "$import(./modules/YOUR_MODULE)",
|
|
22
|
-
"description": "The module containing the policy"
|
|
23
|
-
},
|
|
24
|
-
"options": {
|
|
25
|
-
"type": "object",
|
|
26
|
-
"description": "The options for this policy",
|
|
27
|
-
"required": ["users"],
|
|
28
|
-
"properties": {
|
|
29
|
-
"users": {
|
|
30
|
-
"type": "array",
|
|
31
|
-
"description": "The list of users authorized to access the resource",
|
|
32
|
-
"items": {
|
|
33
|
-
"type": "string",
|
|
34
|
-
"description": "The user's sub"
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
},
|
|
40
|
-
"examples": [
|
|
41
|
-
{
|
|
42
|
-
"_name": "basic",
|
|
43
|
-
"export": "default",
|
|
44
|
-
"module": "$import(./modules/YOUR_MODULE)",
|
|
45
|
-
"options": {
|
|
46
|
-
"users": ["google|12345", "google|23456"]
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
]
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
In this example shows how you can archive the body of incoming requests to AWS
|
|
2
|
-
S3 Storage. This can be useful for auditing, logging, or archival scenarios.
|
|
3
|
-
Additionally, you could use this policy to save the body of a request and then
|
|
4
|
-
enqueue some asynchronous work that uses this body.
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import { PutObjectCommand, S3Client } from "@aws-sdk/client-s3";
|
|
2
|
-
import { ZuploContext, ZuploRequest } from "@zuplo/runtime";
|
|
3
|
-
|
|
4
|
-
type PolicyOptions = {
|
|
5
|
-
region: string;
|
|
6
|
-
bucketName: string;
|
|
7
|
-
path: string;
|
|
8
|
-
accessKeyId: string;
|
|
9
|
-
accessKeySecret: string;
|
|
10
|
-
};
|
|
11
|
-
export default async function (
|
|
12
|
-
request: ZuploRequest,
|
|
13
|
-
context: ZuploContext,
|
|
14
|
-
options: PolicyOptions,
|
|
15
|
-
policyName: string,
|
|
16
|
-
) {
|
|
17
|
-
// NOTE: policy options should be validated, but to keep the sample short,
|
|
18
|
-
// we are skipping that here.
|
|
19
|
-
|
|
20
|
-
// Initialize the S3 client
|
|
21
|
-
const s3Client = new S3Client({
|
|
22
|
-
region: options.region,
|
|
23
|
-
credentials: {
|
|
24
|
-
accessKeyId: options.accessKeyId,
|
|
25
|
-
secretAccessKey: options.accessKeySecret,
|
|
26
|
-
},
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
// Create the file
|
|
30
|
-
const file = `${options.path}/${Date.now()}-${crypto.randomUUID()}.req.txt`;
|
|
31
|
-
|
|
32
|
-
// because we will read the body, we need to
|
|
33
|
-
// create a clone of this request first, otherwise
|
|
34
|
-
// there may be two attempts to read the body
|
|
35
|
-
// causing a runtime error
|
|
36
|
-
const clone = request.clone();
|
|
37
|
-
|
|
38
|
-
// In this example we assume the body could be text, but you could also
|
|
39
|
-
// request the blob() to handle binary data types like images.
|
|
40
|
-
//
|
|
41
|
-
// This example loads the entire body into memory. This is fine for
|
|
42
|
-
// small payloads, but if you have a large payload you should instead
|
|
43
|
-
// save the body via streaming.
|
|
44
|
-
const body = await clone.text();
|
|
45
|
-
|
|
46
|
-
// Create the S3 command
|
|
47
|
-
const command = new PutObjectCommand({
|
|
48
|
-
Bucket: options.bucketName,
|
|
49
|
-
Key: file,
|
|
50
|
-
Body: body,
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
// Use the S3 client to save the object
|
|
54
|
-
await s3Client.send(command);
|
|
55
|
-
|
|
56
|
-
// Continue the request
|
|
57
|
-
return request;
|
|
58
|
-
}
|
|
@@ -1,68 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://json-schema.org/draft-07/schema",
|
|
3
|
-
"$id": "http://zuplo.com/schemas/policies/archive-request-aws-s3-inbound.json",
|
|
4
|
-
"type": "object",
|
|
5
|
-
"title": "Archive Request to AWS S3",
|
|
6
|
-
"isCustom": true,
|
|
7
|
-
"products": ["api-gateway"],
|
|
8
|
-
"description": "Archive the incoming request body to AWS S3 storage",
|
|
9
|
-
"required": ["handler"],
|
|
10
|
-
"properties": {
|
|
11
|
-
"handler": {
|
|
12
|
-
"type": "object",
|
|
13
|
-
"default": {},
|
|
14
|
-
"required": ["export", "module", "options"],
|
|
15
|
-
"properties": {
|
|
16
|
-
"export": {
|
|
17
|
-
"const": "default",
|
|
18
|
-
"description": "The name of the exported type"
|
|
19
|
-
},
|
|
20
|
-
"module": {
|
|
21
|
-
"const": "$import(./modules/YOUR_MODULE)",
|
|
22
|
-
"description": "The module containing the policy"
|
|
23
|
-
},
|
|
24
|
-
"options": {
|
|
25
|
-
"type": "object",
|
|
26
|
-
"description": "The options for this policy",
|
|
27
|
-
"required": [],
|
|
28
|
-
"properties": {
|
|
29
|
-
"region": {
|
|
30
|
-
"type": "string",
|
|
31
|
-
"description": "The AWS region where the bucket is located"
|
|
32
|
-
},
|
|
33
|
-
"bucketName": {
|
|
34
|
-
"type": "string",
|
|
35
|
-
"description": "The name of the storage bucket"
|
|
36
|
-
},
|
|
37
|
-
"path": {
|
|
38
|
-
"type": "string",
|
|
39
|
-
"description": "The path where requests are stored"
|
|
40
|
-
},
|
|
41
|
-
"accessKeyId": {
|
|
42
|
-
"type": "string",
|
|
43
|
-
"description": "The Access Key ID of the account authorized to write to the bucket"
|
|
44
|
-
},
|
|
45
|
-
"accessKeySecret": {
|
|
46
|
-
"type": "string",
|
|
47
|
-
"description": "The Access Key Secret of the account authorized to write to the bucket"
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
},
|
|
52
|
-
"examples": [
|
|
53
|
-
{
|
|
54
|
-
"_name": "basic",
|
|
55
|
-
"export": "ArchiveResponseOutbound",
|
|
56
|
-
"module": "$import(@zuplo/runtime)",
|
|
57
|
-
"options": {
|
|
58
|
-
"region": "us-east-1",
|
|
59
|
-
"bucketName": "test-bucket-123.s3.amazonaws.com",
|
|
60
|
-
"path": "responses/",
|
|
61
|
-
"accessKeyId": "$env(AWS_ACCESS_KEY_ID)",
|
|
62
|
-
"accessKeySecret": "$env(AWS_ACCESS_KEY_SECRET)"
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
]
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|