Tutorial: Applying HTTP security rules with Kubernetes

This blog post focuses on Layer 7 (HTTP) policy rules and how to apply them for both outgoing and incoming connections in the context of a Kubernetes cluster using a ThirdPartyResource. This is a first step in integrating L7 policies into the Kubernetes world, next steps will involve integration with Istio and the Envoy proxy. We will talk about our plans and the details how Cilium empowers both of them in one of the next blog posts.


The Cilium 0.9 release (Release Notes) was a big step towards awesome Kubernetes integration. One of the many things that we added is a new ThirdPartyResource named CiliumNetworkPolicy. The purpose of CiliumNetworkPolicy is to extend the standardized NetworkPolicy resource and make all of the Cilium functionality available that is not yet accessible via the standard NetworkPolicy.

Step by Step Guide

This step by step guide shows how to apply HTTP security rules in three easy steps.

Step1: Deploy demo app

We start out with a standard Kubernetes cluster with three worker nodes:

$ kubectl get nodes
NAME      STATUS    AGE
worker0   Ready     115d
worker1   Ready     115d
worker2   Ready     115d

Cilium is deployed as DaemonSet:

$ kubectl -n kube-system get pods
NAME                                    READY     STATUS    RESTARTS   AGE
cilium-0srz0                            1/1       Running   0          10h
cilium-153hp                            1/1       Running   0          10h
cilium-5pk5c                            1/1       Running   2          10h
cilium-consul-0kf04                     1/1       Running   1          17h

We deploy a simple demo application in the form of Kubernetes deployments. This will create three deployments: app1, app2, and app3. It will also make app1 available via a service app1-service.

$ kubectl create -f https://raw.githubusercontent.com/cilium/cilium/master/examples/minikube/demo.yaml
service "app1-service" created
deployment "app1" created
deployment "app2" created
deployment "app3" created

We can now check the status of these deployments:

$ kubectl get pods
   NAME                       READY     STATUS              RESTARTS   AGE
   po/app1-2741898079-66lz0   0/1       ContainerCreating   0          40s
   po/app1-2741898079-jwfmk   1/1       Running             0          40s
   po/app2-2889674625-wxs08   0/1       ContainerCreating   0          40s
   po/app3-3000954754-fbqtz   0/1       ContainerCreating   0          40s

Step 2: Create L7/HTTP security policy

We want to define a Layer7 (HTTP) policy to protect app1. app1 has two API endpoints which can be called: GET /public and GET /private. We want to continue allowing GET /public but prohibit all calls to GET /private. The following policy achieves this:

apiVersion: "cilium.io/v1"
kind: CiliumNetworkPolicy
description: "L7 policy for getting started using Kubernetes guide"
metadata:
  name: "rule1"
spec:
  endpointSelector:
    matchLabels:
      id: app1
  ingress:
  - fromEndpoints:
    - matchLabels:
        id: app2
  - toPorts:
    - ports:
      - port: "80"
        protocol: TCP
      rules:
        HTTP:
        - method: "GET"
          path: "/public"

We can now import this Layer 7 (HTTP) policy using kubectl:

$ kubectl create -f https://raw.githubusercontent.com/cilium/cilium/master/examples/minikube/l3_l4_l7_policy.yaml

Step 3: Test the policy

app1 is now protected. While we can still access app1/public from app2...

$ kubectl exec $APP2_POD -- curl -s http://${SVC_IP}/public
{ 'val': 'this is public' }

... and we can no longer access app1/private.

$ kubectl exec $APP2_POD -- curl -s http://${SVC_IP}/private
Access denied

Next Steps

This is just a first preview into our first step to integrate HTTP layer policies into Kubernetes. We will cover more of our upcoming next steps in follow-up blog posts:

  • Adding L7/HTTP security rules definitions to the Kubernetes NetworkPolicy to no longer require a ThirdPartyResource or CustomResourceDefinition.
  • Integration with Envoy proxy to enable protocols beyond HTTP (gRPC, MongoDB, ...)
  • The difference between a shared proxy vs a side car proxy model and how Cilium can provide to run a hybrid model where this decision can be made per pod.
  • Tight cooperation with the Envoy proxy where Cilium can share the existing context information is has, e.g. source security identity for ingress rules, existing service loadbalancing/routing decision.
  • Kernel-assisted acceleration of the Envoy proxy
  • Adding support for CustomResoureDefinition as ThirdPartyResource will be deprecated with Kubernetes 1.8

Stay tuned for more blog posts but feel free to ask questions or provide feedback on our journey so far.