Ingress Gateway without TLS Termination
The Securing Gateways with HTTPS task describes how to configure HTTPSingress access to an HTTP service. This example describes how to configure HTTPS ingress access to an HTTPS service,i.e., configure an ingress gateway to perform SNI passthrough, instead of TLS termination on incoming requests.
The example HTTPS service used for this task is a simple NGINX server.In the following steps you first deploy the NGINX service in your Kubernetes cluster.Then you configure a gateway to provide ingress access to the service via host nginx.example.com
.
Generate client and server certificates and keys
- Clone the https://github.com/nicholasjackson/mtls-go-example repository:
$ git clone https://github.com/nicholasjackson/mtls-go-example
- Change directory to the cloned repository:
$ pushd mtls-go-example
- Generate the certificates for
nginx.example.com
.Use any password with the following command:
$ ./generate.sh nginx.example.com <password>
When prompted, select y
for all the questions.
- Move the certificates into the
nginx.example.com
directory:
$ mkdir ../nginx.example.com && mv 1_root 2_intermediate 3_application 4_client ../nginx.example.com
- Return to the root directory:
$ popd
Deploy an NGINX server
- Create a Kubernetes Secret to hold the server’scertificate.
$ kubectl create secret tls nginx-server-certs --key nginx.example.com/3_application/private/nginx.example.com.key.pem --cert nginx.example.com/3_application/certs/nginx.example.com.cert.pem
- Create a configuration file for the NGINX server:
$ cat <<EOF > ./nginx.conf
events {
}
http {
log_format main '$remote_addr - $remote_user [$time_local] $status '
'"$request" $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log;
server {
listen 443 ssl;
root /usr/share/nginx/html;
index index.html;
server_name nginx.example.com;
ssl_certificate /etc/nginx-server-certs/tls.crt;
ssl_certificate_key /etc/nginx-server-certs/tls.key;
}
}
EOF
- Create a Kubernetes ConfigMapto hold the configuration of the NGINX server:
$ kubectl create configmap nginx-configmap --from-file=nginx.conf=./nginx.conf
- Deploy the NGINX server:
$ cat <<EOF | istioctl kube-inject -f - | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: my-nginx
labels:
run: my-nginx
spec:
ports:
- port: 443
protocol: TCP
selector:
run: my-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx
spec:
selector:
matchLabels:
run: my-nginx
replicas: 1
template:
metadata:
labels:
run: my-nginx
spec:
containers:
- name: my-nginx
image: nginx
ports:
- containerPort: 443
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx
readOnly: true
- name: nginx-server-certs
mountPath: /etc/nginx-server-certs
readOnly: true
volumes:
- name: nginx-config
configMap:
name: nginx-configmap
- name: nginx-server-certs
secret:
secretName: nginx-server-certs
EOF
- To test that the NGINX server was deployed successfully, send a request to the server from its sidecar proxywithout checking the server’s certificate (use the
-k
option ofcurl
). Ensure that the server’s certificate isprinted correctly, i.e.,common name
is equal tonginx.example.com
.
$ kubectl exec -it $(kubectl get pod -l run=my-nginx -o jsonpath={.items..metadata.name}) -c istio-proxy -- curl -v -k --resolve nginx.example.com:443:127.0.0.1 https://nginx.example.com
...
SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256
server certificate verification SKIPPED
server certificate status verification SKIPPED
common name: nginx.example.com (matched)
server certificate expiration date OK
server certificate activation date OK
certificate public key: RSA
certificate version: #3
subject: C=US,ST=Denial,L=Springfield,O=Dis,CN=nginx.example.com
start date: Wed, 15 Aug 2018 07:29:07 GMT
expire date: Sun, 25 Aug 2019 07:29:07 GMT
issuer: C=US,ST=Denial,O=Dis,CN=nginx.example.com
> GET / HTTP/1.1
> User-Agent: curl/7.35.0
> Host: nginx.example.com
...
< HTTP/1.1 200 OK
< Server: nginx/1.15.2
...
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
Configure an ingress gateway
- Define a
Gateway
with aserver
section for port 443. Note thePASSTHROUGH
tls
mode
which instructsthe gateway to pass the ingress traffic AS IS, without terminating TLS.
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: mygateway
spec:
selector:
istio: ingressgateway # use istio default ingress gateway
servers:
- port:
number: 443
name: https
protocol: HTTPS
tls:
mode: PASSTHROUGH
hosts:
- nginx.example.com
EOF
- Configure routes for traffic entering via the
Gateway
:
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: nginx
spec:
hosts:
- nginx.example.com
gateways:
- mygateway
tls:
- match:
- port: 443
sni_hosts:
- nginx.example.com
route:
- destination:
host: my-nginx
port:
number: 443
EOF
Follow the instructions inDetermining the ingress IP and portsto define the
SECURE_INGRESS_PORT
andINGRESS_HOST
environment variables.Access the NGINX service from outside the cluster. Note that the correct certificate is returned by the server andit is successfully verified (SSL certificate verify ok is printed).
$ curl -v --resolve nginx.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST --cacert nginx.example.com/2_intermediate/certs/ca-chain.cert.pem https://nginx.example.com:$SECURE_INGRESS_PORT
Server certificate:
subject: C=US; ST=Denial; L=Springfield; O=Dis; CN=nginx.example.com
start date: Aug 15 07:29:07 2018 GMT
expire date: Aug 25 07:29:07 2019 GMT
common name: nginx.example.com (matched)
issuer: C=US; ST=Denial; O=Dis; CN=nginx.example.com
SSL certificate verify ok.
< HTTP/1.1 200 OK
< Server: nginx/1.15.2
...
<html>
<head>
<title>Welcome to nginx!</title>
Cleanup
- Remove created Kubernetes resources:
$ kubectl delete secret nginx-server-certs
$ kubectl delete configmap nginx-configmap
$ kubectl delete service my-nginx
$ kubectl delete deployment my-nginx
$ kubectl delete gateway mygateway
$ kubectl delete virtualservice nginx
- Delete the directory containing the certificates and the repository used to generate them:
$ rm -rf nginx.example.com mtls-go-example
- Delete the generated configuration files used in this example:
$ rm -f ./nginx.conf
See also
Istio as a Proxy for External Services
Configure Istio ingress gateway to act as a proxy for external services.
Kubernetes Ingress with Cert-Manager
Demonstrates how to obtain Let's Encrypt TLS certificates for Kubernetes Ingress automatically using Cert-Manager.
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.
Consuming External Web Services
Describes a simple scenario based on Istio's Bookinfo example.
Describes how to configure an Istio gateway to expose a service outside of the service mesh.