Ingress Gateway без термінації TLS

Завдання Захист Gateways з HTTPS описує, як налаштувати доступ до HTTP-сервісу через HTTPS шлюз входу. У цьому прикладі розглядається, як налаштувати доступ до HTTPS-сервісу через HTTPS шлюз входу, тобто налаштувати шлюз входу для пропуску SNI, замість термінації TLS на вхідних запитах.

Приклад HTTPS-сервісу, що використовується для цього завдання, є простий сервер NGINX. У наступних кроках спочатку розгортаєте сервіс NGINX у вашому кластері Kubernetes. Потім налаштовуєте шлюз для забезпечення доступу до сервісу через хост 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. Створіть Kubernetes ConfigMap для зберігання конфігурації сервера NGINX:

    $ 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 був успішно розгорнутий, надішліть запит до сервера з його sidecar-проксі без перевірки сертифіката сервера (використовуйте параметр -k для curl). Переконайтеся, що сертифікат сервера виводиться правильно, тобто 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>
    ...

Налаштуйте ingress gateway

  1. Визначте Gateway, що відкриває порт 443 з прохідним режимом TLS. Це вказує шлюзу пропускати вхідний трафік “as is”, не перериваючи TLS:
$ kubectl apply -f - <<EOF
apiVersion: networking.istio.io/v1
kind: Gateway
metadata:
  name: mygateway
spec:
  selector:
    istio: ingressgateway # використовуємо стандартний istio 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_PORT та INGRESS_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
Чи була ця інформація корисною?
Чи є у вас пропозиції щодо покращення?

Дякуємо за ваш відгук!