- Secure Gateways (File Mount)
- Before you begin
- Generate server certificate and private key
- Configure a TLS ingress gateway with a file mount-based approach
- Configure a mutual TLS ingress gateway
- Configure a TLS ingress gateway for multiple hosts
- Create a server certificate and private key for bookinfo.com
- Redeploy istio-ingressgateway with the new certificate
- Configure traffic for the bookinfo.com host
- Troubleshooting
- Troubleshooting for mutual TLS
- Cleanup
- See also
Secure Gateways (File Mount)
The Control Ingress Traffic taskdescribes how to configure an ingress gateway to expose an HTTPservice to external traffic. This task shows how to expose a secure HTTPSservice using either simple or mutual TLS.
The TLS required private key, server certificate, and root certificate, are configuredusing a file mount based approach.
Before you begin
Perform the steps in the Before you beginand Determining the ingress IP and portssections of the Control Ingress Traffic task. After performingthose steps you should have Istio and the httpbin service deployed,and the environment variables
INGRESS_HOSTandSECURE_INGRESS_PORTset.For macOS users, verify that you use curl compiled with the LibreSSL library:
$ curl --version | grep LibreSSLcurl 7.54.0 (x86_64-apple-darwin17.0) libcurl/7.54.0 LibreSSL/2.0.20 zlib/1.2.11 nghttp2/1.24.0
If a version of LibreSSL is printed as in the output above, your curl should work correctly with theinstructions in this task. Otherwise, try another installation of curl, for example on a Linux machine.
Generate server certificate and private key
For this task you can use your favorite tool to generate certificates and keys. The commands below useopenssl
- Create a root certificate and private key to sign the certificate for your services:
$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt
- Create a certificate and a private key for
httpbin.example.com:
$ openssl req -out httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization"$ openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in httpbin.example.com.csr -out httpbin.example.com.crt
Configure a TLS ingress gateway with a file mount-based approach
In this section you configure an ingress gateway with port 443 to handle HTTPStraffic. You first create a secret with a certificate and a private key. Thesecret is mounted to a file on the /etc/istio/ingressgateway-certs path. You can thencreate a gateway definition that configures a server on port 443.
- Create a Kubernetes secret to hold the server’s certificate and private key.Use
kubectlto create the secretistio-ingressgateway-certsin namespaceistio-system. The Istio gateway will load the secret automatically.
The secret must be named istio-ingressgateway-certs in the istio-system namespace to align with theconfiguration of the Istio default ingress gateway used in this task.
$ kubectl create -n istio-system secret tls istio-ingressgateway-certs --key httpbin.example.com.key --cert httpbin.example.com.crtsecret "istio-ingressgateway-certs" created
Note that by default all the pods in the istio-system namespace can mount this secret and access theprivate key. You may want to deploy the ingress gateway in a separate namespace and create the secret there, so thatonly the ingress gateway pod will be able to mount it.
Verify that tls.crt and tls.key have been mounted in the ingress gateway pod:
$ kubectl exec -it -n istio-system $(kubectl -n istio-system get pods -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') -- ls -al /etc/istio/ingressgateway-certs
- Define a
Gatewaywith aserversection for port 443.
The location of the certificate and the private key must be /etc/istio/ingressgateway-certs, or the gateway will fail to load them.
$ kubectl apply -f - <<EOFapiVersion: networking.istio.io/v1alpha3kind: Gatewaymetadata:name: httpbin-gatewayspec:selector:istio: ingressgateway # use istio default ingress gatewayservers:- port:number: 443name: httpsprotocol: HTTPStls:mode: SIMPLEserverCertificate: /etc/istio/ingressgateway-certs/tls.crtprivateKey: /etc/istio/ingressgateway-certs/tls.keyhosts:- "httpbin.example.com"EOF
- Configure routes for traffic entering via the
Gateway. Define the sameVirtualServiceas in the Control Ingress Traffic task:
$ kubectl apply -f - <<EOFapiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:name: httpbinspec:hosts:- "httpbin.example.com"gateways:- httpbin-gatewayhttp:- match:- uri:prefix: /status- uri:prefix: /delayroute:- destination:port:number: 8000host: httpbinEOF
- Access the
httpbinservice with HTTPS by sending anhttpsrequest using curl toSECURE_INGRESS_PORT.
The —resolve flag instructs curl to supply theSNI value httpbin.example.com when accessing the gateway IPover TLS. The —cacert option instructs curl to use your generated certificate to verify the server.
The -HHost:httpbin.example.com flag is included but only really needed if SECURE_INGRESS_PORT is differentfrom the actual gateway port (443), for example, if you are accessing the server via a mapped NodePort.
By sending the request to the /status/418 URL path, you get a nice visual clue that your httpbin service wasindeed accessed. The httpbin service will return the418 I’m a Teapot code.
$ curl -v -HHost:httpbin.example.com --resolve httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST --cacert example.com.crt https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418...Server certificate:subject: CN=httpbin.example.com; O=httpbin organizationstart date: Oct 27 19:32:48 2019 GMTexpire date: Oct 26 19:32:48 2020 GMTcommon name: httpbin.example.com (matched)issuer: O=example Inc.; CN=example.comSSL certificate verify ok.SSL certificate verify ok....HTTP/2 418...-=[ teapot ]=-_...._.' _ _ `.| ."` ^ `". _,\_;`"---"`|//| ;/\_ _/`"""`
It might take time for the gateway definition to propagate so you might get the following error:Failed to connect to httpbin.example.com port <your secure port>: Connection refused. Wait for a minute andthen retry the curl call.
Look for the Server certificate section in the curl output and specifically a line with the matched common name:common name: httpbin.example.com (matched). The line SSL certificate verify ok in the output indicatesthat the server’s certificate was verified successfully. If all went well, you should also see a returnedstatus of 418 along with a nice drawing of a teapot.
Configure a mutual TLS ingress gateway
In this section you extend your gateway’s definition from the previous section to supportmutual TLS between external clients and the gateway.
- Create a Kubernetes
Secretto hold the CA certificate thatthe server will use to verify its clients. Create the secretistio-ingressgateway-ca-certsin namespaceistio-systemusingkubectl. The Istio gateway will automatically load the secret.
The secret must be named istio-ingressgateway-ca-certs in the istio-system namespace to align with theconfiguration of the Istio default ingress gateway used in this task.
$ kubectl create -n istio-system secret generic istio-ingressgateway-ca-certs --from-file=example.com.crtsecret "istio-ingressgateway-ca-certs" created
- Redefine your previous
Gatewayto change thetlsmodetoMUTUALand to specifycaCertificates:
The location of the certificate must be /etc/istio/ingressgateway-ca-certs, or the gatewaywill fail to load them. The file (short) name of the certificate must be identical to the one you created the secretfrom, in this case example.com.crt.
$ kubectl apply -f - <<EOFapiVersion: networking.istio.io/v1alpha3kind: Gatewaymetadata:name: httpbin-gatewayspec:selector:istio: ingressgateway # use istio default ingress gatewayservers:- port:number: 443name: httpsprotocol: HTTPStls:mode: MUTUALserverCertificate: /etc/istio/ingressgateway-certs/tls.crtprivateKey: /etc/istio/ingressgateway-certs/tls.keycaCertificates: /etc/istio/ingressgateway-ca-certs/example.com.crthosts:- "httpbin.example.com"EOF
- Access the
httpbinservice by HTTPS as in the previous section:
$ curl -HHost:httpbin.example.com --resolve httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST --cacert example.com.crt https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418curl: (35) error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
It might take time for the gateway definition to propagate so you might still get 418. Wait for a minute andthen retry the curl call.
This time you will get an error since the server refuses to accept unauthenticated requests. You need to pass _curl_a client certificate and your private key for signing the request.
- Create a client certificate for the
httpbin.example.comservice. You can designate the client by thehttpbin-client.example.comURI, or use any other URI.
$ openssl req -out httpbin-client.example.com.csr -newkey rsa:2048 -nodes -keyout httpbin-client.example.com.key -subj "/CN=httpbin-client.example.com/O=httpbin's client organization"$ openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in httpbin-client.example.com.csr -out httpbin-client.example.com.crt
- Resend the previous request by curl, this time passing as parameters your client certificate (additional
—certoption)and your private key (the—keyoption):
$ curl -HHost:httpbin.example.com --resolve httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST --cacert example.com.crt --cert httpbin-client.example.com.crt --key httpbin-client.example.com.key https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418-=[ teapot ]=-_...._.' _ _ `.| ."` ^ `". _,\_;`"---"`|//| ;/\_ _/`"""`
This time the server performed client authentication successfully and you received the pretty teapot drawing again.
Configure a TLS ingress gateway for multiple hosts
In this section you will configure an ingress gateway for multiple hosts, httpbin.example.com and bookinfo.com.The ingress gateway will present to clients a unique certificate corresponding to each requested server.
Unlike the previous sections, the Istio default ingress gateway will not work out of the box because it is onlypreconfigured to support one secure host. You’ll need to first configure and redeploy the ingress gatewayserver with another secret, before you can use it to handle a second host.
Create a server certificate and private key for bookinfo.com
$ openssl req -out bookinfo.com.csr -newkey rsa:2048 -nodes -keyout bookinfo.com.key -subj "/CN=bookinfo.com/O=bookinfo organization"$ openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in bookinfo.com.csr -out bookinfo.com.crt
Redeploy istio-ingressgateway with the new certificate
- Create a new secret to hold the certificate for
bookinfo.com:
$ kubectl create -n istio-system secret tls istio-ingressgateway-bookinfo-certs --key bookinfo.com.key --cert bookinfo.com.crtsecret "istio-ingressgateway-bookinfo-certs" created
- To include a volume mounted from the new created secret, update the
istio-ingressgatewaydeployment.To patch theistio-ingressgatewaydeployment, create the followinggateway-patch.jsonfile:
$ cat > gateway-patch.json <<EOF[{"op": "add","path": "/spec/template/spec/containers/0/volumeMounts/0","value": {"mountPath": "/etc/istio/ingressgateway-bookinfo-certs","name": "ingressgateway-bookinfo-certs","readOnly": true}},{"op": "add","path": "/spec/template/spec/volumes/0","value": {"name": "ingressgateway-bookinfo-certs","secret": {"secretName": "istio-ingressgateway-bookinfo-certs","optional": true}}}]EOF
- Apply
istio-ingressgatewaydeployment patch with the following command:
$ kubectl -n istio-system patch --type=json deploy istio-ingressgateway -p "$(cat gateway-patch.json)"
- Verify that the key and certificate have been successfully loaded in the
istio-ingressgatewaypod:
$ kubectl exec -it -n istio-system $(kubectl -n istio-system get pods -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') -- ls -al /etc/istio/ingressgateway-bookinfo-certs
tls.crt and tls.key should appear in the directory contents.
Configure traffic for the bookinfo.com host
- Deploy the Bookinfo sample application, without a gateway:
Zip
$ kubectl apply -f @samples/bookinfo/platform/kube/bookinfo.yaml@
- Define a gateway for
bookinfo.com:
$ kubectl apply -f - <<EOFapiVersion: networking.istio.io/v1alpha3kind: Gatewaymetadata:name: bookinfo-gatewayspec:selector:istio: ingressgateway # use istio default ingress gatewayservers:- port:number: 443name: https-bookinfoprotocol: HTTPStls:mode: SIMPLEserverCertificate: /etc/istio/ingressgateway-bookinfo-certs/tls.crtprivateKey: /etc/istio/ingressgateway-bookinfo-certs/tls.keyhosts:- "bookinfo.com"EOF
- Configure the routes for
bookinfo.com. Define aVirtualServicelike the one insamples/bookinfo/networking/bookinfo-gateway.yaml:
$ kubectl apply -f - <<EOFapiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:name: bookinfospec:hosts:- "bookinfo.com"gateways:- bookinfo-gatewayhttp:- match:- uri:exact: /productpage- uri:exact: /login- uri:exact: /logout- uri:prefix: /api/v1/productsroute:- destination:host: productpageport:number: 9080EOF
- Send a request to the Bookinfo
productpage:
$ curl -o /dev/null -s -v -w "%{http_code}\n" -HHost:bookinfo.com --resolve bookinfo.com:$SECURE_INGRESS_PORT:$INGRESS_HOST --cacert example.com.crt -HHost:bookinfo.com https://bookinfo.com:$SECURE_INGRESS_PORT/productpage...Server certificate:subject: CN=bookinfo.com; O=bookinfo organizationstart date: Oct 27 20:08:32 2019 GMTexpire date: Oct 26 20:08:32 2020 GMTcommon name: bookinfo.com (matched)issuer: O=example Inc.; CN=example.comSSL certificate verify ok....200
- Verify that
httbin.example.comis accessible as previously. Send a request to it and see again the teapot youshould already love:
$ curl -HHost:httpbin.example.com --resolve httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST --cacert example.com.crt --cert httpbin-client.example.com.crt --key httpbin-client.example.com.key https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418...-=[ teapot ]=-_...._.' _ _ `.| ."` ^ `". _,\_;`"---"`|//| ;/\_ _/`"""`
Troubleshooting
- Inspect the values of the
INGRESS_HOSTandSECURE_INGRESS_PORTenvironmentvariables. Make sure they have valid values, according to the output of thefollowing commands:
$ kubectl get svc -n istio-system$ echo INGRESS_HOST=$INGRESS_HOST, SECURE_INGRESS_PORT=$SECURE_INGRESS_PORT
- Verify that the key and the certificate are successfully loaded in the
istio-ingressgatewaypod:
$ kubectl exec -it -n istio-system $(kubectl -n istio-system get pods -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') -- ls -al /etc/istio/ingressgateway-certs
tls.crt and tls.key should exist in the directory contents.
- If you created the
istio-ingressgateway-certssecret, but the key and thecertificate are not loaded, delete the ingress gateway pod and force theingress gateway pod to restart and reload key and certificate.
$ kubectl delete pod -n istio-system -l istio=ingressgateway
- Verify that the
Subjectis correct in the certificate of the ingress gateway:
$ kubectl exec -i -n istio-system $(kubectl get pod -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].metadata.name}') -- cat /etc/istio/ingressgateway-certs/tls.crt | openssl x509 -text -noout | grep 'Subject:'Subject: CN=httpbin.example.com, O=httpbin organization
- Verify that the proxy of the ingress gateway is aware of the certificates:
$ kubectl exec -ti $(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].metadata.name}') -n istio-system -- pilot-agent request GET certs{"ca_cert": "","cert_chain": "Certificate Path: /etc/istio/ingressgateway-certs/tls.crt, Serial Number: 100212, Days until Expiration: 370"}
- Check the log of
istio-ingressgatewayfor error messages:
$ kubectl logs -n istio-system -l istio=ingressgateway
- For macOS users, verify that you use
curlcompiled with the LibreSSLlibrary, as described in the Before you begin section.
Troubleshooting for mutual TLS
In addition to the steps in the previous section, perform the following:
- Verify that the CA certificate is loaded in the
istio-ingressgatewaypod:
$ kubectl exec -it -n istio-system $(kubectl -n istio-system get pods -l istio=ingressgateway -o jsonpath='{.items[0].metadata.name}') -- ls -al /etc/istio/ingressgateway-ca-certs
example.com.crt should exist in the directory contents.
- If you created the
istio-ingressgateway-ca-certssecret, but the CAcertificate is not loaded, delete the ingress gateway pod and force it toreload the certificate:
$ kubectl delete pod -n istio-system -l istio=ingressgateway
- Verify that the
Subjectis correct in the CA certificate of the ingress gateway:
$ kubectl exec -i -n istio-system $(kubectl get pod -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].metadata.name}') -- cat /etc/istio/ingressgateway-ca-certs/example.com.crt | openssl x509 -text -noout | grep 'Subject:'Subject: O=example Inc., CN=example.com
Cleanup
- Delete the
Gatewayconfiguration, theVirtualService, and the secrets:
$ kubectl delete gateway --ignore-not-found=true httpbin-gateway bookinfo-gateway$ kubectl delete virtualservice httpbin$ kubectl delete --ignore-not-found=true -n istio-system secret istio-ingressgateway-certs istio-ingressgateway-ca-certs$ kubectl delete --ignore-not-found=true virtualservice bookinfo
- Delete the directories of the certificates and the repository used to generate them:
$ rm -rf example.com.crt example.com.key httpbin.example.com.crt httpbin.example.com.key httpbin.example.com.csr httpbin-client.example.com.crt httpbin-client.example.com.key httpbin-client.example.com.csr bookinfo.com.crt bookinfo.com.key bookinfo.com.csr
- Remove the patch file you used for redeployment of
istio-ingressgateway:
$ rm -f gateway-patch.json
- Shutdown the httpbin service:
Zip
$ kubectl delete --ignore-not-found=true -f @samples/httpbin/httpbin.yaml@
See also
Istio as a Proxy for External Services
Configure Istio ingress gateway to act as a proxy for external services.
Deploy a Custom Ingress Gateway Using Cert-Manager
Describes how to deploy a custom ingress gateway using cert-manager manually.
Configuring Istio Ingress with AWS NLB
Describes how to configure Istio ingress with a network load balancer on AWS.
Ingress Gateway without TLS Termination
Describes how to configure SNI passthrough for an ingress gateway.
Ingress Gateways
Describes how to configure an Istio gateway to expose a service outside of the service mesh.
Kubernetes Ingress with Cert-Manager
Demonstrates how to obtain Let's Encrypt TLS certificates for Kubernetes Ingress automatically using Cert-Manager.
