-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(*): add optional wasm filter config validation #11568
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
message: Add support for optional Wasm filter configuration schemas | ||
type: feature | ||
scope: Core | ||
prs: | ||
- 11568 | ||
jiras: | ||
- KAG-662 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
--- | ||
-- JSON schema validation. | ||
-- | ||
-- | ||
local _M = {} | ||
|
||
local lrucache = require "resty.lrucache" | ||
local jsonschema = require "resty.ljsonschema" | ||
local metaschema = require "resty.ljsonschema.metaschema" | ||
local utils = require "kong.tools.utils" | ||
local cjson = require "cjson" | ||
|
||
local type = type | ||
local cjson_encode = cjson.encode | ||
local sha256_hex = utils.sha256_hex | ||
|
||
|
||
---@class kong.db.schema.json.schema_doc : table | ||
--- | ||
---@field id string|nil | ||
---@field ["$id"] string|nil | ||
---@field ["$schema"] string|nil | ||
---@field type string | ||
|
||
|
||
-- The correct identifier for draft-4 is 'http://json-schema.org/draft-04/schema#' | ||
-- with the the fragment (#) intact. Newer editions use an identifier _without_ | ||
-- the fragment (e.g. 'https://json-schema.org/draft/2020-12/schema'), so we | ||
-- will be lenient when comparing these strings. | ||
assert(type(metaschema.id) == "string", | ||
"JSON metaschema .id not defined or not a string") | ||
local DRAFT_4_NO_FRAGMENT = metaschema.id:gsub("#$", "") | ||
local DRAFT_4 = DRAFT_4_NO_FRAGMENT .. "#" | ||
|
||
|
||
---@type table<string, table> | ||
local schemas = {} | ||
|
||
|
||
-- Creating a json schema validator is somewhat expensive as it requires | ||
-- generating and evaluating some Lua code, so we memoize this step with | ||
-- a local LRU cache. | ||
local cache = lrucache.new(1000) | ||
|
||
local schema_cache_key | ||
do | ||
local cache_keys = setmetatable({}, { __mode = "k" }) | ||
|
||
--- | ||
-- Generate a unique cache key for a schema document. | ||
-- | ||
---@param schema kong.db.schema.json.schema_doc | ||
---@return string | ||
function schema_cache_key(schema) | ||
local cache_key = cache_keys[schema] | ||
|
||
if not cache_key then | ||
cache_key = "hash://" .. sha256_hex(cjson_encode(schema)) | ||
cache_keys[schema] = cache_key | ||
end | ||
|
||
return cache_key | ||
end | ||
end | ||
|
||
|
||
---@param id any | ||
---@return boolean | ||
local function is_draft_4(id) | ||
return id | ||
and type(id) == "string" | ||
and (id == DRAFT_4 or id == DRAFT_4_NO_FRAGMENT) | ||
end | ||
|
||
|
||
---@param id any | ||
---@return boolean | ||
local function is_non_draft_4(id) | ||
return id | ||
and type(id) == "string" | ||
and (id ~= DRAFT_4 and id ~= DRAFT_4_NO_FRAGMENT) | ||
end | ||
|
||
|
||
--- | ||
-- Validate input according to a JSON schema document. | ||
-- | ||
---@param input any | ||
---@param schema kong.db.schema.json.schema_doc | ||
---@return boolean? ok | ||
---@return string? error | ||
local function validate(input, schema) | ||
assert(type(schema) == "table") | ||
|
||
-- we are validating a JSON schema document and need to ensure that it is | ||
-- not using supported JSON schema draft/version | ||
if is_draft_4(schema.id or schema["$id"]) | ||
and is_non_draft_4(input["$schema"]) | ||
then | ||
return nil, "unsupported document $schema: '" .. input["$schema"] .. | ||
"', expected: " .. DRAFT_4 | ||
end | ||
|
||
local cache_key = schema_cache_key(schema) | ||
|
||
local validator = cache:get(cache_key) | ||
|
||
if not validator then | ||
validator = assert(jsonschema.generate_validator(schema, { | ||
name = cache_key, | ||
-- lua-resty-ljsonschema's default behavior for detecting an array type | ||
-- is to compare its metatable against `cjson.array_mt`. This is | ||
-- efficient, but we can't assume that all inputs will necessarily | ||
-- conform to this, so we opt to use the heuristic approach instead | ||
-- (determining object/array type based on the table contents). | ||
array_mt = false, | ||
})) | ||
cache:set(cache_key, validator) | ||
end | ||
|
||
return validator(input) | ||
end | ||
|
||
|
||
---@type table | ||
_M.metaschema = metaschema | ||
|
||
|
||
_M.validate = validate | ||
|
||
|
||
--- | ||
-- Validate a JSON schema document. | ||
-- | ||
-- This is primarily for use in `kong.db.schema.metaschema` | ||
-- | ||
---@param input kong.db.schema.json.schema_doc | ||
---@return boolean? ok | ||
---@return string? error | ||
function _M.validate_schema(input) | ||
local typ = type(input) | ||
|
||
if typ ~= "table" then | ||
return nil, "schema must be a table" | ||
end | ||
|
||
return validate(input, _M.metaschema) | ||
end | ||
|
||
|
||
--- | ||
-- Add a JSON schema document to the local registry. | ||
-- | ||
---@param name string | ||
---@param schema kong.db.schema.json.schema_doc | ||
function _M.add_schema(name, schema) | ||
schemas[name] = schema | ||
end | ||
|
||
|
||
--- | ||
-- Retrieve a schema from local storage by name. | ||
-- | ||
---@param name string | ||
---@return table|nil schema | ||
function _M.get_schema(name) | ||
return schemas[name] | ||
end | ||
|
||
|
||
--- | ||
-- Remove a schema from local storage by name (if it exists). | ||
-- | ||
---@param name string | ||
---@return table|nil schema | ||
function _M.remove_schema(name) | ||
schemas[name] = nil | ||
end | ||
|
||
|
||
return _M |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason we don't need
at_least_one_of
for config, json_config?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There can be filters that take no config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, configuration needs to remain optional, as it's perfectly valid to have a proxy-wasm filter that requires no configuration to function.
Specifying a schema for your filter's
json_config
using this newmy-filter.meta.json
method is one means of making it effectively required though.