
Kong is an open source API Gateway and microservice management layer based on Nginx and the lua-nginx-module. It has two versions: the OSS version and the Enterprise mode. The OSS mode provides the admin API and the Kong Manager while the enterprise mode adds on Dev Portal, Vitals and RBAC to these OSS functionalities. The Kong gateway has several plugins and uses them to achieve several added functionalities.
In this blog, we will be using the basic-authentication plugin to secure the Kong admin API. We will up set a API key. We will need to pass this API key with the request header or as query string to authenticate to the admin API server. I will be deploying the Kong gateway on the Kubernetes cluster and expose the admin API with ingress.
Prerequisites
- Kubernetes Cluster(I will be using GKE)
- Helm 3 or higher
Deploying the Kong API gateway using Helm chart
I have provided a minimal values.yaml
file for the Kong helm chart. This values.yaml
file will deploy the Kong ingress controller along with the admin API.
# Create a file values-admin-api.yaml
image:
repository: kong/kong-gateway
tag: "2.7.0.0-alpine"
admin:
enabled: true
type: ClusterIP
http:
enabled: true
tls:
enabled: false
ingress:
enabled: true
ingressClassName: kong
hostname: admin-api.kong.link
To deploy the Kong, execute the following commands:
# To add the Kong helm chart repository
helm repo add kong https://charts.konghq.com
helm repo update
# To install the kong helm chart
helm install kong kong/kong -f values-blog.yaml --namespace kong --create-namespace
# Store the IP and Port for the Kong proxy service, the service for the Kong ingress controller.
HOST=$(kubectl get svc --namespace kong kong-kong-proxy -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
PORT=$(kubectl get svc --namespace kong kong-kong-proxy -o jsonpath='{.spec.ports[0].port}')
export PROXY_IP=${HOST}:${PORT}
Store the PROXY_IP
variable as we will be needing it later.
Securing the admin API
We can check if we can access the admin API using the command:
curl $PROXY_IP/status -H "host: admin-api.kong.link" -I
The request will start with something like:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 2136
Connection: keep-alive
The response status code shows 200
. This means we have access to the admin API. But this is a security vulnerability as it is publicly accessible. So anyone will be able to modify the routes by accessing the API.
So now we will create a Kong Plugin, Kong Consumer to link the plugin to the ingress resource to implement the basic authentication. We will be using Kong Plugin and Kong Consumer CRDs to implement this.
First, we need to delete the ingress that was already deployed with the helm chart for the API.
helm upgrade kong kong/kong -f values-blog.yaml --namespace kong --set admin.ingress.enabled=false
Next, lets create a Kong Plugin, an Ingress and a Kong Consumer to link Plugin and the Ingress.
Creating a secret to store the admin API secrets.
kubectl create secret generic -n kong adminapi-consumer-secret --from-literal=key=admin123 --from-literal=kongCredType=key-auth
Creating the Kong Plugin Manifest
Create a file `KongPluing.yaml` with the following content:
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: admin-api-auth
namespace: kong
config:
key_names:
- apikey
key_in_header: true
key_in_query: true
hide_credentials: true
plugin: key-auth
disabled: false
To apply the yaml manifest, execute:
kubectl apply -f KongPlugin.yaml
Kong Consumer Manifest
We will create a manifest kongConsumer.yaml
with the following content:
apiVersion: configuration.konghq.com/v1
kind: KongConsumer
metadata:
name: adminapi-consumer
namespace: kong
annotations:
kubernetes.io/ingress.class: kong
username: Knoldus
credentials:
- adminapi-consumer-secret
Apply the above manifest using command, kubectl apply -f kongConsumer.yaml
Ingress Resource for Kong Admin API
We will create a ingress.yaml
to store the following content:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: kong-admin-api
namespace: kong
annotations:
konghq.com/plugins: admin-api-auth
spec:
ingressClassName: kong
rules:
- host: admin-api.kong.link
http:
paths:
- backend:
service:
name: kong-kong-admin
port:
number: 8001
path: /
pathType: ImplementationSpecific
Apply the ingress Manifest using the command, kubectl apply -f ingress.yaml
Checking the deployment
We will again curl the admin api using the command:
curl $PROXY_IP/status -H "host: admin-api.kong.link" -I
This time we will notice, the response status code will be 401 unauthorized
.
HTTP/1.1 401 Unauthorized
Date: Tue, 15 Feb 2022 07:22:42 GMT
So we can say that the admin API is now not accessible publicly. Let’s pass the api key we set as the header and query string.
# To pass the api key as query string
curl "$PROXY_IP/status?apikey=admin123" -H "host: admin-api.kong.link" -I
# To pass the API key as Header
curl $PROXY_IP/status -H "host: admin-api.kong.link" -H "apikey: admin123" -I
Both of the above command will have an output starting like:
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Content-Length: 2133
For the final checking lets pass an incorrect API key.
curl $PROXY_IP/status -H "host: admin-api.kong.link" -H "apikey: randomkey" -I
# This will generate an output
HTTP/1.1 401 Unauthorized
Date: Tue, 15 Feb 2022 07:30:52 GMT
Content-Type: application/json; charset=utf-8
So the admin api is secured from any unauthorized access.
Conclusion
In this blog, we will deploy Kong admin API using helm chart and explore how to implement authentication and limited access to admin api using Kong’s basic authentication plugin. The documentation for Kong and KongHub are provided in the link.
Reference
- Kong API Gateway: https://docs.konghq.com/gateway/
- KongHub: https://docs.konghq.com/hub/
- API Gateway overview: https://blog.knoldus.com/api-gateway-whats-in-it-for-me/