Skip to content

Commit d67068c

Browse files
committed
Merged main
2 parents c29091f + bac16cc commit d67068c

File tree

183 files changed

+4341
-403
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

183 files changed

+4341
-403
lines changed

.github/CODEOWNERS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33

44
# BACKEND
5+
gradle/libs.versions.toml @kafbat/backend
56
/build.gradle @kafbat/backend
67
/gradle.properties @kafbat/backend
78
/settings.gradle @kafbat/backend

.github/dependabot.yml

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,20 @@ updates:
77
interval: weekly
88
time: "10:00"
99
timezone: Europe/London
10-
reviewers:
11-
- "kafbat/backend"
1210
open-pull-requests-limit: 10
1311
labels:
1412
- "type/dependencies"
1513
- "scope/backend"
1614
groups:
17-
gradle-dependencies:
15+
spring-boot-dependencies:
16+
patterns:
17+
- "org.springframework.boot:*"
18+
- "io.spring.dependency-management"
19+
# We will handle major upgrades manually
20+
update-types:
21+
- "patch"
22+
- "minor"
23+
other-dependencies:
1824
patterns:
1925
- "*"
2026
update-types:
@@ -27,8 +33,6 @@ updates:
2733
interval: weekly
2834
time: "10:00"
2935
timezone: Europe/London
30-
reviewers:
31-
- "kafbat/backend"
3236
open-pull-requests-limit: 10
3337
ignore:
3438
- dependency-name: "azul/zulu-openjdk-alpine"
@@ -43,8 +47,6 @@ updates:
4347
interval: weekly
4448
time: "10:00"
4549
timezone: Europe/London
46-
reviewers:
47-
- "kafbat/frontend"
4850
open-pull-requests-limit: 10
4951
versioning-strategy: increase-if-necessary
5052
labels:
@@ -64,8 +66,6 @@ updates:
6466
interval: weekly
6567
time: "10:00"
6668
timezone: Europe/London
67-
reviewers:
68-
- "kafbat/devops"
6969
open-pull-requests-limit: 10
7070
labels:
7171
- "type/dependencies"

.github/workflows/cve_checks.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ jobs:
6868
cache-to: type=local,dest=/tmp/.buildx-cache
6969

7070
- name: Run CVE checks
71-
uses: aquasecurity/trivy-action@18f2510ee396bbf400402947b394f2dd8c87dbb0 # infered from @v0.29.0
71+
uses: aquasecurity/trivy-action@dc5a429b52fcf669ce959baa2c2dd26090d2a6c4 # infered from @v0.32.0
7272
with:
7373
image-ref: "ghcr.io/kafbat/kafka-ui:latest"
7474
format: "table"

README.md

Lines changed: 17 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,17 +43,23 @@ We extend our gratitude to Provectus for their past support in groundbreaking wo
4343
![Interface](https://raw.githubusercontent.com/kafbat/kafka-ui/images/overview.gif)
4444

4545
# Features
46-
* **Multi-Cluster Management** — monitor and manage all your clusters in one place
47-
* **Performance Monitoring with Metrics Dashboard** — track key Kafka metrics with a lightweight dashboard
48-
* **View Kafka Brokers** — view topic and partition assignments, controller status
49-
* **View Kafka Topics** — view partition count, replication status, and custom configuration
50-
* **View Consumer Groups** — view per-partition parked offsets, combined and per-partition lag
51-
* **Browse Messages** — browse messages with JSON, plain text, and Avro encoding
52-
* **Dynamic Topic Configuration** — create and configure new topics with dynamic configuration
53-
* **Configurable Authentication**[secure](https://ui.docs.kafbat.io/configuration/authentication) your installation with optional Github/Gitlab/Google OAuth 2.0
54-
* **Custom serialization/deserialization plugins** - [use](https://ui.docs.kafbat.io/configuration/serialization-serde) a ready-to-go serde for your data like AWS Glue or Smile, or code your own!
55-
* **Role based access control** - [manage permissions](https://ui.docs.kafbat.io/configuration/rbac-role-based-access-control) to access the UI with granular precision
56-
* **Data masking** - [obfuscate](https://ui.docs.kafbat.io/configuration/data-masking) sensitive data in topic messages
46+
47+
* **Topic Insights** – View essential topic details including partition count, replication status, and custom configurations.
48+
* **Configuration Wizard** – Set up and configure your Kafka clusters directly through the UI.
49+
* **Multi-Cluster Management** – Monitor and manage all your Kafka clusters in one unified interface.
50+
* **Metrics Dashboard** – Track key Kafka metrics in real time with a streamlined, lightweight dashboard.
51+
* **Kafka Brokers Overview** – Inspect brokers, including partition assignments and controller status.
52+
* **Consumer Group Details** – Analyze parked offsets per partition, and monitor both combined and partition-specific lag.
53+
* **Message Browser** – Explore messages in JSON, plain text, or Avro encoding formats. Live view is supported, enriched with user-defined CEL message filters.
54+
* **Dynamic Topic Management** – Create and configure new topics with flexible, real-time settings.
55+
* **Pluggable Authentication** – Secure your UI using OAuth 2.0 (GitHub, GitLab, Google), LDAP, or basic authentication.
56+
* **Cloud IAM Support** – Integrate with **GCP IAM**, **Azure IAM**, and **AWS IAM** for cloud-native identity and access management.
57+
* **Managed Kafka Service Support** – Full support for **Azure EventHub**, **Google Cloud Managed Service for Apache Kafka**, and **AWS Managed Streaming for Apache Kafka (MSK)**—both server-based and serverless.
58+
* **Custom SerDe Plugin Support** – Use built-in serializers/deserializers like AWS Glue and Smile, or create your own custom plugins.
59+
* **Role-Based Access Control**[Manage granular UI permissions](https://ui.docs.kafbat.io/configuration/rbac-role-based-access-control) with RBAC.
60+
* **Data Masking**[Obfuscate sensitive data](https://ui.docs.kafbat.io/configuration/data-masking) in topic messages to enhance privacy and compliance.
61+
* **MCP Server** - [Model Context Protocol](https://ui.docs.kafbat.io/faq/mcp) Server
62+
5763

5864
## Feature overview
5965

api/Dockerfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# The tag is ignored when a sha is included but the reason to add it are:
22
# 1. Self Documentation: It is difficult to find out what the expected tag is given a sha alone
33
# 2. Helps dependabot during discovery of upgrades
4-
FROM azul/zulu-openjdk-alpine:21.0.6-jre-headless@sha256:75c5cc1ca1429513b56e9cbe3121bce86476cdec18b5b74b6842ab0af4b5a57f
4+
FROM azul/zulu-openjdk-alpine:21.0.8-jre-headless@sha256:9c7b4b7850bd4cdd78f91b369accc5b55beffa9a073b9a2bb94caa42606b9444
55

66
RUN apk add --no-cache \
77
# snappy codec

api/build.gradle

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,18 @@ dependencies {
1414
implementation project(":contract")
1515
implementation project(":serde-api")
1616
implementation libs.spring.starter.webflux
17-
implementation libs.spring.starter.security
17+
implementation(libs.spring.starter.security){
18+
exclude group: 'com.nimbusds', module: 'nimbus-jose-jwt' because("Temporary overwrite to fix CVE-2025-53864. See https://avd.aquasec.com/nvd/2025/cve-2025-53864/")
19+
}
20+
implementation(libs.nimbus.jose.jwt){
21+
because("Fixes CVE-2025-5386. See https://avd.aquasec.com/nvd/2025/cve-2025-53864/")
22+
}
1823
implementation libs.spring.starter.actuator
1924
implementation libs.spring.starter.logging
2025
implementation libs.spring.starter.oauth2.client
2126
implementation libs.spring.security.oauth2.resource.server
2227
implementation libs.spring.boot.actuator
28+
2329
compileOnly libs.spring.boot.devtools
2430

2531
implementation libs.spring.security.ldap
@@ -43,6 +49,7 @@ dependencies {
4349

4450
implementation libs.jackson.databind.nullable
4551
implementation libs.cel
52+
implementation libs.caffeine
4653
antlr libs.antlr
4754
implementation libs.antlr.runtime
4855

@@ -53,15 +60,15 @@ dependencies {
5360
exclude group: 'io.projectreactor.ipc', module: 'reactor-netty'
5461
}
5562

56-
runtimeOnly libs.micrometer.registry.prometheus
63+
runtimeOnly(libs.micrometer.registry.prometheus) {
64+
exclude group: 'com.google.protobuf', module: 'protobuf-java' because("Micrometer uses protobuf-java 4.x, which is incompatible with protobuf-java 3.x used by various dependencies of this project. See https://github.com/prometheus/client_java/issues/1431")
65+
}
5766

5867
// CVE Fixes
5968
implementation libs.apache.commons.compress
6069
implementation libs.okhttp3.logging.intercepter
61-
implementation libs.json.smart
62-
implementation libs.netty.common
63-
implementation libs.netty.handler
64-
implementation libs.spring.context
70+
implementation libs.reactor.netty.http
71+
// CVE Fixes End
6572

6673
implementation libs.modelcontextprotocol.spring.webflux
6774
implementation libs.victools.jsonschema.generator

api/src/main/java/io/kafbat/ui/config/ClustersProperties.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import jakarta.validation.Valid;
66
import jakarta.validation.constraints.NotBlank;
77
import jakarta.validation.constraints.NotNull;
8+
import java.time.Duration;
89
import java.util.ArrayList;
910
import java.util.HashMap;
1011
import java.util.HashSet;
@@ -36,6 +37,8 @@ public class ClustersProperties {
3637

3738
PollingProperties polling = new PollingProperties();
3839

40+
CacheProperties cache = new CacheProperties();
41+
3942
@Data
4043
public static class Cluster {
4144
@NotBlank(message = "field name for for cluster could not be blank")
@@ -183,6 +186,15 @@ public enum LogLevel {
183186
}
184187
}
185188

189+
@Data
190+
@NoArgsConstructor
191+
@AllArgsConstructor
192+
public static class CacheProperties {
193+
boolean enabled = true;
194+
Duration connectCacheExpiry = Duration.ofMinutes(1);
195+
Duration connectClusterCacheExpiry = Duration.ofHours(24);
196+
}
197+
186198
@PostConstruct
187199
public void validateAndSetDefaults() {
188200
if (clusters != null) {

api/src/main/java/io/kafbat/ui/config/auth/RoleBasedAccessControlProperties.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package io.kafbat.ui.config.auth;
22

3+
import io.kafbat.ui.model.rbac.DefaultRole;
34
import io.kafbat.ui.model.rbac.Role;
5+
import jakarta.annotation.Nullable;
46
import jakarta.annotation.PostConstruct;
57
import java.util.ArrayList;
68
import java.util.List;
@@ -11,13 +13,26 @@ public class RoleBasedAccessControlProperties {
1113

1214
private final List<Role> roles = new ArrayList<>();
1315

16+
private DefaultRole defaultRole;
17+
1418
@PostConstruct
1519
public void init() {
1620
roles.forEach(Role::validate);
21+
if (defaultRole != null) {
22+
defaultRole.validate();
23+
}
1724
}
1825

1926
public List<Role> getRoles() {
2027
return roles;
2128
}
2229

30+
public void setDefaultRole(DefaultRole defaultRole) {
31+
this.defaultRole = defaultRole;
32+
}
33+
34+
@Nullable
35+
public DefaultRole getDefaultRole() {
36+
return defaultRole;
37+
}
2338
}

api/src/main/java/io/kafbat/ui/controller/AclsController.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ public Mono<ResponseEntity<Flux<KafkaAclDTO>>> listAcls(String clusterName,
6868
KafkaAclResourceTypeDTO resourceTypeDto,
6969
String resourceName,
7070
KafkaAclNamePatternTypeDTO namePatternTypeDto,
71+
String search,
7172
ServerWebExchange exchange) {
7273
AccessContext context = AccessContext.builder()
7374
.cluster(clusterName)
@@ -88,7 +89,7 @@ public Mono<ResponseEntity<Flux<KafkaAclDTO>>> listAcls(String clusterName,
8889
return validateAccess(context).then(
8990
Mono.just(
9091
ResponseEntity.ok(
91-
aclsService.listAcls(getCluster(clusterName), filter)
92+
aclsService.listAcls(getCluster(clusterName), filter, search)
9293
.map(ClusterMapper::toKafkaAclDto)))
9394
).doOnEach(sig -> audit(context, sig));
9495
}

api/src/main/java/io/kafbat/ui/controller/AuthorizationController.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,12 @@
33
import io.kafbat.ui.api.AuthorizationApi;
44
import io.kafbat.ui.model.ActionDTO;
55
import io.kafbat.ui.model.AuthenticationInfoDTO;
6+
import io.kafbat.ui.model.KafkaCluster;
67
import io.kafbat.ui.model.ResourceTypeDTO;
78
import io.kafbat.ui.model.UserInfoDTO;
89
import io.kafbat.ui.model.UserPermissionDTO;
910
import io.kafbat.ui.model.rbac.Permission;
11+
import io.kafbat.ui.service.ClustersStorage;
1012
import io.kafbat.ui.service.rbac.AccessControlService;
1113
import java.security.Principal;
1214
import java.util.Collection;
@@ -29,8 +31,15 @@
2931
public class AuthorizationController implements AuthorizationApi {
3032

3133
private final AccessControlService accessControlService;
34+
private final ClustersStorage clustersStorage;
3235

3336
public Mono<ResponseEntity<AuthenticationInfoDTO>> getUserAuthInfo(ServerWebExchange exchange) {
37+
List<UserPermissionDTO> defaultRolePermissions = accessControlService.getDefaultRole() != null
38+
? mapPermissions(
39+
accessControlService.getDefaultRole().getPermissions(),
40+
clustersStorage.getKafkaClusters().stream().map(KafkaCluster::getName).toList())
41+
: Collections.emptyList();
42+
3443
Mono<List<UserPermissionDTO>> permissions = AccessControlService.getUser()
3544
.map(user -> accessControlService.getRoles()
3645
.stream()
@@ -39,6 +48,8 @@ public Mono<ResponseEntity<AuthenticationInfoDTO>> getUserAuthInfo(ServerWebExch
3948
.flatMap(Collection::stream)
4049
.toList()
4150
)
51+
// if no roles are found, return default role permissions
52+
.map(userPermissions -> userPermissions.isEmpty() ? defaultRolePermissions : userPermissions)
4253
.switchIfEmpty(Mono.just(Collections.emptyList()));
4354

4455
Mono<String> userName = ReactiveSecurityContextHolder.getContext()

0 commit comments

Comments
 (0)