In the previous post, we discussed about registering the Flask API to KONG service. In this tutorial, we discussed about applying KONG plugins like Key Authentication and Rate Limiting on the registered API.
- Key-Authentication
- Rate-limiting
Key-Authentication Plugin
This Key Authentication plugin can be added to a service or a route. Consumers can add their Apikey either in a querystring parameter or a header to authenticate their requests. Plugins registered can be viewed at http://localhost:8001/plugins.
Adding key-auth plugin to the service
You should provide service_id(d4079539–45d0–4798–96a8–6ac39d86b6cb)
or service_name (testApi)
of that specific service to register the key-auth plugin. Get the service details at http://localhost:8001/services.
Register the key-auth
plugin to the service with the following cQuery.
curl -X POST http://localhost:8001/services/testApi/plugins \
Response:
--data "name=key-auth"
{“created_at”:1536501460000,”config”:{“key_in_body”:false,”run_on_preflight”:true,”anonymous”:””,”hide_credentials”:false,”key_names”:[“apikey”]},”id”:”0fe22dc7–1bae-4a94–9841-d66469a1faaf”,”enabled”:true,”service_id”:”d4079539–45d0–4798–96a8–6ac39d86b6cb”,”name”:”key-auth”}
The above response clearly tells us to pass “apikey”
has to pass as header or querystring parameter.
Now see what happens, if we access our API
curl -i -X GET --url http://localhost:8000/api/v1/test2 --header 'Host: localhost'
Response:
HTTP/1.1 401 Unauthorized
{"message":"No API key found in request"}
Our consumers needs“apikey”
to access the service. Lets set apikey
to each consumer we registered with the following query.
curl -X POST http://localhost:8001/consumers/consumer1/key-auth --data ""
Response:
{"id":"508bee01-613b-4f21-8ced-b098395e0a47","created_at":1536498848000,"key":"M1PyCiEee7QbI44FWC24G4WK7Bb4vZgm","consumer_id":"abd67a95-a247-4141-b329-d74fe6d3fb06"}
Pass the “key”
as header or querystring parameter to access the service
curl -i -X GET --url http://localhost:8000/api/v1/test2 --header 'Host: localhost' --header 'apikey: M1PyCiEee7QbI44FWC24G4WK7Bb4vZgm'
HTTP/1.1 200 OK
Response:
{“message”:”second end point \”test2\” is called”,”status_code”:200}
Consumer keys can be accessed at http://localhost:8001/consumers/consumer1/key-auth
Adding key-auth plugin to route
delete the key-auth plugin of the service and lets add on the route to test.
curl -i -X DELETE http://localhost:8001/plugins/0fe22dc7-1bae-4a94-9841-d66469a1faaf
set key-auth plugin to the route /api/v1/test1 with the following query.
curl -X POST http://localhost:8001/routes/668ac4ab-4226-45f7-9067-e30c032a840f/plugins --data "name=key-auth"
Response:
{"created_at":1536508484000,"config":{"key_in_body":false,"run_on_preflight":true,"anonymous":"","hide_credentials":false,"key_names":["apikey"]},"id":"048d6fcc-f1f0-4f04-b3a4-584754871dd8","enabled":true,"route_id":"668ac4ab-4226-45f7-9067-e30c032a840f","name":"key-auth"}
Now you can access route /api/v1/test2
without authentication and route /api/v1/test1
with authentication, since we just set the authentication on this route. Lets test this
$ curl -i -X GET --url http://localhost:8000/api/v1/test1 --header 'Host: localhost'
HTTP/1.1 401 Unauthorized
{"message":"No API key found in request"}
The above query passed without apikey
and response is 401 Unauthorized
$ curl -i -X GET --url http://localhost:8000/api/v1/test2 --header 'Host: localhost'
HTTP/1.1 200 OK
{"message":"second end point \"test2\" is called","status_code":200}
The above query passed without apikey
and the response is 200 OK.
Because we added key-auth
plugin only on /api/v1/test1
route.
$ curl -i -X GET --url http://localhost:8000/api/v1/test1 --header 'Host: localhost' --header 'apikey: M1PyCiEee7QbI44FWC24G4WK7Bb4vZgm'
HTTP/1.1 200 OK
{"message":"first end point \"test1\" is called","status_code":200}
Here we conclude that we can provide a specific route of the API to specific consumer with key-auth
plugin.
Rate Limiting Plugin
This plugin helps us to restrict consumer making requests to our API/Service in a given period of time(seconds, minute, hour, month, year).
This plugin can be enable on a service or route or consumer with consumer_id.
Enabling on Service – restricts every consumer making requests to the service.
Enabling on route – restricts every consumer making requests to the specific route of the service.
Enabling on consumer – restricts only that specified consumer making requests to any routes of the service.
Adding rate-limiting to the service:
$ curl -X POST http://localhost:8001/services/testApi/plugins \
--data "name=rate-limiting" \
--data "config.minute=2" \
--data "config.hour=100"
Response:{“created_at”:1536558895000,”config”:{“minute”:2,”policy”:”cluster”,”redis_timeout”:2000,”hide_client_headers”:false,”hour”:100,”limit_by”:”consumer”,”redis_port”:6379,”redis_database”:0,”fault_tolerant”:true},”id”:”38586082–7619–4bf7-b418-afcc65d37f28",”enabled”:true,”service_id”:”d4079539–45d0–4798–96a8–6ac39d86b6cb”,”name”:”rate-limiting”}
This plugin is by-default limit by consumer. From the query above, we can send only 2 requests per minute and 100 per hour.
Response from Kong after exceeding limit is {“message”:”API rate limit exceeded”}
.
Lets test this by simple python script.
import requests
from time import sleep
for i in range(1,10):
response = requests.get(“http://localhost:8000/api/v1/test1?apikey=M1PyCiEee7QbI44FWC24G4WK7Bb4vZgm")
print(response.ok, response.text)
sleep(1)
Similarly you can play around with this rate-limiting plugin on consumer or route of the service too. Specify the consumer_id in the following query to add rate-limiting plugin to the consumer.
$ curl -X POST http://localhost:8001/plugins \
--data "name=rate-limiting" \
--data "consumer_id={consumer_id}" \
--data "config.second=5" \
--data "config.hour=10000"
To add rate-limiting plugin on the route of the service, you need to add the route_id to the following query.
$ curl -X POST http://localhost:8001/routes/{route_id}/plugins \
--data "name=rate-limiting" \
--data "config.minute=2" \
--data "config.hour=100"