Недавно мы писали про развертывание Apache Kafka на Kubernetes с помощью open-source проекта Strimzi. Сегодня рассмотрим, как обеспечить безопасный доступ к данным на таком кластере, применив различные методы аутентификации и авторизации. Лучшие практики cybersecurity на практическом примере.
Постановка задачи: пример приложения с безопасным доступом к данным
Напомним, Strimzi – это open-source проект в песочнице CNCF, который использует образы контейнеров и операторов платформы контейнерной виртуализации Kubernetes, чтобы упростить запуск кластера Apache Kafka в различных конфигурациях развертывания. Strimzi предоставляет различные способы защиты кластера Кафка [1]:
- аутентификация с помощью mutual TLS, SCRAM-SHA-512 и OAUTH 2.0 Token;
- авторизация через Simple Authorization, OAUTH 2.0 Token based authorization, OPA (Open Policy Agent) Custom Authorization.
Таким образом, безопасность Kafka на Kubernetes с помощью Strimzi может быть обеспечена на уровне инфраструктуры путем реализации сетевой политики, правил входа, взаимного TLS, а также на уровне приложения через тот же mutual TLS, OAuth, SCRAM. Протокол двусторонней аутентификации (взаимный TLS) на обоих уровнях обеспечивает очень надежную защиту, однако может привести к значительным операционным издержкам.
Рассмотрим подробнее использование SCRAM-SHA-512 для аутентифицированного доступа к Кафка-кластеру и простую авторизацию (Simple Authorization). В качестве примера будем использовать финансовую систему, где приложение-продюсер Core App записывает в топик все финансовые операции клиентов. Приложение-потребитель Notification App считывает их из этого топика Financial-transactions, чтобы отправить уведомления о транзакции владельцу счета. Приложение-продюсер Core App также записывает в топик билеты (tickets, тикеты), где регистрируются все обращения к поддержке (контакт-центру), созданные владельцем учетной записи. А приложение-потребитель данных для контакт-центра Contact Center App отслеживает сообщения в этих обращениях по топикам и инициирует их обработку сотрудниками.
Таким образом, архитектура безопасности для этого примера должна обеспечить следующие возможности:
- только приложение-продюсер Core App может публиковать в топике финансовые транзакции;
- только приложение-продюсер Core App может публиковать в топике тикеты;
- только приложению-потребителю Notification App можно читать топик финансовых транзакций;
- только приложение-потребитель Contact Center App может читать сообщения из топика с тикетами (tickets) тикетов.
Для реализации этих требований необходим ряд системных пользователей для приложений потребителей и продюсера: core-app-usr-1 для Core App, notification-app-usr-1 для Notification App и contact-centre-usr-1 для Contact Center App. Поскольку речь идет о безопасном доступе к кластеру Apache Kafka на Kubernetes, развернутом с помощью Strimzi, необходим защищенный кластер Kubernetes, оператор Strimzi в кластере и работающее подключение к кластеру. Как этого добиться, рассмотрим далее.
Тонкости аутентификации и авторизации к Kafka на Kubernetes с операторами Strimzi
Создать защищенный кластер в выделенном пространстве имен core-kafka-cluster поможет команда в CLI-инструменте Kubernetes для управления кластерами: kubectl create namespace core-kafka-cluster. Если операторы Strimzi установлены в пространстве имен strimzi, следует привязать к ним роли, чтобы разрешить управление кластером Kafka, а потом создать соответствующий оператор. После успешного запуска пода оператора можно создать Кафка-кластер, который прослушивает внешний трафик на порту узла 9094, аутентифицирует пользователя с помощью SCRAM-SHA-512 и использует простую политику авторизации. Запустив созданный кластер, можно получить список серверов начальной загрузки через команду kubectl:
kubectl -n core-kafka-cluster get kafkas.kafka.strimzi.io kafka –o
jsonpath='{.status.listeners[?
(@.type==»external»)].bootstrapServers}’
Эта команда покажет IP-адреса брокеров Kafka и используемые ими порты. Далее для рассматриваемого примера следует создать 3 топика и системных пользователей для них, а также установить требуемые возможности обеспечения безопасности, описанные ранее. Увидеть список пользователей, созданных в кластере, поможет команда kubectl -n core-kafka-cluster get kafkausers.kafka.strimzi.io. Каждому пользователю должно быть установлено значение true под заголовком READY. В процессе создания пользователя Strimzi генерирует секреты аутентификации, т.е. пароль и токен JAAS для каждого. Конфигурации безопасности хранятся в секретном ресурсе Kubernetes, где имя ресурса совпадает с именем пользователя. Получить токен JAAS для пользователя core-app-usr-1 можно с помощью команды kubectl —n core-kafka-cluster get secrets core-app-usr-1 —o jsonpath='{.data.sasl\.jaas\.config}’. Этот токен потребуется пользователю приложения при взаимодействии с кластером Kafka.
Чтобы усилить безопасность в production можно хранить секреты в специализированном надежном хранилище типа Hashicorp, откуда администратор кластера будет их считывать в качестве значений среды в приложения-продюсеров и потребителей. Также можно применять политики списков ограниченного доступа (ACL) Kubernetes, например, с использованием OPA и Gatekeeper, которые делают секреты доступными для приложений продюсеров и потребителей, размещенных в другом пространстве имен в том же кластере. Этот подход не имеет операционных издержек, а секреты никогда не уйдут за периметр платформы. Подробный пример реализации и тестирования рассмотренных приемов обеспечения безопасности кластера Кафка на Kubernetes, развернутого с помощью операторов Strimzi, изложен в источнике [2].
В заключение отметим несколько важных принципов настройки механизмов аутентификации и авторизации пользователей Kafka и официальной документации операторов Strimzi. Используя адрес кластера Kafka, можно предоставить внешний доступ клиенту в другом пространстве имен Kubernetes или полностью за пределами Kubernetes, настроив внешний слушатель определенного типа для предоставления доступа [3]:
- route для использования OpenShift Route и маршрутизатора HAProxy по умолчанию;
- loadbalancer для использования сервисов loadbalancer;
- nodeport для использования портов на узлах Kubernetes;
- ingress для использования Kubernetes Ingress и контроллера NGINX Ingress для Kubernetes.
Выбранный тип внешнего слушателя зависит от требований, среды и инфраструктуры. Например, балансировщики нагрузки могут не подходить для инфраструктуры типа bare metal – вместо этого лучше выбрать порты узлов. Также следует убедиться, что они соответствуют эквивалентной конфигурации самой платформы потоковой передачи событий: KafkaUser.spec.authentication соответствует Kafka.spec.kafka.listeners[*].authentication, а KafkaUser.spec.authorization — Kafka.spec.kafka.authorization. Необходим как минимум один слушатель, поддерживающий аутентификацию, нужную для пользователей Kafka. Кроме того, аутентификация между пользователями и брокерами Kafka зависит от настроек каждого из них. Например, невозможно аутентифицировать пользователя с помощью TLS, если он не включен в конфигурации. Операторы Strimzi автоматизируют процесс настройки:
- оператор кластера создает слушателей и настраивает сертификаты центра сертификации кластера и клиента, чтобы включить аутентификацию в кластере Kafka;
- оператор пользователя создает пользователя, представляющего клиента, и его учетные данные безопасности для аутентификации на основе выбранного типа.
В этой процедуре используются сертификаты, сгенерированные оператором кластера, но их можно заменить на собственные. Также можно настроить слушатель на использование сертификата Kafka, управляемого внешним центром сертификации. Сертификаты доступны в форматах PKCS #12 (.p12) и PEM (.crt) [3].
Узнайте все про администрирование и эксплуатацию Apache Kafka для потоковой аналитики больших данных на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков больших данных в Москве:
Источники