Kong plugin do not run access block

I’m developing a plugin to Kong API Gateway. I created a service pointing it to another service in the local network and basically every request to my service is redirected to the other one, so far so good.

What the plugin has to do is grab the field Authorization Bearer in the header, and pass to the upstream service as part of the URI. E.g.

Request is received on: localhost/service

In its header, it have a Authorization Bearer that contains a JWT

The plugin has to receive it, take the JWT and parse it to URI to the upstream service: productionServer/service/9a8udoadzlkndid813gru1gr <-JWT took from header

My attempt till now:

local singletons = require “kong.singletons”
local BasePlugin = require “kong.plugins.base_plugin”
local responses = require “kong.tools.responses”
local utils = require “kong.tools.utils”
local constants = require “kong.constants”
local multipart = require “multipart”
local cjson = require “cjson”
local url = require “socket.url”
local access = require “kong.plugins.ctk.access”

local CtkHandler = BasePlugin:extend()

CtkHandler.PRIORITY = 3505
CtkHandler.VERSION = “0.1.0”

file = io.open("/usr/local/kong/logs/ctk.lua", “a+”)
io.input(file)
file:write("— JUST EXTENDED THE BASE PLUGIN —")

function CtkHandler:new()
CtkHandler.super.new(self, “ctk”)
file = io.open("/usr/local/kong/logs/ctk.lua", “a+”)
io.input(file)
file:write("— INSTACIATED ITSELF —")
end

function CtkHandler:access(conf)
CtkHandler.super.access(self)
file = io.open("/usr/local/kong/logs/ctk.lua", “a+”)
io.input(file)
file:write("— STARTED THE ACCESS PART —")
do_authentication()
access.execute()
end

file:close()

return CtkHandler

And the access.lua file

local singletons = require “kong.singletons”
local BasePlugin = require “kong.plugins.base_plugin”
local responses = require “kong.tools.responses”
local constants = require “kong.constants”
local utils = require “kong.tools.utils”
local multipart = require “multipart”
local cjson = require “cjson”
local url = require “socket.url”
local basic_serializer = require “kong.plugins.log-serializers.basic”
local string_format = string.format
local ngx_set_header = ngx.req.set_header
local get_method = ngx.req.get_method
local req_set_uri_args = ngx.req.set_uri_args
local req_get_uri_args = ngx.req.get_uri_args
local req_set_header = ngx.req.set_header
local req_get_headers = ngx.req.get_headers
local req_clear_header = ngx.req.clear_header
local req_set_method = ngx.req.set_method
local ngx_decode_args = ngx.decode_args
local ngx_re_gmatch = ngx.re.gmatch
local string_format = string.format
local cjson_encode = cjson.encode
local ipairs = ipairs
local request = ngx.request

local _M = {}

local function retrieve_token(request, conf)
file = io.open("/usr/local/kong/logs/ctk.lua", “a+”)
io.input(file)
file:write("— RUNNING RETRIEVE TOKEN —")
local uri_parameters = request.get_uri_args()

for _, v in ipairs(conf.uri_param_names) do
  if uri_parameters[v] then
    return uri_parameters[v]
  end
end

local ngx_var = ngx.var
for _, v in ipairs(conf.cookie_names) do
  local jwt_cookie = ngx_var["cookie_" .. v]
  if jwt_cookie and jwt_cookie ~= "" then
    return jwt_cookie
  end
end

local authorization_header = request.get_headers()["authorization"]
if authorization_header then
  local iterator, iter_err = ngx_re_gmatch(authorization_header, "\\s*[Bb]earer\\s+(.+)")
  if not iterator then
    return nil, iter_err
  end

  local m, err = iterator()
  if err then
    return nil, err
  end

  if m and #m > 0 then
    return m[1]
  end
end

end

local function do_authentication(conf)
file = io.open("/usr/local/kong/logs/ctk.lua", “a+”)
io.input(file)
file:write("— RUNNING DO_AUTHENTICATION —")
local token, err = retrieve_token(ngx.req, conf)
if err then
return responses.send_HTTP_INTERNAL_SERVER_ERROR(err)
end

local ttype = type(token)
if ttype ~= "string" then
  if ttype == "nil" then
    return false, {status = 401}
  elseif ttype == "table" then
    return false, {status = 401, message = "Multiple tokens provided"}
  else
    return false, {status = 401, message = "Unrecognizable token"}
  end
  append_uri(token)
  return true
end

end

local function append_uri(token)
file = io.open("/usr/local/kong/logs/ctk.lua", “a+”)
io.input(file)
file:write("— FUNCTION APPEND_URL —")
local uri = ngx.get_uri_args
ngx.req.set_uri(ngx.unescape_uri("/" … token))
end

return _M

In the Kong server, after installing the plugin above, I receive:

— JUST EXTENDED THE BASE PLUGIN ------ INSTACIATED ITSELF —

Which is the control inserted inside the code to trace it.

Any ideas?

Hi,

The way you are opening and closing the file (opening it at the top of the plugin and closing it at the end) will almost certainly provoke errors, which you can probably see if you open the nginx log file.

Instead of using your own logfile with io.* functions, use ngx.log, like this:

   ngx.log(ngx.WARN, "JUST EXTENDED THE BASE PLUGIN")

That will log inside the nginx logfile.

The nginx logfile contains a lot more info that would help you a lot more when debugging your plugin.

Thanks kikito;

Actually using your method I wans’t able to see the logs in:

/usr/local/kong/logs/

issuing the command:

find / | grep ngx.log

I receive 0 results

Try this instead:

cd /usr/local/kong/logs
grep "JUST EXTENDED THE BASE PLUGIN" *

You nailed it. It actually runs the access block now. Now I will proceed debugging the main logic in the access.lua. Thanks kikito.

2018/05/23 13:39:53 [warn] 3419#0: [lua] handler.lua:14: --- ctk --- JUST EXTENDED THE BASE PLUGIN
2018/05/23 13:39:53 [warn] 3419#0: [lua] handler.lua:18: new(): --- ctk --- INSTACIATED ITSELF
2018/05/23 13:42:12 [warn] 3428#0: *169 [lua] handler.lua:23: --- ctk --- STARTED THE ACCESS PROCESS, client: 10.0.2.2, server: kong, request: "POST /access/ HTTP/1.1", host: "localhost:8000"

Between, I know you are a busy man, but where can I find all the methods I can issue from nginx using kong?

like ngx.log(), ngx.req_get_headers() and so on…

I firmly believe that lua is an easy language, but not knowing the methods really bugs me.

Hi,

All the methods available from nginx are docummented here:

They are generally low-level, but are available.

In addition to those, kong also provides higher-level methods. They are documented here:

We are aware that having to go through several documents and APIs in order to build plugins is a current pain point and are working on improving that. Stay tunned. And good luck with your plugin!