Describe the bug
In Kafka 4.x KRaft mode, the ACL menu is always visible in the UI even when ACL/authorization is not enabled on the broker. This is a regression compared to ZooKeeper-based clusters where the ACL menu is correctly hidden.
Root Cause
The FeatureService detects whether ACL is enabled by calling AdminClient.describeAcls():
// ReactiveAdminClient.java
private static Mono<Boolean> isAuthorizedSecurityEnabled(AdminClient ac, @Nullable Float kafkaVersion) {
return toMono(ac.describeAcls(AclBindingFilter.ANY).values())
.thenReturn(true)
.onErrorReturn(false); // SecurityDisabledException → false
}
In ZooKeeper mode: when authorizer.class.name is not configured on the broker, describeAcls() throws SecurityDisabledException → the feature is not detected → ACL menu is hidden ✅
In KRaft mode: describeAcls() requests are always forwarded via Envelope to the active controller, which has StandardAuthorizer loaded by default (as it stores ACLs in __cluster_metadata). The call succeeds and returns an empty list instead of throwing SecurityDisabledException → the feature is falsely detected as enabled → ACL menu is always shown ❌
This behavior is inherent to the KRaft architecture (KIP-801): the controller always has a StandardAuthorizer regardless of whether the user has explicitly enabled ACL on brokers.
Expected behavior
The ACL menu should be hidden when the Kafka cluster does not have ACL/authorization enabled, regardless of whether the cluster runs in ZooKeeper or KRaft mode.
Steps to reproduce
- Deploy a Kafka 4.x cluster in KRaft mode (split mode:
process.roles=broker for brokers, process.roles=controller for controllers)
- Do NOT configure
authorizer.class.name on the broker side (ACL not enabled)
- Connect Kafbat UI to the broker
- Observe that the ACL menu is visible in the sidebar
Environment
- Kafka: 4.x (KRaft mode)
- Kafbat UI: v1.5.0 (also confirmed on commit afc9c91)
Suggested fix
The isAuthorizedSecurityEnabled() method should not rely solely on whether describeAcls() throws an exception. Possible approaches:
- Check the broker config
authorizer.class.name via describeConfigs() — if empty/blank, ACL is not enabled on the broker side
- Introduce a configuration option in
application.yml (e.g., kafka.clusters[].aclEnabled: true/false) to allow explicit control
- Check if
allow.everyone.if.no.acl.found is set on the broker as an additional signal
Approach 1 seems most aligned with the current auto-detection philosophy. Approach 2 provides a reliable escape hatch for edge cases.
Describe the bug
In Kafka 4.x KRaft mode, the ACL menu is always visible in the UI even when ACL/authorization is not enabled on the broker. This is a regression compared to ZooKeeper-based clusters where the ACL menu is correctly hidden.
Root Cause
The
FeatureServicedetects whether ACL is enabled by callingAdminClient.describeAcls():In ZooKeeper mode: when
authorizer.class.nameis not configured on the broker,describeAcls()throwsSecurityDisabledException→ the feature is not detected → ACL menu is hidden ✅In KRaft mode:
describeAcls()requests are always forwarded via Envelope to the active controller, which hasStandardAuthorizerloaded by default (as it stores ACLs in__cluster_metadata). The call succeeds and returns an empty list instead of throwingSecurityDisabledException→ the feature is falsely detected as enabled → ACL menu is always shown ❌This behavior is inherent to the KRaft architecture (KIP-801): the controller always has a
StandardAuthorizerregardless of whether the user has explicitly enabled ACL on brokers.Expected behavior
The ACL menu should be hidden when the Kafka cluster does not have ACL/authorization enabled, regardless of whether the cluster runs in ZooKeeper or KRaft mode.
Steps to reproduce
process.roles=brokerfor brokers,process.roles=controllerfor controllers)authorizer.class.nameon the broker side (ACL not enabled)Environment
Suggested fix
The
isAuthorizedSecurityEnabled()method should not rely solely on whetherdescribeAcls()throws an exception. Possible approaches:authorizer.class.nameviadescribeConfigs()— if empty/blank, ACL is not enabled on the broker sideapplication.yml(e.g.,kafka.clusters[].aclEnabled: true/false) to allow explicit controlallow.everyone.if.no.acl.foundis set on the broker as an additional signalApproach 1 seems most aligned with the current auto-detection philosophy. Approach 2 provides a reliable escape hatch for edge cases.