Обеспечение безопасности в Apache Kafka

94273715d7716923b855095d7bf5cd1c.png

В предыдущих статьях мы рассмотрели архитектуру решения Apache Kafka, развернули продукт и разобрались с отправкой и получением сообщений. Можно было бы, конечно, дальше погрузиться в тему использования данного решения, но в Интернете есть множество различных публикаций с примерами использования Kafka для различных задач и различных сред разработки. Поэтому данная статья будет целиком и полностью посвящена такой важной теме, как обеспечение безопасности Apache Kafka.

По своему предназначению Kafka является посредником между различными системами при их обмене сообщениями. Для этого, как мы помним, есть топики и разделы. Но проблема заключается в том, что при стандартной настройке Kafka по умолчанию, любой пользователь или приложение может писать любые сообщения в любой топик, а также считывать данные из любых топиков. Естественно, для сколько-нибудь промышленного применения системы такой подход недопустим. Например, в случае, когда несколько приложений используют один и тот же кластер Kafka, или когда кластер используется в качестве облачного сервиса для сторонних приложений, ну и естественно, когда в Kafka начинает обрабатываться конфиденциальная информация.

В статье мы будем говорить о встроенных в Kafka механизмах защиты и не будем касаться использования каких-либо наложенных средств. Начиная с версии 0.9.0.0 в продукт были добавлены ряд функций, которые позволяют повысить уровень защищенности Kafka. Вот основные функции:

  • Аутентификация подключений к брокерам от клиентов (продьюсеров и консьюмеров), других брокеров и приложениями, использующими SSL или SASL (Kerberos).

  • Аутентификация подключений от брокеров к ZooKeeper.

  • Шифрование данных, передаваемых между брокерами и клиентами, между брокерами или между брокерами и инструментами, с использованием SSL (обратите внимание, что при включении SSL происходит снижение производительности, величина которого зависит от типа процессора и реализации JVM).

  • Авторизация операций чтения/записи, выполняемых клиентами.

  • Авторизация подключаема и поддерживается интеграция с внешними службами авторизации.

Далее в статье я не буду уделять слишком много внимания «матчасти», то есть описанию работы тех или иных широко распространенных механизмов защиты, таких как SSL. При необходимости читатель может найти всю необходимую информацию в Интернете. Вместо этого мы уделим больше внимания непосредственно настройке защитных механизмов в Kafka.

Работаем с SSL

SSL (secure sockets layer) представляет собой криптографический протокол для безопасной связи. В Kafka по умолчанию этот протокол отключен. Но мы можем в любой момент включить SSL.

Работа с SSL как и в большинстве других систем, в Kafka начинается с создания сертификата. Когда мы устанавливали Zookeeper и Kafka, то предварительно была развернута Java, в состав которой входит утилита keytool. Далее мы сгенерируем ключ во временном хранилище ключей, чтобы позже экспортировать и подписать его с центром сертификации  

keytool -keystore server.keystore.jks -alias localhost -validity {validity} -genkey

В моем примере был сгенерирован такой ключ. Обратите внимание на необходимость обязательного указания пароля.

7b890e31bf5341a76b8ed8edccc48c7d.png

Параметр keystroke указывает в каком файле хранить ключ, а validity это период действия сертификата в днях. Помните про то, что для корректной работы сертификатов необходима правильная настройка DNS, позволяющая корректно разрешать имена узлов.

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

Сейчас у нас имеются сертификаты, но они являются самоподписанными, то есть злоумышленник может при желании тоже сгенерировать свой сертификат, и обменявшись открытыми ключами с парой легальных участников читать и модифицировать весь их трафик (атака Man in the Middle).  Поэтому важно предотвратить подделку сертификатов, подписав их для каждой машины в кластере. Для решения этой задачи необходим центр сертификации (CA), который отвечает за подписание сертификатов. Центр сертификации подписывает сертификаты, и криптография гарантирует, что подписанный сертификат сложно подделать с вычислительной точки зрения. Таким образом, пока центр сертификации является подлинным и заслуживающим доверия органом, клиенты могут быть уверены в том, что они подключаются к подлинным машинам.

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

openssl req -new -x509 -keyout ca-key -out ca-cert -days 365
keytool -keystore server.truststore.jks -alias CARoot -import -file ca-cert

ecb01833386552425b71688da408af8d.png

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

Теперь нам необходимо подписать наш сгенерированный сертификат сертификатом ЦС. Для этого мы сначала экспортируем сертификат из хранилища, а затем подпишем его сертификатом ЦС и импортируем оба сертификата в свое хранилище:

keytool -keystore server.keystore.jks -alias CARoot -import -file ca-cert
keytool -keystore server.keystore.jks -alias localhost -import -file cert-signed

Настройка брокеров

Настройка брокеров начинается с указания списка портов, ка которых мы будем принимать соединения. Так как мы используем соединение по SSL, то на стороне брокера необходимо выполнить следующие настройки:

ssl.keystore.location=/var/private/ssl/kafka.server.keystore.jks
        ssl.keystore.password=…
        ssl.key.password=…
        ssl.truststore.location=/var/private/ssl/kafka.server.truststore.jks
        ssl.truststore.password=…

Для проверки корректности работы выполненных настроек, вы можете выполнить следующие команды:

openssl s_client -debug -connect localhost:9093 -tls1

Настраиваем SASL

SASL (Simple Authentication and Security Layer) — это платформа для аутентификации и защиты данных в интернет-протоколах. Он направлен на то, чтобы отделить интернет-протоколы от конкретных механизмов аутентификации. Рассмотрим принципы работы SASL.

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

47b49edf1c693580a022cfd2b60b09cb.png

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

Вернемся к настройке Kafka. Для настройки аутентификации нам потребуется протокол Kerberos, то есть мы можем использовать для аутентификации Active Directory. Если в вашей сети нет AD, то необходимо будет развернуть сторонний сервер Kerberos. Так или иначе вам необходимо создать записи (принципалы) в вашем каталоге AD или другой системе для каждого брокера Kafka в вашем кластере.

В каталоге с конфигурациями брокера создадим файл  kafka_server_jaas.conf следующего содержания:

Затем нам необходимо указать Kafka пути к конфигурационным файлам:

    -Djava.security.krb5.conf=/etc/kafka/krb5.conf

    -Djava.security.auth.login.config=/etc/kafka/kafka_server_jaas.conf

Добавим порты, которые система должна слушать:

listeners=SASL_PLAINTEXT://host.name:port

Если используется SASL_SSL, то также необходимо настроить SSL. Если вы настраиваете только порт SASL (или если вы хотите, чтобы брокеры Kafka аутентифицировали друг друга с помощью SASL), то убедитесь, что вы установили один и тот же протокол SASL для взаимодействия между брокерами:

security.inter.broker.protocol=SASL_PLAINTEXT

Мы также должны настроить имя службы в server.properties, которое должно соответствовать основному имени брокеров kafka. В приведенном выше примере принципалом является »kafka/kafka1.hostname.com@EXAMPLE.com», так что:

sasl.kerberos.service.name=kafka

Подключаем клиентов

Клиенты нашего кластера Kafka будут проходить аутентификацию в кластере с помощью своего собственного аккаунта (обычно с тем же именем, что и у пользователя, запускающего клиент). Для каждого клиента нам потребуется создать файл JAAS аналогично тому, как мы это делали выше. Ниже приведен пример конфигурации для клиента, использующего keytab:

KafkaClient {

        com.sun.security.auth.module.Krb5LoginModule required
        useKeyTab=true
        storeKey=true
        keyTab="/etc/security/keytabs/kafka_client.keytab"
        principal="kafka-client-1@EXAMPLE.COM";
  
    };

В разделе Kafka Client описано, как клиенты, такие как продьюсеры и консьюмеры, могут подключаться к Kafka Broker. Далее передадим системе пути к конфигурационным файлам также, как мы это делали выше.

    -Djava.security.krb5.conf=/etc/kafka/krb5.conf

    -Djava.security.auth.login.config=/etc/kafka/kafka_client_jaas.conf

И в завершение нам необходимо настроить на наших продьюсерах и консьюмерах следующие свойства в producer.properties или consumer.properties

security.protocol=SASL_PLAINTEXT (or SASL_SSL)
    sasl.kerberos.service.name=kafka

Про ACL

В заключении темы безопасности Kafka рассмотрим возможности по работе со списками доступа ACL. По умолчанию, если какой-либо ресурс не связан с ACL, то никто, кроме суперпользователя не получит к нему доступ. Изменить эти настройки можно с помощью правок в файле broker.properties.

allow.everyone.if.no.acl.found=true

Если же мы хотим добавить каких-либо пользователей в группу суперпользователей, то необходимо перечислить их (обратите внимание, что разделителем является точка с запятой, поскольку имена пользователей SSL могут содержать запятую).

super.users=User:Bob;User:Alice

Заключение

На этом тему базовой настройки безопасности в Apache Kafka можно считать завершенной. Мы рассмотрели работу с SSL, SASL аутентификацию и соответствующие настройки на клиентах. А прямо сейчас хочу пригласить вас на бесплатный вебинар, в рамках которого рассмотрим как в приложениях на Spring Boot можно работать с Kafka. Узнаем, что предоставляет платформа Spring для ускоренной разработки приложений, работающих с Kafka. Посмотрим, какие есть настройки, как это все конфигурируется. Проведем границу между «родным функционалом» Kafka api и «добавками» от Spring Boot.

© Habrahabr.ru