Skip to content
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

Ensure that the apicast post_action phase runs only if access runs #985

Merged
merged 7 commits into from
Jan 23, 2019
Prev Previous commit
Next Next commit
policy/apicast: add flag to run post_action() only if acess() ran
This commit adds a flag to run post_action() only when access() was
executed.

Other policies can call ngx.exit(4xx) on access() or rewrite. If they're
placed before APIcast in the chain, the request will be denied and this
access() phase will no be run. However, ngx.exit(4xx) skips some phases,
but not post_action. Post_action would run if we did not set this flag,
and we want to avoid that. Otherwise, post_action could call authrep()
even when another policy denied the request.
davidor committed Jan 23, 2019
commit afe7fb5876c843b681bba55ea422ed3b6145084b
12 changes: 12 additions & 0 deletions gateway/src/apicast/policy/apicast/apicast.lua
Original file line number Diff line number Diff line change
@@ -62,6 +62,8 @@ end
function _M:post_action(context)
if context.skip_apicast_post_action then return end

if not (context[self] and context[self].run_post_action) then return end

local p = context and context.proxy or ngx.ctx.proxy or self.proxy

if p then
@@ -75,6 +77,16 @@ end
function _M:access(context)
if context.skip_apicast_access then return end

-- Flag to run post_action() only when access() was executed.
-- Other policies can call ngx.exit(4xx) on access() or rewrite. If they're
-- placed before APIcast in the chain, the request will be denied and this
-- access() phase will no be run. However, ngx.exit(4xx) skips some phases,
-- but not post_action. Post_action would run if we did not set this flag,
-- and we want to avoid that. Otherwise, post_action could call authrep()
-- even when another policy denied the request.
context[self] = context[self] or {}
context[self].run_post_action = true

local ctx = ngx.ctx
local p = context and context.proxy or ctx.proxy or self.proxy

48 changes: 48 additions & 0 deletions spec/policy/apicast/apicast_spec.lua
Original file line number Diff line number Diff line change
@@ -9,4 +9,52 @@ describe('APIcast policy', function()
it('has a version', function()
assert.truthy(_M._VERSION)
end)

describe('.access', function()
it('stores in the context a flag that indicates that post_action should be run', function()
local context = {}
local apicast = _M.new()

apicast:access(context)

assert.is_true(context[apicast].run_post_action)
end)
end)

describe('.post_action', function()
describe('when the "run_post_action" flag is set to true', function()
it('runs its logic', function()
-- A way to know whether the logic of the method run consists of
-- checking if post_action() was called on the proxy of the context.

local apicast = _M.new()
local context = {
proxy = { post_action = function() end },
[apicast] = { run_post_action = true }
}

stub(context.proxy, 'post_action')

apicast:post_action(context)

assert.spy(context.proxy.post_action).was_called()
end)
end)

describe('when the "run_post_action" flag is not set', function()
it('does not run its logic', function()
local apicast = _M.new()
local context = {
proxy = { post_action = function() end },
[apicast] = { run_post_action = nil }
}

stub(context.proxy, 'post_action')

apicast:post_action(context)

assert.spy(context.proxy.post_action).was_not_called()
end)
end)
end)
end)