Skip to content

rpk: add OAUTHBEARER SASL mechanism support#30169

Draft
david-yu wants to merge 6 commits intodevfrom
rpk-oauthbearer-support
Draft

rpk: add OAUTHBEARER SASL mechanism support#30169
david-yu wants to merge 6 commits intodevfrom
rpk-oauthbearer-support

Conversation

@david-yu
Copy link
Copy Markdown

@david-yu david-yu commented Apr 15, 2026

Summary

  • Add OAUTHBEARER as a supported SASL mechanism for rpk, enabling OIDC-based authentication with Kafka brokers
  • The token is passed via --password (supports both raw token and token:<TOKEN> format)
  • OAUTHBEARER support added to Kafka client, admin API, and schema registry clients
  • Unit tests for token extraction, admin API auth, and Kafka client error paths
  • Updated -X help / -X list and profile docs to document all four SASL mechanisms

Ref: https://docs.redpanda.com/current/manage/security/authentication/#oidc
Ref: https://github.com/david-yu/redpanda-operator-mtls-oidc-listeners

Usage Examples

Obtain an OIDC token

# Example: get a token from Dex via password grant
export OIDC_TOKEN=$(curl -s -X POST "https://dex.example.com/dex/token" \
  -d "grant_type=password&username=user@example.com&password=password" \
  -d "client_id=redpanda&client_secret=redpanda-secret&scope=openid email" \
  | jq -r '.access_token')

Topic operations

# List topics
rpk topic list \
  --brokers localhost:31094 \
  --tls-enabled \
  --tls-truststore certs/ca.crt \
  --sasl-mechanism OAUTHBEARER \
  --password "token:${OIDC_TOKEN}"

# Create a topic
rpk topic create oidc-test \
  --brokers localhost:31094 \
  --tls-enabled \
  --tls-truststore certs/ca.crt \
  --sasl-mechanism OAUTHBEARER \
  --password "token:${OIDC_TOKEN}"

# Produce messages
echo "hello from OIDC client" | rpk topic produce oidc-test \
  --brokers localhost:31094 \
  --tls-enabled \
  --tls-truststore certs/ca.crt \
  --sasl-mechanism OAUTHBEARER \
  --password "token:${OIDC_TOKEN}"

# Consume messages
rpk topic consume oidc-test --num 1 \
  --brokers localhost:31094 \
  --tls-enabled \
  --tls-truststore certs/ca.crt \
  --sasl-mechanism OAUTHBEARER \
  --password "token:${OIDC_TOKEN}"

# Describe a topic
rpk topic describe oidc-test \
  --brokers localhost:31094 \
  --tls-enabled \
  --tls-truststore certs/ca.crt \
  --sasl-mechanism OAUTHBEARER \
  --password "token:${OIDC_TOKEN}"

# Delete a topic
rpk topic delete oidc-test \
  --brokers localhost:31094 \
  --tls-enabled \
  --tls-truststore certs/ca.crt \
  --sasl-mechanism OAUTHBEARER \
  --password "token:${OIDC_TOKEN}"

Consumer group operations

# List consumer groups
rpk group list \
  --brokers localhost:31094 \
  --tls-enabled \
  --tls-truststore certs/ca.crt \
  --sasl-mechanism OAUTHBEARER \
  --password "token:${OIDC_TOKEN}"

# Describe a consumer group
rpk group describe my-group \
  --brokers localhost:31094 \
  --tls-enabled \
  --tls-truststore certs/ca.crt \
  --sasl-mechanism OAUTHBEARER \
  --password "token:${OIDC_TOKEN}"

Cluster operations

# Cluster info
rpk cluster info \
  --brokers localhost:31094 \
  --tls-enabled \
  --tls-truststore certs/ca.crt \
  --sasl-mechanism OAUTHBEARER \
  --password "token:${OIDC_TOKEN}"

# Cluster health
rpk cluster health \
  --brokers localhost:31094 \
  --tls-enabled \
  --tls-truststore certs/ca.crt \
  --sasl-mechanism OAUTHBEARER \
  --password "token:${OIDC_TOKEN}"

ACL operations

# List ACLs
rpk security acl list \
  --brokers localhost:31094 \
  --tls-enabled \
  --tls-truststore certs/ca.crt \
  --sasl-mechanism OAUTHBEARER \
  --password "token:${OIDC_TOKEN}"

# Create an ACL
rpk security acl create --allow-principal User:user@example.com \
  --operation all --topic oidc-test \
  --brokers localhost:31094 \
  --tls-enabled \
  --tls-truststore certs/ca.crt \
  --sasl-mechanism OAUTHBEARER \
  --password "token:${OIDC_TOKEN}"

Using a profile (avoids repeating flags)

rpk profile create oidc-profile \
  --set kafka_api.brokers=localhost:31094 \
  --set kafka_api.tls.ca_file=certs/ca.crt \
  --set kafka_api.sasl.mechanism=OAUTHBEARER \
  --set kafka_api.sasl.password="token:${OIDC_TOKEN}"

# Now commands use the profile automatically
rpk topic list
rpk topic create oidc-test
rpk cluster info

Test plan

Unit tests (all passing)

  • oauthBearerToken helper — token prefix stripping, raw tokens, empty inputs, case sensitivity
  • GetAuth with OAUTHBEARER — bearer token construction, case-insensitivity, empty token error, token:-only error
  • GetAuth regression — SCRAM-SHA-256 still returns BasicAuth, no-SASL still returns NopAuth
  • NewFranzClient error paths — OAUTHBEARER with empty token, token:-only prefix, unknown mechanism

E2E tested locally on Kind + Dex OIDC provider

Tested with a local rpk build against a Kind cluster running Redpanda with Dex as the OIDC provider
(setup).
Redpanda configured with oidc_discovery_url, oidc_token_audience, oidc_principal_mapping,
and an OIDC listener with sasl_mechanisms_overrides: [OAUTHBEARER] on NodePort 31094.

# Test Result
1 rpk topic list Listed topics (_schemas, mtls-test)
2 rpk topic create oidc-rpk-test Created OK
3 rpk topic produce oidc-rpk-test Produced to partition 0, offset 0
4 rpk topic consume oidc-rpk-test --num 1 Consumed message
5 rpk topic describe oidc-rpk-test Full topic config returned
6 rpk group list Listed groups
7 rpk cluster info Cluster ID, broker, topics returned
8 rpk topic delete oidc-rpk-test Deleted OK
9 Raw token (no token: prefix) Worked
10 No token provided Error: "OAUTHBEARER requires a token"
11 Empty token: prefix Error: "OAUTHBEARER requires a token"

🤖 Generated with Claude Code

Allow rpk to authenticate with Kafka brokers using the OAUTHBEARER SASL
mechanism. This enables OIDC-based authentication workflows where users
pass an OAuth token via --sasl-password (with optional "token:" prefix).

The token is used as an OAuth bearer token for Kafka connections, admin
API requests, and schema registry access.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@CLAassistant
Copy link
Copy Markdown

CLAassistant commented Apr 15, 2026

CLA assistant check
All committers have signed the CLA.

@CLAassistant
Copy link
Copy Markdown

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.
You have signed the CLA already but the status is still pending? Let us recheck it.

Test the oauthBearerToken helper (token: prefix stripping, raw tokens,
empty inputs) and GetAuth with OAUTHBEARER profiles (bearer token
construction, case-insensitivity, error paths).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
david-yu added a commit to david-yu/redpanda-operator-mtls-oidc-listeners that referenced this pull request Apr 15, 2026
Key finding: sasl_mechanisms_overrides works through the CRD bootstrap
config passthrough when using the correct Redpanda list-of-objects format:
  - listener: oidc
    sasl_mechanisms:
      - OAUTHBEARER

The previous map format ({oidc: [OAUTHBEARER]}) was the wrong format
for this Redpanda property. No chart/operator code change needed.

Updated:
- manifests/redpanda-cr.yaml: correct list-of-objects format, removed
  the "must set post-deploy via rpk" comment
- README: CRD listener config snippets, rpk OAUTHBEARER tracking PR
  (redpanda-data/redpanda#30169), corrected test results showing
  overrides work via CRD, removed workaround instructions
- scripts/oidc-test-pod.yaml: cleaned up test script

Validated end-to-end on Kind:
- sasl_mechanisms_overrides correctly applied via CRD bootstrap config
- OIDC token acquisition from Dex: PASS
- SASL/OAUTHBEARER authentication: PASS
- mTLS create/produce/consume: PASS
Comment thread src/go/rpk/pkg/config/profile_doc.go Outdated
david-yu and others added 4 commits April 15, 2026 10:07
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The sasl.mechanism help in both -X help and -X list was missing PLAIN
and OAUTHBEARER. Update to list all four supported mechanisms and
document the token: password prefix for OAUTHBEARER.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Test that NewFranzClient returns the correct errors for OAUTHBEARER
with empty token, token:-only prefix, and unknown SASL mechanisms.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants