Предоставьте свои микросервисы внешнему миру через TLS

Istio предоставляет вам множество функций, которые помогут вам подключаться, защищать, контролировать и наблюдать за вашими микросервисами. Это дает Kubernetes большой контроль над тем, на что он обычно способен. Шлюзы Istio - это мощный ресурс, который позволяет вам определять точки входа в вашу сервисную сеть из внешнего мира.

В предыдущей статье мы представили приложение BookInfo протоколу HTTP. Однако Istio предоставляет безопасные шлюзы для размещения ваших микросервисов по протоколу HTTPS. Istio обеспечивает как простую, так и взаимную аутентификацию TLS, что упрощает вашу жизнь, поскольку вам больше не нужно управлять сертификатами вне кластера Kubernetes.

Эта статья является продолжением статьи Как управлять трафиком с помощью Istio в Kubernetes. Сегодня давайте обсудим, как предоставить доступ к микросервисам внешнему миру через HTTPS с помощью безопасных шлюзов Istio.

Предпосылки

Для практического упражнения вам понадобится работающий кластер Kubernetes.

Установите Istio в своем кластере Kubernetes, следуя руководству Начало работы с Istio в Kubernetes.

Определите INGRESS_HOST и SECURE_INGRESS_PORT, выполнив приведенный ниже код.

Если вы используете балансировщик нагрузки, выполните следующее.

$ export INGRESS_HOST=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
$ export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].port}')

Если вы не используете балансировщик нагрузки, вы также можете использовать комбинацию IP-адреса узла и порта узла. Запустите ниже, чтобы использовать это.

export INGRESS_HOST=<worker-node-address>
export SECURE_INGRESS_PORT=$(kubectl -n istio-system get service istio-ingressgateway -o jsonpath='{.spec.ports[?(@.name=="https")].nodePort}')

Создать сертификаты TLS

Для практической демонстрации мы предполагаем, что домен example.com.

Давайте воспользуемся OpenSSL для создания самозаверяющего корневого сертификата для example.com.

$ 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

Создайте сертификат и закрытый ключ для bookinfo.example.com, используя корневой сертификат example.com. Давайте сначала сгенерируем закрытый ключ и CSR, а затем воспользуемся корневым сертификатом example.com, чтобы подписать CSR и создать общедоступный bookinfo.example.com сертификат.

$ openssl req -out bookinfo.example.com.csr -newkey rsa:2048 -nodes -keyout bookinfo.example.com.key -subj "/CN=bookinfo.example.com/O=bookinfo organization"
$ openssl x509 -req -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in bookinfo.example.com.csr -out bookinfo.example.com.crt

Настройте простой TLS для приложения BookInfo

Создайте секрет с сгенерированным ключом и сертификатом в пространстве имен istio-system. Обратите внимание, что имя секрета не должно начинаться с istio или prometheus, поскольку это ключевые слова, зарезервированные для системных секретов.

$ kubectl create -n istio-system secret tls bookinfo-credential --key=bookinfo.example.com.key --cert=bookinfo.example.com.crt
secret/bookinfo-credential created

Создайте шлюз BookInfo на входящем входе Istio по умолчанию, используя учетные данные. Нижеприведенный YAML определяет шлюз с именем bookinfogateway на Istio ingressgateway по умолчанию, прослушивает порт 443 по simple протоколу TLS и использует bookinfo-credential для хоста bookinfo.example.com.

Создайте виртуальный сервис для подключения к странице продукта.

Примените правила назначения.

$ kubectl apply -f samples/bookinfo/networking/destination-rule-all.yaml
destinationrule.networking.istio.io/productpage created
destinationrule.networking.istio.io/reviews created
destinationrule.networking.istio.io/ratings created
destinationrule.networking.istio.io/details created

Сделайте следующую запись в вашем хост-файле. Он нужен, если вы хотите получить доступ к странице продукта из браузера.

<INGRESS_HOST> bookinfo.example.com

Откройте приложение BookInfo из браузера.

Перейдите на https://bookinfo.example.com/productpage, и вы должны увидеть следующее.

Поскольку сертификат является самоподписанным, мы получаем небезопасное предупреждение. Если вы используете сертификат, подписанный общедоступным центром сертификации, уведомление должно исчезнуть.

Давайте зайдем на страницу через curl, чтобы увидеть, получим ли мы ошибку проверки, если мы будем использовать example.com сертификат CA для проверки.

И мы получаем HTTP 200 ответ. Это доказывает, что простой TLS работает нормально.

Ротация сертификатов

Ротация сертификатов для входящего шлюза находится всего в нескольких командах.

Создайте новый набор сертификатов из корневого сертификата.

$ 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/bookinfo.example.com.csr -newkey rsa:2048 -nodes -keyout new_certificates/bookinfo.example.com.key -subj "/CN=bookinfo.example.com/O=bookinfo organization"
$ openssl x509 -req -days 365 -CA new_certificates/example.com.crt -CAkey new_certificates/example.com.key -set_serial 0 -in new_certificates/bookinfo.example.com.csr -out new_certificates/bookinfo.example.com.crt

Теперь удалите старый секрет и создайте новый с новыми учетными данными.

$ kubectl -n istio-system delete secret bookinfo-credential
secret "bookinfo-credential" deleted
$ kubectl create -n istio-system secret tls bookinfo-credential \
--key=new_certificates/bookinfo.example.com.key \
--cert=new_certificates/bookinfo.example.com.crt
secret/bookinfo-credential created

Теперь перейдем к приложению BookInfo с помощью нового сертификата.

Что бы произошло, если бы мы использовали старые сертификаты для подключения к сервису? Давайте разберемся.

И это не удается! Это показывает, что ротация сертификатов работает правильно.

Настройка взаимного TLS

Взаимный TLS может потребоваться, если вам нужно установить доверительные отношения между клиентом и сервером и наоборот. Это может быть необходимо, если вы размещаете API и хотите, чтобы к нему имели доступ только доверенные клиенты.

Чтобы шлюз использовал Mutual TLS, нам нужно переопределить bookinfo-credential, чтобы установить свойства tls.key, tls.cert и cacert для хранения сертификата CA. Это необходимо, так как теперь сервер должен доверять клиенту, и ему необходимо проверить сертификат клиента, используя настроенный сертификат CA.

$ kubectl -n istio-system delete secret bookinfo-credential
secret "bookinfo-credential" deleted
$ kubectl create -n istio-system secret generic bookinfo-credential --from-file=tls.key=bookinfo.example.com.key \
--from-file=tls.crt=bookinfo.example.com.crt --from-file=ca.crt=example.com.crt
secret/bookinfo-credential created

Обновите входной шлюз, чтобы использовать MUTUAL TLS-аутентификацию.

Теперь обратимся к приложению старым методом.

И получаем ошибку! Это означает, что для аутентификации в приложении BookInfo требуется сертификат клиента. Давайте сгенерируем клиентский ключ и сертификат с помощью OpenSSL.

$ 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 -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 1 -in client.example.com.csr -out client.example.com.crt

Давайте воспользуемся сертификатом клиента для аутентификации в приложении BookInfo.

И мы получаем HTTP 200 ответ.

Попробуем зайти в приложение BookInfo из браузера.

И теперь мы видим, что он не позволяет нам подключиться, потому что мы не предоставили действительный сертификат клиента, когда открываем страницу из браузера.

Поздравляю! Вы успешно настроили взаимный TLS в Istio!

Заключение

Спасибо за прочтение. Надеюсь, вам понравилась статья.

В следующей части я расскажу о зеркалировании трафика в Kubernetes с использованием Istio с практической демонстрацией, так что до встречи!