This repo shows how to protect your APIs using the Kong API Gateway working as PEP proxy with a Keycloak integration for authentication and authorization of incoming requests.
- API protection with Kong API Gateway and Keycloak integration
The source code of all plugins must be in the respective folder, meaning:
- luaplugins : This folder contains plugins written in lua language. Currently, the plugin "multi-tenancy" which validates for the fiware-service header in the request against the one in the presented auth token, and the plugin "rbac" which supports role based access control for upstream services are included. The "query-checker" plugin is included - yet, it's still in development. Plugins written in lua language provide the advantage of configuration via a GUI using Konga. Konga is a web GUI for the kong proxy.
- plugins : You can create your own plugins written in JavaScript here.
To use kong, we need to build an image using docker. Simply 1) clone this repo and navigate towards the kong folder and 2) use the command:
docker-compose build kong
If kong is run for the first time, it is necessary to perform Database migration using the below commands:
docker-compose up -d kong-db
docker-compose run --rm kong kong migrations bootstrap
docker-compose run --rm kong kong migrations up (for upgrading from previous version)
Once the data migrations is performed , you can start the remaining services.
docker-compose up -d kong
docker-compose up -d konga
Make sure all the services are up and running.
Note : If it is not the first time starting kong and kong-db services , you can clone and run docker-compose up -d
directly.
All the configurations below are done using a GUI for kong called konga. After the inital setup, you need to create an admin account in Konga GUI which can be accessed at http://<YourIP>:1337
Furthermore, establish a connection between konga and kong when konga is started for the first time. Enter a name and the URL where konga can find kong's admin API according to the picture below.
Once the initial setup is done, you can start to configure your services, routes, and plugins.
Create a new service by clicking the Services button in the left navigation bar. Fill in the necessary details in the GUI. As a example, we create a service for the Orion Context Broker.
Note : If you are deploying on a local machine it is important to use the ip address of the local machine instead of localhost due to issues with kong.
Creating new routes for a given service is fairly simple. Just like creating a new service, a route can be added/created for a service. So click on the Routes tab in the services page (after clicking on a service), in this example orion service. Fill in details for Paths, e.g. /v2/entities and headers in case you need to check any particular headers. Note : fiware-service header will be checked using the multi-tenancy plugin, so there is no need to enter it here.
In this excample, a global plugin will be used in order to validate every incoming request against this plugin. In this case, every request needs to be authenticated against a Keycloak server.
- Click on the 'Plugins' tab in the main navigation bar on the left side.
- Click on 'ADD GLOBAL PLUGINS'.
- Click on 'Other' and then select 'Add Plugin' option on the 'oidc' plugin Configure the OIDC plugins as shown in the image below with the configurations as per your client.
To add any other plugin, we follow the same procedure as done before with the OIDC plugin. Here, we give an example on how to add the multi-tenany plugin for the orion service.
- Go to the orion service created in Step 3.1, click on the plugins tab on the left side under the selected service.
- Click on ADD PLUGIN option on the right side, then click on others and select multi-tenancy plugin in the option. There is no need to fill any values as the plugin matches fiware-service header to the same in the Auth Token.
- Note: Make sure to use the OIDC plugin in combination with other plugins to ensure token validity! Only the OIDC plugin checks whether the presented token is valid against the Keycloak server!
You can add the plugin at global, service or at route level. Select the plugin in the 'Add Plugin' section.
tenant name
(required) field defines the custom header name. It can be renamed as per your custom requirement. This field will be checked against the token presented in the request.
Ex: As shown in the image above, we have set the tenant name to fiware-service
. In the incoming request to kong, it is mandatory to have a request header with name "fiware-service" and the value set in keycloak for the given user.
Note: See section 4.5 for more details to configure keycloak.
Similar to the multi-tenancy plugin, this plugin can be used at global, service or routes level.
When use custom roles
is disabled, the plugin expects the role in the form tenantname_role. Ex: if the tenant name is set to fiware-service:app, then the accepted roles are app_read
, app_write
and app_admin
.
-
tenant name
(required)(String) field defines the custom header name. It can be renamed as per your custom requirement. -
use custom roles
(optional)(Bool) is a boolean field that decides whether to include custom roles for rbac. -
read role
(depends on 'use custom roles')(String) Pre-defined role needed for GET-requests. -
write role
(depends on 'use custom roles')(String) Pre-defined role needed for PATCH, PUT, and POST requests. -
admin role
(depends on 'use custom roles')(String) Pre-defined role needed for DELETE requests. -
include client role
(optional)(Bool) field indicated whether to use client roles or user roles configured in Keycloak. -
client name
(depends on include client role)(String) field is used to specify the name of the client.
Note: See section 4.6 for more details to configure keycloak.
Note: This plugin is intended for future use with release of oriod-ld.
With this plugin its possible to validate the scopes sent as headers by the client against the permission given to the client in Keycloak. Make sure the headers and token attributes are set with the name as scopes
plus allowed
(Boolean) field used to decide plus(+) wildcard entries in scope Ex: /fiware/+/temparature allows /fiware/kitchen/temparature, /fiware/room1/temparature ..hash allowed
(Boolean) field used to decide hash(#) wildcard entries in scope Ex: /fiware/kitchen/# allows /fiware/kitchen/temparature , /fiware/kitchen/pressure ..
This plugin is used to authorize request path with query
path
(String) speicfy the full path that has to checked. Ex: /v2/entities/urn:ngsi-ld:Product:010?type=Productwildcard allowed
(Boolean) field used to include * wildcard as shown in fig
Note: If you have a running keycloak serverThe images are taken from a previous version 16.1.0. Changes may apply.
-
Create a new Realm if needed.
- Select the pop-up with
Add realm
option under Master on the left top of Keycloak admin page. - Set the name of the realm, Ex: kong and click
create
- Select the pop-up with
-
Kong client :
- Create new client with client id
kong
- Under client settings, set access type to
confidential
- Set service accounts
enabled
- Set valid redirect uris
*
- Click on Credentials, use the Secret to configure kong in konga as mentioned in section 3.3
- Create new client with client id
-
App Client:
- Create new client with client id
app
- Under client settings, set access type to
public
orconfidential
- Set valid redirect uris
app
- Create new client with client id
-
Create a user in keycloak to get token using client id
app
-
To support multi-tenancy plugin, it is necessary to have tenant name in token:
- Click on Clients on the left navigation bar
- Click Mappers under Clients and create
- Set the Name,User Attribute and Token Claim Name as to tenant name, Ex:
fiware-service
and save - Use the other follwing settings as shown in the image below.
- Now go to Users in the left navigation bar,view all users and select the user.
- Click on Attributes and configure for fiware service as shown below.
- The attributes can be multivalued with format attr1##attr2 Ex: test1##test2
-
To support RBAC plugin, it is necessary to configure roles in keycloak:
- Go to Roles in the left navigation bar, select Add Role.
- Set the name in the form
tenantname_role
, ex:test1_read
and save. - Go to Users and select the user to set roles.
- Select Role Mapping under given user and select the roles to be added under Available Roles and click Add selected.
- You can also create
client roles
under Clients and then select Roles, create new role using Add Role - Now under a given user, select Role Mapping, choose the client under Client Roles and add avaiable roles
After following the above steps, you can test the funcionalities of kong and its plugins using any rest client, e.g. postman or insomnia.
- Get a token from keycloak after creating a user.
- Use the Authorization header to fill the above recieved token in the format 'Bearer <token>'
- Add necessary headers depending on the plugins in the request and make sure it is put in the user token.
- Send the request and verify.
Ex: To use postman for testing, please check the image below to configure token.
- kong-docs-url: https://docs.konghq.com/
- kong-js-plugins: https://github.com/Kong/docker-kong-js-pdk
- OIDC-plugin: https://github.com/nokia/kong-oidc