HTTPS listeners

  1. Follow the Get started guide to install K8sGateway, set up a gateway resource, and deploy the httpbin sample app.

  2. Make sure that you have the OpenSSL version of openssl, not LibreSSL. The openssl version must be at least 1.1.

    1. Check the openssl version that is installed. If you see LibreSSL in the output, continue to the next step.

      openssl version
    2. Install the OpenSSL version (not LibreSSL). For example, you might use Homebrew.

      brew install openssl
    3. Review the output of the OpenSSL installation for the path of the binary file. You can choose to export the binary to your path, or call the entire path whenever the following steps use an openssl command.

      • For example, openssl might be installed along the following path: /usr/local/opt/openssl@3/bin/
      • To run commands, you can append the path so that your terminal uses this installed version of OpenSSL, and not the default LibreSSL. /usr/local/opt/openssl@3/bin/openssl req -new -newkey rsa:4096 -x509 -sha256 -days 3650...

Create a TLS certificate

  1. Create a directory to store your TLS credentials in.

    mkdir example_certs
  2. Create a self-signed root certificate. The following command creates a root certificate that is valid for a year and can serve any hostname. You use this certificate to sign the server certificate for the gateway later. For other command options, see the OpenSSL docs.

    # root cert
    openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=any domain/CN=*' -keyout example_certs/root.key -out example_certs/root.crt
  3. Use the root certificate to sign the gateway certificate.

    openssl req -out example_certs/gateway.csr -newkey rsa:2048 -nodes -keyout example_certs/gateway.key -subj "/CN=*/O=any domain"
    openssl x509 -req -sha256 -days 365 -CA example_certs/root.crt -CAkey example_certs/root.key -set_serial 0 -in example_certs/gateway.csr -out example_certs/gateway.crt
  4. Create a Kubernetes secret to store your server TLS ertificate. You create the secret in the same cluster and namespace that the gateway is deployed to.

    kubectl create secret tls -n gloo-system https \
      --key example_certs/gateway.key \
      --cert example_certs/gateway.crt
    kubectl label secret https gateway=https --namespace gloo-system

Set up an HTTPS listener

  1. Create a gateway resource and configure an HTTPS listener.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: https
      namespace: gloo-system
      labels:
        gateway: https
    spec:
      gatewayClassName: gloo-gateway
      listeners:
        - name: https
          port: 443
          protocol: HTTPS
          hostname: https.example.com
          tls:
            mode: Terminate
            certificateRefs:
              - name: https
                kind: Secret
          allowedRoutes:
            namespaces:
              from: All
    EOF
    Setting Description
    spec.gatewayClassName The name of the Kubernetes gateway class that you want to use to configure the gateway. When you set up K8sGateway, a default gateway class is set up for you.
    spec.listeners Configure the listeners for this gateway. In this example, you configure an HTTPS gateway that listens for incoming traffic on port 443.
    spec.listeners.tls.mode The TLS mode that you want to use for incoming requests. In this example, HTTPS requests are terminated at the gateway and the unecrypted request is forwarded to the service in the cluster.
    spec.listeners.tls.certificateRefs The Kubernetes secret that holds the TLS certificate and key for the gateway. The gateway uses these credentials to establish the TLS connection with a client, and to decrypt incoming HTTPS requests.
  2. Verify that the status of the gateway shows ACCEPTED.

    kubectl get gateway/https -n gloo-system -o yaml
  3. Create an HTTP route for the httpbin app and add it to the HTTPS gateway that you created.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: HTTPRoute
    metadata:
      name: httpbin-https
      namespace: httpbin
      labels:
        example: httpbin-route
        gateway: https
    spec:
      parentRefs:
        - name: https
          namespace: gloo-system
      rules:
        - backendRefs:
            - name: httpbin
              port: 8000
    EOF  
  4. Verify that the HTTP route is applied successfully.

    kubectl get httproute/httpbin-https -n httpbin -o yaml
  5. Get the external address of the gateway and save it in an environment variable. Note that it might take a few seconds for the gateway address to become available.

    export INGRESS_GW_ADDRESS=$(kubectl get svc -n gloo-system gloo-proxy-https -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}")
    echo $INGRESS_GW_ADDRESS   
    kubectl port-forward svc/gloo-proxy-https -n gloo-system 8443:443

  6. Send a request to the httpbin app and verify that you see the TLS handshake and you get back a 200 HTTP response code.

    curl -vik --resolve "https.example.com:443:${INGRESS_GW_ADDRESS}" https://https.example.com:443/status/200
    curl -vik --connect-to https.example.com:443:localhost:8443 https://https.example.com:443/status/200

    Example output:

    * ALPN, offering h2
    * ALPN, offering http/1.1
    * successfully set certificate verify locations:
    *  CAfile: /etc/ssl/cert.pem
    *  CApath: none
    * TLSv1.2 (OUT), TLS handshake, Client hello (1):
    * TLSv1.2 (IN), TLS handshake, Server hello (2):
    * TLSv1.2 (IN), TLS handshake, Certificate (11):
    * TLSv1.2 (IN), TLS handshake, Server key exchange (12):
    * TLSv1.2 (IN), TLS handshake, Server finished (14):
    * TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
    * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
    * TLSv1.2 (OUT), TLS handshake, Finished (20):
    * TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
    * TLSv1.2 (IN), TLS handshake, Finished (20):
    * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
    * ALPN, server accepted to use h2
    * Server certificate:
    *  subject: CN=*; O=gateway
    *  start date: Nov  5 01:54:04 2023 GMT
    *  expire date: Nov  2 01:54:04 2033 GMT
    *  issuer: CN=*; O=root
    *  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
    * Using HTTP2, server supports multi-use
    * Connection state changed (HTTP/2 confirmed)
    * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
    * Using Stream ID: 1 (easy handle 0x15200e800)
    > GET /status/200 HTTP/2
    > Host: https.example.com
    > user-agent: curl/7.77.0
    > accept: */*
    > 
    *  Connection state changed (MAX_CONCURRENT_STREAMS == 2147483647)!
    < HTTP/2 200 
    HTTP/2 200 
    ...

Cleanup

You can optionally remove the resources that you created as part of this guide.

  1. Remove the HTTP route for the httpbin app, the HTTPS gateway, and the Kubernetes secret that holds the TLS certificate and key.

    kubectl delete httproute,gateway,secret -A -l gateway=https
  2. Remove the example_certs directory that stores your TLS credentials.

    rm -rf example_certs