TLS終端なしのイングレスゲートウェイ
HTTPSでゲートウェイを保護するタスクでは、HTTPサービスへのHTTPSイングレスアクセスを構成する方法について説明しています。この例では、HTTPSサービスへのHTTPSイングレスアクセスを構成する方法、つまり、受信リクエストでTLS終端を実行するのではなく、SNIパススルーを実行するようにイングレスゲートウェイを構成する方法について説明します。
このタスクで使用されるHTTPSサービスの例は、シンプルなNGINXサーバーです。次のステップでは、まずKubernetesクラスターにNGINXサービスをデプロイします。次に、ホストnginx.example.com
を介してサービスへのイングレスアクセスを提供するようにゲートウェイを構成します。
始める前に
インストールガイドの手順に従って Istio をセットアップします。
クライアントとサーバーの証明書およびキーを生成する
このタスクでは、証明書と鍵を生成するためにお好みのツールを使用できます。以下のコマンドは openssl を使用しています。
サービスの証明書に署名するためのルート証明書と秘密鍵を作成します。
$ mkdir example_certs $ openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example_certs/example.com.key -out example_certs/example.com.crt
nginx.example.com
の証明書と秘密鍵を作成します。$ openssl req -out example_certs/nginx.example.com.csr -newkey rsa:2048 -nodes -keyout example_certs/nginx.example.com.key -subj "/CN=nginx.example.com/O=some organization" $ openssl x509 -req -sha256 -days 365 -CA example_certs/example.com.crt -CAkey example_certs/example.com.key -set_serial 0 -in example_certs/nginx.example.com.csr -out example_certs/nginx.example.com.crt
NGINXサーバーをデプロイする
サーバーの証明書を保持するための Kubernetes Secret を作成します。
$ kubectl create secret tls nginx-server-certs \ --key example_certs/nginx.example.com.key \ --cert example_certs/nginx.example.com.crt
NGINX サーバーの設定ファイルを作成します。
$ 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
NGINX サーバーの設定を保持するための Kubernetes ConfigMap を作成します。
$ kubectl create configmap nginx-configmap --from-file=nginx.conf=./nginx.conf
NGINX サーバーをデプロイします。
$ cat <<EOF | 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 sidecar.istio.io/inject: "true" 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
NGINX サーバーが正常にデプロイされたことをテストするには、サーバーの証明書をチェックせずに(
curl
の-k
オプションを使用)、サイドカープロキシからサーバーにリクエストを送信します。サーバーの証明書が正しく出力されていること、つまり、common name (CN)
がnginx.example.com
と等しいことを確認してください。$ kubectl exec "$(kubectl get pod -l run=my-nginx -o jsonpath={.items..metadata.name})" -c istio-proxy -- curl -sS -v -k --resolve nginx.example.com:443:127.0.0.1 https://nginx.example.com ... SSL connection using TLSv1.2 / ECDHE-RSA-AES256-GCM-SHA384 ALPN, server accepted to use http/1.1 Server certificate: subject: CN=nginx.example.com; O=some organization start date: May 27 14:18:47 2020 GMT expire date: May 27 14:18:47 2021 GMT issuer: O=example Inc.; CN=example.com SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway. > GET / HTTP/1.1 > User-Agent: curl/7.58.0 > Host: nginx.example.com ... < HTTP/1.1 200 OK < Server: nginx/1.17.10 ... <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ...
イングレスゲートウェイを構成する
- ポート 443 をパススルー TLS モードで公開する
Gateway
を定義します。これは、ゲートウェイに TLS を終端せずにイングレストラフィックを「そのまま」渡すように指示します。
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
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
$ kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: mygateway
spec:
gatewayClassName: istio
listeners:
- name: https
hostname: "nginx.example.com"
port: 443
protocol: TLS
tls:
mode: Passthrough
allowedRoutes:
namespaces:
from: All
EOF
Gateway
を介して入ってくるトラフィックのルートを構成します。
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: VirtualService
metadata:
name: nginx
spec:
hosts:
- nginx.example.com
gateways:
- mygateway
tls:
- match:
- port: 443
sniHosts:
- nginx.example.com
route:
- destination:
host: my-nginx
port:
number: 443
EOF
$ kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1alpha2
kind: TLSRoute
metadata:
name: nginx
spec:
parentRefs:
- name: mygateway
hostnames:
- "nginx.example.com"
rules:
- backendRefs:
- name: my-nginx
port: 443
EOF
- イングレス IP とポートを決定します。
以下のコマンドを使用して、SECURE_INGRESS_PORT
および INGRESS_HOST
環境変数を設定します。
$ kubectl wait --for=condition=programmed gtw mygateway
$ export INGRESS_HOST=$(kubectl get gtw mygateway -o jsonpath='{.status.addresses[0].value}')
$ export SECURE_INGRESS_PORT=$(kubectl get gtw mygateway -o jsonpath='{.spec.listeners[?(@.name=="https")].port}')
クラスター外から NGINX サービスにアクセスします。サーバーから正しい証明書が返され、正常に検証される(SSL certificate verify ok と表示される)ことを確認してください。
$ curl -v --resolve "nginx.example.com:$SECURE_INGRESS_PORT:$INGRESS_HOST" --cacert example_certs/example.com.crt "https://nginx.example.com:$SECURE_INGRESS_PORT" Server certificate: subject: CN=nginx.example.com; O=some organization start date: Wed, 15 Aug 2018 07:29:07 GMT expire date: Sun, 25 Aug 2019 07:29:07 GMT issuer: O=example Inc.; CN=example.com SSL certificate verify ok. < HTTP/1.1 200 OK < Server: nginx/1.15.2 ... <html> <head> <title>Welcome to nginx!</title>
クリーンアップ
- ゲートウェイの設定とルートを削除します。
$ kubectl delete gateway mygateway
$ kubectl delete virtualservice nginx
$ kubectl delete gtw mygateway
$ kubectl delete tlsroute nginx
NGINX リソースと設定ファイルを削除します。
$ kubectl delete secret nginx-server-certs $ kubectl delete configmap nginx-configmap $ kubectl delete service my-nginx $ kubectl delete deployment my-nginx $ rm ./nginx.conf
証明書と鍵を削除します。
$ rm -rf ./example_certs