Dieser Artikel ist Teil einer Reihe.
- Teil 1: Kubernetes sicher und transparent – Erste Schritte mit Cilium
- Teil 2: Kubernetes sicher und transparent – Erste Schritte mit Cilium
- Teil 3: Kubernetes sicher und transparent – Erste Schritte mit Cilium (dieser Artikel)
Einleitung
Nachdem wir im letzten Teil der Serie den Todesstern erfolgreich zerstören konnten, begeben wir uns nun auf die dunkle Seite der Macht und schützen unseren Todesstern durch die Anwendung von Cilium-Netzwerkpolicies auf OSI-Schicht 3/4 und vor allem auf Schicht 7 vor den bösen Allianz-X-Wings, aber auch vor den eigenen Tie-Fightern, die ja auch mal Fehler machen können.
The empire strikes back!
Als erstes verbieten wir es Allianz-Raumschiffen, auf dem Todesstern zu landen. Dafür nutzen wir eine Policy, die auf OSI-Schicht 3 und 4 operiert.
Wenden wir die entsprechende Policy also an:
$ kubectl create -f - <<EOF
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "deathstar-policy"
spec:
description: "L3-L4 policy to restrict deathstar access to empire ships only"
endpointSelector:
matchLabels:
org: empire
class: deathstar
ingress:
- fromEndpoints:
- matchLabels:
org: empire
toPorts:
- ports:
- port: "80"
protocol: TCP
EOF
Hiermit verbieten wir aus Todesstern-Sicht eingehende Kommunikation aller Cilium-Endpunkte mit dem Label org=empire
auf TCP-Port 80. Versuchen wir erneut, mit dem X-Wing auf dem Todesstern zu landen:
$ kubectl exec xwing -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
Der Aufruf «hängt» und läuft irgendwann in einen Timeout (oder wird von uns via ctrl+c abgebrochen). Unsere Regel greift also, super! Zur Sicherheit prüfen wir auch, ob die imperialen Tie-Fighter immer noch landen können:
$ kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
Ship landed
Jawohl, das können sie. Ziel erreicht! Oder… oder?! Moment, da war doch was. Der Todesstern hat eine böse Schwachstelle. Genau, den v1/exhaust-port
-Endpunkt. Nun können feindliche X-Wings diesen zwar nicht mehr erreichen, aber vielleicht klaut eine böse Rebellin ja einen Tie-Fighter, oder ein Stormtrooper macht mal einen Fehler.
Simulieren wir das doch mal:
$ kubectl exec tiefighter -- curl -s -XPUT deathstar.default.svc.cluster.local/v1/exhaust-port
Panic: deathstar exploded
...
Oh je. Wir haben immer noch ein Problem! Bevor Darth Vader das jetzt mitbekommt, sollten wir es lieber schnell lösen. «Eigentlich» sollten Raumschiffe nur mit dem Lande-Endpunkt des Todessterns interagieren können. Derzeit ist das Prinzip aber «ganz oder gar nicht», durch die Anwendung der grobgranularen Policy auf OSI-Schicht 3 und 4. Unser Ziel können wir wie folgt beschreiben:
Wir wollen hier feingranulare Zugriffsregeln auf einzelne HTTP-Verben für einzelnen API-Endpunkte festlegen. Dies wäre mit Kubernetes-Netzwerkpolicies definitiv nicht möglich, weil wir uns hier auf OSI-Schicht 7 befinden.
Fügen wir also nun eine zweite Policy mit Regeln der OSI-Schicht 7 hinzu und schauen, ob wir den verbotenen Schwachpunkt noch erreichen können:
$ kubectl create -f - <<EOF
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "deathstar-policy-2"
spec:
description: "L7 policy to restrict access to specific HTTP call"
endpointSelector:
matchLabels:
org: empire
class: deathstar
ingress:
- fromEndpoints:
- matchLabels:
org: empire
toPorts:
- ports:
- port: "80"
protocol: TCP
rules:
http:
- method: "POST"
path: "/v1/request-landing"
EOF
Rufen wir nun den verbotenen Endpunkt erneut auf (Vorsicht, Falle!):
$ kubectl exec tiefighter -- curl -s -XPUT deathstar.default.svc.cluster.local/v1/exhaust-port
Panic: deathstar exploded
...
Oha! Der Todesstern explodiert immer noch. Das haben wir so nicht erwartet. Was ist hier passiert?
Nun, wir haben hier schmerzhaft gelernt, dass die NetworkPolicy und auch Ciliums entsprechende Derivate additiv sind. Sie führen Policies zusammen, wenn mehr als eine Policy für die gleiche Entität vorliegt.
Da wir in unserer Schicht-3/4-Policy festlegen, dass der gesamte eingehende TCP-Traffic auf Port 80 erlaubt ist, führt das abstrahiert zu folgender Rechnung:
all-tcp-port80-ingress-traffic + subset-of-tcp-port-80-ingress-traffic
== immer-noch-all-tcp-port-80-ingress-traffic
Wenn also unsere Bestehende Schicht-4-Regel allen eingehenden Traffic auf TCP unter Port 80 erlaubt, die Schicht-7-Regel dies dann aber einschränkt, gilt wegen der generellen Additivität immer noch «alles ist erlaubt».
Auch hier gibt es etwas von Ratiopharm Cilium, die so genannten Deny Policies, die sich nicht additiv verhalten.
Nachdem wir nun aber einen generellen Policy-Fallstrick besser kennengelernt haben, fixen wir lieber erstmal schnell unser Problem, bevor der Imperator guckt. Zuerst löschen wir dafür die neue Policy:
$ kubectl delete CiliumNetworkPolicy deathstar-policy-2
ciliumnetworkpolicy.cilium.io "deathstar-policy-2" deleted
Nun aktualisieren wir stattdessen unsere bestehende Policy, damit sie auch die entsprechenden Schicht-7-Regeln enthält:
$ kubectl apply -f - <<EOF
apiVersion: "cilium.io/v2"
kind: CiliumNetworkPolicy
metadata:
name: "deathstar-policy"
spec:
description: "L7 policy to restrict access to specific HTTP call"
endpointSelector:
matchLabels:
org: empire
class: deathstar
ingress:
- fromEndpoints:
- matchLabels:
org: empire
toPorts:
- ports:
- port: "80"
protocol: TCP
rules:
http:
- method: "POST"
path: "/v1/request-landing"
EOF
Versuchen wir nun, den Todesstern wieder zu zerstören:
$ kubectl exec tiefighter -- curl -s -XPUT deathstar.default.svc.cluster.local/v1/exhaust-port
Access denied
Wir erhalten wir eine Access Denied-Meldung. Sehr gut! Können die imperialen Tie-Fighter denn immer noch landen?
$ kubectl exec tiefighter -- curl -s -XPOST deathstar.default.svc.cluster.local/v1/request-landing
Ship landed
Ja. Auftrag erfüllt, wir dürfen unseren Kopf behalten. Der Imperator wird zufrieden sein. Bereiten wir noch alles für die große Präsentation vor - mit Hilfe der Service Map.
Schauen wir uns die Regeln mit Blick auf die bösen Allianz-X-Wings an, sieht das wie folgt aus:
Die Ansicht für den Tie-Fighter dagegen zeigt, dass wir nur Landeanfragen stellen dürfen:
Im obigen Bild sehen wir im unteren Bereich auch den Livestream der Events im Namespace. Dort kann der Imperator dann schön sehen, dass der X-Wing zwar versucht, auf dem Todesstern zu landen, dies aber nun durch unsere Policy verboten wurde. Und da klingt auch schon der Imperial March durch die Gänge…