Add gateway-api instructions: secure-ingress (#12051)

* Add gateway-api instructions: secure-ingress

* fix lint and test

* fixes

* mtls problem

* not work

* update option key

* regen

* mtls support

* wait

* improvements

* longer timeout

* lint
This commit is contained in:
Frank Budinsky 2022-10-07 15:37:15 -04:00 committed by GitHub
parent 4bc3929ce1
commit d0fadfed00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 900 additions and 465 deletions

View File

@ -24,7 +24,11 @@ This task describes how to configure Istio to expose a service outside of the se
* Make sure your current directory is the `istio` directory.
{{< boilerplate start-httpbin-service >}}
* Start the [httpbin]({{< github_tree >}}/samples/httpbin) sample:
{{< text bash >}}
$ kubectl apply -f @samples/httpbin/httpbin.yaml@
{{< /text >}}
## Configuring ingress using a gateway
@ -398,7 +402,7 @@ available for edge services.
In the preceding steps, you created a service inside the service mesh
and exposed an HTTP endpoint of the service to external traffic.
## Accessing the ingress gateway using node ports
## Using node ports of the ingress gateway service
{{< warning >}}
You should not use these instructions if your Kubernetes environment has an external load balancer supporting

View File

@ -20,7 +20,10 @@
# docs/tasks/traffic-management/ingress/ingress-control/index.md
####################################################################################################
source "content/en/boilerplates/snips/gateway-api-support.sh"
source "content/en/boilerplates/snips/start-httpbin-service.sh"
snip_before_you_begin_1() {
kubectl apply -f samples/httpbin/httpbin.yaml
}
snip_configuring_ingress_using_a_gateway_1() {
kubectl apply -f - <<EOF
@ -238,31 +241,31 @@ spec:
EOF
}
snip_accessing_the_ingress_gateway_using_node_ports_1() {
snip_using_node_ports_of_the_ingress_gateway_service_1() {
export INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="http2")].nodePort}')
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')
export TCP_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="tcp")].nodePort}')
}
snip_accessing_the_ingress_gateway_using_node_ports_2() {
snip_using_node_ports_of_the_ingress_gateway_service_2() {
export INGRESS_HOST=worker-node-address
}
snip_accessing_the_ingress_gateway_using_node_ports_3() {
snip_using_node_ports_of_the_ingress_gateway_service_3() {
gcloud compute firewall-rules create allow-gateway-http --allow "tcp:$INGRESS_PORT"
gcloud compute firewall-rules create allow-gateway-https --allow "tcp:$SECURE_INGRESS_PORT"
}
snip_accessing_the_ingress_gateway_using_node_ports_4() {
snip_using_node_ports_of_the_ingress_gateway_service_4() {
ibmcloud ks workers --cluster cluster-name-or-id
export INGRESS_HOST=public-IP-of-one-of-the-worker-nodes
}
snip_accessing_the_ingress_gateway_using_node_ports_5() {
snip_using_node_ports_of_the_ingress_gateway_service_5() {
export INGRESS_HOST=127.0.0.1
}
snip_accessing_the_ingress_gateway_using_node_ports_6() {
snip_using_node_ports_of_the_ingress_gateway_service_6() {
export INGRESS_HOST=$(kubectl get po -l istio=ingressgateway -n istio-system -o jsonpath='{.items[0].status.hostIP}')
}

View File

@ -0,0 +1,30 @@
#!/usr/bin/env bash
# shellcheck disable=SC1090,SC2154
# Copyright Istio Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
source "tests/util/gateway-api.sh"
install_gateway_api_crds
# @setup profile=default
source "content/en/docs/tasks/traffic-management/ingress/secure-ingress/test.sh"
# TODO fix cleanup approach and remove this temporary hack
# @cleanup
snip_cleanup_2
snip_cleanup_3
snip_cleanup_4
remove_gateway_api_crds

View File

@ -11,19 +11,22 @@ test: yes
---
The [Control Ingress Traffic task](/docs/tasks/traffic-management/ingress/ingress-control)
describes how to configure an ingress gateway to expose an HTTP
service to external traffic. This task shows how to expose a secure HTTPS
service using either simple or mutual TLS.
describes how to configure an ingress gateway to expose an HTTP service to external traffic.
This task shows how to expose a secure HTTPS service using either simple or mutual TLS.
{{< boilerplate gateway-api-support >}}
## Before you begin
1. Perform the steps in the [Before you begin](/docs/tasks/traffic-management/ingress/ingress-control#before-you-begin).
and [Determining the ingress IP and ports](/docs/tasks/traffic-management/ingress/ingress-control/#determining-the-ingress-ip-and-ports)
sections of the [Control Ingress Traffic](/docs/tasks/traffic-management/ingress/ingress-control) task. After performing
those steps you should have Istio and the [httpbin]({{< github_tree >}}/samples/httpbin) service deployed,
and the environment variables `INGRESS_HOST` and `SECURE_INGRESS_PORT` set.
* Setup Istio by following the instructions in the [Installation guide](/docs/setup/).
1. For macOS users, verify that you use `curl` compiled with the [LibreSSL](http://www.libressl.org) library:
* Start the [httpbin]({{< github_tree >}}/samples/httpbin) sample:
{{< text bash >}}
$ kubectl apply -f @samples/httpbin/httpbin.yaml@
{{< /text >}}
* For macOS users, verify that you use `curl` compiled with the [LibreSSL](http://www.libressl.org) library:
{{< text bash >}}
$ curl --version | grep LibreSSL
@ -36,43 +39,89 @@ and the environment variables `INGRESS_HOST` and `SECURE_INGRESS_PORT` set.
## Generate client and server certificates and keys
For this task you can use your favorite tool to generate certificates and keys. The commands below use
[openssl](https://man.openbsd.org/openssl.1)
This task requires several sets of certificates and keys which are used in the following examples.
You can use your favorite tool to create them or use the commands below to generate them using
[openssl](https://man.openbsd.org/openssl.1).
1. Create a root certificate and private key to sign the certificates for your services:
{{< text bash >}}
$ 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
$ mkdir example_certs1
$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example_certs1/example.com.key -out example_certs1/example.com.crt
{{< /text >}}
1. Create a certificate and a private key for `httpbin.example.com`:
1. Generate a certificate and a private key for `httpbin.example.com`:
{{< text bash >}}
$ 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 -sha256 -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in httpbin.example.com.csr -out httpbin.example.com.crt
$ openssl req -out example_certs1/httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs1/httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization"
$ openssl x509 -req -sha256 -days 365 -CA example_certs1/example.com.crt -CAkey example_certs1/example.com.key -set_serial 0 -in example_certs1/httpbin.example.com.csr -out example_certs1/httpbin.example.com.crt
{{< /text >}}
### Configure a TLS ingress gateway for a single host
1. Create a second set of the same kind of certificates and keys:
1. Ensure you have deployed the [httpbin]({{< github_tree >}}/samples/httpbin) service from [Before you begin](/docs/tasks/traffic-management/ingress/ingress-control#before-you-begin).
{{< text bash >}}
$ mkdir example_certs2
$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example_certs2/example.com.key -out example_certs2/example.com.crt
$ openssl req -out example_certs2/httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs2/httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization"
$ openssl x509 -req -sha256 -days 365 -CA example_certs2/example.com.crt -CAkey example_certs2/example.com.key -set_serial 0 -in example_certs2/httpbin.example.com.csr -out example_certs2/httpbin.example.com.crt
{{< /text >}}
1. Generate a certificate and a private key for `helloworld.example.com`:
{{< text bash >}}
$ openssl req -out example_certs1/helloworld.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs1/helloworld.example.com.key -subj "/CN=helloworld.example.com/O=helloworld organization"
$ openssl x509 -req -sha256 -days 365 -CA example_certs1/example.com.crt -CAkey example_certs1/example.com.key -set_serial 1 -in example_certs1/helloworld.example.com.csr -out example_certs1/helloworld.example.com.crt
{{< /text >}}
1. Generate a client certificate and private key:
{{< text bash >}}
$ openssl req -out example_certs1/client.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs1/client.example.com.key -subj "/CN=client.example.com/O=client organization"
$ openssl x509 -req -sha256 -days 365 -CA example_certs1/example.com.crt -CAkey example_certs1/example.com.key -set_serial 1 -in example_certs1/client.example.com.csr -out example_certs1/client.example.com.crt
{{< /text >}}
You can confirm that you have all of the needed files by running the following command:
{{< text bash >}}
$ ls example_cert*
example_certs1:
client.example.com.crt example.com.key httpbin.example.com.crt
client.example.com.csr helloworld.example.com.crt httpbin.example.com.csr
client.example.com.key helloworld.example.com.csr httpbin.example.com.key
example.com.crt helloworld.example.com.key
example_certs2:
example.com.crt httpbin.example.com.crt httpbin.example.com.key
example.com.key httpbin.example.com.csr
{{< /text >}}
### Configure a TLS ingress gateway for a single host
1. Create a secret for the ingress gateway:
{{< text bash >}}
$ kubectl create -n istio-system secret tls httpbin-credential --key=httpbin.example.com.key --cert=httpbin.example.com.crt
$ kubectl create -n istio-system secret tls httpbin-credential \
--key=example_certs1/httpbin.example.com.key \
--cert=example_certs1/httpbin.example.com.crt
{{< /text >}}
1. Define a gateway with a `servers:` section for port 443, and specify values for
`credentialName` to be `httpbin-credential`. The values are the same as the
secret's name. The TLS mode should have the value of `SIMPLE`.
1. Configure the ingress gateway:
{{< text bash >}}
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
{{< tabset category-name="config-api" >}}
{{< tab name="Istio classic" category-value="istio-classic" >}}
First, define a gateway with a `servers:` section for port 443, and specify values for
`credentialName` to be `httpbin-credential`. The values are the same as the
secret's name. The TLS mode should have the value of `SIMPLE`.
{{< text bash >}}
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: mygateway
spec:
spec:
selector:
istio: ingressgateway # use istio default ingress gateway
servers:
@ -85,19 +134,19 @@ For this task you can use your favorite tool to generate certificates and keys.
credentialName: httpbin-credential # must be the same as secret
hosts:
- httpbin.example.com
EOF
{{< /text >}}
EOF
{{< /text >}}
1. Configure the gateway's ingress traffic routes. Define the corresponding
virtual service.
Next, configure the gateway's ingress traffic routes by defining a corresponding
virtual service:
{{< text bash >}}
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
{{< text bash >}}
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: httpbin
spec:
spec:
hosts:
- "httpbin.example.com"
gateways:
@ -113,41 +162,89 @@ For this task you can use your favorite tool to generate certificates and keys.
port:
number: 8000
host: httpbin
EOF
{{< /text >}}
EOF
{{< /text >}}
1. Send an HTTPS request to access the `httpbin` service through HTTPS:
Finally, follow [these instructions](/docs/tasks/traffic-management/ingress/ingress-control/#determining-the-ingress-ip-and-ports)
to set the `INGRESS_HOST` and `SECURE_INGRESS_PORT` variables for accessing the gateway.
{{< /tab >}}
{{< tab name="Gateway API" category-value="gateway-api" >}}
First, create a [Kubernetes Gateway](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io%2fv1beta1.Gateway):
{{< text bash >}}
$ cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: mygateway
namespace: istio-system
spec:
gatewayClassName: istio
listeners:
- name: https
hostname: "httpbin.example.com"
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: httpbin-credential
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
kubernetes.io/metadata.name: default
EOF
{{< /text >}}
Next, configure the gateway's ingress traffic routes by defining a corresponding `HTTPRoute`:
{{< text bash >}}
$ cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: httpbin
spec:
parentRefs:
- name: mygateway
namespace: istio-system
hostnames: ["httpbin.example.com"]
rules:
- matches:
- path:
type: PathPrefix
value: /status
- path:
type: PathPrefix
value: /delay
backendRefs:
- name: httpbin
port: 8000
EOF
{{< /text >}}
Finally, get the gateway address and port from the `Gateway` resource:
{{< text bash >}}
$ kubectl wait --for=condition=ready gtw mygateway -n istio-system
$ export INGRESS_HOST=$(kubectl get gtw mygateway -n istio-system -o jsonpath='{.status.addresses[*].value}')
$ export SECURE_INGRESS_PORT=$(kubectl get gtw mygateway -n istio-system -o jsonpath='{.spec.listeners[?(@.name=="https")].port}')
{{< /text >}}
{{< /tab >}}
{{< /tabset >}}
3) Send an HTTPS request to access the `httpbin` service through HTTPS:
{{< text bash >}}
$ 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"
{{< /text >}}
The `httpbin` service will return the
[418 I'm a Teapot](https://tools.ietf.org/html/rfc7168#section-2.3.3) code.
1. Delete the gateway's secret and create a new one to change the ingress
gateway's credentials.
{{< text bash >}}
$ kubectl -n istio-system delete secret httpbin-credential
{{< /text >}}
{{< text bash >}}
$ mkdir new_certificates
$ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout new_certificates/example.com.key -out new_certificates/example.com.crt
$ openssl req -out new_certificates/httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout new_certificates/httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization"
$ openssl x509 -req -sha256 -days 365 -CA new_certificates/example.com.crt -CAkey new_certificates/example.com.key -set_serial 0 -in new_certificates/httpbin.example.com.csr -out new_certificates/httpbin.example.com.crt
$ kubectl create -n istio-system secret tls httpbin-credential \
--key=new_certificates/httpbin.example.com.key \
--cert=new_certificates/httpbin.example.com.crt
{{< /text >}}
1. Access the `httpbin` service using `curl` using the new certificate chain:
{{< text bash >}}
$ curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \
--cacert new_certificates/example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
--cacert example_certs1/example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
...
HTTP/2 418
...
@ -162,11 +259,42 @@ For this task you can use your favorite tool to generate certificates and keys.
`"""`
{{< /text >}}
1. If you try to access `httpbin` with the previous certificate chain, the attempt now fails.
The `httpbin` service will return the [418 I'm a Teapot](https://tools.ietf.org/html/rfc7168#section-2.3.3) code.
1) Change the gateway's credentials by deleting the gateway's secret and then recreating it using
different certificates and keys:
{{< text bash >}}
$ kubectl -n istio-system delete secret httpbin-credential
$ kubectl create -n istio-system secret tls httpbin-credential \
--key=example_certs2/httpbin.example.com.key \
--cert=example_certs2/httpbin.example.com.crt
{{< /text >}}
1) Access the `httpbin` service with `curl` using the new certificate chain:
{{< text bash >}}
$ 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"
--cacert example_certs2/example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
...
HTTP/2 418
...
-=[ teapot ]=-
_...._
.' _ _ `.
| ."` ^ `". _,
\_;`"---"`|//
| ;/
\_ _/
`"""`
{{< /text >}}
1) If you try to access `httpbin` using the previous certificate chain, the attempt now fails:
{{< text bash >}}
$ curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \
--cacert example_certs1/example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
...
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
@ -178,87 +306,51 @@ For this task you can use your favorite tool to generate certificates and keys.
### Configure a TLS ingress gateway for multiple hosts
You can configure an ingress gateway for multiple hosts,
`httpbin.example.com` and `helloworld-v1.example.com`, for example. The ingress gateway
retrieves unique credentials corresponding to a specific `credentialName`.
`httpbin.example.com` and `helloworld.example.com`, for example. The ingress gateway
is configured with unique credentials corresponding to each host.
1. To restore the credentials for `httpbin`, delete its secret and create it again.
1. Restore the `httpbin` credentials from the previous example by deleting and recreating the secret
with the original certificates and keys:
{{< text bash >}}
$ kubectl -n istio-system delete secret httpbin-credential
$ kubectl create -n istio-system secret tls httpbin-credential \
--key=httpbin.example.com.key \
--cert=httpbin.example.com.crt
--key=example_certs1/httpbin.example.com.key \
--cert=example_certs1/httpbin.example.com.crt
{{< /text >}}
1. Start the `helloworld-v1` sample
1. Start the `helloworld-v1` sample:
{{< text bash >}}
$ cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: helloworld-v1
labels:
app: helloworld-v1
spec:
ports:
- name: http
port: 5000
selector:
app: helloworld-v1
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloworld-v1
spec:
replicas: 1
selector:
matchLabels:
app: helloworld-v1
version: v1
template:
metadata:
labels:
app: helloworld-v1
version: v1
spec:
containers:
- name: helloworld
image: istio/examples-helloworld-v1
resources:
requests:
cpu: "100m"
imagePullPolicy: IfNotPresent #Always
ports:
- containerPort: 5000
EOF
$ kubectl apply -f @samples/helloworld/helloworld.yaml@ -l service=helloworld
$ kubectl apply -f @samples/helloworld/helloworld.yaml@ -l version=v1
{{< /text >}}
1. Generate a certificate and a private key for `helloworld-v1.example.com`:
1. Create a `helloworld-credential` secret:
{{< text bash >}}
$ openssl req -out helloworld-v1.example.com.csr -newkey rsa:2048 -nodes -keyout helloworld-v1.example.com.key -subj "/CN=helloworld-v1.example.com/O=helloworld organization"
$ openssl x509 -req -sha256 -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 1 -in helloworld-v1.example.com.csr -out helloworld-v1.example.com.crt
$ kubectl create -n istio-system secret tls helloworld-credential \
--key=example_certs1/helloworld.example.com.key \
--cert=example_certs1/helloworld.example.com.crt
{{< /text >}}
1. Create the `helloworld-credential` secret:
1. Configure the ingress gateway with hosts `httpbin.example.com` and `helloworld.example.com`:
{{< text bash >}}
$ kubectl create -n istio-system secret tls helloworld-credential --key=helloworld-v1.example.com.key --cert=helloworld-v1.example.com.crt
{{< /text >}}
{{< tabset category-name="config-api" >}}
1. Define a gateway with two server sections for port 443. Set the value of
`credentialName` on each port to `httpbin-credential` and `helloworld-credential`
respectively. Set TLS mode to `SIMPLE`.
{{< tab name="Istio classic" category-value="istio-classic" >}}
{{< text bash >}}
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
Define a gateway with two server sections for port 443. Set the value of
`credentialName` on each port to `httpbin-credential` and `helloworld-credential`
respectively. Set TLS mode to `SIMPLE`.
{{< text bash >}}
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: mygateway
spec:
spec:
selector:
istio: ingressgateway # use istio default ingress gateway
servers:
@ -279,22 +371,21 @@ retrieves unique credentials corresponding to a specific `credentialName`.
mode: SIMPLE
credentialName: helloworld-credential
hosts:
- helloworld-v1.example.com
EOF
{{< /text >}}
- helloworld.example.com
EOF
{{< /text >}}
1. Configure the gateway's traffic routes. Define the corresponding
virtual service.
Configure the gateway's traffic routes by defining a corresponding virtual service.
{{< text bash >}}
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: helloworld-v1
spec:
{{< text bash >}}
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: helloworld
spec:
hosts:
- helloworld-v1.example.com
- helloworld.example.com
gateways:
- mygateway
http:
@ -303,25 +394,104 @@ retrieves unique credentials corresponding to a specific `credentialName`.
exact: /hello
route:
- destination:
host: helloworld-v1
host: helloworld
port:
number: 5000
EOF
{{< /text >}}
EOF
{{< /text >}}
1. Send an HTTPS request to `helloworld-v1.example.com`:
{{< /tab >}}
{{< tab name="Gateway API" category-value="gateway-api" >}}
Configure a `Gateway` with two listeners for port 443. Set the value of
`certificateRefs` on each listener to `httpbin-credential` and `helloworld-credential`
respectively.
{{< text bash >}}
$ cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: mygateway
namespace: istio-system
spec:
gatewayClassName: istio
listeners:
- name: https-httpbin
hostname: "httpbin.example.com"
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: httpbin-credential
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
kubernetes.io/metadata.name: default
- name: https-helloworld
hostname: "helloworld.example.com"
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: helloworld-credential
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
kubernetes.io/metadata.name: default
EOF
{{< /text >}}
Configure the gateway's traffic routes for the `helloworld` service:
{{< text bash >}}
$ cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: helloworld
spec:
parentRefs:
- name: mygateway
namespace: istio-system
hostnames: ["helloworld.example.com"]
rules:
- matches:
- path:
type: Exact
value: /hello
backendRefs:
- name: helloworld
port: 5000
EOF
{{< /text >}}
{{< /tab >}}
{{< /tabset >}}
5) Send an HTTPS request to `helloworld.example.com`:
{{< text bash >}}
$ curl -v -HHost:helloworld-v1.example.com --resolve "helloworld-v1.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \
--cacert example.com.crt "https://helloworld-v1.example.com:$SECURE_INGRESS_PORT/hello"
$ curl -v -HHost:helloworld.example.com --resolve "helloworld.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \
--cacert example_certs1/example.com.crt "https://helloworld.example.com:$SECURE_INGRESS_PORT/hello"
...
HTTP/2 200
...
{{< /text >}}
1. Send an HTTPS request to `httpbin.example.com` and still get a teapot in return:
1) Send an HTTPS request to `httpbin.example.com` and still get a teapot in return:
{{< text bash >}}
$ 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"
--cacert example_certs1/example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
...
-=[ teapot ]=-
@ -336,27 +506,34 @@ retrieves unique credentials corresponding to a specific `credentialName`.
### Configure a mutual TLS ingress gateway
You can extend your gateway's definition to support
[mutual TLS](https://en.wikipedia.org/wiki/Mutual_authentication). Change
the credentials of the ingress gateway by deleting its secret and creating a new one.
The server uses the CA certificate to verify
its clients, and we must use the name `cacert` to hold the CA certificate.
You can extend your gateway's definition to support [mutual TLS](https://en.wikipedia.org/wiki/Mutual_authentication).
{{< text bash >}}
$ kubectl -n istio-system delete secret httpbin-credential
$ kubectl create -n istio-system secret generic httpbin-credential --from-file=tls.key=httpbin.example.com.key \
--from-file=tls.crt=httpbin.example.com.crt --from-file=ca.crt=example.com.crt
{{< /text >}}
1. Change the gateway's definition to set the TLS mode to `MUTUAL`.
1. Change the credentials of the ingress gateway by deleting its secret and creating a new one.
The server uses the CA certificate to verify its clients, and we must use the name `cacert` to hold the CA certificate.
{{< text bash >}}
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
$ kubectl -n istio-system delete secret httpbin-credential
$ kubectl create -n istio-system secret generic httpbin-credential \
--from-file=tls.key=example_certs1/httpbin.example.com.key \
--from-file=tls.crt=example_certs1/httpbin.example.com.crt \
--from-file=ca.crt=example_certs1/example.com.crt
{{< /text >}}
1. Configure the ingress gateway:
{{< tabset category-name="config-api" >}}
{{< tab name="Istio classic" category-value="istio-classic" >}}
Change the gateway's definition to set the TLS mode to `MUTUAL`.
{{< text bash >}}
$ cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: mygateway
spec:
spec:
selector:
istio: ingressgateway # use istio default ingress gateway
servers:
@ -369,14 +546,56 @@ $ kubectl create -n istio-system secret generic httpbin-credential --from-file=t
credentialName: httpbin-credential # must be the same as secret
hosts:
- httpbin.example.com
EOF
{{< /text >}}
EOF
{{< /text >}}
1. Attempt to send an HTTPS request using the prior approach and see how it fails:
{{< /tab >}}
{{< tab name="Gateway API" category-value="gateway-api" >}}
Because the Kubernetes Gateway API does not currently support mutual TLS termination in a
[Gateway](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io%2fv1beta1.Gateway),
we use an Istio-specific option, `gateway.istio.io/tls-terminate-mode: MUTUAL`,
to configure it:
{{< text bash >}}
$ cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: mygateway
namespace: istio-system
spec:
gatewayClassName: istio
listeners:
- name: https
hostname: "httpbin.example.com"
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: httpbin-credential
options:
gateway.istio.io/tls-terminate-mode: MUTUAL
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
kubernetes.io/metadata.name: default
EOF
{{< /text >}}
{{< /tab >}}
{{< /tabset >}}
3) Attempt to send an HTTPS request using the prior approach and see how it fails:
{{< text bash >}}
$ 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"
--cacert example_certs1/example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
@ -391,20 +610,13 @@ $ kubectl create -n istio-system secret generic httpbin-credential --from-file=t
* OpenSSL SSL_read: error:1409445C:SSL routines:ssl3_read_bytes:tlsv13 alert certificate required, errno 0
{{< /text >}}
1. Generate client certificate and private key:
{{< text bash >}}
$ openssl req -out client.example.com.csr -newkey rsa:2048 -nodes -keyout client.example.com.key -subj "/CN=client.example.com/O=client organization"
$ openssl x509 -req -sha256 -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 1 -in client.example.com.csr -out client.example.com.crt
{{< /text >}}
1. Pass a client certificate and private key to `curl` and resend the request.
1) Pass a client certificate and private key to `curl` and resend the request.
Pass your client's certificate with the `--cert` flag and your private key
with the `--key` flag to `curl`.
with the `--key` flag to `curl`:
{{< text bash >}}
$ curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \
--cacert example.com.crt --cert client.example.com.crt --key client.example.com.key \
--cacert example_certs1/example.com.crt --cert example_certs1/client.example.com.crt --key example_certs1/client.example.com.key \
"https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
...
-=[ teapot ]=-
@ -431,9 +643,9 @@ Istio supports reading a few different Secret formats, to support integration wi
### SNI Routing
An HTTPS `Gateway` with a `hosts` field value other than `*` will perform
[SNI](https://en.wikipedia.org/wiki/Server_Name_Indication) matching before forwarding a request,
which may cause some requests to fail. See [configuring SNI routing](/docs/ops/common-problems/network-issues/#configuring-sni-routing-when-not-sending-sni) for details.
An HTTPS `Gateway` will perform [SNI](https://en.wikipedia.org/wiki/Server_Name_Indication) matching against its configured host(s)
before forwarding a request, which may cause some requests to fail.
See [configuring SNI routing](/docs/ops/common-problems/network-issues/#configuring-sni-routing-when-not-sending-sni) for details.
## Troubleshooting
@ -446,11 +658,10 @@ which may cause some requests to fail. See [configuring SNI routing](/docs/ops/c
$ echo "INGRESS_HOST=$INGRESS_HOST, SECURE_INGRESS_PORT=$SECURE_INGRESS_PORT"
{{< /text >}}
* Check the log of the `istio-ingressgateway` controller for error messages:
* Check the log of the gateway controller for error messages:
{{< text bash >}}
$ kubectl logs -n istio-system "$(kubectl get pod -l istio=ingressgateway \
-n istio-system -o jsonpath='{.items[0].metadata.name}')"
{{< text syntax=bash snip_id=none >}}
$ kubectl logs -n istio-system <gateway-service-pod>
{{< /text >}}
* If using macOS, verify you are using `curl` compiled with the [LibreSSL](http://www.libressl.org)
@ -467,11 +678,10 @@ which may cause some requests to fail. See [configuring SNI routing](/docs/ops/c
list.
* Check the logs to verify that the ingress gateway agent has pushed the
key/certificate pair to the ingress gateway.
key/certificate pair to the ingress gateway:
{{< text bash >}}
$ kubectl logs -n istio-system "$(kubectl get pod -l istio=ingressgateway \
-n istio-system -o jsonpath='{.items[0].metadata.name}')"
{{< text syntax=bash snip_id=none >}}
$ kubectl logs -n istio-system <gateway-service-pod>
{{< /text >}}
The log should show that the `httpbin-credential` secret was added. If using mutual
@ -485,25 +695,41 @@ which may cause some requests to fail. See [configuring SNI routing](/docs/ops/c
## Cleanup
1. Delete the gateway configuration, the virtual service definition, and the secrets:
1. Delete the gateway configuration and routes:
{{< tabset category-name="config-api" >}}
{{< tab name="Istio classic" category-value="istio-classic" >}}
{{< text bash >}}
$ kubectl delete gateway mygateway
$ kubectl delete virtualservice httpbin helloworld
{{< /text >}}
{{< /tab >}}
{{< tab name="Gateway API" category-value="gateway-api" >}}
{{< text bash >}}
$ kubectl delete -n istio-system gtw mygateway
$ kubectl delete httproute httpbin helloworld
{{< /text >}}
{{< /tab >}}
{{< /tabset >}}
2) Delete the secrets, certificates and keys:
{{< text bash >}}
$ kubectl delete gateway mygateway
$ kubectl delete virtualservice httpbin
$ kubectl delete --ignore-not-found=true -n istio-system secret httpbin-credential \
helloworld-credential
$ kubectl delete --ignore-not-found=true virtualservice helloworld-v1
$ kubectl delete -n istio-system secret httpbin-credential helloworld-credential
$ rm -rf ./example_certs1 ./example_certs2
{{< /text >}}
1. Delete the certificates and keys:
1) Shutdown the `httpbin` and `helloworld` services:
{{< text bash >}}
$ rm -rf example.com.crt example.com.key httpbin.example.com.crt httpbin.example.com.key httpbin.example.com.csr helloworld-v1.example.com.crt helloworld-v1.example.com.key helloworld-v1.example.com.csr client.example.com.crt client.example.com.csr client.example.com.key ./new_certificates
{{< /text >}}
1. Shutdown the `httpbin` and `helloworld-v1` services:
{{< text bash >}}
$ kubectl delete deployment --ignore-not-found=true httpbin helloworld-v1
$ kubectl delete service --ignore-not-found=true httpbin helloworld-v1
$ kubectl delete -f samples/httpbin/httpbin.yaml
$ kubectl delete deployment helloworld-v1
$ kubectl delete service helloworld
{{< /text >}}

View File

@ -19,26 +19,67 @@
# WARNING: THIS IS AN AUTO-GENERATED FILE, DO NOT EDIT. PLEASE MODIFY THE ORIGINAL MARKDOWN FILE:
# docs/tasks/traffic-management/ingress/secure-ingress/index.md
####################################################################################################
source "content/en/boilerplates/snips/gateway-api-support.sh"
snip_before_you_begin_1() {
kubectl apply -f samples/httpbin/httpbin.yaml
}
snip_before_you_begin_2() {
curl --version | grep LibreSSL
}
! read -r -d '' snip_before_you_begin_1_out <<\ENDSNIP
! read -r -d '' snip_before_you_begin_2_out <<\ENDSNIP
curl 7.54.0 (x86_64-apple-darwin17.0) libcurl/7.54.0 LibreSSL/2.0.20 zlib/1.2.11 nghttp2/1.24.0
ENDSNIP
snip_generate_client_and_server_certificates_and_keys_1() {
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
mkdir example_certs1
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example_certs1/example.com.key -out example_certs1/example.com.crt
}
snip_generate_client_and_server_certificates_and_keys_2() {
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 -sha256 -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in httpbin.example.com.csr -out httpbin.example.com.crt
openssl req -out example_certs1/httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs1/httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization"
openssl x509 -req -sha256 -days 365 -CA example_certs1/example.com.crt -CAkey example_certs1/example.com.key -set_serial 0 -in example_certs1/httpbin.example.com.csr -out example_certs1/httpbin.example.com.crt
}
snip_generate_client_and_server_certificates_and_keys_3() {
mkdir example_certs2
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example_certs2/example.com.key -out example_certs2/example.com.crt
openssl req -out example_certs2/httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs2/httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization"
openssl x509 -req -sha256 -days 365 -CA example_certs2/example.com.crt -CAkey example_certs2/example.com.key -set_serial 0 -in example_certs2/httpbin.example.com.csr -out example_certs2/httpbin.example.com.crt
}
snip_generate_client_and_server_certificates_and_keys_4() {
openssl req -out example_certs1/helloworld.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs1/helloworld.example.com.key -subj "/CN=helloworld.example.com/O=helloworld organization"
openssl x509 -req -sha256 -days 365 -CA example_certs1/example.com.crt -CAkey example_certs1/example.com.key -set_serial 1 -in example_certs1/helloworld.example.com.csr -out example_certs1/helloworld.example.com.crt
}
snip_generate_client_and_server_certificates_and_keys_5() {
openssl req -out example_certs1/client.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs1/client.example.com.key -subj "/CN=client.example.com/O=client organization"
openssl x509 -req -sha256 -days 365 -CA example_certs1/example.com.crt -CAkey example_certs1/example.com.key -set_serial 1 -in example_certs1/client.example.com.csr -out example_certs1/client.example.com.crt
}
snip_generate_client_and_server_certificates_and_keys_6() {
ls example_cert*
}
! read -r -d '' snip_generate_client_and_server_certificates_and_keys_6_out <<\ENDSNIP
example_certs1:
client.example.com.crt example.com.key httpbin.example.com.crt
client.example.com.csr helloworld.example.com.crt httpbin.example.com.csr
client.example.com.key helloworld.example.com.csr httpbin.example.com.key
example.com.crt helloworld.example.com.key
example_certs2:
example.com.crt httpbin.example.com.crt httpbin.example.com.key
example.com.key httpbin.example.com.csr
ENDSNIP
snip_configure_a_tls_ingress_gateway_for_a_single_host_1() {
kubectl create -n istio-system secret tls httpbin-credential --key=httpbin.example.com.key --cert=httpbin.example.com.crt
kubectl create -n istio-system secret tls httpbin-credential \
--key=example_certs1/httpbin.example.com.key \
--cert=example_certs1/httpbin.example.com.crt
}
snip_configure_a_tls_ingress_gateway_for_a_single_host_2() {
@ -89,27 +130,66 @@ EOF
}
snip_configure_a_tls_ingress_gateway_for_a_single_host_4() {
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"
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: mygateway
namespace: istio-system
spec:
gatewayClassName: istio
listeners:
- name: https
hostname: "httpbin.example.com"
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: httpbin-credential
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
kubernetes.io/metadata.name: default
EOF
}
snip_configure_a_tls_ingress_gateway_for_a_single_host_5() {
kubectl -n istio-system delete secret httpbin-credential
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: httpbin
spec:
parentRefs:
- name: mygateway
namespace: istio-system
hostnames: ["httpbin.example.com"]
rules:
- matches:
- path:
type: PathPrefix
value: /status
- path:
type: PathPrefix
value: /delay
backendRefs:
- name: httpbin
port: 8000
EOF
}
snip_configure_a_tls_ingress_gateway_for_a_single_host_6() {
mkdir new_certificates
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout new_certificates/example.com.key -out new_certificates/example.com.crt
openssl req -out new_certificates/httpbin.example.com.csr -newkey rsa:2048 -nodes -keyout new_certificates/httpbin.example.com.key -subj "/CN=httpbin.example.com/O=httpbin organization"
openssl x509 -req -sha256 -days 365 -CA new_certificates/example.com.crt -CAkey new_certificates/example.com.key -set_serial 0 -in new_certificates/httpbin.example.com.csr -out new_certificates/httpbin.example.com.crt
kubectl create -n istio-system secret tls httpbin-credential \
--key=new_certificates/httpbin.example.com.key \
--cert=new_certificates/httpbin.example.com.crt
kubectl wait --for=condition=ready gtw mygateway -n istio-system
export INGRESS_HOST=$(kubectl get gtw mygateway -n istio-system -o jsonpath='{.status.addresses[*].value}')
export SECURE_INGRESS_PORT=$(kubectl get gtw mygateway -n istio-system -o jsonpath='{.spec.listeners[?(@.name=="https")].port}')
}
snip_configure_a_tls_ingress_gateway_for_a_single_host_7() {
curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \
--cacert new_certificates/example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
--cacert example_certs1/example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
}
! read -r -d '' snip_configure_a_tls_ingress_gateway_for_a_single_host_7_out <<\ENDSNIP
@ -128,11 +208,38 @@ HTTP/2 418
ENDSNIP
snip_configure_a_tls_ingress_gateway_for_a_single_host_8() {
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"
kubectl -n istio-system delete secret httpbin-credential
kubectl create -n istio-system secret tls httpbin-credential \
--key=example_certs2/httpbin.example.com.key \
--cert=example_certs2/httpbin.example.com.crt
}
! read -r -d '' snip_configure_a_tls_ingress_gateway_for_a_single_host_8_out <<\ENDSNIP
snip_configure_a_tls_ingress_gateway_for_a_single_host_9() {
curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \
--cacert example_certs2/example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
}
! read -r -d '' snip_configure_a_tls_ingress_gateway_for_a_single_host_9_out <<\ENDSNIP
...
HTTP/2 418
...
-=[ teapot ]=-
_...._
.' _ _ `.
| ."` ^ `". _,
\_;`"---"`|//
| ;/
\_ _/
`"""`
ENDSNIP
snip_configure_a_tls_ingress_gateway_for_a_single_host_10() {
curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \
--cacert example_certs1/example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
}
! read -r -d '' snip_configure_a_tls_ingress_gateway_for_a_single_host_10_out <<\ENDSNIP
...
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
@ -144,63 +251,22 @@ ENDSNIP
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_1() {
kubectl -n istio-system delete secret httpbin-credential
kubectl create -n istio-system secret tls httpbin-credential \
--key=httpbin.example.com.key \
--cert=httpbin.example.com.crt
--key=example_certs1/httpbin.example.com.key \
--cert=example_certs1/httpbin.example.com.crt
}
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_2() {
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Service
metadata:
name: helloworld-v1
labels:
app: helloworld-v1
spec:
ports:
- name: http
port: 5000
selector:
app: helloworld-v1
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: helloworld-v1
spec:
replicas: 1
selector:
matchLabels:
app: helloworld-v1
version: v1
template:
metadata:
labels:
app: helloworld-v1
version: v1
spec:
containers:
- name: helloworld
image: istio/examples-helloworld-v1
resources:
requests:
cpu: "100m"
imagePullPolicy: IfNotPresent #Always
ports:
- containerPort: 5000
EOF
kubectl apply -f samples/helloworld/helloworld.yaml -l service=helloworld
kubectl apply -f samples/helloworld/helloworld.yaml -l version=v1
}
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_3() {
openssl req -out helloworld-v1.example.com.csr -newkey rsa:2048 -nodes -keyout helloworld-v1.example.com.key -subj "/CN=helloworld-v1.example.com/O=helloworld organization"
openssl x509 -req -sha256 -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 1 -in helloworld-v1.example.com.csr -out helloworld-v1.example.com.crt
kubectl create -n istio-system secret tls helloworld-credential \
--key=example_certs1/helloworld.example.com.key \
--cert=example_certs1/helloworld.example.com.crt
}
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_4() {
kubectl create -n istio-system secret tls helloworld-credential --key=helloworld-v1.example.com.key --cert=helloworld-v1.example.com.crt
}
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_5() {
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
@ -227,19 +293,19 @@ spec:
mode: SIMPLE
credentialName: helloworld-credential
hosts:
- helloworld-v1.example.com
- helloworld.example.com
EOF
}
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_6() {
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_5() {
cat <<EOF | kubectl apply -f -
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: helloworld-v1
name: helloworld
spec:
hosts:
- helloworld-v1.example.com
- helloworld.example.com
gateways:
- mygateway
http:
@ -248,27 +314,92 @@ spec:
exact: /hello
route:
- destination:
host: helloworld-v1
host: helloworld
port:
number: 5000
EOF
}
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_7() {
curl -v -HHost:helloworld-v1.example.com --resolve "helloworld-v1.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \
--cacert example.com.crt "https://helloworld-v1.example.com:$SECURE_INGRESS_PORT/hello"
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_6() {
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: mygateway
namespace: istio-system
spec:
gatewayClassName: istio
listeners:
- name: https-httpbin
hostname: "httpbin.example.com"
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: httpbin-credential
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
kubernetes.io/metadata.name: default
- name: https-helloworld
hostname: "helloworld.example.com"
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: helloworld-credential
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
kubernetes.io/metadata.name: default
EOF
}
! read -r -d '' snip_configure_a_tls_ingress_gateway_for_multiple_hosts_7_out <<\ENDSNIP
HTTP/2 200
ENDSNIP
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_7() {
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: helloworld
spec:
parentRefs:
- name: mygateway
namespace: istio-system
hostnames: ["helloworld.example.com"]
rules:
- matches:
- path:
type: Exact
value: /hello
backendRefs:
- name: helloworld
port: 5000
EOF
}
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_8() {
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"
curl -v -HHost:helloworld.example.com --resolve "helloworld.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \
--cacert example_certs1/example.com.crt "https://helloworld.example.com:$SECURE_INGRESS_PORT/hello"
}
! read -r -d '' snip_configure_a_tls_ingress_gateway_for_multiple_hosts_8_out <<\ENDSNIP
...
HTTP/2 200
...
ENDSNIP
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_9() {
curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \
--cacert example_certs1/example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
}
! read -r -d '' snip_configure_a_tls_ingress_gateway_for_multiple_hosts_9_out <<\ENDSNIP
...
-=[ teapot ]=-
@ -283,8 +414,10 @@ ENDSNIP
snip_configure_a_mutual_tls_ingress_gateway_1() {
kubectl -n istio-system delete secret httpbin-credential
kubectl create -n istio-system secret generic httpbin-credential --from-file=tls.key=httpbin.example.com.key \
--from-file=tls.crt=httpbin.example.com.crt --from-file=ca.crt=example.com.crt
kubectl create -n istio-system secret generic httpbin-credential \
--from-file=tls.key=example_certs1/httpbin.example.com.key \
--from-file=tls.crt=example_certs1/httpbin.example.com.crt \
--from-file=ca.crt=example_certs1/example.com.crt
}
snip_configure_a_mutual_tls_ingress_gateway_2() {
@ -310,11 +443,40 @@ EOF
}
snip_configure_a_mutual_tls_ingress_gateway_3() {
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"
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: mygateway
namespace: istio-system
spec:
gatewayClassName: istio
listeners:
- name: https
hostname: "httpbin.example.com"
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: httpbin-credential
options:
gateway.istio.io/tls-terminate-mode: MUTUAL
allowedRoutes:
namespaces:
from: Selector
selector:
matchLabels:
kubernetes.io/metadata.name: default
EOF
}
! read -r -d '' snip_configure_a_mutual_tls_ingress_gateway_3_out <<\ENDSNIP
snip_configure_a_mutual_tls_ingress_gateway_4() {
curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \
--cacert example_certs1/example.com.crt "https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
}
! read -r -d '' snip_configure_a_mutual_tls_ingress_gateway_4_out <<\ENDSNIP
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
@ -329,15 +491,10 @@ curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:$SECURE_INGRES
* OpenSSL SSL_read: error:1409445C:SSL routines:ssl3_read_bytes:tlsv13 alert certificate required, errno 0
ENDSNIP
snip_configure_a_mutual_tls_ingress_gateway_4() {
openssl req -out client.example.com.csr -newkey rsa:2048 -nodes -keyout client.example.com.key -subj "/CN=client.example.com/O=client organization"
openssl x509 -req -sha256 -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 1 -in client.example.com.csr -out client.example.com.crt
}
snip_configure_a_mutual_tls_ingress_gateway_5() {
curl -v -HHost:httpbin.example.com --resolve "httpbin.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" \
--cacert example.com.crt --cert client.example.com.crt --key client.example.com.key \
"https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
--cacert example_certs1/example.com.crt --cert example_certs1/client.example.com.crt --key example_certs1/client.example.com.key \
"https://httpbin.example.com:$SECURE_INGRESS_PORT/status/418"
}
! read -r -d '' snip_configure_a_mutual_tls_ingress_gateway_5_out <<\ENDSNIP
@ -358,33 +515,27 @@ kubectl get svc -n istio-system
echo "INGRESS_HOST=$INGRESS_HOST, SECURE_INGRESS_PORT=$SECURE_INGRESS_PORT"
}
snip_troubleshooting_2() {
kubectl logs -n istio-system "$(kubectl get pod -l istio=ingressgateway \
-n istio-system -o jsonpath='{.items[0].metadata.name}')"
}
snip_troubleshooting_3() {
kubectl -n istio-system get secrets
}
snip_troubleshooting_4() {
kubectl logs -n istio-system "$(kubectl get pod -l istio=ingressgateway \
-n istio-system -o jsonpath='{.items[0].metadata.name}')"
}
snip_cleanup_1() {
kubectl delete gateway mygateway
kubectl delete virtualservice httpbin
kubectl delete --ignore-not-found=true -n istio-system secret httpbin-credential \
helloworld-credential
kubectl delete --ignore-not-found=true virtualservice helloworld-v1
kubectl delete virtualservice httpbin helloworld
}
snip_cleanup_2() {
rm -rf example.com.crt example.com.key httpbin.example.com.crt httpbin.example.com.key httpbin.example.com.csr helloworld-v1.example.com.crt helloworld-v1.example.com.key helloworld-v1.example.com.csr client.example.com.crt client.example.com.csr client.example.com.key ./new_certificates
kubectl delete -n istio-system gtw mygateway
kubectl delete httproute httpbin helloworld
}
snip_cleanup_3() {
kubectl delete deployment --ignore-not-found=true httpbin helloworld-v1
kubectl delete service --ignore-not-found=true httpbin helloworld-v1
kubectl delete -n istio-system secret httpbin-credential helloworld-credential
rm -rf ./example_certs1 ./example_certs2
}
snip_cleanup_4() {
kubectl delete -f samples/httpbin/httpbin.yaml
kubectl delete deployment helloworld-v1
kubectl delete service helloworld
}

View File

@ -1,5 +1,5 @@
#!/usr/bin/env bash
# shellcheck disable=SC1090,SC2154
# shellcheck disable=SC1090,SC2154,SC2155
# Copyright Istio Authors
#
@ -21,6 +21,8 @@ set -o pipefail
source "tests/util/samples.sh"
GATEWAY_API="${GATEWAY_API:-false}"
# @setup profile=default
kubectl label namespace default istio-injection=enabled --overwrite
@ -28,43 +30,53 @@ kubectl label namespace default istio-injection=enabled --overwrite
# start the httpbin sample
startup_httpbin_sample
# export the INGRESS_ environment variables
_set_ingress_environment_variables
snip_generate_client_and_server_certificates_and_keys_1
snip_generate_client_and_server_certificates_and_keys_2
snip_generate_client_and_server_certificates_and_keys_3
snip_generate_client_and_server_certificates_and_keys_4
snip_generate_client_and_server_certificates_and_keys_5
# creating httpbin gateway secrets
snip_configure_a_tls_ingress_gateway_for_a_single_host_1
# deploying httpbin gateway
snip_configure_a_tls_ingress_gateway_for_a_single_host_2
if [ "$GATEWAY_API" == "true" ]; then
snip_configure_a_tls_ingress_gateway_for_a_single_host_4
snip_configure_a_tls_ingress_gateway_for_a_single_host_5
# deploying httpbin virtual service
snip_configure_a_tls_ingress_gateway_for_a_single_host_3
#snip_configure_a_tls_ingress_gateway_for_a_single_host_6
# TODO ^^^ default timeout is 30s ... too short?
kubectl wait --for=condition=ready --timeout=2m gtw mygateway -n istio-system
export INGRESS_HOST=$(kubectl get gtw mygateway -n istio-system -o jsonpath='{.status.addresses[*].value}')
export SECURE_INGRESS_PORT=$(kubectl get gtw mygateway -n istio-system -o jsonpath='{.spec.listeners[?(@.name=="https")].port}')
# TODO ^^^ better way to change the timeout while still calling snips?
else
# deploying httpbin gateway
snip_configure_a_tls_ingress_gateway_for_a_single_host_2
# wait for config to propagate
_wait_for_istio gateway default mygateway
_wait_for_istio virtualservice default httpbin
# deploying httpbin virtual service
snip_configure_a_tls_ingress_gateway_for_a_single_host_3
# wait for config to propagate
_wait_for_istio gateway default mygateway
_wait_for_istio virtualservice default httpbin
# export the INGRESS_ environment variables
_set_ingress_environment_variables
fi
# verifying httpbin deployment
_verify_lines snip_configure_a_tls_ingress_gateway_for_a_single_host_4 "
+ HTTP/2 418
+ -=[ teapot ]=-
"
_verify_elided snip_configure_a_tls_ingress_gateway_for_a_single_host_7 "$snip_configure_a_tls_ingress_gateway_for_a_single_host_7_out"
# deleting httpbin secret and re-creating
snip_configure_a_tls_ingress_gateway_for_a_single_host_5
snip_configure_a_tls_ingress_gateway_for_a_single_host_6
snip_configure_a_tls_ingress_gateway_for_a_single_host_8
# TODO: wait for the secret change to propagate
# verifying new httpbin credentials
_verify_elided snip_configure_a_tls_ingress_gateway_for_a_single_host_7 "$snip_configure_a_tls_ingress_gateway_for_a_single_host_7_out"
_verify_elided snip_configure_a_tls_ingress_gateway_for_a_single_host_9 "$snip_configure_a_tls_ingress_gateway_for_a_single_host_9_out"
# verifying old httpbin credentials no longer work
_verify_failure snip_configure_a_tls_ingress_gateway_for_a_single_host_8
_verify_failure snip_configure_a_tls_ingress_gateway_for_a_single_host_10
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_1
@ -76,34 +88,43 @@ _wait_for_deployment default helloworld-v1
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_3
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_4
if [ "$GATEWAY_API" == "true" ]; then
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_6
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_7
else
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_4
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_5
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_5
snip_configure_a_tls_ingress_gateway_for_multiple_hosts_6
# waiting for configuration to propagate
_wait_for_istio gateway default mygateway
_wait_for_istio virtualservice default helloworld-v1
_verify_contains snip_configure_a_tls_ingress_gateway_for_multiple_hosts_7 "$snip_configure_a_tls_ingress_gateway_for_multiple_hosts_7_out"
# waiting for configuration to propagate
_wait_for_istio gateway default mygateway
_wait_for_istio virtualservice default helloworld-v1
fi
_verify_elided snip_configure_a_tls_ingress_gateway_for_multiple_hosts_8 "$snip_configure_a_tls_ingress_gateway_for_multiple_hosts_8_out"
_verify_elided snip_configure_a_tls_ingress_gateway_for_multiple_hosts_9 "$snip_configure_a_tls_ingress_gateway_for_multiple_hosts_9_out"
snip_configure_a_mutual_tls_ingress_gateway_1
snip_configure_a_mutual_tls_ingress_gateway_2
if [ "$GATEWAY_API" == "true" ]; then
snip_configure_a_mutual_tls_ingress_gateway_3
else
snip_configure_a_mutual_tls_ingress_gateway_2
# wait for the change to propagate
_wait_for_istio gateway default mygateway
# wait for the change to propagate
_wait_for_istio gateway default mygateway
fi
_verify_failure snip_configure_a_mutual_tls_ingress_gateway_3
if [ "$GATEWAY_API" != "true" ]; then
_verify_failure snip_configure_a_mutual_tls_ingress_gateway_4
snip_configure_a_mutual_tls_ingress_gateway_4
_verify_elided snip_configure_a_mutual_tls_ingress_gateway_5 "$snip_configure_a_mutual_tls_ingress_gateway_5_out"
_verify_elided snip_configure_a_mutual_tls_ingress_gateway_5 "$snip_configure_a_mutual_tls_ingress_gateway_5_out"
fi
# TODO ^^^ Mutual tls is currently not working with gateway API. Remove above guard when fixed.
# @cleanup
snip_cleanup_1
snip_cleanup_2
snip_cleanup_3
if [ "$GATEWAY_API" != "true" ]; then
snip_cleanup_1
snip_cleanup_3
snip_cleanup_4
fi