For ages I’ve been waiting for a way to enforce netwok policies on AKS, so last weekend while I was googling around, I found this hidden gem posted by Marcus Robinson: Enforcing Network Policies using kube-router on AKS and had to test the proposed solution.

Prerequisites:

Create a service exposed throuh your AKS DNS Zone


Let’s start by deploying the following service to your Kubernetes cluster, by saving the following content to a file named dni-function.yaml and replacing [YOUR_DNS__ZONE_NAME] with the corresponding value of your service:

 1apiVersion: apps/v1beta1
 2kind: Deployment
 3metadata:
 4  name: dni-function
 5spec:
 6  replicas: 1
 7  template:
 8    metadata:
 9      labels:
10        app: dni-function
11    spec:
12      containers:
13      - name: dni-function
14        image: cmendibl3/dni:1.0.0
15        ports:
16        - containerPort: 80
17---
18apiVersion: v1
19kind: Service
20metadata:
21  name: dni-function
22spec:
23  type: ClusterIP
24  ports:
25  - name:
26    port: 80
27  selector:
28    app: dni-function
29---
30apiVersion: extensions/v1beta1
31kind: Ingress
32metadata:
33  name: dni-function
34  annotations:
35    kubernetes.io/ingress.class: addon-http-application-routing
36spec:
37  rules:
38  - host: dni-function.[YOUR_DNS__ZONE_NAME]
39    http:
40      paths:
41      - backend:
42          serviceName: dni-function
43          servicePort: 80
44        path: /

Now deploy it to Kubernetes:

1kubectl apply -f ./dni-function.yaml

In a few seconds you’ll have a working Web API (Validates Spanish National Identification Numbers).

Now test the service with the following command:

1curl -k http://dni-function.[YOUR_DNS__ZONE_NAME]/api/validate?dni=88410248L

which should return true.

Deploy kube-router


Thanks to Marcus Robinson we can deploy kube-router to AKS:

1kubectl apply -f https://raw.githubusercontent.com/marrobi/kube-router/marrobi/aks-yaml/daemonset/kube-router-firewall-daemonset-aks.yaml

Deny all traffic to the service


Now let’s try to deny all the traffic to the service, creating a dni-function-deny-all.yaml file with the following contents:

1kind: NetworkPolicy
2apiVersion: networking.k8s.io/v1
3metadata:
4  name: dni-function-deny-all
5spec:
6  podSelector:
7    matchLabels:
8      app: dni-function
9  ingress: []

Deploy the policy:

1kubectl apply -f ./dni-function-deny-all.yaml

Try calling the service again:

1curl -k http://dni-function.[YOUR_DNS__ZONE_NAME]/api/validate?dni=88410248L

This time you should get:

1<html>
2<head><title>502 Bad Gateway</title></head>
3<body bgcolor="white">
4<center><h1>502 Bad Gateway</h1></center>
5<hr><center>nginx/1.13.12</center>
6</body>
7</html>

That’s it! Your service is no longer available!!!

Allow only traffic from a specific pod

Create a dni-function-allow-internal.yaml file with the following contents:

 1kind: NetworkPolicy
 2apiVersion: networking.k8s.io/v1
 3metadata:
 4  name: dni-function-allow-internal
 5spec:
 6  podSelector:
 7    matchLabels:
 8      app: dni-function
 9  ingress:
10  - from:
11      - podSelector:
12          matchLabels:
13            app: internal

Deploy the policy, which restricts the traffic to pods with the label: app=internal, and check that you still can’t connect:

1kubectl apply -f ./dni-function-allow-internal.yaml
2curl -k http://dni-function.[YOUR_DNS__ZONE_NAME]/api/validate?dni=88410248L

Now let’s create a pod with the expected label and try calling the dni-function service from it:

1kubectl run internal-function-tester --rm -i -t --image=alpine --labels app=internal -- sh
2wget -qO- --timeout=2 http://dni-function/api/validate?dni=88410248L

This time you should get true as the result!!!

To learn more about Network Policies check the kubernetes-network-policy-recipes repo and feel free to download the code and files for this post here