HTTPS redirect

Redirect HTTP traffic to HTTPS.

For more information, see the Kubernetes Gateway API documentation.

Before you begin

  1. Follow the Get started guide to install kgateway.

  2. Follow the Sample app guide to create an API gateway proxy with an HTTP listener and deploy the httpbin sample app.

  3. Get the external address of the gateway and save it in an environment variable.

    export INGRESS_GW_ADDRESS=$(kubectl get svc -n kgateway-system http -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}")
    echo $INGRESS_GW_ADDRESS  
    kubectl port-forward deployment/http -n kgateway-system 8080:8080

Set up an HTTPS listener

  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 certificate. You create the secret in the same cluster and namespace that the gateway is deployed to.

    kubectl create secret tls -n kgateway-system https \
      --key example_certs/gateway.key \
      --cert example_certs/gateway.crt
    kubectl label secret https gateway=https --namespace kgateway-system
  1. Configure an HTTPS listener on the Gateway that you created earlier. Note that your Gateway now has two listeners, http and https. You reference these listeners later in this guide to configure the HTTP to HTTPS redirect.
    kubectl apply -f- <<EOF                                                          
    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: http
      namespace: kgateway-system
    spec:
      gatewayClassName: kgateway
      listeners:
      - protocol: HTTP
        port: 8080
        name: http
        allowedRoutes:
          namespaces:
            from: All
      - name: https
        port: 443
        protocol: HTTPS
        tls:
          mode: Terminate
          certificateRefs:
            - name: https
              kind: Secret
        allowedRoutes:
          namespaces:
            from: All
    EOF

Redirect HTTP traffic to HTTPS

  1. Create an HTTPRoute for the httpbin app that sets up a RequestRedirect filter. By using the https scheme, you instruct the Gateway to redirect HTTP traffic to HTTPS and send back a 301 HTTP response code to the client.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin-https-redirect
      namespace: httpbin
      labels:
        example: httpbin-route
        gateway: https
    spec:
      parentRefs:
        - name: http
          namespace: kgateway-system
          sectionName: http
      hostnames: 
        - redirect.example
      rules:
        - filters:
          - type: RequestRedirect
            requestRedirect:
              scheme: https
              statusCode: 301
    EOF
    Setting Description
    spec.parentRefs.name
    spec.parentRefs.namespace
    The name and namespace of the Gateway resource that serves the route. In this example, you use the Gateway that you set up earlier.
    spec.parentRefs.sectionName The Gateway listener to bind this route to. In this example, you want to apply the HTTPS redirect to all traffic that is sent to the HTTP listener on the Gateway.
    spec.hostnames The hostname for which you want to apply the redirect.
    spec.rules.filters.type The type of filter that you want to apply to incoming requests. In this example, the RequestRedirect is used.
    spec.rules.filters.requestRedirect.scheme The type of redirect that you want to apply. The https scheme redirects all incoming HTTP traffic to HTTPS.
    spec.rules.filters.requestRedirect.statusCode The HTTP status code that you want to return to the client in case of a redirect. For a permanent redirect, use the 301 HTTP status code.
  2. Create another HTTPRoute for the httpbin app that routes incoming HTTPS traffic to the httpbin app. Note that you bind this HTTPRoute to the HTTPS listener on your gateway by using sectionName: https.

    kubectl apply -f- <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
      name: httpbin-https
      namespace: httpbin
      labels:
        example: httpbin-route
        gateway: https
    spec:
      parentRefs:
        - name: http
          namespace: kgateway-system
          sectionName: https
      hostnames: 
        - redirect.example
      rules:
        - backendRefs:
            - name: httpbin
              port: 8000
    EOF
  3. Send an HTTP request to the httpbin app on the redirect.example domain. Verify that you get back a 301 HTTP response code and that your redirect location shows https://redirect.example:8080/status/200.

    curl -vik http://$INGRESS_GW_ADDRESS:8080/status/200 -H "host: redirect.example"
    curl -vik localhost:8080/status/200 -H "host: redirect.example"

    Example output:

    * Mark bundle as not supporting multiuse
    < HTTP/1.1 301 Moved Permanently
    HTTP/1.1 301 Moved Permanently
    < location: https://redirect.example:8080/status/200
    location: https://redirect.example:8080/status/200
    < date: Mon, 06 Nov 2024 01:48:12 GMT
    date: Mon, 06 Nov 2024 01:48:12 GMT
    < server: envoy
    server: envoy
    < content-length: 0
    content-length: 0
  4. Send an HTTPS request to the httpbin app on the redirect.example domain. Verify that you get back a 200 HTTP response code and that you can see a successful TLS handshake with the gateway.

    curl -vik https://$INGRESS_GW_ADDRESS:443/status/200 -H "host: redirect.example"
    1. Port-forward the gateway proxy service on port 8443.

      kubectl port-forward svc/http -n kgateway-system 8443:443
    2. Send an HTTPS request to the redirect.example domain.

      curl -vik --connect-to redirect.example:443:localhost:8443 https://redirect.example/status/200

    Example output:

    * ALPN: curl offers h2,http/1.1
    * (304) (OUT), TLS handshake, Client hello (1):
    * (304) (IN), TLS handshake, Server hello (2):
    * (304) (IN), TLS handshake, Unknown (8):
    * (304) (IN), TLS handshake, Certificate (11):
    * (304) (IN), TLS handshake, CERT verify (15):
    * (304) (IN), TLS handshake, Finished (20):
    * (304) (OUT), TLS handshake, Finished (20):
    * SSL connection using TLSv1.3 / AEAD-CHACHA20-POLY1305-SHA256 / [blank] / UNDEF
    * ALPN: server did not agree on a protocol. Uses default.
    * Server certificate:
    *  subject: CN=*; O=any domain
    *  start date: Mar 14 13:37:22 2025 GMT
    *  expire date: Mar 14 13:37:22 2026 GMT
    *  issuer: O=any domain; CN=*
    *  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
    * using HTTP/1.x
    > GET /status/200 HTTP/1.1
    > Host: redirect.example
    > User-Agent: curl/8.7.1
    > Accept: */*
    > 
    * Request completely sent off
    < HTTP/1.1 200 OK
    HTTP/1.1 200 OK
    ...

Cleanup

You can remove the resources that you created in this guide.
  1. Remove the HTTPRoutes for the httpbin app and the Kubernetes secret that holds the TLS certificate and key.

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

    rm -rf example_certs
  3. Remove the HTTPS listener from your Gateway.

    kubectl apply -f- <<EOF                                                          
    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1
    metadata:
      name: http
      namespace: kgateway-system
    spec:
      gatewayClassName: kgateway
      listeners:
      - protocol: HTTP
        port: 8080
        name: http
        allowedRoutes:
          namespaces:
            from: All
    EOF