当 Debezium 连接器部署到 Kafka Connect 实例时,有时需要对 Connect API 的其他用户隐藏数据库凭据。
让我们回顾一下 MySQL Debezium 连接器的连接器注册请求是什么样的:
{
"name": "inventory-connector",
"config": {
"connector.class": "io.debezium.connector.mysql.MySqlConnector",
"tasks.max": "1",
"database.hostname": "mysql",
"database.port": "3306",
"database.user": "debezium",
"database.password": "dbz",
"database.server.id": "184054",
"database.server.name": "dbserver1",
"database.whitelist": "inventory",
"database.history.kafka.bootstrap.servers": "kafka:9092",
"database.history.kafka.topic": "schema-changes.inventory"
}
} username 和 password 以明文形式传递给 API。更糟糕的是,任何有权访问 Kafka Connect 集群及其 REST API 的人都可以发出 GET 请求,以获取连接器的配置,包括数据库凭据。
curl -s https://:8083/connectors/inventory-connector | jq . {
"name": "inventory-connector",
"config": {
"connector.class": "io.debezium.connector.mysql.MySqlConnector",
"database.user": "debezium",
"database.server.id": "184054",
"tasks.max": "1",
"database.hostname": "mysql",
"database.password": "dbz",
"database.history.kafka.bootstrap.servers": "kafka:9092",
"database.history.kafka.topic": "schema-changes.inventory",
"name": "inventory-connector",
"database.server.name": "dbserver1",
"database.whitelist": "inventory",
"database.port": "3306"
},
"tasks": [
{
"connector": "inventory-connector",
"task": 0
}
],
"type": "source"
} 如果一个 Kafka Connect 集群由多个连接器/团队共享,那么出于安全原因,这种行为可能是不希望的。
为了解决这个问题,Kafka 2.0 中实现了 KIP-297(“连接器配置的秘密外部化”)。
外部化要求至少有一个 org.apache.kafka.common.config.provider.ConfigProvider 接口的实现类。Kafka Connect 提供了参考实现 org.apache.kafka.common.config.provider.FileConfigProvider,该类从文件中读取秘密。可用的配置提供程序在 Kafka Connect 工作节点级别进行配置(例如,在 connect-distributed.properties 中),并在连接器配置中引用。
工作节点配置的示例是这样的:
config.providers=file
config.providers.file.class=org.apache.kafka.common.config.provider.FileConfigProvider 连接器注册请求将如此引用它:
{
"name": "inventory-connector",
"config": {
"connector.class": "io.debezium.connector.mysql.MySqlConnector",
"tasks.max": "1",
"database.hostname": "mysql",
"database.port": "3306",
"database.user": "${file:/secrets/mysql.properties:user}",
"database.password": "${file:/secrets/mysql.properties:password}",
"database.server.id": "184054",
"database.server.name": "dbserver1",
"database.whitelist": "inventory",
"database.history.kafka.bootstrap.servers": "kafka:9092",
"database.history.kafka.topic": "schema-changes.inventory"
}
} 此处,占位符 ${file:/secrets/mysql.properties:user} 表示将使用文件配置提供程序,该提供程序读取属性文件 /secrets/mysql.properties 并从中提取 user 属性。
文件配置提供程序可能是最简单的实现,并且可以预期会出现其他提供程序,这些提供程序将与秘密存储库或身份管理系统集成。不过,值得注意的是,文件配置提供程序在 Kubernetes/OpenShift 部署中是令人满意的,因为 secrets 对象可以作为文件注入到集群 pod 中,从而被其使用。
我们创建了 Debezium 教程示例 的一个版本,该版本演示了外部化秘密的部署。请注意 Docker Compose connect 服务中的两个环境变量:
- CONNECT_CONFIG_PROVIDERS=file
- CONNECT_CONFIG_PROVIDERS_FILE_CLASS=org.apache.kafka.common.config.provider.FileConfigProvider 这些环境变量直接映射到 Kafka Connect 工作节点属性,这是 debezium/connect 映像的功能。
当您发出 REST 调用以获取连接器配置时,您将看到敏感信息已被外部化并对未经授权的用户进行了屏蔽。
curl -s https://:8083/connectors/inventory-connector | jq . {
"name": "inventory-connector",
"config": {
"connector.class": "io.debezium.connector.mysql.MySqlConnector",
"database.user": "${file:/secrets/mysql.properties:user}",
"database.server.id": "184054",
"tasks.max": "1",
"database.hostname": "mysql",
"database.password": "${file:/secrets/mysql.properties:password}",
"database.history.kafka.bootstrap.servers": "kafka:9092",
"database.history.kafka.topic": "schema-changes.inventory",
"name": "inventory-connector",
"database.server.name": "dbserver1",
"database.whitelist": "inventory",
"database.port": "3306"
},
"tasks": [
{
"connector": "inventory-connector",
"task": 0
}
],
"type": "source"
} 有关完整说明,请参阅教程示例的 README。
关于 Debezium
Debezium 是一个开源的分布式平台,可以将现有数据库转变为事件流,使应用程序能够几乎即时地看到并响应数据库中已提交的每个行级更改。Debezium 构建在 Kafka 之上,并提供了 Kafka Connect 兼容的连接器,用于监控特定的数据库管理系统。Debezium 将数据更改的历史记录在 Kafka 日志中,这样您的应用程序可以随时停止和重新启动,并可以轻松地消费在未运行时错过的所有事件,确保所有事件都被正确且完整地处理。Debezium 在 Apache 许可证 2.0 下是 开源 的。