Secure gateways
Configure transport layer security (TLS) certificates in your Gloo Mesh virtual gateway. Then, your Istio ingress gateways can serve HTTPS traffic.
Before you begin
- Complete the demo setup to install Gloo Mesh, Istio, and Bookinfo in your cluster. As part of this setup, keep in mind the following points.
- License: Make sure to use your Gloo Mesh Gateway license key when you install Gloo Mesh Enterprise.
- Namespaces: The setup example deploys the gateways into the
istio-system
namespace. If you use a different namespace, update the example configuration files.
-
The default
openssl
version that is included in macOS is LibreSSL, which does not work with these instructions.Make sure that you have the OpenSSL version of
openssl
, not LibreSSL. Theopenssl
version must be at least 1.1.- Check the
openssl
version that is installed. If you see LibreSSL in the output, continue to the next step.openssl version
- Install the OpenSSL version (not LibreSSL). For example, you might use Homebrew.
brew install openssl
- 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...
- For example,
- Check the
- Set up environment variables for your certificates.
- Update the
DNS_NAME
with the domain name that the certificate is for. - Update the
GATEWAY_NAMESPACE
and$REMOTE_CONTEXT
values to match the cluster and namespace that the Istio ingress gateway is deployed to.
ROOT_CERT_NAME=gateway-root DNS_NAME=www.example.com SERVER_CERT_NAME=north-south-gw-tls GATEWAY_NAMESPACE=istio-system GATEWAY_KUBE_CONTEXT=$REMOTE_CONTEXT
- Update the
Create TLS certificate and key pair
In production scenarios, you might have a TLS certificate and key pair from a certificate management tool that you use. In this case, continue to the next section.
To create your own for a test environment, complete the following steps.
- Create the root certificate. The following command creates a root key for 10 years for the DNS hostname that you previously set as an environment variable. You can create a separate root key for each hostname. You might also use wildcards in the DNS hostname, such as to make a root key for multiple subdomains (
*.example.com
), or to create a test root key for any host (*
). For more information, see the OpenSSL docs.# root cert openssl req -new -newkey rsa:4096 -x509 -sha256 \ -days 3650 -nodes -out ${ROOT_CERT_NAME}.crt -keyout ${ROOT_CERT_NAME}.key \ -subj "/CN=${DNS_NAME}/O=${ROOT_CERT_NAME}" \ -addext "subjectAltName = DNS:${DNS_NAME}"
- Use the root certificate to create the server certificate.
# server cert cat > "${SERVER_CERT_NAME}.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 = ${DNS_NAME} EOF openssl genrsa -out "${SERVER_CERT_NAME}.key" 2048 openssl req -new -key "${SERVER_CERT_NAME}.key" -out ${SERVER_CERT_NAME}.csr -subj "/CN=${DNS_NAME}/O=${SERVER_CERT_NAME}" -config "${SERVER_CERT_NAME}.conf" openssl x509 -req \ -days 3650 \ -CA ${ROOT_CERT_NAME}.crt -CAkey ${ROOT_CERT_NAME}.key \ -set_serial 0 \ -in ${SERVER_CERT_NAME}.csr -out ${SERVER_CERT_NAME}.crt \ -extensions v3_req -extfile "${SERVER_CERT_NAME}.conf"
Configure TLS for the virtual gateway
In your Gloo Mesh VirtualGateway
custom resource to include add the TLS configuration details, including an HTTPS redirect. Then, Gloo Mesh applies the updates to each Istio ingress gateway that the virtual gateway selects so that the gateways handle HTTPS traffic for your hosts.
-
Add your server certificate to the service mesh by using a Kubernetes
Secret
. You create the secret in the same cluster and namespace that the ingress gateway is deployed to.# create secret from server cert kubectl create secret generic ${SERVER_CERT_NAME}-secret \ --from-file=tls.key=${SERVER_CERT_NAME}.key \ --from-file=tls.crt=${SERVER_CERT_NAME}.crt \ --dry-run=client -oyaml | kubectl apply -f- \ --context ${GATEWAY_KUBE_CONTEXT} \ --namespace ${GATEWAY_NAMESPACE}
-
If you have ingress gateways in multiple clusters or namespaces, repeat the previous step for each namespace in each cluster that an ingress gateway is installed. The name of the secret must be the same in all clusters, although the secret can be in different namespaces as appropriate.
-
Configure the
VirtualGateway
custom resource with the TLS details. Review the following example. For more information, see the API docs.Review the following table to understand this configuration.kubectl --context ${REMOTE_CONTEXT} apply -f - <<EOF apiVersion: networking.gloo.solo.io/v2 kind: VirtualGateway metadata: name: ${SERVER_CERT_NAME} namespace: {GATEWAY_NAMESPACE} spec: workloads: - selector: labels: istio: ingressgateway cluster: ${REMOTE_CLUSTER} listeners: - http: {} port: number: 443 tls: mode: SIMPLE secretName: ${SERVER_CERT_NAME}-secret httpsRedirect: true allowedRouteTables: - host: '${DNS_NAME}' EOF
Setting Description metadata.namespace Create the virtual gateway in a namespace that is in the same workspace as your Istio ingress gateway, such as the same namespace. spec.workloads Select the Istio ingress gateways that you want to secure traffic to. spec.listeners.port Select the HTTPS port 443, or you could use the port.name
to select HTTPS.spec.listeners.tls Configure the mode and secret to use to secure traffic. Remember that each cluster and namespace for each gateway must have the secret. spec.listeners.httpsRedirect Set to true so that any HTTP requests from port 80 are automatically redirected to HTTPS on port 443, with a 301 Moved Permanently
response code.spec.listeners.allowedRouteTables You can specify the host name that the certificates are valid for, or select the route tables to use.
Verify the secure connection
Production setup: If you have your own domain, certificates, DNS, and load balancer exposed on port 443 set up, you can test the secure connection by curling the HTTPS address.
curl https://${DNS_NAME}/ratings/1
Test setup: If you do not have DNS and a load balancer or node port set up, you can still test the secure connection by tweaking a few settings.
-
Enable port-forwarding for the
istio-ingressgateway
workload on port 443. Port-forwarding on 443 requires admin privileges, such as to runsudo
on Linux or macOS. If you do not have admin privileges to listen locally on port 443, use a number greater than 1024 instead.# Note: You need sudo priviliges to listen on port 443 locally: sudo kubectl port-forward -n istio-system service/istio-ingressgateway 443
# Listen on port 8443 locally: kubectl port-forward -n istio-system service/istio-ingressgateway 8443:443
-
Send a curl request that uses the HTTPS protocol for your domain, such as
www.example.com
.# Note: Assumes you are listening on port 443 locally curl -k --resolve www.example.com:443:127.0.0.1 https://www.example.com/ratings/1
# Note: Assumes you are listening on port 8443 locally curl -k --resolve www.example.com:8443:127.0.0.1 https://www.example.com:8443/ratings/1
The
ratings
service returns a response, such as{"id":1,"ratings":{"Reviewer1":5,"Reviewer2":4}}
. -
Print more verbose output by adding the
-v
option to the curl command.# Note: Assumes you are listening on port 443 locally curl -vik --resolve www.example.com:443:127.0.0.1 https://www.example.com/ratings/1
# Note: Assumes you are listening on port 8443 locally curl -vik --resolve www.example.com:8443:127.0.0.1 https://www.example.com:8443/ratings/1
Note the TLS information that is used for the request.
* Added www.example.com:8443:127.0.0.1 to DNS cache * Hostname www.example.com was found in DNS cache * Trying 127.0.0.1... * TCP_NODELAY set * Connected to www.example.com (127.0.0.1) port 8443 (#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=www.example.com; O=gw-ssl * start date: Aug 6 18:27:18 2021 GMT * expire date: Aug 4 18:27:18 2031 GMT * issuer: CN=www.example.com; O=gateway-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 0x7fb3c7010a00) > GET /ratings/1 HTTP/2 > Host: www.example.com:8443 > User-Agent: curl/7.64.1 > Accept: */* > * Connection state changed (MAX_CONCURRENT_STREAMS == 2147483647)! < HTTP/2 200 HTTP/2 200 < content-type: application/json content-type: application/json < date: Fri, 06 Aug 2021 21:46:05 GMT date: Fri, 06 Aug 2021 21:46:05 GMT < x-envoy-upstream-service-time: 2 x-envoy-upstream-service-time: 2 < server: istio-envoy server: istio-envoy * Connection #0 to host www.example.com left intact {"id":1,"ratings":{"Reviewer1":5,"Reviewer2":4}}* Closing connection 0