I am tasked with migrating AWS lambda microservices to Kubernetes. For simplicity, there are two service endpoints: /admin
and /user
where you can GET or POST a request to get something done.
You have to be in admin
group (defined in an external authZ provider) to hit /admin
endpoint, or otherwise, you get 401. You have to be in user
group to have access to /user
endpoint.
I will have each endpoint exposed as a service running in a docker container. The question is - what is the correct way to add routing and path-based authorization in Kubernetes?
Like, if I go to /admin
in the browser, I need Kubernetes to check if I am in admin
group and then route me to admin
service; otherwise, it should return 401.
I can write this router myself, but I want to check if there is a built-in solution in Kubernetes for that.
You can explore istio's traffic management. They provide routing based on user identity (https://istio.io/docs/tasks/traffic-management/request-routing/#route-based-on-user-identity). But they do this by finding the user from request header. If you have an admin group then not sure whether this can be used as is.
Sample virtual service:
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: reviews
...
spec:
hosts:
- reviews
http:
- match:
- headers:
end-user:
exact: jason
route:
- destination:
host: reviews
subset: v2
- route:
- destination:
host: reviews
subset: v1
The above service can be accessed from outside the cluster using istio gateway.
check if there is a built-in solution in Kubernetes
Nope, there's no built-in solution for L7 network policies. Network Policies in Kubernetes are at L4 level, so things like rate limiting, path based firewall rules etc are not possible. Although you could look into a Service Mesh, like Linkerd, Istio or even using a different CNI plugin based on eBPF
such as Cilium.
Cilium has a CRD CiliumNetworkPolicy
which would help you with your usecase. You can put any proxy like Nginx/Caddy/HAProxy in front of it or an API Gateway like Kong, if you want to offload the authentication/authorization process. You can apply the following network policy, which would restrict the /admin
endpoint on any pod with label app: customapp
and would only allow it from a pod with label app: proxyapp
.
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "allow-from-proxy"
specs:
- endpointSelector:
matchLabels:
app: customapp
ingress:
- fromEndpoints:
- matchLabels:
app: proxyapp
toPorts:
- ports:
- port: "8080"
protocol: "TCP"
rules:
http:
- method: "GET"
path: "/admin"