TLS終端なしのイングレスゲートウェイ

HTTPSでゲートウェイを保護するタスクでは、HTTPサービスへのHTTPSイングレスアクセスを構成する方法について説明しています。この例では、HTTPSサービスへのHTTPSイングレスアクセスを構成する方法、つまり、受信リクエストでTLS終端を実行するのではなく、SNIパススルーを実行するようにイングレスゲートウェイを構成する方法について説明します。

このタスクで使用されるHTTPSサービスの例は、シンプルなNGINXサーバーです。次のステップでは、まずKubernetesクラスターにNGINXサービスをデプロイします。次に、ホストnginx.example.comを介してサービスへのイングレスアクセスを提供するようにゲートウェイを構成します。

始める前に

インストールガイドの手順に従って Istio をセットアップします。

クライアントとサーバーの証明書およびキーを生成する

このタスクでは、証明書と鍵を生成するためにお好みのツールを使用できます。以下のコマンドは openssl を使用しています。

  1. サービスの証明書に署名するためのルート証明書と秘密鍵を作成します。

    $ 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
    
  2. 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サーバーをデプロイする

  1. サーバーの証明書を保持するための Kubernetes Secret を作成します。

    $ kubectl create secret tls nginx-server-certs \
      --key example_certs/nginx.example.com.key \
      --cert example_certs/nginx.example.com.crt
    
  2. 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
    
  3. NGINX サーバーの設定を保持するための Kubernetes ConfigMap を作成します。

    $ kubectl create configmap nginx-configmap --from-file=nginx.conf=./nginx.conf
    
  4. 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
    
  5. 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>
    ...
    

イングレスゲートウェイを構成する

  1. ポート 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
  1. 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
  1. イングレス IP とポートを決定します。
イングレス IP とポートの決定の手順に従って、SECURE_INGRESS_PORTINGRESS_HOST 環境変数を設定します。
  1. クラスター外から 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>
    

クリーンアップ

  1. ゲートウェイの設定とルートを削除します。
$ kubectl delete gateway mygateway
$ kubectl delete virtualservice nginx
  1. 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
    
  2. 証明書と鍵を削除します。

    $ rm -rf ./example_certs
    
この情報は役に立ちましたか?
改善のための提案はありますか?

フィードバックありがとうございます!