KGateway¶
kgateway is the most mature and widely deployed Envoy-based gateway in the market today. Built on open source and open standards, kgateway implements the Kubernetes Gateway API with a control plane that scales from lightweight microgateway deployments between services, to massively parallel centralized gateways handling billions of API calls, to advanced AI gateway use cases for safety, security, and governance when serving models or integrating applications with third-party LLMs. kgateway brings omni-directional API connectivity to any cloud and any environment.
This tutorial shows how kgateway can be configured to delegate authorization decisions to the Kyverno Authz Server.
Setup¶
Prerequisites¶
- A Kubernetes cluster
- Helm to install kgateway the Kyverno Authz Server
- kubectl to interact with the cluster
Setup a cluster (optional)¶
If you don't have a cluster at hand, you can create a local one with kind.
KIND_IMAGE=kindest/node:v1.31.1
# create cluster
kind create cluster --image $KIND_IMAGE --wait 1m
Install KGateway¶
First we need to install KGateway in the cluster.
# install gateway API CDRDs
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.1/standard-install.yaml
# install kgateway CDRDs
helm upgrade -i --create-namespace --namespace kgateway-system --version v2.0.3 --wait kgateway-crds oci://cr.kgateway.dev/kgateway-dev/charts/kgateway-crds
# install kgateway
helm upgrade -i --namespace kgateway-system --version v2.0.3 --wait kgateway oci://cr.kgateway.dev/kgateway-dev/charts/kgateway
Deploy a sample application¶
Httpbin is a well-known application that can be used to test HTTP requests and helps to show quickly how we can play with the request and response attributes.
# create the demo namespace
kubectl create ns demo
# deploy the httpbin application
kubectl apply \
-n demo \
-f https://raw.githubusercontent.com/istio/istio/master/samples/httpbin/httpbin.yaml
Set up an API gateway¶
Create an API gateway with an HTTP listener by using the Kubernetes Gateway API.
kubectl apply -f - <<EOF
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1
metadata:
name: http
namespace: kgateway-system
spec:
gatewayClassName: kgateway
listeners:
- name: http
protocol: HTTP
port: 80
allowedRoutes:
namespaces:
from: All
EOF
Info
Using Kind and getting a CrashLoopBackOff error with a Failed to create temporary file message in the logs? You might have a multi-arch platform issue on macOS. In your Docker Desktop settings, uncheck Use Rosetta, restart Docker, re-create your Kind cluster, and try again.
Expose the app on the gateway¶
Now that you have an app and a gateway proxy, you can create a route to access the app.
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: httpbin
namespace: demo
labels:
example: httpbin-route
spec:
parentRefs:
- name: http
namespace: kgateway-system
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- group: ''
kind: Service
name: httpbin
port: 8000
weight: 1
EOF
Deploy cert-manager¶
The Kyverno Authz Server comes with a validation webhook and needs a certificate to let the api server call into it.
Let's deploy cert-manager
to manage the certificate we need.
# install cert-manager
helm install cert-manager \
--namespace cert-manager --create-namespace \
--wait \
--repo https://charts.jetstack.io cert-manager \
--set crds.enabled=true
# create a self-signed cluster issuer
kubectl apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: selfsigned-issuer
spec:
selfSigned: {}
EOF
For more certificate management options, refer to Certificates management.
Deploy the Kyverno Authz Server¶
Now deploy the Kyverno Authz Server.
# deploy the kyverno authz server
helm install kyverno-authz-server \
--namespace kyverno --create-namespace \
--wait \
--repo https://kyverno.github.io/kyverno-envoy-plugin kyverno-authz-server \
--set service.appProtocol="kubernetes.io/h2c" \
--set certificates.certManager.issuerRef.group=cert-manager.io \
--set certificates.certManager.issuerRef.kind=ClusterIssuer \
--set certificates.certManager.issuerRef.name=selfsigned-issuer
Create a Kyverno AuthorizationPolicy¶
In summary the policy below does the following:
- Checks that the JWT token is valid
- Checks that the action is allowed based on the token payload
role
and the request path
# deploy kyverno authorization policy
kubectl apply -f - <<EOF
apiVersion: envoy.kyverno.io/v1alpha1
kind: AuthorizationPolicy
metadata:
name: demo
spec:
failurePolicy: Fail
variables:
- name: authorization
expression: object.attributes.request.http.headers[?"authorization"].orValue("").split(" ")
- name: token
expression: >
size(variables.authorization) == 2 && variables.authorization[0].lowerAscii() == "bearer"
? jwt.Decode(variables.authorization[1], "secret")
: null
deny:
# request not authenticated -> 401
- match: >
variables.token == null || !variables.token.Valid
response: >
envoy.Denied(401).Response()
# request authenticated but not admin role -> 403
- match: >
variables.token.Claims.?role.orValue("") != "admin"
response: >
envoy.Denied(403).Response()
allow:
# request authenticated and admin role -> 200
- response: >
envoy
.Allowed()
.WithHeader("x-validated-by", "my-security-checkpoint")
.WithoutHeader("x-force-authorized")
.WithResponseHeader("x-add-custom-response-header", "added")
.Response()
EOF
TBC
Create a GatewayExtension to delegate auth to the Kyverno Authz Server¶
kubectl apply -f - <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: GatewayExtension
metadata:
namespace: kgateway-system
name: kyverno-authz-server
spec:
type: ExtAuth
extAuth:
grpcService:
backendRef:
name: kyverno-authz-server
namespace: kyverno
port: 9081
EOF
kubectl apply -f - <<EOF
apiVersion: gateway.kgateway.dev/v1alpha1
kind: TrafficPolicy
metadata:
namespace: kgateway-system
name: kyverno-authz-server
spec:
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: http
extAuth:
extensionRef:
name: kyverno-authz-server
EOF
Grant access to the Kyverno Authz Server service¶
Last thing we need to configure is to grant access to the Kyverno Authz Server service for our GatewayExtension to take effect.
# grant access
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1beta1
kind: ReferenceGrant
metadata:
name: kgateway-gateway
namespace: kyverno
spec:
from:
- group: gateway.kgateway.dev
kind: GatewayExtension
namespace: kgateway-system
to:
- group: ""
kind: Service
EOF
Testing¶
At this we have deployed and configured KGateway, the Kyverno Authz Server, a sample application, and the authorization and security policies.
Start an in-cluster shell¶
Let's start a pod in the cluster with a shell to call into the sample application.
# run an in-cluster shell
kubectl run -i -t busybox --image=alpine --restart=Never -n demo
Install curl¶
We will use curl to call into the sample application but it's not installed in our shell, let's install it in the pod.
# install curl
apk add curl
Call into the sample application¶
Now we can send request to the sample application and verify the result.
For convenience, we will store Alice’s and Bob’s tokens in environment variables.
Here Bob is assigned the admin role and Alice is assigned the guest role.
export ALICE_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjIyNDEwODE1MzksIm5iZiI6MTUxNDg1MTEzOSwicm9sZSI6Imd1ZXN0Iiwic3ViIjoiWVd4cFkyVT0ifQ.ja1bgvIt47393ba_WbSBm35NrUhdxM4mOVQN8iXz8lk"
export BOB_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjIyNDEwODE1MzksIm5iZiI6MTUxNDg1MTEzOSwicm9sZSI6ImFkbWluIiwic3ViIjoiWVd4cFkyVT0ifQ.veMeVDYlulTdieeX-jxFZ_tCmqQ_K8rwx2OktUHv5Z0"
Calling without a JWT token will return 401
:
curl -s -w "\nhttp_code=%{http_code}" http.kgateway-system/get
Calling with Alice’s JWT token will return 403
:
curl -s -w "\nhttp_code=%{http_code}" http.kgateway-system/get -H "authorization: Bearer $ALICE_TOKEN"
Calling with Bob’s JWT token will return 200
:
curl -s -w "\nhttp_code=%{http_code}" http.kgateway-system/get -H "authorization: Bearer $BOB_TOKEN"
Wrap Up¶
Congratulations on completing the tutorial!
This tutorial demonstrated how to configure kgateway to utilize the Kyverno Authz Server as an external authorization service.
Additionally, the tutorial provided an example policy to decode a JWT token and make a decision based on it.