Managing microservices and APIs with Kong and Konga

Tselentis Panagis
8 min readJul 20, 2018

--

TL;DR

This article will be focusing on how to manage microservices using Kong and Konga. We will go through the deployment process of both applications and provide a basic example of accessing an API through the gateway as well as securing it’s resources using Authentication plugins and Access Control Lists.

What is Kong?

Kong is a widely adopted, open source API Gateway, written in Lua. It runs on top of Nginx, leveraging the OpenResty framework and provides a simple RESTful API that can be used to provision your infrastructure in a dynamic way.

What about Konga?

Konga is a fully featured open source, multi-user GUI, that makes the hard task of managing multiple Kong installations a breeze.

It can be integrated with some of the most popular databases out of the box and provides the visual tools you need to better understand and maintain your architecture.

Installing Kong

For this tutorial, we’re going to use docker containers. Other ways to install Kong can be found here: https://konghq.com/install

  1. To begin with, we need to create a network so that the containers can discover and communicate with each other.
$ docker network create kong-net

2. We will be using PostgreSQL as Kong’s database (it can be either that or Cassandra).

$ docker run -d --name kong-database \ 
--network=kong-net \
-p 5432:5432 \
-e “POSTGRES_USER=kong” \
-e “POSTGRES_DB=kong” \
postgres:9.6

3. Let us now prepare our database by starting an ephemeral Kong container which will run the appropriate migrations and die!

$ docker run --rm \     
--network=kong-net \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-database" \
kong:latest kong migrations up

4. Everything is now set and ready to start Kong!

$ docker run -d --name kong \     
--network=kong-net \
-e "KONG_DATABASE=postgres" \
-e "KONG_PG_HOST=kong-database" \
-e "KONG_PROXY_ACCESS_LOG=/dev/stdout" \
-e "KONG_ADMIN_ACCESS_LOG=/dev/stdout" \
-e "KONG_PROXY_ERROR_LOG=/dev/stderr" \
-e "KONG_ADMIN_ERROR_LOG=/dev/stderr" \
-e "KONG_ADMIN_LISTEN=0.0.0.0:8001, 0.0.0.0:8444 ssl" \
-p 8000:8000 \
-p 8443:8443 \
-p 8001:8001 \
-p 8444:8444 \
kong:latest

5. Test it out!

Kong’s admin API is exposed on port 8001 and the gateway on port 8000

$ curl -i http://localhost:8001/$ curl -i http://localhost:8000/

Installing Konga

Konga ports with it’s own file system storage and although it’s not recommended for production, it can be safely used as long as kongadata folder persists in a volume.

If you decide to go down that road, running Konga is as simple as this:

$ docker run -d -p 1337:1337 \
--network=kong-net \
--name konga \
-v /var/data/kongadata:/app/kongadata \
-e "NODE_ENV=production" \
pantsel/konga

For this tutorial, since we already have a running PostgreSQL instance, we might as well make our lifes a bit more complicated and use it.

Like before, we will need to prepare Konga’s database by starting an ephemeral container.

$ docker run --rm \ 
--network=kong-net \
pantsel/konga -c prepare -a postgres -u postgresql://kong@kong-database:5432/konga_db

When the migrations run, we can start the app.

$ docker run -p 1337:1337 \
--network=kong-net \
-e "DB_ADAPTER=postgres" \
-e "DB_HOST=kong-database" \
-e "DB_USER=kong" \
-e "DB_DATABASE=konga_db" \
-e "KONGA_HOOK_TIMEOUT=120000" \
-e "NODE_ENV=production" \
--name konga \
pantsel/konga

Here’s a docker-compose example for the lazy: https://gist.github.com/pantsel/73d949774bd8e917bfd3d9745d71febf

After a while, Konga will be available at:

http://<your-servers-public-ip-or-host>:1337

Login with the default credentials:

Login: admin | Password: adminadminadmin

After successful login, you will land here:

At this point, you can manually create a connection to Kong’s admin API but, since we deployed everything using the “default” way, Konga has already created that initial connection for us.

If you open the connections page, you’ll notice that a connection to the previously created Kong instace is already there but not yet active.

Hit the activate button. If everything is set up properly, Konga will connect to Kong and the interface will be filled with all kinds of coolness.

Important note: Don’t forget to change the default admin and user accounts provided by Konga. This can be easily done in the users page.

Quick tour

Let’s take a quick tour and explain some of the core concepts in a nutshell.

Dashboard

The dashboard displays basic information about the Kong instance you’re currently connected, the underlying database and the available plugins.

More detailed information can be found in the INFO page.

Snapshots

The snapshots feature, allows you to easily backup, restore and move your Kong configuration across nodes. You can also schedule automated snapshots of your Kong instances.

Settings

The settings page, provides a simple way to configure Konga and set up a basic ACL for user accounts. Bare in mind, that user permissions are set globally and refer to the user account as an entity. Individual user ACLs are not yet supported.

Creating Services and Routes

Moving on to the important stuff. Let’s see how we can create services and routes to our APIs.

For this tutorial, we’re going to use the excelent online fake API for testing and prototyping provided by typicode .

Navigate to the services page and add a new service. Fill in the form as follows:

Submit it and boom! The service will be created.

The jsonplaceholder API provides the following resources:

We need to create routes to those resources.

There are a number of ways we can do that depending on the use case but, for this tutorial, we will only need two routes.

The first one will be used for fetching and listing and the second one for creating, updating and deleting.

Click on the json-placeholder service, select the routes tab and add a new route.

Fill in the form as follows and hit submit:

This route will respond to GET requests.

Try it out:

$ curl -i http://localhost:8000/fake-api/users

Likewise, create a second route that responds to POST , PUT , PATCH and DELETE requests.

Go on and test it by creating a new user:

$ curl -X POST \
-H "Content-Type: application/json" \
-d '{"name":"JohnDoe","username":"jdoe"}' \
http://localhost:8000/fake-api/users

Neat! So, what’s the story so far?

We’ve sucessfully deployed Kong & Konga and managed to access the jsonplaceholder API through our gateway.

Next, we need to secure our resources, and provide manager access to only certain consumers.

Securing resources

Kong provides a number of ways to do that by using Authentication and security plugins. To keep things simple, we’re going to use the key authentication plugin on our service.

Navigate to thejson-placeholder service, select the plugins tab, hit the add plugin button and select the key auth plugin.

Submit the form using the default values. A Key Authentication layer is added to our service and both of our routes are now secure.

If you try:

curl -i http://localhost:8000/fake-api/users

you’ll get a 401 Unauthorized response from the Gateway.

Next thing we need to do is create a consumer with the appropriate credentials.

Go to the consumers page and create a new consumer

From the consumer’s page, under the credentials tab, select api keys->create api key .

Submit the form, the key will be auto-generated.

If we now try to consume the resource using the generated apikey in the headers, everything works as expected:

$ curl -i -H "apikey:{{your-api-key}}" http://localhost:8000/fake-api/users

Golden! But, there’s one caveat. Apart from fetching and listing, our consumer can also create, update and delete resources. In real world applications, the readers should only be able to read. Managing resources is something only administrators/managers should be allowed to do.

Our management route, — the one that accepts POST , PUT , PATCH and DELETE requests — , should only be accessible by certain consumer groups.

In order to achieve that, we can use Access Control Lists.

Create a new consumer with the username manager. The username can be whatever you like, we’re just using the specific one so it’s easier to indentify their roles.

Assign an apikey credential to the new consumer like before.

The only extra step we need to take, is to add this consumer to a group .

In the respective consumer page, select the groups tab and add a new group called managers.

Back to the jsoonplaceholder service. Select the routes tab and edit the management route. Go to plugins and add the ACL plugin which can be found under the security group.

In the plugin form, type the name of the managers group, hit enter and submit.

After submitting, select the eligible consumers tab. You’ll notice that only the manager is listed. That means only that consumer can access the specific route.

Try creating a resource using the reader’s apikey as oposed to the manager’s:

$ curl -X POST \
-H "Content-Type: application/json" \
-H "apikey: {{reader-apikey}}" \
-d '{"name":"JohnDoe","username":"jdoe"}' \
http://localhost:8000/fake-api/users
HTTP/1.1 401 Unauthorized$ curl -X POST \
-H "Content-Type: application/json" \
-H "apikey: {{manager-apikey}}" \
-d '{"name":"JohnDoe","username":"jdoe"}' \
http://localhost:8000/fake-api/users
HTTP/1.1 201 Created

Kong & Konga constitute a set of powerfull open source tools that can spare you lots of time and distress. This basic introductory example barely scratches the surface but nevertheless, it’s a solid starting point.

On future articles we will focus on more complex scenarios and use cases.

Until then, go on and take those stuff for a ride.

Peace.

--

--

Tselentis Panagis

I'm a heavy metal software engineer born on the Day of the Tentacle, forged in the fires of an AMSTRAD CPC6128.