Исходящие шлюзы Istio с исходящим сертификатом TLS CERTIFICATE_VERIFY_FAILED

#ssl #kubernetes #istio

#ssl #kubernetes #istio

Вопрос:

Я пытаюсь настроить istio (v1.7.3) на AKS (v1.16.13) таким образом, чтобы для некоторых HTTP-адресатов выполнялась инициализация TLS. Поэтому, когда один из моих модулей вызывает abc.mydomain.com при использовании HTTP выходной запрос будет обновлен до HTTPS, а проверка TLS будет выполнена через Выходной шлюз.

Я следовал этим 2 руководствам, чтобы добиться этого:

В итоге я получил что-то вроде этого (abc.mydomain.com является внешним URL-адресом, поэтому я создал для него ServiceEntry):

 apiVersion: networking.istio.io/v1alpha3
kind: ServiceEntry
metadata:
  name: abc.mydomain.com
spec:
  hosts:
  - abc.mydomain.com
  ports:
  - number: 80
    name: http
    protocol: HTTP
  - number: 443
    name: https
    protocol: HTTPS
  resolution: DNS
---
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: istio-egressgateway
  namespace: istio-system
spec:
  selector:
    istio: egressgateway
  servers:
  - port:
      number: 443
      name: https
      protocol: HTTPS
    hosts:
    - abc.mydomain.com
    tls:
      mode: ISTIO_MUTUAL
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: egressgateway-for-abc
  namespace: istio-system
spec:
  host: istio-egressgateway.istio-system.svc.cluster.local
  subsets:
  - name: abc
    trafficPolicy:
      loadBalancer:
        simple: ROUND_ROBIN
      portLevelSettings:
      - port:
          number: 443
        tls:
          mode: ISTIO_MUTUAL
          sni: abc.mydomain.com
---
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
  name: direct-abc-through-egress-gateway
  namespace: istio-system
spec:
  hosts:
  - abc.mydomain.com
  gateways:
  - istio-egressgateway
  - mesh
  http:
  - match:
    - gateways:
      - mesh
      port: 80
    route:
    - destination:
        host: istio-egressgateway.istio-system.svc.cluster.local
        subset: abc
        port:
          number: 443
      weight: 100
  - match:
    - gateways:
      - istio-egressgateway
      port: 443
    route:
    - destination:
        host: abc.mydomain.com
        port:
          number: 443
      weight: 100
---
apiVersion: networking.istio.io/v1alpha3
kind: DestinationRule
metadata:
  name: originate-tls-for-abc
  namespace: istio-system
spec:
  host: abc.mydomain.com
  trafficPolicy:
    loadBalancer:
      simple: ROUND_ROBIN
    portLevelSettings:
    - port:
        number: 443
      tls:
        mode: SIMPLE
        credentialName: abc # this must match the secret created earlier without the "-cacert" suffix
        sni: abc.mydomain.com
  

Я создаю секрет для своего корневого центра сертификации с помощью: kubectl create secret generic abc-cacert --from-file=ca.crt=mydomainrootca.crt -n istio-system

Я использовал тот же сертификат для своих Java-приложений, и я могу успешно вызвать HTTPS для того же URL-адреса с помощью JKS. Кажется, сертификат правильно загружен в egress ( kubectl logs -f -l istio=egressgateway -n istio-system ):

 2020-10-06T20:00:36.611607Z     info    sds     resource:abc-cacert new connection
2020-10-06T20:00:36.612907Z     info    sds     Skipping waiting for gateway secret
2020-10-06T20:00:36.612994Z     info    cache   GenerateSecret abc-cacert
2020-10-06T20:00:36.613063Z     info    sds     resource:abc-cacert pushed root cert to proxy
  

Когда я вызываю curl abc.mydomain.com модуль, запущенный в моем кластере, я получаю эту ошибку от выходного шлюза:

 [2020-10-06T19:33:40.902Z] "GET / HTTP/1.1" 503 UF,URX "-" "TLS error: 268435581:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED" 0 91 172 - "192.244.0.191" "curl/7.64.0" "b618b1e6-e543-4053-bf2f-8ae56664545f" "abc.mydomain.com" "192.223.24.254:443" outbound|443||abc.mydomain.com - 192.244.0.188:8443 192.244.0.191:41306 abc.mydomain.com -
  

Есть идеи, что я могу делать неправильно? Я совсем новичок в istio, и я не понимаю всей необходимости DestinationRule / VirtualService, поэтому, пожалуйста, поделитесь со мной.

ОБНОВЛЕНИЕ1

После ввода правил назначения в пространство имен, в котором запущен мой модуль, я получаю следующее:

 curl abc.mydomain.com
<html>
<head><title>400 The plain HTTP request was sent to HTTPS port</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<center>The plain HTTP request was sent to HTTPS port</center>
<hr><center>nginx/1.17.10</center>
</body>
</html>
  

Вот вывод istioctl proxy-status :

 NAME                                                            CDS        LDS        EDS        RDS        ISTIOD                      VERSION
istio-egressgateway-695dc4fc7c-p5p42.istio-system               SYNCED     SYNCED     SYNCED     SYNCED     istiod-5c6b7b5b8f-csggg     1.7.3
istio-ingressgateway-5689f7c67-j54m7.istio-system               SYNCED     SYNCED     SYNCED     SYNCED     istiod-5c6b7b5b8f-csggg     1.7.3
test-5bbfdb8f4b-hg7vf.test                                      SYNCED     SYNCED     SYNCED     SYNCED     istiod-5c6b7b5b8f-csggg     1.7.3
  

Комментарии:

1. Привет, я вижу, что вы помещаете почти все в пространство имен istio-system, в некоторых случаях это может быть проблематично. Вызываете ли вы curl из модуля, в который внедрен istio?

2. Да, это внедренный istio. Какие части вы бы предложили переместить в пространство имен модуля?

3. DestinationRule должно находиться в том же пространстве имен, что и соответствующая служба. Документы . Можете ли вы добавить полную команду curl, которую вы использовали для вызова службы?

4. Dzieki 🙂 Я использую именно команду curl, как описано выше: curl abc.mydomain.com

5. Кстати, я только что понял, что для меня было бы достаточно использовать подход с подстановочным знаком без инициализации (istio может перехватить рукопожатие https) и увидел аналогичную проблему в обсуждении istio, поэтому я разместил там свой вопрос: discuss.istio.io/t /. … Не уверен, следует ли мне размещать его в stackoverflow… Но если у вас есть ответ на этот вопрос, я буду более чем счастлив принять ваше решение в stack.