alchemy 0.50.0 → 0.51.0
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/lib/apply.js +10 -9
- package/lib/apply.js.map +1 -1
- package/lib/aws/control/types.d.ts +4 -4
- package/lib/cloudflare/api-gateway-operation.d.ts +141 -0
- package/lib/cloudflare/api-gateway-operation.d.ts.map +1 -0
- package/lib/cloudflare/api-gateway-operation.js +153 -0
- package/lib/cloudflare/api-gateway-operation.js.map +1 -0
- package/lib/cloudflare/api-mitigation.d.ts +19 -0
- package/lib/cloudflare/api-mitigation.d.ts.map +1 -0
- package/lib/cloudflare/api-mitigation.js +1 -0
- package/lib/cloudflare/api-mitigation.js.map +1 -0
- package/lib/cloudflare/api-schema.d.ts +137 -0
- package/lib/cloudflare/api-schema.d.ts.map +1 -0
- package/lib/cloudflare/api-schema.js +197 -0
- package/lib/cloudflare/api-schema.js.map +1 -0
- package/lib/cloudflare/api-shield.d.ts +366 -0
- package/lib/cloudflare/api-shield.d.ts.map +1 -0
- package/lib/cloudflare/api-shield.js +427 -0
- package/lib/cloudflare/api-shield.js.map +1 -0
- package/lib/cloudflare/certificate-pack.d.ts +1 -1
- package/lib/cloudflare/certificate-pack.d.ts.map +1 -1
- package/lib/cloudflare/certificate-pack.js +18 -88
- package/lib/cloudflare/certificate-pack.js.map +1 -1
- package/lib/cloudflare/compatibility-date.gen.d.ts +1 -1
- package/lib/cloudflare/compatibility-date.gen.js +1 -1
- package/lib/cloudflare/index.d.ts +3 -0
- package/lib/cloudflare/index.d.ts.map +1 -1
- package/lib/cloudflare/index.js +3 -0
- package/lib/cloudflare/index.js.map +1 -1
- package/lib/cloudflare/zone.d.ts +12 -0
- package/lib/cloudflare/zone.d.ts.map +1 -1
- package/lib/cloudflare/zone.js +35 -0
- package/lib/cloudflare/zone.js.map +1 -1
- package/lib/destroy.d.ts.map +1 -1
- package/lib/destroy.js +26 -18
- package/lib/destroy.js.map +1 -1
- package/lib/scope.d.ts.map +1 -1
- package/lib/scope.js +2 -2
- package/lib/scope.js.map +1 -1
- package/package.json +2 -1
- package/src/apply.ts +11 -12
- package/src/aws/control/types.ts +4 -4
- package/src/cloudflare/api-gateway-operation.ts +340 -0
- package/src/cloudflare/api-mitigation.ts +22 -0
- package/src/cloudflare/api-schema.ts +364 -0
- package/src/cloudflare/api-shield.ts +676 -0
- package/src/cloudflare/certificate-pack.ts +28 -152
- package/src/cloudflare/compatibility-date.gen.ts +1 -1
- package/src/cloudflare/index.ts +3 -0
- package/src/cloudflare/zone.ts +52 -0
- package/src/destroy.ts +26 -20
- package/src/scope.ts +3 -3
- package/templates/tanstack-start/package.json +3 -3
- package/templates/tanstack-start/vite.config.ts +2 -6
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
import * as yaml from "yaml";
|
|
2
|
+
import { Resource } from "../resource.js";
|
|
3
|
+
import { CloudflareApiError, handleApiError } from "./api-error.js";
|
|
4
|
+
import { createCloudflareApi, } from "./api.js";
|
|
5
|
+
import { findZoneForHostname } from "./zone.js";
|
|
6
|
+
/**
|
|
7
|
+
* Cloudflare API Gateway Schema manages OpenAPI v3 schemas for API validation.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ## Basic schema upload with inline YAML
|
|
11
|
+
*
|
|
12
|
+
* const apiSchema = await APISchema("my-api-schema", {
|
|
13
|
+
* zone: myZone,
|
|
14
|
+
* name: "my-api-v1"
|
|
15
|
+
* schema: `
|
|
16
|
+
* openapi: 3.0.0
|
|
17
|
+
* info:
|
|
18
|
+
* title: My API
|
|
19
|
+
* version: 1.0.0
|
|
20
|
+
* servers:
|
|
21
|
+
* - url: https://api.example.com
|
|
22
|
+
* paths:
|
|
23
|
+
* /users:
|
|
24
|
+
* get:
|
|
25
|
+
* operationId: getUsers
|
|
26
|
+
* responses:
|
|
27
|
+
* '200':
|
|
28
|
+
* description: Success
|
|
29
|
+
* `,
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* ## Schema upload from file
|
|
34
|
+
*
|
|
35
|
+
* const fileSchema = await APISchema("api-schema-from-file", {
|
|
36
|
+
* zone: "example.com",
|
|
37
|
+
* schemaFile: "./openapi.yaml",
|
|
38
|
+
* name: "production-api-v2",
|
|
39
|
+
* enabled: false // Upload but don't enable validation yet
|
|
40
|
+
* });
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ## Schema with typed OpenAPI object
|
|
44
|
+
*
|
|
45
|
+
* import type { OpenAPIV3 } from "openapi-types";
|
|
46
|
+
*
|
|
47
|
+
* const typedSchema: OpenAPIV3.Document = {
|
|
48
|
+
* openapi: "3.0.0",
|
|
49
|
+
* info: { title: "Typed API", version: "1.0.0" },
|
|
50
|
+
* paths: {
|
|
51
|
+
* "/health": {
|
|
52
|
+
* get: {
|
|
53
|
+
* operationId: "healthCheck",
|
|
54
|
+
* responses: { "200": { description: "OK" } }
|
|
55
|
+
* }
|
|
56
|
+
* }
|
|
57
|
+
* }
|
|
58
|
+
* };
|
|
59
|
+
*
|
|
60
|
+
* const schema = await APISchema("typed-schema", {
|
|
61
|
+
* zone: myZone,
|
|
62
|
+
* schema: typedSchema
|
|
63
|
+
* });
|
|
64
|
+
*/
|
|
65
|
+
export const APISchema = Resource("cloudflare::APISchema", async function (id, props) {
|
|
66
|
+
const api = await createCloudflareApi(props);
|
|
67
|
+
// Resolve zone ID and name
|
|
68
|
+
const zoneId = typeof props.zone === "string"
|
|
69
|
+
? (await findZoneForHostname(api, props.zone)).zoneId
|
|
70
|
+
: props.zone.id;
|
|
71
|
+
if (this.phase === "delete") {
|
|
72
|
+
if (this.output?.id) {
|
|
73
|
+
await deleteSchema(api, zoneId, this.output.id);
|
|
74
|
+
}
|
|
75
|
+
return this.destroy();
|
|
76
|
+
}
|
|
77
|
+
// Load schema content
|
|
78
|
+
const parsedSchema = props.schema;
|
|
79
|
+
let schemaDetails;
|
|
80
|
+
if (this.phase === "update" && this.output?.id) {
|
|
81
|
+
// Check if we need to replace due to name, schema content change, or disabling validation
|
|
82
|
+
if (props.name !== this.output.name ||
|
|
83
|
+
JSON.stringify(parsedSchema) !== JSON.stringify(this.output.schema) ||
|
|
84
|
+
(this.output.enabled === true && props.enabled === false)) {
|
|
85
|
+
// Name, schema content changed, or trying to disable validation - need to replace
|
|
86
|
+
this.replace();
|
|
87
|
+
}
|
|
88
|
+
// Update existing schema (can only update validation_enabled)
|
|
89
|
+
schemaDetails = await updateSchema(api, zoneId, this.output.id, {
|
|
90
|
+
validation_enabled: props.enabled !== false,
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
// Create new schema
|
|
95
|
+
schemaDetails = await uploadSchema(api, zoneId, {
|
|
96
|
+
file: yaml.stringify(parsedSchema),
|
|
97
|
+
name: props.name || id,
|
|
98
|
+
validation_enabled: props.enabled !== false,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
return this({
|
|
102
|
+
id: schemaDetails.id,
|
|
103
|
+
name: schemaDetails.name,
|
|
104
|
+
schema: parsedSchema,
|
|
105
|
+
source: schemaDetails.source,
|
|
106
|
+
enabled: schemaDetails.validationEnabled,
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
async function uploadSchema(api, zoneId, params) {
|
|
110
|
+
const body = {
|
|
111
|
+
source: params.file,
|
|
112
|
+
name: params.name,
|
|
113
|
+
kind: "openapi_v3",
|
|
114
|
+
validation_enabled: params.validation_enabled ?? true,
|
|
115
|
+
};
|
|
116
|
+
const response = await api.post(`/zones/${zoneId}/schema_validation/schemas`, body);
|
|
117
|
+
if (!response.ok) {
|
|
118
|
+
await handleApiError(response, "uploading", "schema", params.name);
|
|
119
|
+
}
|
|
120
|
+
const data = (await response.json());
|
|
121
|
+
return {
|
|
122
|
+
id: data.result.schema_id,
|
|
123
|
+
name: data.result.name,
|
|
124
|
+
source: data.result.source,
|
|
125
|
+
validationEnabled: data.result.validation_enabled,
|
|
126
|
+
createdAt: data.result.created_at,
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
async function updateSchema(api, zoneId, schemaId, params) {
|
|
130
|
+
const response = await api.patch(`/zones/${zoneId}/schema_validation/schemas/${schemaId}`, params);
|
|
131
|
+
if (!response.ok) {
|
|
132
|
+
await handleApiError(response, "updating", "schema", schemaId);
|
|
133
|
+
}
|
|
134
|
+
const data = (await response.json());
|
|
135
|
+
return {
|
|
136
|
+
id: data.result.schema_id,
|
|
137
|
+
name: data.result.name,
|
|
138
|
+
source: data.result.source,
|
|
139
|
+
validationEnabled: data.result.validation_enabled,
|
|
140
|
+
createdAt: data.result.created_at,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
export async function deleteSchema(api, zoneId, schemaId) {
|
|
144
|
+
const response = await api.delete(`/zones/${zoneId}/schema_validation/schemas/${schemaId}`);
|
|
145
|
+
const data = (await response.json());
|
|
146
|
+
if (response.status === 404) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
else if (response.status === 400 && data.errors[0].code === 19400) {
|
|
150
|
+
// Bad request: schema with this ID does not exist
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
if (!response.ok) {
|
|
154
|
+
await handleApiError(response, "deleting", "schema", schemaId);
|
|
155
|
+
}
|
|
156
|
+
else if (!data.success) {
|
|
157
|
+
throw new CloudflareApiError(data.errors[0].message, response);
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Get schema details
|
|
162
|
+
*/
|
|
163
|
+
export async function getSchema(api, zoneId, schemaId) {
|
|
164
|
+
const response = await api.get(`/zones/${zoneId}/schema_validation/schemas/${schemaId}`);
|
|
165
|
+
if (response.status === 404) {
|
|
166
|
+
return null;
|
|
167
|
+
}
|
|
168
|
+
if (!response.ok) {
|
|
169
|
+
await handleApiError(response, "getting", "schema", schemaId);
|
|
170
|
+
}
|
|
171
|
+
const data = (await response.json());
|
|
172
|
+
return {
|
|
173
|
+
id: data.result.schema_id,
|
|
174
|
+
name: data.result.name,
|
|
175
|
+
source: data.result.source,
|
|
176
|
+
validationEnabled: data.result.validation_enabled,
|
|
177
|
+
createdAt: data.result.created_at,
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* List all schemas in a zone
|
|
182
|
+
*/
|
|
183
|
+
export async function listSchemas(api, zoneId) {
|
|
184
|
+
const response = await api.get(`/zones/${zoneId}/schema_validation/schemas`);
|
|
185
|
+
if (!response.ok) {
|
|
186
|
+
await handleApiError(response, "listing", "schemas", zoneId);
|
|
187
|
+
}
|
|
188
|
+
const data = (await response.json());
|
|
189
|
+
return data.result.map((schema) => ({
|
|
190
|
+
id: schema.schema_id,
|
|
191
|
+
name: schema.name,
|
|
192
|
+
source: schema.source,
|
|
193
|
+
validationEnabled: schema.validation_enabled,
|
|
194
|
+
createdAt: schema.created_at,
|
|
195
|
+
}));
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=api-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-schema.js","sourceRoot":"","sources":["../../src/cloudflare/api-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
import type { OpenAPIV3 } from "openapi-types";
|
|
2
|
+
import { Resource } from "../resource.ts";
|
|
3
|
+
import { APIGatewayOperation } from "./api-gateway-operation.ts";
|
|
4
|
+
import type { APIMitigation, APIMitigations } from "./api-mitigation.ts";
|
|
5
|
+
import { APISchema } from "./api-schema.ts";
|
|
6
|
+
import { type CloudflareApi, type CloudflareApiOptions } from "./api.ts";
|
|
7
|
+
import type { Zone } from "./zone.ts";
|
|
8
|
+
/**
|
|
9
|
+
* Properties for creating or updating Schema Validation
|
|
10
|
+
*/
|
|
11
|
+
export interface APIShieldProps<S extends string | URL | OpenAPIV3.Document> extends CloudflareApiOptions {
|
|
12
|
+
/**
|
|
13
|
+
* The zone to configure schema validation for
|
|
14
|
+
*/
|
|
15
|
+
zone: string | Zone;
|
|
16
|
+
/**
|
|
17
|
+
* The name of the schema validation
|
|
18
|
+
*
|
|
19
|
+
* @default id
|
|
20
|
+
*/
|
|
21
|
+
name?: string;
|
|
22
|
+
/**
|
|
23
|
+
* The schema resource to use for validation
|
|
24
|
+
*
|
|
25
|
+
* Can be one of:
|
|
26
|
+
* 1. a string containing OpenAPI v3 schema
|
|
27
|
+
* 2. a string path to a file containing OpenAPI v3 schema
|
|
28
|
+
* 3. a file://, http:// or https:// URL pointing to an OpenAPI v3 schema
|
|
29
|
+
* 4. a literal OpenAPI v3 schema object
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* await APIShield("my-validation", {
|
|
33
|
+
* zone: myZone,
|
|
34
|
+
* schema: "path/to/openapi.yaml",
|
|
35
|
+
* });
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* await APIShield("my-validation", {
|
|
39
|
+
* zone: myZone,
|
|
40
|
+
* schema: new URL("file:///path/to/openapi.yaml"),
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* await APIShield("my-validation", {
|
|
45
|
+
* zone: myZone,
|
|
46
|
+
* schema: new URL("https://api.example.com/openapi.yaml"),
|
|
47
|
+
* });
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
* await APIShield("my-validation", {
|
|
51
|
+
* zone: myZone,
|
|
52
|
+
* schema: `
|
|
53
|
+
* openapi: 3.0.0
|
|
54
|
+
* info:
|
|
55
|
+
* title: My API
|
|
56
|
+
* version: 1.0.0
|
|
57
|
+
* paths:
|
|
58
|
+
* /users:
|
|
59
|
+
* get:
|
|
60
|
+
* operationId: getUsers
|
|
61
|
+
* responses:
|
|
62
|
+
* '200':
|
|
63
|
+
* description: Success
|
|
64
|
+
* `,
|
|
65
|
+
* });
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* await APIShield("my-validation", {
|
|
69
|
+
* zone: myZone,
|
|
70
|
+
* schema: `
|
|
71
|
+
* openapi: 3.0.0
|
|
72
|
+
* info:
|
|
73
|
+
* title: My API
|
|
74
|
+
* version: 1.0.0
|
|
75
|
+
* paths:
|
|
76
|
+
* /users:
|
|
77
|
+
* get:
|
|
78
|
+
* operationId: getUsers
|
|
79
|
+
* responses:
|
|
80
|
+
* '200':
|
|
81
|
+
* description: Success
|
|
82
|
+
* `
|
|
83
|
+
* });
|
|
84
|
+
*/
|
|
85
|
+
schema: S;
|
|
86
|
+
/**
|
|
87
|
+
* Whether to enable the schema validation
|
|
88
|
+
*
|
|
89
|
+
* @default true
|
|
90
|
+
*/
|
|
91
|
+
enabled?: boolean;
|
|
92
|
+
/**
|
|
93
|
+
* Per-operation validation overrides using OpenAPI-style path structure
|
|
94
|
+
*
|
|
95
|
+
* Can specify mitigations per HTTP method or a blanket action for all methods on a path:
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* // Per-method configuration
|
|
99
|
+
* {
|
|
100
|
+
* "/users": {
|
|
101
|
+
* get: "none",
|
|
102
|
+
* post: "block"
|
|
103
|
+
* },
|
|
104
|
+
* "/users/{id}": {
|
|
105
|
+
* delete: "block"
|
|
106
|
+
* }
|
|
107
|
+
* }
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* // Blanket action for all methods on a path
|
|
111
|
+
* {
|
|
112
|
+
* "/users": "none",
|
|
113
|
+
* "/users/{id}": "block",
|
|
114
|
+
* "/admin": "block"
|
|
115
|
+
* }
|
|
116
|
+
*/
|
|
117
|
+
mitigations?: APIMitigations<S extends string | URL ? OpenAPIV3.Document : S>;
|
|
118
|
+
/**
|
|
119
|
+
* Default validation action for all operations
|
|
120
|
+
*
|
|
121
|
+
* @default "none"
|
|
122
|
+
*/
|
|
123
|
+
defaultMitigation?: APIMitigation;
|
|
124
|
+
/**
|
|
125
|
+
* Action for requests that don't match any operation
|
|
126
|
+
* @default "none"
|
|
127
|
+
*/
|
|
128
|
+
unknownOperationMitigation?: APIMitigation;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Global validation settings
|
|
132
|
+
*/
|
|
133
|
+
export interface ValidationSettings {
|
|
134
|
+
/**
|
|
135
|
+
* Default mitigation action
|
|
136
|
+
*/
|
|
137
|
+
defaultMitigation: APIMitigation;
|
|
138
|
+
/**
|
|
139
|
+
* Override mitigation action for specific operations
|
|
140
|
+
*/
|
|
141
|
+
overrideMitigation?: APIMitigation;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Schema Validation output
|
|
145
|
+
*/
|
|
146
|
+
export interface APIShield<S extends OpenAPIV3.Document = OpenAPIV3.Document> extends Resource<"cloudflare::APIShield"> {
|
|
147
|
+
/**
|
|
148
|
+
* The schema resource
|
|
149
|
+
*/
|
|
150
|
+
schema: APISchema<S>;
|
|
151
|
+
/**
|
|
152
|
+
* Zone ID
|
|
153
|
+
*/
|
|
154
|
+
zoneId: string;
|
|
155
|
+
/**
|
|
156
|
+
* The API Schema's API Gateway Operations (and their respective mitigation actions)
|
|
157
|
+
*/
|
|
158
|
+
operations: APIGatewayOperation[];
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Cloudflare Schema Validation protects your API endpoints by validating incoming requests
|
|
162
|
+
* against an OpenAPI v3 schema. It can log or block requests that don't match your schema,
|
|
163
|
+
* helping prevent malformed requests and potential security issues.
|
|
164
|
+
*
|
|
165
|
+
* @example
|
|
166
|
+
* ## Basic schema validation with inline YAML
|
|
167
|
+
*
|
|
168
|
+
* Enable schema validation with a simple OpenAPI schema as YAML string
|
|
169
|
+
*
|
|
170
|
+
* const apiSchema = await APISchema("my-schema", {
|
|
171
|
+
* zone: myZone,
|
|
172
|
+
* schema: `
|
|
173
|
+
* openapi: 3.0.0
|
|
174
|
+
* info:
|
|
175
|
+
* title: My API
|
|
176
|
+
* version: 1.0.0
|
|
177
|
+
* servers:
|
|
178
|
+
* - url: https://api.example.com
|
|
179
|
+
* paths:
|
|
180
|
+
* /users:
|
|
181
|
+
* get:
|
|
182
|
+
* operationId: getUsers
|
|
183
|
+
* responses:
|
|
184
|
+
* '200':
|
|
185
|
+
* description: Success
|
|
186
|
+
* /users/{id}:
|
|
187
|
+
* get:
|
|
188
|
+
* operationId: getUser
|
|
189
|
+
* parameters:
|
|
190
|
+
* - name: id
|
|
191
|
+
* in: path
|
|
192
|
+
* required: true
|
|
193
|
+
* schema:
|
|
194
|
+
* type: string
|
|
195
|
+
* `,
|
|
196
|
+
* });
|
|
197
|
+
*
|
|
198
|
+
* const shield = await APIShield("api-validation", {
|
|
199
|
+
* zone: myZone,
|
|
200
|
+
* schema: apiSchema,
|
|
201
|
+
* defaultAction: "none"
|
|
202
|
+
* });
|
|
203
|
+
*
|
|
204
|
+
* @example
|
|
205
|
+
* ## API Shield with typed OpenAPI object
|
|
206
|
+
*
|
|
207
|
+
* Use strongly-typed OpenAPI v3 objects for better IDE support
|
|
208
|
+
*
|
|
209
|
+
* import type { OpenAPIV3 } from "openapi-types";
|
|
210
|
+
*
|
|
211
|
+
* const apiSchema: OpenAPIV3.Document = {
|
|
212
|
+
* openapi: "3.0.0",
|
|
213
|
+
* info: {
|
|
214
|
+
* title: "My API",
|
|
215
|
+
* version: "1.0.0",
|
|
216
|
+
* },
|
|
217
|
+
* servers: [
|
|
218
|
+
* { url: "https://api.example.com" }
|
|
219
|
+
* ],
|
|
220
|
+
* paths: {
|
|
221
|
+
* "/users": {
|
|
222
|
+
* get: {
|
|
223
|
+
* operationId: "getUsers",
|
|
224
|
+
* responses: {
|
|
225
|
+
* "200": {
|
|
226
|
+
* description: "Success",
|
|
227
|
+
* content: {
|
|
228
|
+
* "application/json": {
|
|
229
|
+
* schema: {
|
|
230
|
+
* type: "array",
|
|
231
|
+
* items: {
|
|
232
|
+
* type: "object",
|
|
233
|
+
* properties: {
|
|
234
|
+
* id: { type: "string" },
|
|
235
|
+
* name: { type: "string" }
|
|
236
|
+
* }
|
|
237
|
+
* }
|
|
238
|
+
* }
|
|
239
|
+
* }
|
|
240
|
+
* }
|
|
241
|
+
* }
|
|
242
|
+
* }
|
|
243
|
+
* }
|
|
244
|
+
* }
|
|
245
|
+
* }
|
|
246
|
+
* };
|
|
247
|
+
*
|
|
248
|
+
* const schema = await APISchema("my-schema", {
|
|
249
|
+
* zone: myZone,
|
|
250
|
+
* schema: apiSchema,
|
|
251
|
+
* });
|
|
252
|
+
*
|
|
253
|
+
* const shield = await APIShield("api-validation", {
|
|
254
|
+
* zone: myZone,
|
|
255
|
+
* schema: schema,
|
|
256
|
+
* defaultAction: "none"
|
|
257
|
+
* });
|
|
258
|
+
*
|
|
259
|
+
* @example
|
|
260
|
+
* ## API Shield with file
|
|
261
|
+
*
|
|
262
|
+
* Load schema from an external file with custom settings
|
|
263
|
+
*
|
|
264
|
+
* const schema = await APISchema("my-schema", {
|
|
265
|
+
* zone: "example.com",
|
|
266
|
+
* schema: new URL("file:///path/to/openapi.yaml"),
|
|
267
|
+
* name: "production-api-v2",
|
|
268
|
+
* });
|
|
269
|
+
*
|
|
270
|
+
* const shield = await APIShield("api-validation", {
|
|
271
|
+
* zone: "example.com",
|
|
272
|
+
* schema: schema,
|
|
273
|
+
* defaultAction: "none",
|
|
274
|
+
* mitigations: {
|
|
275
|
+
* "/users": {
|
|
276
|
+
* get: "none", // No mitigation for read operations
|
|
277
|
+
* post: "log", // Log violations for writes (requires paid plan)
|
|
278
|
+
* },
|
|
279
|
+
* "/users/{id}": {
|
|
280
|
+
* delete: "block" // Block destructive operations (requires paid plan)
|
|
281
|
+
* }
|
|
282
|
+
* },
|
|
283
|
+
* unknownOperationAction: "none"
|
|
284
|
+
* });
|
|
285
|
+
*
|
|
286
|
+
* @example
|
|
287
|
+
* ## Monitor API traffic without impact
|
|
288
|
+
*
|
|
289
|
+
* Use validation in monitoring mode to understand traffic patterns
|
|
290
|
+
*
|
|
291
|
+
* const schema = await APISchema("my-schema", {
|
|
292
|
+
* zone: myZone,
|
|
293
|
+
* schema: new URL("file:///path/to/api-schema.json"),
|
|
294
|
+
* });
|
|
295
|
+
*
|
|
296
|
+
* const monitoring = await APIShield("api-monitoring", {
|
|
297
|
+
* zone: myZone,
|
|
298
|
+
* schema: schema,
|
|
299
|
+
* defaultAction: "none"
|
|
300
|
+
* });
|
|
301
|
+
*
|
|
302
|
+
* @example
|
|
303
|
+
* ## Log schema violations
|
|
304
|
+
*
|
|
305
|
+
* Track non-compliant requests without blocking (requires paid plan)
|
|
306
|
+
*
|
|
307
|
+
* const schema = await APISchema("my-schema", {
|
|
308
|
+
* zone: myZone,
|
|
309
|
+
* schema: new URL("file:///path/to/api-schema.json"),
|
|
310
|
+
* });
|
|
311
|
+
*
|
|
312
|
+
* const withLogging = await APIShield("api-logging", {
|
|
313
|
+
* zone: myZone,
|
|
314
|
+
* schema: schema,
|
|
315
|
+
* defaultAction: "log"
|
|
316
|
+
* });
|
|
317
|
+
*
|
|
318
|
+
* @example
|
|
319
|
+
* ## Protect critical endpoints with blanket mitigations
|
|
320
|
+
*
|
|
321
|
+
* Apply mitigations to entire paths or specific methods (requires paid plan)
|
|
322
|
+
*
|
|
323
|
+
* const schema = await APISchema("my-schema", {
|
|
324
|
+
* zone: myZone,
|
|
325
|
+
* schema: new URL("file:///path/to/api-schema.json"),
|
|
326
|
+
* });
|
|
327
|
+
*
|
|
328
|
+
* const protection = await APIShield("api-protection", {
|
|
329
|
+
* zone: myZone,
|
|
330
|
+
* schema: schema,
|
|
331
|
+
* defaultAction: "log",
|
|
332
|
+
* mitigations: {
|
|
333
|
+
* "/admin": "block", // Block all methods on admin endpoints
|
|
334
|
+
* "/payments": {
|
|
335
|
+
* post: "block", // Block payment creation
|
|
336
|
+
* put: "block" // Block payment updates
|
|
337
|
+
* },
|
|
338
|
+
* "/users/{id}": {
|
|
339
|
+
* delete: "block" // Block user deletion
|
|
340
|
+
* },
|
|
341
|
+
* "/public": "none", // Allow all methods on public endpoints
|
|
342
|
+
* "/products": "none" // Allow all methods on products
|
|
343
|
+
* }
|
|
344
|
+
* });
|
|
345
|
+
*
|
|
346
|
+
* @see https://developers.cloudflare.com/api-shield/security/schema-validation/
|
|
347
|
+
*/
|
|
348
|
+
export declare function APIShield<S extends string | URL | OpenAPIV3.Document>(id: string, props: APIShieldProps<S>): Promise<APIShield<S extends string | URL ? OpenAPIV3.Document : S>>;
|
|
349
|
+
/**
|
|
350
|
+
* Get global schema validation settings for a zone
|
|
351
|
+
*/
|
|
352
|
+
export declare function getGlobalSettingsForZone(api: CloudflareApi, zoneId: string): Promise<CloudflareGlobalSettings>;
|
|
353
|
+
export interface CloudflareGlobalSettings {
|
|
354
|
+
validation_default_mitigation_action: APIMitigation;
|
|
355
|
+
validation_override_mitigation_action?: APIMitigation;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* Extract operations from an OpenAPI schema
|
|
359
|
+
*/
|
|
360
|
+
export declare function parseSchemaOperations(schema: OpenAPIV3.Document): Array<{
|
|
361
|
+
method: string;
|
|
362
|
+
endpoint: string;
|
|
363
|
+
operationId?: string;
|
|
364
|
+
host: string;
|
|
365
|
+
}>;
|
|
366
|
+
//# sourceMappingURL=api-shield.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-shield.d.ts","sourceRoot":"","sources":["../../src/cloudflare/api-shield.ts"],"names":[],"mappings":"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"}
|