After the gateway receives and accepts HTTPS traffic, the gateway terminates the TLS connection, and forwards the unencrypted HTTP request to the destination in the cluster.

Figure: HTTPS listener setup
Figure: HTTPS listener setup

Before you begin

  1. Set up Gloo Mesh Gateway in a single cluster.
  2. Install Bookinfo and other sample apps.
  3. The openssl version must be at least 1.1.

    1. Check your openssl version. 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 self-signed TLS certificates

Create a self-signed root certificate that you use to sign a server certificate for the HTTPS/TLS listener on your gateway.

To create your own TLS certificate for a test environment, complete the following steps.

  1. Create a self-signed root certificate. The following command creates a root certificate that is valid for a year and that 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 -new -newkey rsa:4096 -x509 -sha256 \
        -days 365 -nodes -out root.crt -keyout root.key \
        -subj "/CN=*/O=root" \
        -addext "subjectAltName = DNS:*"
      
  2. Use the root certificate to sign the server certificate for the gateway.
      # server cert
    cat > "gateway.conf" <<EOF
    [req]
    req_extensions = v3_req
    distinguished_name = req_distinguished_name
    [req_distinguished_name]
    [ v3_req ]
    basicConstraints = CA:FALSE
    keyUsage = nonRepudiation, digitalSignature, keyEncipherment
    extendedKeyUsage = clientAuth, serverAuth
    subjectAltName = @alt_names
    [alt_names]
    DNS = *
    EOF
    
    openssl genrsa -out "gateway.key" 2048
    openssl req -new -key "gateway.key" -out gateway.csr -subj "/CN=*/O=root" -config "gateway.conf"
    openssl x509 -req \
      -days 3650 \
      -CA root.crt -CAkey root.key \
      -set_serial 0 \
      -in gateway.csr -out gateway.crt \
      -extensions v3_req -extfile "gateway.conf"
      

Set up an HTTPS/TLS listener

Configure your gateway with the server TLS certificate to start serving HTTPS traffic on your gateway.

  1. Create a Kubernetes secret to store the TLS certificate for the gateway. You create the secret in the same cluster and namespace that the Istio ingress gateway pod is deployed to. If you followed the Get started guide, the ingress gateway pod is deployed to the gloo-mesh-gateways namespace by default.

      kubectl create secret generic gw-ssl-1-secret \
    --from-file=tls.key=gateway.key \
    --from-file=tls.crt=gateway.crt \
    --dry-run=client -oyaml | kubectl apply -f- \
    --namespace gloo-mesh-gateways
      
  2. If you have ingress gateway proxies in multiple clusters or namespaces, repeat the previous step for each namespace in each cluster that an Istio ingress gateway pod is installed. The name of the secret must be the same in all clusters, although the secret can be in different namespaces as appropriate.

  3. Configure an HTTPS listener on your gateway. The following example adds the HTTPS listener to the virtual gateway resource that you created as part of the Get started guide guide. For more information about virtual gateways, see the API docs.

      kubectl apply -f - <<EOF
    apiVersion: networking.gloo.solo.io/v2
    kind: VirtualGateway
    metadata:
      name: istio-ingressgateway
      namespace: bookinfo
    spec:
      listeners: 
      - allowedRouteTables:
        - host: '*'
        http: {}
        port:
          number: 443
        tls:
          mode: SIMPLE
          secretName: gw-ssl-1-secret
      - allowedRouteTables:
        - host: '*'
        http: {}
        httpsRedirect: true
        port:
          number: 80
      workloads:
      - selector:
          labels:
            istio: ingressgateway
    EOF
      
    Review the following table to understand this configuration.
    SettingDescription
    metadata.namespaceCreate the virtual gateway in a namespace that is in the same workspace as your ingress gateway.
    spec.listeners.allowedRouteTablesYou can specify the hostname that the certificates are valid for, or select the route tables to use.
    spec.listeners.portSelect the HTTPS port 443, or you could use the port.name to select HTTPS.
    spec.listeners.tlsConfigure the TLS mode and secret to use to secure traffic. The SIMPLE TLS mode ensures that incoming TLS connections are terminated at the gateway, and that the unencrypted HTTP traffic is forwarded to the destination. Note that if you set up multiple gateways in multiple namespaces or clusters, each of those clusters and namespaces must have the TLS secret.
    spec.workloadsUse a workload selector label for the ingress gateway service that you want the virtual gateway to configure. In this example, you configure the Istio ingress gateway that you set up as part of the Get started guide.

Verify the secure connection

Now that you set up your TLS certificate for your domain, verify that HTTPS requests can be sent successfully.

  1. Save the external address of the ingress gateway. If you deployed your ingress gateway in a different namespace or with a different version, update the command.

      export INGRESS_GW_ADDRESS=$(kubectl get svc -n gloo-mesh-gateways istio-ingressgateway -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}")
    echo $INGRESS_GW_ADDRESS
      
  2. Send a request to the httpbin app on the https.example.com domain. Verify that you see a successful TLS handshake, the server TLS certificate that you created earlier, and a 200 HTTP response code from the httpbin app.

      curl -vik -H "X-httpbin: true" --resolve "www.example.com:443:${INGRESS_GW_ADDRESS}" https://www.example.com:443/status/200
      

    Example output:

      * Added www.example.com:443:34.86.217.21 to DNS cache
    * Hostname www.example.com was found in DNS cache
    *   Trying 34.86.217.21:443...
    * Connected to www.example.com (34.86.217.21) port 443 (#0)
    * 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=root
    *  start date: Dec 15 19:12:08 2023 GMT
    *  expire date: Dec 12 19:12:08 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 0x150012400)
    > GET /status/200 HTTP/2
    > Host: www.example.com
    > user-agent: curl/7.77.0
    > accept: */*
    > x-httpbin: true
    > 
    * Connection state changed (MAX_CONCURRENT_STREAMS == 2147483647)!
    < HTTP/2 200 
    HTTP/2 200 
    < access-control-allow-credentials: true
    access-control-allow-credentials: true
    < access-control-allow-origin: *
    access-control-allow-origin: *
    < date: Fri, 15 Dec 2023 19:17:20 GMT
    date: Fri, 15 Dec 2023 19:17:20 GMT
    < content-length: 0
    content-length: 0
    < x-envoy-upstream-service-time: 0
    x-envoy-upstream-service-time: 0
    < server: istio-envoy
    server: istio-envoy
      

Verify HTTPS listeners in local test setups

If you test locally by using minikube or kind, or if you have insufficient permissions in your cloud platform, the load balancer service that exposes the Istio ingress gateway is not assigned an external IP address or hostname and remains in a <pending> state. You can follow the steps in this guide to verify that your HTTPS listener works.

Next steps

Now that you have the virtual gateway configured, you can add other Gloo Mesh Gateway resources to control traffic that is routed through the gateway.