Недавно мы рассматривали пример шифрования полезной нагрузки с чувствительными данными на стороне продюсера и их расшифровку на потребителе Apache Kafka. Такой примитивный способ подходит для интеграции нескольких приложений, но в больших масштабах становится очень неудобным. Читайте, как Conduktor Gateway для Apache Kafka поможет выйти из этой ситуации, обеспечив защиту конфиденциальных данных и улучшив управляемость EDA-системы.
Проблема сквозного шифрования в Kafka
Apache Kafka часто используется в качестве middleware-слоя для асинхронной интеграции множества приложений и для взаимодействия компонентов микросервисной архитектуры. Каждая часть такой сложной системы является независимым элементом развертывания и обычно реализована с помощью уникального стека технологий. Поэтому наивный подход с шифрованием чувствительных данных в полезной нагрузке на стороне продюсера и расшифровкой на потребителе, как мы рассматривали здесь, становится неудобным. Например, данные, зашифрованные с помощью Python-библиотеки, проблематично расшифровать с помощью Java.
Помимо обеспечения языковой совместимости, необходимо также обеспечить управление ротацией ключей. Это требует более сложного контракта интерфейса или хранения ключей в заголовках записей, проходящих через библиотеку шифрования. По мере включения в потоковый конвейер новых приложений с разными библиотеками шифрации/дешифрации данных возникает потребность в матрице совместимости, чтобы каждая команда, ответственная за разработку нового сервиса знала об ограничениях стека технологий.
Кроме постоянной поддержки такой матрицы совместимости и развития инструмента сквозного шифрования, необходимо также определять политики доступа к операции шифрования, что усложняет развертывание и интеграционное тестирование. Сквозное шифрование требует много скоординированных усилий, общего понимания, общих целей и ответственности, чего сложно достичь в крупной распределенной экосистеме.
Упростить проблему шифрования данных в Apache Kafka можно с помощью Java-приложения Conductor Gateway, которое полностью совместимо с протоколом Kafka и не зависит от провайдера платформы. Что оно собой представляет, рассмотрим далее.
Что такое Conduktor Gateway
Ядро Conduktor Gateway используется в качестве транспортного уровня между клиентскими приложениями Kafka и кластерами Kafka. Этот транспортный уровень расширяется за счет взаимодействия с Kafka, изменения данных или выполнения логических операций для повышения ценности. Сам шлюз состоит из двух концептуальных частей: ядра и перехватчиков, обеспечивая следующие функции:
- виртуализация кластеров для клиентов посредством мультиарендности;
- шифрование на уровне полей в записях Kafka;
- хаос-инжиниринг для тестирования сбоев по различным сценариям;
- защита структуры и правильного использования среды Kafka.
Подключения Conduktor Gateway к Kafka настраиваются с помощью префиксов и преобразованных переменных среды. Любая переменная с префиксом KAFKA_будет рассматриваться как параметр соединения. Оставшаяся часть переменной окружения будет записана строчными буквами и заменена _на две точки (..). Например, переменная для обращения к Kafka-кластеру KAFKA_BOOTSTRAP_SERVERS эквивалентна свойству bootstrap.servers
При обеспечении безопасности шлюза следует учитывать два набора настроек:
- соединение между клиентами Kafka и шлюзом;
- соединение между шлюзом и кластером Kafka.
При этом можно использовать все механизмы обеспечения безопасности Kafka: PLAINTEXT, SASL, OAuthBearer, Kerberos, например:
conduktor-gateway: image: conduktor/conduktor-gateway:2.1.4 environment: KAFKA_BOOTSTRAP_SERVERS: kafka1:9092,kafka2:9092 KAFKA_SASL_MECHANISM: PLAIN KAFKA_SECURITY_PROTOCOL: SASL_PLAINTEXT KAFKA_SASL_JAAS_CONFIG: org.apache.kafka.common.security.plain.PlainLoginModule required username="admin" password="admin-secret";
По умолчанию Conduktor использует установленный KAFKA_SECURITY_PROTOCOL логин и пароль.
Затем шлюз передаст учетные данные в базовый кластер Kafka, используя существующую систему безопасности и списки управления доступом. Это включено значением по умолчанию GATEWAY_FEATURE_FLAGS_MULTI_TENANCY: false.
Виртуальные кластеры по умолчанию отключены, чтобы ускорить и упростить работу со шлюзом. Если этот параметр отключен, шлюз будет использовать существующие учетные данные клиентского приложения Kafka для подключения к кластеру, позволяя ему проходить через шлюз. Для наиболее эффективного использования Conduktor Gateway можно включить мультиарендность. Отключить эту сквозную передачу и активировать виртуальные кластеры поможет установка переменной среды GATEWAY_FEATURE_FLAGS_MULTI_TENANCY: true. Помимо установки конфигурации GATEWAY_FEATURE_FLAGS_MULTI_TENANCY в значение true, для работы с виртуальными кластерами необходимо создать имя пользователя для подключения к виртуальному кластеру и обновить клиент, чтобы он использовал его при подключении. Например,
conduktor-gateway: image: conduktor/conduktor-gateway:2.1.4 environment: KAFKA_BOOTSTRAP_SERVERS: kafka1:9092,kafka2:9092 KAFKA_SASL_MECHANISM: PLAIN KAFKA_SECURITY_PROTOCOL: SASL_PLAINTEXT KAFKA_SASL_JAAS_CONFIG: org.apache.kafka.common.security.plain.PlainLoginModule required username="admin" password="admin-secret"; GATEWAY_FEATURE_FLAGS_MULTI_TENANCY: true
Conduktor Gateway следует развертывать как отказоустойчивую распределенную службу. Для производственных развертываний рекомендуется использовать внешний балансировщик нагрузки TCP, например, HA-proxy, при этом следует отключить внутреннюю балансировку нагрузки с помощью GATEWAY_FEATURE_FLAGS_INTERNAL_LOAD_BALANCING:false.
Разобравшись с основными принципами работы Conduktor Gateway, далее посмотрим, как это Java-приложение упрощает сквозное шифрование в Kafka.
Шифрование и дешифрация полезной нагрузки в Apache Kafka с Conduktor Gateway
Поскольку Conduktor Gateway полностью соответствует протоколу Kafka, cквозное шифрование с этим шлюзом не требует никаких изменений в клиентских приложениях. При этом обеспечивается полная независимость от языка и даже поддерживается работа с kafka-console-consumer.sh. Таким образом, разработчики контролируют свои данные, не беспокоясь о безопасности, версий и совместимости на всех языках. Инженеры по безопасности могут выявлять, маркировать и применять адаптированные правила шифрования, поскольку все инструменты для этого консолидированы в одном месте. Инженеры по эксплуатации способствуют плавной интеграции усилий разработчиков и команды безопасности, делая сложный механизм операций с данными невидимым для постороннего глаза. Такое эффективное разграничение ролей повышает эффективность каждой команды и приводит к слаженной работе, обеспечивающей безопасную и бесперебойную эксплуатацию Apache Kafka.
Рассмотрим пример, когда инженеры по безопасности определили правила шифрования/расшифровки полей password и visa в топике customers:
docker compose exec kafka-client curl \ --silent \ --request POST "gateway:8888/tenant/tom/feature/encryption" \ --user "superUser:superUser" \ --header 'Content-Type: application/json' \ --data-raw '{ "config": { "topic": "customers", "fields": [ { "fieldName": "password", "keySecretId": "secret-key-password", "algorithm": { "type": "TINK/AES_GCM", "kms": "TINK/KMS_INMEM" } }, { "fieldName": "visa", "keySecretId": "secret-key-visaNumber", "algorithm": { "type": "TINK/AES_GCM", "kms": "TINK/KMS_INMEM" } }] }, "direction": "REQUEST", "apiKeys": "PRODUCE" }' "SUCCESS"
Разработчики потоковых приложений могут создавать программы, используя свои привычные инструменты (Spring Boot, Python, Go и т. д.!), не беспокоясь о каком-либо шифровании. При этом не нужно настраивать что-то дополнительно, включая специальные сериализаторы, Java-агенты, пользовательские библиотеки или перехватчики Kafka. Например, разработчик создает топик customers, для которого инженеры по безопасности ранее определили правила шифрования:
docker compose exec kafka-client \ kafka-topics \ --bootstrap-server gateway:6969 \ --command-config /clientConfig/tom.properties \ --topic customers \ --replication-factor 2 \ --partitions 3 \ --create Created topic customers.
Предположим, следующий JSON-документ отправляется в топик Kafka с настроенным шифрованием:
echo '{ "name": "tom", "username": "tom@conduktor.io", "password": "motorhead", "visa": "#abc123", "address": "Chancery lane, London" }' | jq -c | docker compose exec -T schema-registry \ kafka-json-schema-console-producer \ --bootstrap-server gateway:6969 \ --producer.config /clientConfig/tom.properties \ --topic customers \ --property value.schema='{ "title": "Customer", "type": "object", "properties": { "name": { "type": "string" }, "username": { "type": "string" }, "password": { "type": "string" }, "visa": { "type": "string" }, "address": { "type": "string" } } }'
При обращении к топику данные в полях password и visa будут зашифрованы:
docker compose exec schema-registry \ kafka-json-schema-console-consumer \ --bootstrap-server gateway:6969 \ --consumer.config /clientConfig/tom.properties \ --topic customers \ --from-beginning \ --max-messages 1 | jq . { "name": "tom", "username": "tom@conduktor.io", "password": "AQEzYlKrLZrtxU9jqCJPLggBbx6T+quj2NVsMcJ4zVhcvi77ZaT3wnYleSBYuuqJxQ==", "visa": "AURBygF0lxL3x1Tmq0Nv7gSbX4cyEIqytG+5+7BawKllrQm/T9GS38Ty/E1Jh3M=", "address": "Chancery lane, London" }
Если правила расшифровки данных по какой-то причине неизвестны, Conduktor Gateway позволяет определить, как расшифровывать эти поля при ответе или poll-запросе к Kafka:
docker compose exec kafka-client \ curl \ --silent \ --request POST "gateway:8888/tenant/tom/feature/decryption" \ --user "superUser:superUser" \ --header 'Content-Type: application/json' \ --data-raw '{ "config": { "topic": "customers", "fields": [ { "fieldName": "password", "keySecretId": "secret-key-password", "algorithm": { "type": "TINK/AES_GCM", "kms": "TINK/KMS_INMEM" } }, { "fieldName": "visa", "keySecretId": "secret-key-visaNumber", "algorithm": { "type": "TINK/AES_GCM", "kms": "TINK/KMS_INMEM" } }] }, "direction": "RESPONSE", "apiKeys": "FETCH" }' "SUCCESS"
Таким образом, с точки зрения приложения этапы шифрования/дешифрования абсолютно прозрачны, при этом данные в состоянии покоя шифруются, причем правила шифрования/дешифрования хранятся в одном месте и удобно управляются. Кроме того, Conduktor Gateway поддерживает работу с реестром схем Apache Kafka,что особенно удобно в крупной экосистеме со множеством приложений, которые асинхронно обмениваются данными.
Читайте в нашей новой статье про сквозное шифрования на уровне полей для Apache Kafka Connect с open-source библиотекой Kryptonite.
Администрирование кластера Kafka
Код курса
KAFKA
Ближайшая дата курса
21 октября, 2024
Продолжительность
24 ак.часов
Стоимость обучения
72 000 руб.
Освойте администрирование и эксплуатацию Apache Kafka для потоковой аналитики больших данных на специализированных курсах в нашем лицензированном учебном центре обучения и повышения квалификации для разработчиков, менеджеров, архитекторов, инженеров, администраторов, Data Scientist’ов и аналитиков Big Data в Москве:
- Apache Kafka для инженеров данных
- Администрирование кластера Kafka
- Администрирование Arenadata Streaming Kafka
Источники