-
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(cors) match configured origins as a regular expression #2482
Conversation
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.
Nice and user-friendly approach 👍 Just a few things to tweak imo
kong/plugins/cors/handler.lua
Outdated
@@ -25,21 +25,26 @@ local function configure_origin(ngx, conf) | |||
if #conf.origins == 1 then | |||
if conf.origins[1] == "*" then | |||
ngx.ctx.cors_allow_all = true | |||
ngx.header["Access-Control-Allow-Origin"] = "*" | |||
return | |||
|
|||
else |
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.
because of the new return
in the previous branch, this else
becomes obsolete, better remove it
kong/plugins/cors/handler.lua
Outdated
-- if this doesnt look like a regex, set the ACAO header directly | ||
-- otherwise, we'll fall through to an iterative search and | ||
-- set the ACAO header based on the client Origin | ||
if re_find(conf.origins[1], "^[A-Za-z0-9.:/-]+$", "jo") 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.
I think we should log possible errors here, just as a standardized practice among our codebase when using the ngx.re.*
API (I believe other places do it, or should).
kong/plugins/cors/schema.lua
Outdated
for _, origin in ipairs(value) do | ||
local _, err = re_match("just a string to test", origin) | ||
if err then | ||
return false, "origin " .. origin .. " is not a valid regex" |
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.
Mind adding single quotes around the user-provided origin that failed this check? Error messages in our codebase do that, or at least, should :)
BTW: cool trick!
["www.example.com"] = true, | ||
["example-foo.com"] = true, | ||
["www.example-foo.com"] = true, | ||
["www.example-fo0.com"] = false |
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.
style: missing a trailing comma, I can see this list being revised in the future
}) | ||
assert.res_status(200, res) | ||
assert.equal(domains[domain] and domain or nil, | ||
res.headers["Access-Control-Allow-Origin"]) |
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.
style: arguments on subsequent lines should align below the first argument (domains[domain]
) of the caller's line
local ok, err = validate_entity({ origins = mock_origins }, cors_schema) | ||
|
||
assert.False(ok) | ||
assert.same(err.origins, "origin " .. mock_origins[2] .. " is not a valid regex") |
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 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.
ah yep, i had this as assert.same
as i was comparing the whole table, then just switched to the field without changing the assertion, good catch
kong/plugins/cors/handler.lua
Outdated
-- if this doesnt look like a regex, set the ACAO header directly | ||
-- otherwise, we'll fall through to an iterative search and | ||
-- set the ACAO header based on the client Origin | ||
local plain, err = re_find(conf.origins[1], "^[A-Za-z0-9.:/-]+$", "jo") |
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.
local from, to, err =
, as per our recent change to the router :)
kong/plugins/cors/handler.lua
Outdated
-- set the ACAO header based on the client Origin | ||
local plain, err = re_find(conf.origins[1], "^[A-Za-z0-9.:/-]+$", "jo") | ||
if err then | ||
ngx.log(ngx.ERR, "[cors] could not inspect origin for type") |
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.
Shouldn't we log the error itself?
"[cors] could not determine if configured origin is a regex: ", err)
local ok, err = validate_entity({ origins = mock_origins }, cors_schema) | ||
|
||
assert.False(ok) | ||
assert.same("origin '" .. mock_origins[2] .. "' is not a valid regex", err.origins) |
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 is still assert.same
)
kong/plugins/cors/handler.lua
Outdated
-- if this doesnt look like a regex, set the ACAO header directly | ||
-- otherwise, we'll fall through to an iterative search and | ||
-- set the ACAO header based on the client Origin | ||
local from, to, err = re_find(conf.origins[1], "^[A-Za-z0-9.:/-]+$", "jo") |
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 this will fail linting because to
is unused :(
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.
seems like it didn't, maybe we're ignoring those now? That's ok I think!
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.
Yes, I ran the linter before submitting as I think this came up once before? I'll make a note to look over linter behavior shortly.
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.
Yes, it happened on a spec/
file which, while not elegant, was acceptable. It is worrying that it is happening in a source file 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.
Shall we adjust to local from, _, err
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.
Depends on the linter's current state of rules (maight be desired, might be a bug), I will check... Feel free to if you have the chance!
Use the ngx.re API to match configured origins as regular expressions against the client Origin header. In cases where a single origin is configured for the plugin, set the ACAO header if the configuration contains only non-PCRE metacharacters; otherwise, treat the single configured origin as a though multiple origins were configured, by iterating through the array and setting the ACAO header based on the client Origin.
configured in case of non-matched. The CORS plugin currently always sets the ACAO header based on the plugin configuration if the configuration only has a single entry and contains only non-PCRE metacharacters. This behavior is first introduced in #2482 and doesn't seem to have any real impact on the functionality I think. But this seems is not following the [mozilla guidelines](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin) > Specifies an origin. Only a single origin can be specified. If the server supports clients from multiple origins, it must return the origin for the specific client making the request. This fixes behavior by no longer sending an ACAO header in this case.
configured in case of non-matched. The CORS plugin currently always sets the ACAO header based on the plugin configuration if the configuration only has a single entry and contains only non-PCRE metacharacters. This behavior is first introduced in #2482 and doesn't seem to have any real impact on the functionality I think. But this seems is not following the [mozilla guidelines](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin) > Specifies an origin. Only a single origin can be specified. If the server supports clients from multiple origins, it must return the origin for the specific client making the request. This fixes behavior by no longer sending an ACAO header in this case.
configured in case of non-matched. The CORS plugin currently always sets the ACAO header based on the plugin configuration if the configuration only has a single entry and contains only non-PCRE metacharacters. This behavior is first introduced in #2482 and doesn't seem to have any real impact on the functionality I think. But this seems is not following the [mozilla guidelines](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin) > Specifies an origin. Only a single origin can be specified. If the server supports clients from multiple origins, it must return the origin for the specific client making the request. This fixes behavior by no longer sending an ACAO header in this case.
Summary
Use the ngx.re API to match configured origins as regular expressions against the client Origin header. In cases where a single origin is configured for the plugin, set the ACAO header based on the plugin configuration if the configuration contains only non-PCRE metacharacters; otherwise, treat the single configured origin as a though multiple origins were configured, by iterating through the array and setting the ACAO header based on the client Origin.
This changeset will be accompanied by a sister PR that includes a migration of existing configured
origins
to escape.
characters. Because such a migration will target Kong 0.11, and this PR targets Kong 0.10.3, we will commit these as separate PRs.Full changelog
origins
as a full expressionorigins
as a valid regular expression.