enable acl switch

This commit is contained in:
许晓东
2021-09-08 16:45:59 +08:00
parent 6cd87643c3
commit 8a76f226a1
9 changed files with 137 additions and 13 deletions

View File

@@ -1,13 +1,23 @@
# kafka可视化管理平台
目前支持aclSASL认证机制及受权管理操作
实现spring boot + scala + vue + kafka
## 功能支持
* 基于SASL_SCRAM认证授权管理
* Topic管理
* 消费组管理
* 运维
## 技术栈
* spring boot
* java、scala
* kafka
* h2
* vue
## kafka版本
* kafka 2.8.0
* 当前使用的kafka 2.8.0
# 打包、部署
## 打包
环境要求
* maven 3+
* jdk 8
* git
```
git clone https://github.com/xxd763795151/kafka-console-ui.git
cd kafka-console-ui

View File

@@ -31,6 +31,8 @@ public class KafkaConfig {
private String zookeeperAddr;
private boolean enableAcl;
public String getBootstrapServer() {
return bootstrapServer;
}
@@ -102,4 +104,12 @@ public class KafkaConfig {
public void setZookeeperAddr(String zookeeperAddr) {
this.zookeeperAddr = zookeeperAddr;
}
public boolean isEnableAcl() {
return enableAcl;
}
public void setEnableAcl(boolean enableAcl) {
this.enableAcl = enableAcl;
}
}

View File

@@ -0,0 +1,33 @@
package com.xuxd.kafka.console.controller;
import com.xuxd.kafka.console.beans.ResponseData;
import com.xuxd.kafka.console.config.KafkaConfig;
import com.xuxd.kafka.console.utils.ConvertUtil;
import java.util.Map;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* kafka-console-ui.
*
* @author xuxd
* @date 2021-09-08 16:08:22
**/
@RestController
@RequestMapping("/config")
public class ConfigController {
private final KafkaConfig config;
private final Map<String, Object> configMap;
public ConfigController(KafkaConfig config) {
this.config = config;
this.configMap = ConvertUtil.toMap(config);
}
@GetMapping
public Object getConfig() {
return ResponseData.create().data(configMap).success();
}
}

View File

@@ -208,7 +208,7 @@ public class AclServiceImpl implements AclService, SmartInitializingSingleton {
}
@Override public void afterSingletonsInstantiated() {
if (kafkaConfig.isAdminCreate()) {
if (kafkaConfig.isEnableAcl() && kafkaConfig.isAdminCreate()) {
log.info("Start create admin user, username: {}, password: {}", kafkaConfig.getAdminUsername(), kafkaConfig.getAdminPassword());
boolean done = configConsole.addOrUpdateUserWithZK(kafkaConfig.getAdminUsername(), kafkaConfig.getAdminPassword());
if (!done) {

View File

@@ -0,0 +1,40 @@
package com.xuxd.kafka.console.utils;
import com.google.common.base.Preconditions;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.ClassUtils;
/**
* kafka-console-ui.
*
* @author xuxd
* @date 2021-09-08 16:21:43
**/
@Slf4j
public class ConvertUtil {
public static Map<String, Object> toMap(Object src) {
Preconditions.checkNotNull(src);
Map<String, Object> res = new HashMap<>();
for (Class<?> clz = src.getClass(); clz != Object.class; clz = clz.getSuperclass()) {
if (ClassUtils.isCglibProxyClass(clz)) {
continue;
}
Arrays.stream(clz.getDeclaredFields()).forEach(f -> {
try {
boolean accessible = f.isAccessible();
f.setAccessible(true);
res.put(f.getName(), f.get(src));
f.setAccessible(accessible);
} catch (IllegalAccessException ignore) {
log.error("filed: " + f.getName(), ignore);
}
});
}
return res;
}
}

View File

@@ -9,6 +9,8 @@ kafka:
# kafka broker地址多个以逗号分隔
bootstrap-server: 'localhost:9092'
request-timeout-ms: 60000
# 服务端是否启用acl如果不启用下面的几项都忽略即可
enable-acl: true
security-protocol: SASL_PLAINTEXT
sasl-mechanism: SCRAM-SHA-256
# 超级管理员用户名在broker上已经配置为超级管理员

View File

@@ -41,9 +41,11 @@ class KafkaConsole(config: KafkaConfig) {
val props: Properties = new Properties();
props.put(AdminClientConfig.BOOTSTRAP_SERVERS_CONFIG, config.getBootstrapServer)
props.put(AdminClientConfig.REQUEST_TIMEOUT_MS_CONFIG, config.getRequestTimeoutMs())
props.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, config.getSecurityProtocol())
props.put(SaslConfigs.SASL_MECHANISM, config.getSaslMechanism())
props.put(SaslConfigs.SASL_JAAS_CONFIG, config.getSaslJaasConfig())
if (config.isEnableAcl) {
props.put(CommonClientConfigs.SECURITY_PROTOCOL_CONFIG, config.getSecurityProtocol())
props.put(SaslConfigs.SASL_MECHANISM, config.getSaslMechanism())
props.put(SaslConfigs.SASL_JAAS_CONFIG, config.getSaslJaasConfig())
}
Admin.create(props)
}

View File

@@ -2,16 +2,39 @@
<div id="app">
<div id="nav">
<router-link to="/" class="pad-l-r">主页</router-link>
|<router-link to="/acl" class="pad-l-r">Acl</router-link>
<!-- |<router-link-->
<!-- to="/topic"-->
<!-- class="pad-l-r"-->
<!-- >主题</router-link-->
<!-- >-->
<span>|</span
><router-link to="/topic" class="pad-l-r">Topic</router-link>
<span>|</span
><router-link to="/group" class="pad-l-r">消费组</router-link>
<span v-show="config.enableAcl">|</span
><router-link to="/acl" class="pad-l-r" v-show="config.enableAcl"
>Acl</router-link
>
<span>|</span><router-link to="/op" class="pad-l-r">运维</router-link>
</div>
<router-view class="content" />
</div>
</template>
<script>
import { KafkaAclApi } from "@/utils/api";
import request from "@/utils/request";
export default {
data() {
return {
config: {},
};
},
created() {
request({
url: KafkaAclApi.getConfig.url,
method: KafkaAclApi.getConfig.method,
}).then((res) => {
this.config = res.data;
});
},
};
</script>
<style>
#app {

View File

@@ -47,4 +47,8 @@ export const KafkaAclApi = {
url: "/acl",
method: "delete",
},
getConfig: {
url: "/config",
method: "get",
},
};