Apache Kafka API AdminClient Scram账户的操作(增删改查)

本文详细介绍了如何使用Kafka API 2.8.0版本中的alterUserScramCredentials方法创建、删除及查询SCRAM账户。通过具体示例代码展示了创建账户所需参数及其构造过程,并提供了账户信息查询的方法。

前言

很久没有更新Kafka API相关的文档了,因为笔者工作变动Kafka这部分内容在工作中接触的就相对于之前少了一些。但架不住kafka官方还是一如既往的勤奋,官方操作Scram账户的创建与删除这部分已经更新了好久了,这次也算是填坑吧,主要就是针对alterUserScramCredentials方法做一个功能说明和demo。给网上少之又少的Kafka API中文使用教程做个增补,本次基于Kafka API 2.8.0,同时适用于2.7.0版本,但是该版本API并不是很完善,创建的账户可能会有无法读写Topic的问题。如果你使用的Kafka还没有升级到这么高的版本,请参考【Apache Kafka API AdminClient Scram账户的创建与删除】这篇博客,其是针对2.7.0及其以下的Scram账户操作。更多内容请点击【Apache Kafka API AdminClient 目录】

操作Scram账户的方法

首先我们先看官方文档中对于操作Scram账户是怎么说的,查询官方的文档只提供了一个方法:

Modifier and TypeMethodDescription
default AlterUserScramCredentialsResultalterUserScramCredentials(List< UserScramCredentialAlteration> alterations)Alter SASL/SCRAM credentials for the given users.
AlterUserScramCredentialsResultalterUserScramCredentials(List< UserScramCredentialAlteration> alterations, AlterUserScramCredentialsOptions options)Alter SASL/SCRAM credentials.

根据官方给的文档描述,上表中第二个方法是对第一个方法的扩展,所以这里不做讨论。我们主要集中于alterUserScramCredentials()方法的使用上。根据描述,该方法只接受一个泛型为UserScramCredentialAlteration 的List参数,接着看下UserScramCredentialAlteration是什么样子。

Field Summary

Modifier and TypeFieldDescription
protectedString user

Constructor Summary

ModifierConstructorDescription
protectedUserScramCredentialAlteration(String user)

Method Summary

Modifier and TypeMethodDescription
Stringuser()

根据官方文档描述里面只有一个String类型的user字段,显然不可能只根据这一个字段构造一个能够使用的账户。其实UserScramCredentialAlteration是一个抽象的类,它还有两个子类UserScramCredentialDeletionUserScramCredentialUpsertion。从名字就可以看出来,创建大概是UserScramCredentialUpsertion,删除则应该是UserScramCredentialDeletion。所以我们传入的List中的泛型,也就是这两个类的具体实现了。

创建一个Scram账户

UserScramCredentialUpsertion

官方文档对UserScramCredentialUpsertion类的解释是:

A request to update/insert a SASL/SCRAM credential for a user.

看来这个类不仅仅能做创建,而且也能做更新,大方向是没问题了。首先我们还是看下创建UserScramCredentialUpsertion这个类要怎么构造:

ConstructorDescription
UserScramCredentialUpsertion(String user, ScramCredentialInfo credentialInfo, byte[] password)Constructor that generates a random salt
UserScramCredentialUpsertion(String user, ScramCredentialInfo credentialInfo, byte[] password, byte[] salt)Constructor that accepts an explicit salt
UserScramCredentialUpsertion(String user, ScramCredentialInfo credentialInfo, String password)Constructor that generates a random salt

从上述表格中可以看到这个类有三个构造方法,构建这个类除了需要父类提供的user名字以外,还需要另外两个参数ScramCredentialInfopassword。可以看到其实最后一个构造方法passwordString,这个可以说是最方便的了。第二个中为什么还要有一个salt参数,笔者深入代码只发现了一句话new Field("salt", Type.COMPACT_BYTES, "A random salt generated by the client.")。可能是给用户自定义什么功能用的,但是kafka自己也会生成这个东西,由于官方文档和源码都没有找到更多的解释,我们暂且忽略,如果哪位笔者知道这点,也行评论区不吝赐教。

ScramCredentialInfo

那么我们就转向ScramCredentialInfo这个类的构造:

ConstructorDescription
ScramCredentialInfo(ScramMechanism mechanism, int iterations)

可以看到这个类的构建就比较简单明了,两个参数一个是ScramMechanism也就是Scram认证机制,这是一个enum类型内置SCRAM_SHA_256SCRAM_SHA_512UNKNOWN三个类型,UNKNOWN类型会在创建时报异常。另外一个iterations是循环次数the number of iterations used when creating the credential,代表你要创建的账户个数,也就是List.size()吧。

示例代码
public void createAccount(String name, String pwd, String salt) throws ExecutionException, InterruptedException {
    //创建User列表
    List<UserScramCredentialAlteration> alterations = new ArrayList<>();
    //构造Scram认证机制信息,这里笔者选择了SCRAM_SHA_512,大家也可以选择 ScramMechanism.SCRAM_SHA_256
    //alterations.size()此时为0,或许会报错,可以试下传入数字构造,比如下面添加了一个认证信息,那么这里传入数字1。
    // ScramCredentialInfo info=new ScramCredentialInfo(ScramMechanism.SCRAM_SHA_512, alterations.size()); //这里时间久远,忘记当时写例子的场景了
    ScramCredentialInfo info=new ScramCredentialInfo(ScramMechanism.SCRAM_SHA_512, 10000);
    //三个UserScramCredentialAlteration构造方法,三选一笔者选了一个最简单的
    //UserScramCredentialAlteration userScramCredentialAdd=new UserScramCredentialUpsertion(name,info,pwd.getBytes());
    //UserScramCredentialAlteration userScramCredentialAdd=new UserScramCredentialUpsertion(name,info,pwd.getBytes(),salt.getBytes());
    UserScramCredentialAlteration userScramCredentialAdd=new UserScramCredentialUpsertion(name,info,pwd);
    //添加认证信息到列表
    alterations.add(userScramCredentialAdd);
    //执行方法,并拿到返回结果
    AlterUserScramCredentialsResult result = adminClient.alterUserScramCredentials(alterations);
    //阻塞等待结果完成
    result.all().get();
}

通过官网给出的解释,我们知道对账户的更新操作也是使用UserScramCredentialUpsertion类进行,因此只要保证user name一致即可对相应的user中的内容进行更新,这点大家自己验证吧。

删除一个Scram账户

删除账户用的则是子类UserScramCredentialDeletion,一样我们先看它的构造方法:

ConstructorDescription
UserScramCredentialDeletion(String user, ScramMechanism mechanism)

果然删除就不会像增加或者修改一样墨迹,只有一个构造方法可用,参数上面也都说过了,直接上示例代码:

public void deleteAccount(String name) throws ExecutionException, InterruptedException {
    //创建删除列表
    List<UserScramCredentialAlteration> alterations = new ArrayList<>();
    //构建删除用的UserScramCredentialAlteration
    UserScramCredentialAlteration userScramCredentialDel=new UserScramCredentialDeletion(name,ScramMechanism.SCRAM_SHA_512);
    //添加认证信息到列表
    alterations.add(userScramCredentialDel);
    //执行方法,并拿到返回结果
    AlterUserScramCredentialsResult result = adminClient.alterUserScramCredentials(alterations);
    //阻塞等待结果完成
    result.all().get();
}

查询Scram账户信息

说完对Scram账户的增删改以后,剩下的自然就剩下查询了,官方也提供了一个方法用于查询:

Modifier and TypeMethodDescription
default DescribeUserScramCredentialsResultdescribeUserScramCredentials()Describe all SASL/SCRAM credentials.
default DescribeUserScramCredentialsResultdescribeUserScramCredentials(List< String> users)Describe SASL/SCRAM credentials for the given users.
DescribeUserScramCredentialsResultdescribeUserScramCredentials(List< String> users, DescribeUserScramCredentialsOptions options)Describe SASL/SCRAM credentials.

可以看到大体上也是只有一个方法describeUserScramCredentials(),只不过对这个方法做了一个重载,用于指定查询某些用户的信息,参数很简单不用多说,直接上示例代码:

public void describeAccount() throws ExecutionException, InterruptedException {
	//***************************************查询所有用户信息*****************************************************
    //查询所有的账户,这也是默认方法
    DescribeUserScramCredentialsResult result = adminClient.describeUserScramCredentials();
    //执行方法,并拿到返回结果
    Map<String, UserScramCredentialsDescription> future = result.all().get();
    //输出
    future.forEach((name,info)-> System.out.println("[ScramUserName:"+name+"]:[ScramUserInfo:"+info.toString()+"]"));

    //***************************************这里是分割线*****************************************************
    //***************************************查询指定的用户信息*****************************************************
    //构造指定的用户列表
    List<String> userScramList=new ArrayList<>();
    //添加两个用户
    userScramList.add("user1");
    userScramList.add("user2");
    //传入特定用户列表执行方法,并拿到返回结果
    DescribeUserScramCredentialsResult targetResult = adminClient.describeUserScramCredentials(userScramList);
    //执行方法,并拿到返回结果
    Map<String, UserScramCredentialsDescription> targetFuture = targetResult.all().get();
    //输出
    targetFuture.forEach((name,info)-> System.out.println("[ScramUserName:"+name+"]:[ScramUserInfo:"+info.toString()+"]"));
}

结语

这一篇终于把之前的坑填上了,自从笔者不再需要对Kafka平台进行维护以后,Kafka的版本也发生了好多巨大的更新,一个最明显的变化就是Kafka的去zookeeper操作。笔者之前操纵2.7.0的时候,Kafka官方还是警告2.8版本最好不要用于生产环境,而今天官方的态度已经有了一个模糊的转变,可见Kafka已经大体上完成了对Zookeeper的解耦工作。由于笔者工作的变动不再管理Kafka相关的平台内容,所以这部分内容就会更新的比较慢,毕竟懒癌晚期的笔者能补上这个坑已经算是祖坟冒烟了。不过好在笔者已经够把大多数关键的Kafka管理操作的API使用方法更新完毕,希望这些内容对网上寥寥无几的Kafka文档有所补充,也希望这些博客能够帮助到那些正在管理Kafka平台的小伙伴们,希望以后还有机会对更新的版本进行更深一步的探究吧。

<think>好的,我现在需要帮助用户解决他们在执行Kafka命令时遇到的错误。用户运行了`./kafka-topics.sh --list`并指定了bootstrap-server和command-config,结果抛出了多个异常,主要是“Failed to create new KafkaAdminClient”和“JAAS config entry not terminated by semi-colon”。我需要逐步分析这个问题。 首先,用户提供的错误堆栈中有提到`IllegalArgumentException: JAAS config entry not terminated by semi-colon`。这表明问题与JAAS配置文件的格式有关。JAAS文件中的每个配置块需要用分号结束,如果用户没有正确添加分号,就会导致这个错误。 接下来,我需要回顾用户之前的问题,他们之前遇到了SASL认证的问题,现在可能是在配置auth.conf时遗漏了分号。用户可能在auth.conf文件中写入了类似`username="user" password="pass"`的内容,但忘记了在最后加上分号,导致解析失败。 然后,我需要考虑其他可能的原因。比如,auth.conf文件中的属性是否正确,比如`sasl.mechanism`、`security.protocol`等是否配置正确。此外,还要检查Kafka的版本兼容性,以及网络连接是否正常,但根据错误信息,更可能的是JAAS配置的问题。 然后,我需要给出具体的解决步骤。首先检查auth.conf的格式,确保每个LoginModule的配置以分号结尾。例如,正确的配置应该是: sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required username="admin" password="admin-password"; 用户可能漏掉了最后的那个分号。此外,还要检查是否有多个配置项没有正确分隔,或者使用了错误的语法,比如换行符未转义。 另外,用户可能在命令行参数中指定了--command-config,这个文件应该包含必要的安全配置,比如security.protocol、sasl.mechanism等。需要确认这些参数是否与Broker的配置一致,比如Broker使用SASL_SSL,而客户端配置了SASL_PLAINTEXT,这也会导致连接失败。 另外,可能还需要检查auth.conf文件的路径是否正确,是否有权限读取该文件。如果文件不存在或权限不足,也会导致错误,但根据错误信息,这里更可能的是JAAS语法问题。 最后,建议用户使用kafka-console工具测试连接,以确认配置是否正确。同时,提醒用户检查Kafka客户端和Broker的版本是否兼容,并查看更详细的日志来定位问题。</think>根据错误信息,该问题核心原因是 **JAAS配置文件格式错误**,导致Kafka客户端无法正确解析认证配置。以下是逐步分析与解决方案: --- ### **1. 错误原因分析** - **关键错误**:`java.lang.IllegalArgumentException: JAAS config entry not terminated by semi-colon` 表明JAAS配置文件中某个配置块未以分号(`;`)结尾,违反了JAAS语法规则。 - **深层原因**: 在`auth.conf`文件中,`sasl.jaas.config`属性的值未正确闭合(缺少分号),导致Kafka客户端解析失败,进而无法创建`KafkaAdminClient`。 --- ### **2. 解决方案步骤** #### **步骤1:检查`auth.conf`的JAAS配置格式** - **正确示例**(注意结尾分号): ```properties # auth.conf security.protocol=SASL_PLAINTEXT # 或 SASL_SSL sasl.mechanism=PLAIN sasl.jaas.config=org.apache.kafka.common.security.plain.PlainLoginModule required \ username="your_username" \ password="your_password"; # 必须以此分号结尾! ``` - **常见错误**: - 漏写分号:`password="your_password"`(缺少`;`)。 - 分号位置错误:将分号写在反斜杠(`\`)前。 #### **步骤2:验证配置语法** - **规则**: - 若配置值跨多行,需用反斜杠(`\`)连接。 - **必须确保最后一个参数以分号结尾**。 - **错误示例修正**: ```properties sasl.jaas.config=org.apache.kafka.common.security.scram.ScramLoginModule required \ username="user" \ password="pass"; # 分号必须在此行末尾 ``` #### **步骤3:检查`auth.conf`其他配置项** 确保以下参数与Broker配置一致: ```properties # 认证协议类型(需与Broker的listeners协议匹配) security.protocol=SASL_PLAINTEXT # 或 SASL_SSL # SASL机制类型(需与Broker的sasl.enabled.mechanisms一致) sasl.mechanism=PLAIN # 或 SCRAM-SHA-256等 ``` #### **步骤4:测试连接** 使用简化的命令验证配置是否生效: ```bash # 直接指定JAAS配置(临时测试) ./kafka-topics.sh --list --bootstrap-server 10.3.5.74:9092 \ --command-config /root/auth.conf ``` #### **步骤5:启用DEBUG日志(可选)** 在`auth.conf`中添加日志配置,定位更详细的错误: ```properties # auth.conf debug=all ``` --- ### **3. 补充说明** #### **(1) JAAS配置文件格式要点** - 分号是JAAS配置的终止符,缺失会导致整个配置解析失败。 - 若配置值包含特殊字符(如`;`或`"`),需使用反斜杠转义。 #### **(2) 其他可能原因** - **文件权限问题**:确保`/root/auth.conf`对执行命令的用户可读。 - **Broker协议不匹配**:若Broker监听的是`SASL_SSL`,客户端需配置`security.protocol=SASL_SSL`。 --- ### **4. 验证工具** 使用`kafka-console-producer`快速测试认证配置: ```bash echo "test-message" | ./kafka-console-producer.sh \ --bootstrap-server 10.3.5.74:9092 \ --topic test_topic \ --producer.config /root/auth.conf ``` --- 通过修正JAAS配置的语法错误,即可解决`KafkaAdminClient`初始化失败的问题。若仍存在问题,请提供`auth.conf`的完整内容(隐藏敏感信息)以进一步排查。
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值