-
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
Conversation
After a chat with @hishamhm today, a good chunk of this is going to get re-shaped, so I dismissed the pending reviews for now. |
02cee27
to
fbba361
Compare
b9f6c73
to
bc03afe
Compare
b7bf6e7
to
8496922
Compare
19ff350
to
8399ea2
Compare
a23a528
to
8d86e51
Compare
f811372
to
a4e646b
Compare
{ raw_config = { type = "string", required = false, }, }, | ||
{ enabled = { type = "boolean", default = true, required = true, }, }, | ||
|
||
{ config = { | ||
type = "json", | ||
required = false, | ||
json_schema = { | ||
parent_subschema_key = "name", | ||
namespace = constants.SCHEMA_NAMESPACES.PROXY_WASM_FILTERS, | ||
optional = true, | ||
}, | ||
}, | ||
}, |
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.
I'm thinking it might be better to reverse this, so config
stays the same, and we add a new field called json_config
.
- It would simplify this PR, because we'd no longer require a migration to rename existing
config
fields toraw_config
. - Users still reap the same convenience benefit of not needing to serialize their configuration, and
config
/json_config
is arguably a bit more intuitive. - It's a little bit more forward-compatible on the off chance we want to support a different serialization format. Having a choice of
config | json_config | yaml_config
is more intuitive thanconfig | raw_config | yaml_config
I don't think config
/raw_config
is bad by any stretch, but if we want to go that route we can always do the config
=> raw_config
/ json_config
=> config
swap in a smaller PR some time in the coming weeks.
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.
BTW I have a commit for this change that is passing tests locally and ready to be pushed, so it won't add any extra turnaround time if we choose to do this. :)
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.
This feels like the right move for this PR; I'm making a judgment call and pushing that commit. As mentioned, I'm fine with re-introducing the change before the release if we'd like to.
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.
I think it's better for it to remain config
, not json_config
. At the level of our entity configuration, the meaning of config
is that it is our nested configuration data structure, which happens to be validated via JSON Schema and which we happen to serialize as JSON when we pass to the filter. If we ever want to support different serialization formats, we can still use the same config
, still validate it using JSON Schema, and then use a new field to specify the serialization format, instead of adding a new data-storage field.
As a side benefit, config
helps pushing the JSON-based format as the "preferred default".
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.
Sounds reasonable enough to me; I don't have a strong opinion either way. If you feel like doing some more old school gateway development you can push this through while I'm out next week. Otherwise I don't think it should be too difficult for me to get it over the line in time for feature freeze when I am back at my desk.
@@ -70,6 +70,11 @@ | |||
- libc.so.6 | |||
Runpath : /usr/local/kong/lib | |||
|
|||
- Path : /usr/local/lib/lua/5.1/cjson.so |
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.
Explanation: this feature depends on lua-resty-ljsonschema
, which explicitly takes lua-cjson
as a dependency, so we're now getting an additional cjson.so
in the manifest. On my machine this file is a measly 42K, so we're not blowing up our package/image sizes.
If we want, I can put the lua-resty-ljsonschema
addition in its own commit before merging so that it's more clear to future us why this is here.
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.
Update: I did put this in its own commit, but feel free to squash if that makes more sense.
@@ -541,18 +580,83 @@ local function get_filter_chain_for_request(route, service) | |||
end | |||
|
|||
|
|||
---@param filters kong.configuration.wasm_filter[]|nil | |||
local function discover_filter_metadata(filters) |
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.
I think it's just about time to refactor some code out of kong.runloop.wasm
and into a new kong.wasm
module that is not focused on runloop/proxy things, but that will be done later.
end | ||
end | ||
end | ||
|
||
if field.type == "json" | ||
and field.json_schema | ||
and field.json_schema.parent_subschema_key | ||
then | ||
local parent_subschema_key = field.json_schema.parent_subschema_key | ||
local found = false | ||
|
||
for i = 1, #parent_schema.fields do | ||
local item = parent_schema.fields[i] | ||
local parent_field_name = next(item) | ||
local parent_field = item[parent_field_name] | ||
|
||
if parent_subschema_key == parent_field_name then | ||
if parent_field.type ~= "string" then | ||
errors[k] = errors[k] or {} | ||
errors[k].json_schema = { | ||
parent_subschema_key = meta_errors.JSON_PARENT_KEY_TYPE | ||
} | ||
end | ||
found = true | ||
break | ||
end | ||
end | ||
|
||
if not found then | ||
errors[k] = errors[k] or {} | ||
errors[k].json_schema = { | ||
parent_subschema_key = meta_errors.JSON_PARENT_KEY | ||
} | ||
return | ||
end | ||
end |
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.
FYI for the sake of stylistic consistency, this was copy/pasted and modified from the subschema_key
metaschema validation code, since it serves a similar function.
22bb0ed
to
017ee6c
Compare
Rebased and cleaned up git history. From my side this is ready to go once the tests are green. |
}, | ||
|
||
}, | ||
entity_checks = { |
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 new my-filter.meta.json
method is one means of making it effectively required though.
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.
This PR LGTM. Great work, @flrgh!
I left a tiny nitpick comment that can be addressed in a future PR (or never). Also, there is some code style inconsistency, most related to leaving a single line between logical blocks.
Neither are blockers, but I am not approving right now as there is a conflict pending of resolution. I will try to fix it, rebase to latest master
and wait for green tests before approving/merging.
for _, filter in ipairs(chain.filters) do | ||
if filter.enabled then | ||
-- serialize all JSON configurations up front | ||
if not filter.config and filter.json_config ~= nil then |
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.
if not filter.config and filter.json_config ~= nil then | |
if filter.json_config then |
Nit: Per kong.db.schema.entities.filter_chains
those fields are already mutually exclusive.
This rock takes lua-cjson as a dependency, so now we have an additional cjson.so file in the manifest. It's looking like about 42K in size, so it shouldn't bloat our packages/images
017ee6c
to
0e3f293
Compare
0e3f293
to
5dea9ef
Compare
Changes:
json
field type with JSON schema-powered validation{{ filter }}.meta.json
files for providing Kong with Wasm filter metadata (such as configuration schema)json_config
field tofilter_chains.filters[]
which is optionally validated against JSON schema from the filter metadata file (if present)KAG-662