Proxy-Wasm Filter Configuration

Proxy-Wasm Filter Configuration

As of this writing, only Draft 4 of the JSON schema specification is supported.

Purpose

The Proxy-Wasm specification defines filter runtime configuration only as an array of bytes. The finer details of configuration-handling (encoding, serialization, validation) are left to the filter to implement.

As a result, Proxy-Wasm implementations have no means of validating configuration until runtime, when a filter instance is created. In Kong Gateway, executing a filter with an invalid configuration will trigger a 500 error, as Kong has no choice but to assume that it is not safe to continue processing the request.

This presents a challenge for filter deployment: how do operators prevent users from creating improperly-configured filters?

JSON Schema for Filter Configuration

Filters that take configuration in JSON form can optionally make use of Kong Gateway’s JSON schema validation.

This is accomplished by providing a JSON schema in a filter metadata file adjacent to the filter’s bytecode within the wasm_filters_path directory:

  1. /path/to/wasm-filters
  2. ├── my-filter.wasm
  3. ├── my-filter.meta.json
  4. ├── other-filter.wasm
  5. └── other-filter.meta.json

The configuration schema is supplied in the config_schema metadata field. For example:

  1. {
  2. "config_schema": {
  3. "type": "object",
  4. "properties": {
  5. "my-property": {
  6. "type": "string"
  7. }
  8. },
  9. "required": [
  10. "my-property"
  11. ]
  12. }
  13. }

The presence of a schema allows Kong to interpret the filter configuration as JSON instead of treating it as an opaque string when reading and writing request and response bodies.

Without a schema, JSON filter configuration must be serialized as a string in API requests:

  1. POST /services/test/filter-chains HTTP/1.1
  2. Host: kong
  3. User-Agent: curl/8.0.1
  4. Content-Type: application/json
  5. Accept: application/json
  6. Content-Length: 143
  7. {
  8. "name": "my-filter-chain",
  9. "filters": [
  10. {
  11. "name": "my-filter",
  12. "config": "{ \"my-property\": \"My value\" }"
  13. }
  14. ]
  15. }

But with a schema, the configuration is accepted as JSON:

  1. POST /services/test/filter-chains HTTP/1.1
  2. Host: kong
  3. User-Agent: curl/8.0.1
  4. Content-Type: application/json
  5. Accept: application/json
  6. Content-Length: 151
  7. {
  8. "name": "my-filter-chain",
  9. "filters": [
  10. {
  11. "name": "my-filter",
  12. "config": {
  13. "my-property": "My value"
  14. }
  15. }
  16. ]
  17. }

Example

In this example, set-response-header is a filter that sets a single response header. It takes a JSON configuration with a header name and value.

Here are the contents of $KONG_WASM_FILTERS_PATH/set-response-header.meta.json:

  1. {
  2. "config_schema": {
  3. "type": "object",
  4. "properties": {
  5. "header-name": {
  6. "type": "string"
  7. },
  8. "header-value": {
  9. "type": "string"
  10. }
  11. },
  12. "required": [
  13. "header-name",
  14. "header-value"
  15. ]
  16. }
  17. }

With the schema in place, configurations that do not pass validation are rejected:

  1. POST /services/test/filter-chains HTTP/1.1
  2. Host: kong
  3. User-Agent: curl/8.0.1
  4. Content-Type: application/json
  5. Accept: application/json
  6. Content-Length: 171
  7. {
  8. "name": "my-filter-chain",
  9. "filters": [
  10. {
  11. "name": "set-response-header",
  12. "config": {
  13. "header-name": "X-My-Custom-Header"
  14. }
  15. }
  16. ]
  17. }

Response:

  1. HTTP/1.1 400 Bad Request
  2. Access-Control-Allow-Credentials: true
  3. Access-Control-Allow-Origin: *
  4. Connection: keep-alive
  5. Content-Length: 203
  6. Content-Type: application/json; charset=utf-8
  7. Date: Mon, 06 Nov 2023 00:11:33 GMT
  8. Server: kong/3.6.0
  9. X-Kong-Admin-Latency: 6
  10. {
  11. "code": 2,
  12. "fields": {
  13. "filters": [
  14. {
  15. "config": "property header-value is required"
  16. }
  17. ]
  18. },
  19. "message": "schema violation (filters.1: {\n config = \"property header-value is required\"\n})",
  20. "name": "schema violation"
  21. }

Whereas valid configurations are accepted:

  1. POST /services/test/filter-chains HTTP/1.1
  2. Host: kong
  3. User-Agent: curl/8.0.1
  4. Content-Type: application/json
  5. Accept: application/json
  6. Content-Length: 211
  7. {
  8. "name": "my-filter-chain",
  9. "filters": [
  10. {
  11. "name": "set-response-header",
  12. "config": {
  13. "header-name": "X-My-Custom-Header",
  14. "header-value": "Hello, Wasm!"
  15. }
  16. }
  17. ]
  18. }

Response:

  1. HTTP/1.1 201 Created
  2. Access-Control-Allow-Credentials: true
  3. Access-Control-Allow-Origin: *
  4. Connection: keep-alive
  5. Content-Length: 348
  6. Content-Type: application/json; charset=utf-8
  7. Date: Mon, 06 Nov 2023 00:21:30 GMT
  8. Server: kong/3.6.0
  9. X-Kong-Admin-Latency: 23
  10. {
  11. "created_at": 1699230090,
  12. "enabled": true,
  13. "filters": [
  14. {
  15. "config": {
  16. "header-name": "X-My-Custom-Header",
  17. "header-value": "Hello, Wasm!"
  18. },
  19. "enabled": true,
  20. "name": "set-response-header"
  21. }
  22. ],
  23. "id": "da8659e3-db85-435f-ba62-f95ec7615ddc",
  24. "name": "my-filter-chain",
  25. "route": null,
  26. "service": {
  27. "id": "992c4491-9962-48ff-8d5d-249ba82848d1"
  28. },
  29. "tags": null,
  30. "updated_at": 1699230090
  31. }

Further Reading


Previous Create a Proxy-Wasm filter