HTTPS Example

This example builds on the previous HTTP Example and add TLS termination for two HTTP routes. For simplicity, the second route to productpage is omitted.

apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: tls-gateway
spec:
  gatewayClassName: cilium
  listeners:
  - name: https-1
    protocol: HTTPS
    port: 443
    hostname: "bookinfo.cilium.rocks"
    tls:
      certificateRefs:
      - kind: Secret
        name: demo-cert
  - name: https-2
    protocol: HTTPS
    port: 443
    hostname: "hipstershop.cilium.rocks"
    tls:
      certificateRefs:
      - kind: Secret
        name: demo-cert
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: https-app-route-1
spec:
  parentRefs:
  - name: tls-gateway
  hostnames:
  - "bookinfo.cilium.rocks"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /details
    backendRefs:
    - name: details
      port: 9080
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: https-app-route-2
spec:
  parentRefs:
  - name: tls-gateway
  hostnames:
  - "hipstershop.cilium.rocks"
  rules:
  - matches:
    - path:
        type: PathPrefix
        value: /
    backendRefs:
    - name: productpage
      port: 9080

Create TLS Certificate and Private Key

For demonstration purposes we will use a TLS certificate signed by a made-up, self-signed certificate authority (CA). One easy way to do this is with minica. We want a certificate that will validate bookinfo.cilium.rocks and hipstershop.cilium.rocks, as these are the host names used in this example.

$ minica -domains '*.cilium.rocks'

On first run, minica generates a CA certificate and key (minica.pem and minica-key.pem). It also creates a directory called _.cilium.rocks containing a key and certificate file that we will use for the TLS configuration.

Create a Kubernetes secret with this demo key and certificate:

$ kubectl create secret tls demo-cert --key=_.cilium.rocks/key.pem --cert=_.cilium.rocks/cert.pem

Deploy the Gateway and HTTPRoute

The Gateway configuration for this demo provides the similar routing to the details and productpage services.

$ kubectl apply -f https://raw.githubusercontent.com/cilium/cilium/HEAD/examples/kubernetes/gateway/basic-https.yaml

External IP address will be shown up in Gateway. Also, the host names should be shown up in related HTTPRoutes.

$ kubectl get gateway tls-gateway
NAME          CLASS    ADDRESS         READY   AGE
tls-gateway   cilium   10.104.247.23   True    29s

$ kubectl get httproutes https-app-route-1 https-app-route-2
NAME                HOSTNAMES                      AGE
https-app-route-1   ["bookinfo.cilium.rocks"]      29s
https-app-route-2   ["hipstershop.cilium.rocks"]   29s

Update /etc/hosts with the host names and IP address of the Gateway:

$ sudo perl -ni -e 'print if !/\.cilium\.rocks$/d' /etc/hosts; sudo tee -a /etc/hosts \
  <<<"$(kubectl get gateway tls-gateway -o jsonpath='{.status.addresses[0].value}') bookinfo.cilium.rocks hipstershop.cilium.rocks"

Make HTTPS Requests

By specifying the CA’s certificate on a curl request, you can say that you trust certificates signed by that CA.

$ curl --cacert minica.pem -v https://bookinfo.cilium.rocks/details/1
$ curl --cacert minica.pem -v https://hipstershop.cilium.rocks/

If you prefer, instead of supplying the CA you can specify -k to tell the curl client not to validate the server’s certificate. Without either, you will get an error that the certificate was signed by an unknown authority.

Specifying -v on the curl request, you can see that the TLS handshake took place successfully.