Developers want to focus more on adding the business values/features, rather than solving problems that don’t add business values. Separation of concerns is popular method to separate different sections in a software (e.g. main business logic, authentication, authorization, caching, routing, etc.). There are lots of solutions that can provide out-of-box capabilities that enable developers to write less code and focus on core features, e.g. service mesh (istio, linkerd, consul connect), api gateway (kong, ambassador), dapr.
In this article, I would like to show you how you can add api key security authentication to a vanilla API (e.g. mlflow)in Kubernetes, with Kong API gateway, which requires no code modification. In Kong-Kubernetes-way, the steps are:
- Install Kong API gateway
- Deploy vanilla API and create ingress
- Enable api key plugin in Kong
- Enable api key plugin for the application
- Create api key secret
- Create Kongconsumer for the application
Prerequisite
Install Kong API gateway
helm repo add kong https://charts.konghq.com
helm repo update
# Helm 2
helm install kong/kong
# Helm 3
helm install kong/kong --generate-name --set ingressController.installCRDs=false
Deploy vanilla API and create ingress rule
kubectl apply -f https://bit.ly/k8s-httpbin
service/httpbin created
deployment.apps/httpbin created
create ingress rule
echo '
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: demo
annotations:
konghq.com/strip-path: "true"
kubernetes.io/ingress.class: kong
spec:
rules:
- http:
paths:
- path: /foo
backend:
serviceName: httpbin
servicePort: 80
' | kubectl apply -f -
ingress.extensions/demo created
Test API
export PROXY_NAME=$(kubectl get -o jsonpath="{.status.loadBalancer.ingress[0].hostname}" service -n kong kong-proxy)
curl -i $PROXY_NAME/foo
Enable api key plugin in Kong
echo "
apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
name: httpbin-auth
plugin: key-auth
" | kubectl apply -f -
Enable api key plugin for the application
echo '
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: demo
annotations:
konghq.com/strip-path: "true"
konghq.com/plugins: httpbin-auth
kubernetes.io/ingress.class: kong
spec:
rules:
- http:
paths:
- path: /foo
backend:
serviceName: httpbin
servicePort: 80
' | kubectl apply -f -
Now curl requires api key
curl -i $PROXY_NAME/foo
{"message":"No API key found in request"}
Create api key secret
kubectl create secret generic harry-apikey \
--from-literal=kongCredType=key-auth \
--from-literal=key=my-sooper-secret-key
secret/harry-apikey created
Notice that kongCredType is key-auth, and key is the api key.
Create Kongconsumer for the application
echo "apiVersion: configuration.konghq.com/v1
kind: KongConsumer
metadata:
name: harry
annotations:
kubernetes.io/ingress.class: kong
username: harry" | kubectl apply -f -
kongconsumer.configuration.konghq.com/harry created
Now test with api key
curl -i -H 'apikey: my-sooper-secret-key' $PROXY_NAME/foo