Mit der neuen Version des Cilium CNI auf unserem Kubernetes-Service erhältst Du die Möglichkeit, den Datenverkehr anhand von L7-Eigenschaften zu filtern. Das ist normalerweise Service-Meshes vorbehalten und kann bei der Sicherheit deiner Dienste sehr hilfreich sein. In diesem Tutorial werden wir einen API-Endpunkt so absichern, dass unser Client nur auf bestimmte Routen zugreifen kann. Alle anderen Anfragen werden gar nicht erst an den Dienst weitergeleitet, um die Belastung der API so gering wie möglich zu halten.
Voraussetzungen
Bevor Du beginnst, benötigst Du Folgendes:
- Ein Kubernetes-Cluster, der mit Cilium in Betrieb ist.
- kubectl Befehlszeilentool installiert und für die Kommunikation mit deinem Cluster konfiguriert ist.
- Grundlegende Kenntnisse über Kubernetes Pods, Dienste und Namespaces.
Erstellen von API + API-Client
$ kubectl apply -f https://gist.github.com/modzilla99/0cbdd39cc838e752ae8cdb5ec3cdd03a/raw/adb7218bb1e9195c42192d71809f6f7043e50cd7/deploy.yaml configmap/apiconfig created deployment.apps/api created service/api created pod/api-client created
Wir haben nun einen Dienst namens „api“ erstellt, der an das Deployment „api“ gebunden ist. Er hat zwei Endpunkte. Die Route /secret sollte privat und /greetings sollte öffentlich zugänglich sein. Da wir keine NetworkPolicies definiert haben, sind beide Routen für jeden im Cluster laufenden Pod zugänglich.
Testen der API
Probieren wir also zunächst die API aus:
$ kubectl exec -it api-client -- curl -H 'X-Security-Header: mysecret' api/secret/mysecret { "name": "mysecret", "secret": "syferghewg" } $ kubectl exec -it api-client -- curl api/greetings/World Greetings, World! $ kubectl exec -it api-client -- curl google.com The document has moved
Wie Du siehst, ist die API ohne Einschränkungen zugänglich und der api-client pod hat zudem vollen/ungefilterten externen Zugriff.
Zugriff einschränken
Um den Zugriff zu minimieren, wollen wir den Zugriff der Pods ausschließlich auf unsere API und api.github.com beschränken. Mit der folgenden NetworkPolicy lässt sich dieses Ziel effektiv erreichen:
--- apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: name: allow-client-egress spec: endpointSelector: # Apply policy to api client matchLabels: app: client type: production ingress: # Drop all incoming traffic - {} egress: # Allow API acccess to GitHub only via HTTPs - toFQDNs: - matchName: api.github.com toPorts: - ports: - port: "443" # Allow access to our API - toEndpoints: - matchLabels: app: api type: production toPorts: - ports: - port: "6090" protocol: TCP # Allow DNS queries - toEndpoints: - matchLabels: io.kubernetes.pod.namespace: kube-system k8s-app: kube-dns toPorts: - ports: - port: "53" rules: dns: - matchPattern: "*"
Jetzt kann der Pod nur noch mit unserer und der GitHub-API kommunizieren und den Kubernetes-DNS-Server abfragen. Jede Anfrage an andere Ressourcen wird jetzt fehlschlagen:
$ kubectl exec -it api-client -- curl -4 --connect-timeout 3 -v google.com * processing: google.com * Trying 142.250.184.238:80... * ipv4 connect timeout after 2974ms, move on! * Failed to connect to google.com port 80 after 3001 ms: Timeout was reached * Closing connection curl: (28) Failed to connect to google.com port 80 after 3001 ms: Timeout was reached $ kubectl exec -it api-client -- curl -4 https://api.github.com/user { "message": "Requires authentication", "documentation_url": "https://docs.github.com/rest/users/users#get-the-authenticated-user" }
Als nächstes wollen wir unsere API absichern. Wir wollen nicht, dass der Pod nach außen kommunizieren kann und er soll nur den Zugang zu unseren beiden Routen erlauben. Da der /greetings Endpunkt öffentlich sein soll, öffnen wir den Zugang für jeden, während wir den Zugang zur /secret Route auf unseren API-Client beschränken.
--- apiVersion: cilium.io/v2 kind: CiliumNetworkPolicy metadata: name: allow-api-ingress spec: endpointSelector: matchLabels: app: api type: production egress: # Deny any external traffic - {} ingress: # Allow access to /secret route from our api client - fromEndpoints: - matchLabels: app: client type: production toPorts: - ports: - port: "6090" protocol: TCP rules: http: - method: "GET" path: "/secret/.*" # Require HTTP header for authorization headers: - 'X-Security-Header: mysecret' # Allow access to /greetings route from anyone - toPorts: - ports: - port: "6090" protocol: TCP rules: http: - method: "GET" path: "/greetings/.*"
Jetzt können wir nur auf die /secret-Route mit dem erforderlichen Header und vom Api-Client-Pod aus zugreifen:
$ kubectl exec -it api-client -- curl api/secret/mysecret Access denied $ kubectl exec -it api-client -- curl -H 'X-Security-Header: mysecret' api/secret/mysecret { "name": "mysecret", "secret": "adasge53whbetn" }
Fazit
Cilium NetworkPolicies sind eine leistungsstarke Methode zur Kontrolle des Netzwerkverkehrs innerhalb deines Clusters. Durch die Definition von Regeln für eingehenden und ausgehenden Traffic kannst Du deine Anwendungen sichern und bei Bedarf isolieren. In diesem Tutorial wurden die Grundlagen der Erstellung und Verwendung von NetworkPolicies behandelt, aber Du kannst auch komplexere Richtlinien erstellen, die deinen speziellen Anforderungen entsprechen.
Benötigst Du Hilfe zu diesem Thema? Schicke uns eine Nachricht oder abonniere unseren Newsletter, um weitere Infos zu diesem Thema zu erhalten.