DEV Community

Mert Simsek
Mert Simsek

Posted on • Edited on

Go Plugin Development on Kong

Earlier this year, Kong has announced brilliant features. You check it out the following.

https://konghq.com/blog/kong-gateway-2-0-0-released/

I was very interested in one of them which is we will be able to develop Go plugins on Kong. I built a plugin to test and as soon as possible I'm writing this blog post eventually. I'm going to demonstrate a plugin that checks the consumer key from query string.

I used to run DB-less Kong on Docker and I prefer that either.

FROM kong/go-plugin-tool:2.0.4-alpine-latest AS builder

RUN mkdir -p /tmp/key-checker/

COPY . /tmp/key-checker/

RUN cd /tmp/key-checker/ && \
    go get github.com/Kong/go-pdk && \
    go mod init kong-go-plugin && \
    go get -d -v github.com/Kong/go-pluginserver && \
    go build github.com/Kong/go-pluginserver && \
    go build -buildmode plugin key-checker.go

FROM kong:2.0.4-alpine

RUN mkdir /tmp/go-plugins
COPY --from=builder  /tmp/key-checker/go-pluginserver /usr/local/bin/go-pluginserver
COPY --from=builder  /tmp/key-checker/key-checker.so /tmp/go-plugins
COPY config.yml /tmp/config.yml

USER root
RUN chmod -R 777 /tmp
RUN /usr/local/bin/go-pluginserver -version && \
    cd /tmp/go-plugins && \
    /usr/local/bin/go-pluginserver -dump-plugin-info key-checker
USER kong
Enter fullscreen mode Exit fullscreen mode

In this way, we copy our required files. Let's go into details. Firstly, we create a builder image and I copy my key-checker.go file and I build it as a go plugin. After that, I get that file from the builder image and I put it in Kong image. That's straightforward.

Let's look over the Go file.

package main

import (
    "github.com/Kong/go-pdk"
)

// it represents to config parameters into the config.yml
type Config struct {
    Apikey string
}

func New() interface{} {
    return &Config{}
}

func (conf Config) Access(kong *pdk.PDK) {
    key, err := kong.Request.GetQueryArg("key")
    apiKey := conf.Apikey 

    if err != nil {
        kong.Log.Err(err.Error())
    }

    //it adjusts the header parameters in this way.
    x := make(map[string][]string)
    x["Content-Type"] = append(x["Content-Type"], "application/json")

    //If the key of the consumer is not equal to the claimed key, kong doesn't ensure the proxy
    if apiKey != key {
        kong.Response.Exit(403, "You have no correct consumer key.", x) 
    }
}
Enter fullscreen mode Exit fullscreen mode

This file tells us that we check the key from the query string. If it is not equal to the key from the config file, we don't provide proxy service. In another case, it will ensure the proxy well and clearly the claimed URL from the config file. This is the config file. Also, I try to show changing header parameters and I write content type as a parameter for only showing.

# go.yml
_format_version: "1.1"
services:
- url: https://reqres.in/api/users?page=2
  routes:
  - paths:
    - "/"
  plugins:
  - name: key-checker
    config:
      apikey: mysecretconsumerkey
Enter fullscreen mode Exit fullscreen mode

To build the Dockerfile I run this command.

docker build -t kong-demo .
Enter fullscreen mode Exit fullscreen mode

Once it built, I run the following command. I point the related directories by using environment variables.

docker run -ti --rm --name kong-go-plugins \
  -e "KONG_DATABASE=off" \
  -e "KONG_GO_PLUGINS_DIR=/tmp/go-plugins" \
  -e "KONG_DECLARATIVE_CONFIG=/tmp/config.yml" \
  -e "KONG_PLUGINS=key-checker" \
  -e "KONG_PROXY_LISTEN=0.0.0.0:8000" \
  -p 8000:8000 \
  kong-demo
Enter fullscreen mode Exit fullscreen mode

Right, we're able to check the service. As you can see, the key is not equal. Therefore the status code is 403 and proxy service is not working.

Alt Text

When I enter the correct consumer key, as expected Kong ensures the proxy service clearly and URL is requested.

Alt Text

Conclusion

This feature drastically will be useful for Go developers and you could build pretty cool plugins in this way. I also want to share some practical URLs like the following. I hope the blog post ignites the minds to build awesome Go plugins on Kong. Happy Konging!

https://docs.konghq.com/2.0.x/go

https://godoc.org/github.com/Kong/go-pdk

https://github.com/gszr/kong-2.0-demo

Top comments (2)

Collapse
 
ifree321 profile image
Karl Lu

Hi Simsek,
I have some problem when I use go plugin, can i ask for your help?
I hope to use kong.Response.GetStatus() or kong.ServiceResponse.Getxxx func then do some thing,bug i got error: 'function cannot be called in access phase (only in: header_filter, body_filter, log)'. Do you know how to fix it?

Collapse
 
_mertsimsek profile image
Mert Simsek

I'm not sure but there is an issue about this on Github repository. Perhaps, you could type this clarification about that.

github.com/Kong/kong/issues/4848