How to Install Kong Custom Lua Plugin
There is no doubt that Kong is one of the best API gateways on the market. One of its cool features is that you can extend its functionality by writing custom plugins. I’ve got a couple viewers asking me to talk about how to install custom plugins, that’s what I am going to talk about in this post.
Kong used to support Lua plugins only but you can use Go, Javascript or Python plugins as of version 2.4. I will cover how to install Lua plugin on this post and Go Plugin on the next one.
Please note this post is about INSTALLING plugins. If you are looking for a tutorial about developing kong plugins, please read official post.
Prerequisites:
Docker: You need to have Docker installed and understand the basics of Docker.
Terminal: We will use terminal to run docker container and build docker images.
JQ: We will use JQ to filter outputs.
Start Kong
I will run Kong in DBless mode for our demo, container name is kong-demo
. To start this Kong container, let’s run below command.
Please note the container will be removed when it stop. If you don’t want this behaviour, please remove
--rm
flag from the command. I am also running this container indetached mode
as it is easier to play with.
1 | docker run --rm --detach --name kong-demo \ |
Now that we have our container running, we can install plugins.
Lua Plugin
I will be using kong-jwt2header as our example.
Install with lua files
This repo is extremely easy to use as the repo owner provides a script to install.
Clone repo
1 | git clone https://github.com/yesinteractive/kong-jwt2header.git |
Modify Script
Kong used to be running as root user but it is no longer the case. Therefore we need to modify this script to use Kong for reload.
Let’s cd kong-jwt2header
to the folder and then use the editor of your choice to modify update_docker.sh
file.
You need to change below line
1 | docker exec --user root -e KONG_PLUGINS="bundled,$dir" $container kong reload - vv |
to
1 | docker exec --user kong -e KONG_PLUGINS="bundled,$dir" $container kong reload - vv |
Run script
Now we can run our script.
1 | ./update_docker.sh |
We will be asked to enter our container name. We enter kong-demo
and enter.
Check plugin
1 | curl http://localhost:8001 -s | jq .plugins | grep kong-jwt2header |
We should see "kong-jwt2header": true
in the result.
What this script does was
- Create folder
/usr/local/share/lua/5.1/kong/plugins/kong-jwt2header
inside kong-demo container. - Copy two plugins files into this folder.
- Add environment variable
KONG_PLUGINS="bundled,kong-jwt2header"
and then reload Kong.
Install with Luarocks
This might not work after GitHub made this change.
If you are getting below error, you probably need to update your rockspec or use the manual installation method.
1 | docker exec -it --user root kong-demo luarocks install kong-jwt2header |
We can also install plugins with luarocks. Luarocks is the package manager for Lua modules. As Kong has luarocks installed by default, we can easily install rock files inside container. We will still use kong-jwt2header because it is also available on luarocks website.
Install Rock file
Let’s stop and start a new kong-demo container first.
Then we run below command.
1 | docker exec -it --user root kong-demo luarocks install kong-jwt2header |
As you can see I am running luarocks install
as root user inside the container and luarocks will fetch and install plugin automatically.
Enable Plugin and reload
We need to add environment variable KONG_PLUGINS="bundled,kong-jwt2header"
and reload Kong.
1 | docker exec --user kong -e KONG_PLUGINS="bundled,kong-jwt2header" kong-demo kong reload -vv |
Check plugin
1 | curl http://localhost:8001 -s | jq .plugins | grep kong-jwt2header |
We should see "kong-jwt2header": true
in the result as well.
Build custom image
In my opinion the best way to use custom plugin is to build a custom image because you don’t need to install plugin manually in case you need to rotate your pod.
To build a custom image is quite simple, here is an example.
Please save below to
Dockerfile
.1
2
3
4
5
6
7
8
9
10FROM alpine:latest as builder
RUN apk add --no-cache git
RUN mkdir /jwt2header
RUN git clone https://github.com/yesinteractive/kong-jwt2header.git /jwt2header
FROM kong:2.4-alpine
USER root
RUN mkdir /usr/local/share/lua/5.1/kong/plugins/kong-jwt2header
COPY --from=builder /jwt2header/plugin/. /usr/local/share/lua/5.1/kong/plugins/kong-jwt2header
USER kongBuild image
Below command builds the image and tag it askong-demo
. It will also replace existingkong-demo
image if you already have one.1
docker build --no-cache -t kong-demo .
Start Kong with custom image
1
2
3
4
5
6
7docker run --rm --detach --name kong-demo \
-p "8000-8001:8000-8001" \
-e "KONG_ADMIN_LISTEN=0.0.0.0:8001" \
-e "KONG_PROXY_LISTEN=0.0.0.0:8000" \
-e "KONG_DATABASE=off" \
-e "KONG_PLUGINS=bundled,kong-jwt2header" \
kong-demo
Use custom plugin
As the plugin is installed and enabled, let me show you how to use this plugin.
kong-jwt2header
plugin can be used to extract claim:value
from a passed in JWT token and apply its value to header. It can be used to change the routing or simply add extra headers to upstream.
As we are running Kong in dbless mode, we need to pass our declarative config to Kong. You can choose to mount this file inside container so Kong will start with all the configs. However, I will post this config to kong via admin api /config
endpoint.
Create Config file
Let’s save this file as test.yaml
in our current folder.
1 | _format_version: "2.1" |
As you can see I’ve got two services with two routes. The first route match all request go to <proxy_node>/demo
and the second route match when the requests go to path <proxy_node>/demo
with a header x-kong-jwt-claim-demo: test
.
We also enable this plugin globally and set config.strip_claims
and config.token_required
as false.
Let’s apply this config with below command.
1 | curl -X POST http://localhost:8001/config -F [email protected] |
Test Plugin
Test
first-demo-route
We should reach httpbin with below request.1
curl http://localhost:8000/demo
Test
second-demo-route
We should reach mockbin with below request.1
curl http://localhost:8000/demo --header "x-kong-jwt-claim-demo:test"
Generate JWT
You can use jwt.io to create your token. I am using JWT-cli.1
jwt encode --secret=demo '{"demo":"test"}'
We should get a JWT token like this one.
1
eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkZW1vIjoidGVzdCIsImlhdCI6MTYyNDAxMDU0MH0.HxVkGI1N0woJPtjiJRYZI-xwbMJ77w9dC1QhYcoFCbU
Call route with token
1
2curl http://localhost:8000/demo \
--header "authorization:bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJkZW1vIjoidGVzdCIsImlhdCI6MTYyNDAxMDU0MH0.HxVkGI1N0woJPtjiJRYZI-xwbMJ77w9dC1QhYcoFCbU"
We can see we are being routed to second-demo-route
because plugin extract claim demo:test
from JWT token and created x-kong-jwt-claim-demo:test
header, hence the new request match the second route.
In the following post, I will cover how to use Custom Go plugin with Kong.
Thanks for reading.