Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
127 changes: 127 additions & 0 deletions _posts/2026-09-02-release-0_24_0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
---
layout: post
title: "Kroxylicious release 0.24.0"
date: 2026-09-02 00:00:00 +0000
author: "Sam Barker"
author_url: "https://github.com/sambarker"
# noinspection YAMLSchemaValidation
categories: blog kroxylicious-proxy releases
tags: [ "releases", "kroxylicious-proxy" ]
---

# Kroxylicious 0.24.0: SASL Termination & API Evolution for 1.0

Kroxylicious 0.24.0 has snapped 🐊 into existence!

As a maintainer group, introducing breaking API changes is something we are genuinely disappointed to do. We never take breaking changes lightly, but after careful consideration, we determined this shift was unavoidable to secure the long-term stability of the project.

Alongside this API update, 0.24.0 also delivers a major new feature we're excited to share: **SASL Termination**.

> **Release Highlights at a Glance:**
> * **New Feature:** SASL Termination (OAUTHBEARER, SCRAM-SHA-256/512) directly at the proxy layer.
> * **API Change:** Relocated core API types from `org.apache.kafka.*` to `io.kroxylicious.kafka.*`.
> * **Automated Upgrade:** OpenRewrite recipes available to migrate your codebase automatically.
> * **Community Feedback:** Active discussion open on upcoming design proposals.

---

### Introducing SASL Termination

Kroxylicious 0.24.0 adds built-in **SASL Termination**, allowing the proxy to authenticate incoming client connections directly rather than forwarding authentication handshakes to upstream Kafka brokers.

**Why SASL Termination?**

Filters that rely on client identity—such as custom authorization or dynamic routing—need to know *who* is making a request. However, challenge-response mechanisms like SCRAM generate unique per-server nonces, making passthrough inspection impossible.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This paragraph is incorrect, and describes the wrong thing.

Firstly, SASL Inspection does support SCRAM. The identity goes through the SCRAM mechanism in plain text, so SaslInspection can (and does) sniff it. io.kroxylicious.it.SaslInspectionIT#shouldAuthenticateWhenSameMechanism_SCRAM_SHA_256 proves it works.

Secondly, the need for SASL Termination is really routers with multiple upstreams. In this use case, SASL inspection doesn't really work:

  1. For SASL PLAIN/OAUTH, it works providing the password db or oauth configs are the same.
  2. For SCRAM, it falls flat on its face. There would be two server nonces.

There are use-cases for SASL Termination in a single upstream use-cases - where your client side SASL authn requirements differ from your server side's authn requirements. Say interfaces clients that use SASL with a Cluster that can only use TLS client auth.


By terminating SASL at the proxy level:

* **Verified Client Identity:** Kroxylicious authenticates the client directly and exposes a verified `ClientSaslContext` down the filter chain.
* **Supported Mechanisms:** 0.24.0 ships with support for **OAUTHBEARER**, **SCRAM-SHA-256**, and **SCRAM-SHA-512**.
* **Credential Offloading:** It lays the groundwork for authentication swapping, letting client-facing security policies differ from upstream cluster configurations.

To explore the architecture and design behind this feature, take a look at [Design Proposal 124](https://github.com/kroxylicious/design/blob/main/proposals/124-sasl-termination.md).

---

### The API Shift: Decoupling for 1.0

In previous releases, our API JAR relied on Apache Kafka’s `kafka-clients` JAR. In Kafka 4.3, upstream maintainers restructured what they consider non-public APIs into internal packages to make that distinction clearer.

Because our API relied on those types, this upstream refactoring automatically introduced a breaking change for us. Rather than risk a trickle of unpredictable breaking changes in future upstream releases, we chose to take control now with a single, deliberate update. Our goal for Kroxylicious 1.0 is to offer a stable, predictable API completely under our control.

**What Changed?**

We relocated a minimal subset of classes previously imported from `org.apache.kafka.*` into our own namespace: `io.kroxylicious.kafka.*`.

We moved **only** the specific classes required to keep our API functional. If you encounter any gaps or missing classes in your custom filters after upgrading, please [open an issue on GitHub](https://github.com/kroxylicious/kroxylicious/issues) so we can address it.

---

### Automated Migration with OpenRewrite

To make updating your codebase as smooth as possible, we are providing automated migration recipes powered by **OpenRewrite**. While we make it sound like a simple `x -> y` transition, a bash one-liner isn't going to cut it (no matter how good your Perl is—yes, I'm looking at you, Claude).

**Maven**

```bash
mvn org.openrewrite.maven:rewrite-maven-plugin:run \
-Drewrite.recipeArtifactCoordinates=io.kroxylicious:kroxylicious-rewrite:0.24.0 \
-Drewrite.activeRecipes=io.kroxylicious.migrations.rewrite.v0_24.MigrateTo0_24
```

**Gradle**

```groovy
plugins {
id("org.openrewrite.rewrite") version "6.x.x"
}

rewrite {
activeRecipe("io.kroxylicious.migrations.rewrite.v0_24.MigrateTo0_24")
}
```

```bash
gradle rewriteRun
```

Further details around running these migrations can be found on (GitHub)[https://github.com/kroxylicious/kroxylicious/tree/main/kroxylicious-proxy-core/kroxylicious-migrations].

---

### Design Proposals & Shaping the Future

We explored the trade-offs and options for this migration in [Design Proposal 116](https://github.com/kroxylicious/design/blob/main/proposals/116-kafka-api-migration.md).

If you read Proposal 116, you will notice it originally suggested a simple `sed` script for migration. Design proposals are point-in-time snapshots of our thinking, not unchangeable commandments. As we got into implementation, OpenRewrite offered a far superior, AST-aware refactoring experience.

This shift highlights the importance of our proposal process. If API stability or new proxy features impact how you use Kroxylicious, we strongly encourage you to review and participate in active design proposals on the [Kroxylicious Design Repository](https://github.com/kroxylicious/design). Your feedback helps shape the project as we head toward 1.0.

### Community Contributions

This release included commits from:
- [AdityaThakur1998](https://github.com/AdityaThakur1998)
- [DragonFSKY](https://github.com/DragonFSKY)
- [jjj-n](https://github.com/jjj-n)
- [k-wall](https://github.com/k-wall)
- [lntutor](https://github.com/lntutor)
- [lukman48](https://github.com/lukman48)
- [matheusandre1](https://github.com/matheusandre1)
- [oozan](https://github.com/oozan)
- [piotrpdev](https://github.com/piotrpdev)
- [RafaelReia](https://github.com/RafaelReia)
- [robobario](https://github.com/robobario)
- [SamBarker](https://github.com/SamBarker)
- [tamikikoz](https://github.com/tamikikoz)
- [TheDarkniteFalls](https://github.com/TheDarkniteFalls)
- [tombentley](https://github.com/tombentley)

Thank you all, your hard work is massively appreciated by the PMC!

### Artefacts

Download binary distributions and container images from the [download](https://kroxylicious.io/download/0.23.0/) page.

### Feedback

Drop by and say hello on [Slack](https://kroxylicious.slack.com), [GitHub](https://github.com/kroxylicious/kroxylicious/issues), or [bsky](https://bsky.app/profile/kroxylicious.io). You can also join us in person at a [community call]({% link join-us/community-call/index.md %}).
Loading