Skip to content

[improve][broker] Add authn/authz to Scalable Topics Admin API (PIP-460)#25618

Merged
merlimat merged 2 commits into
apache:masterfrom
lhotari:lh-improve-scalable-topics-authz
Apr 29, 2026
Merged

[improve][broker] Add authn/authz to Scalable Topics Admin API (PIP-460)#25618
merlimat merged 2 commits into
apache:masterfrom
lhotari:lh-improve-scalable-topics-authz

Conversation

@lhotari
Copy link
Copy Markdown
Member

@lhotari lhotari commented Apr 29, 2026

Closes #25598

PIP: 460

Follow-up to #25565, which introduced the Scalable Topics (Topics v5) Admin API without enforcing authentication or authorization on its REST endpoints.

Motivation

The initial Scalable Topics Admin API merged in #25565 only called validateNamespaceName(...) (a name-format parser) on its REST endpoints. None of the 9 endpoints under /admin/v2/scalable/... performed any authn/authz check, and the 3 endpoints under /admin/v2/segments/... only did validateTopicOwnershipAsync(...) (a routing/ownership check, not an authorization check). The OpenAPI annotations on the ScalableTopics endpoints already advertise 401 / 403 responses, so the public contract was written but not enforced.

PIP-460 §Security Considerations states: "The new admin API endpoints for segment operations (split, merge, metadata read) will require the same permissions as equivalent topic-level admin operations." This PR wires that up, mirroring the patterns used elsewhere in the Admin API (PersistentTopics / PersistentTopicsBase).

Modifications

pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/ScalableTopics.java — added an authz call as the first step of the async chain on each of the 9 endpoints. Operation mapping follows the conventions used by the partitioned-topic admin API:

Endpoint Authorization
GET /{tenant}/{ns} (list) validateNamespaceOperationAsync(GET_TOPICS)
PUT /{tenant}/{ns}/{topic} (create) validateNamespaceOperationAsync(CREATE_TOPIC)
GET /{tenant}/{ns}/{topic} (metadata) validateTopicOperationAsync(GET_METADATA)
DELETE /{tenant}/{ns}/{topic} (delete) validateNamespaceOperationAsync(DELETE_TOPIC)
GET .../stats validateTopicOperationAsync(GET_STATS)
PUT .../subscriptions/{sub} validateTopicOperationAsync(SUBSCRIBE, subscription)
DELETE .../subscriptions/{sub} validateTopicOperationAsync(UNSUBSCRIBE, subscription)
POST .../split/{segmentId} validateSuperUserAccessAsync()
POST .../merge/{id1}/{id2} validateSuperUserAccessAsync()

splitSegment and mergeSegments are super-user only for now. Auto-split / auto-merge and any tenant-admin-initiated workflows can revisit this without breaking compatibility (relaxing access is non-breaking; tightening is breaking).

pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/Segments.java — all three endpoints (createSegment, terminateSegment, deleteSegment) now call validateSuperUserAccessAsync() before the existing validateTopicOwnershipAsync(...) routing check. These endpoints are cross-broker coordination primitives invoked by the controller broker during split/merge — not user-facing. The controller broker uses its broker-internal credentials, which are super-user, so internal coordination continues to work; tenant admins (and other principals) cannot bypass the super-user requirement on splitSegment/mergeSegments by calling the segment-level endpoints directly. Class-level Javadoc documents this security boundary, and 401/403 are added to @ApiResponses on each endpoint.

pulsar-broker/src/test/java/org/apache/pulsar/broker/admin/ScalableTopicsAuthZTest.java — new TestNG class modeled after TopicAuthZTest. 12 tests cover all 12 endpoints (9 in ScalableTopics, 3 in Segments) against three roles: anonymous (NOBODY_TOKEN), tenant admin, and super-user. The test asserts the authz contract only — non-NotAuthorized failures from the underlying service are tolerated, since the happy paths are already covered by ScalableTopicServiceTest / ScalableTopicControllerTest.

When authentication or authorization is disabled, the existing validateXxxAsync helpers complete immediately with null, so behavior is unchanged for clusters that do not enable auth.

Verifying this change

  • Make sure that the change passes the CI checks.

This change added tests and can be verified as follows:

  • New ScalableTopicsAuthZTest (12 tests): all pass. Covers nobody / tenant-admin / super-user roles against all 12 endpoints.
  • Existing scalable-topic suite — ConsumerSessionTest, DagWatchSessionTest, ScalableTopicControllerTest, ScalableTopicServiceTest, SegmentLayoutTest, SubscriptionCoordinatorTest — 92/92 pass, no regressions.
  • ./gradlew :pulsar-broker:checkstyleMain :pulsar-broker:checkstyleTest clean.

Does this pull request potentially affect one of the following parts:

  • Dependencies (add or upgrade a dependency)
  • The public API
  • The schema
  • The default values of configurations
  • The threading model
  • The binary protocol
  • The REST endpoints
  • The admin CLI options
  • The metrics
  • Anything that affects deployment

The REST endpoints under /admin/v2/scalable/* and /admin/v2/segments/* now enforce authentication/authorization. Clusters that previously relied on these endpoints being unauthenticated will see 401/403 for non-super-user (and, for the segment-level endpoints, non-super-user-only) callers when authentication and authorization are enabled. This brings the endpoints in line with the rest of the Admin API and matches the contract already advertised by the existing @ApiResponses annotations.

The initial Scalable Topics Admin API (apache#25565) did not enforce
authentication or authorization on its REST endpoints — they only
parsed the namespace name. This wires up the same authz model used by
the rest of the Admin API.

ScalableTopics (/admin/v2/scalable):
- list/create/delete: validateNamespaceOperationAsync
  (GET_TOPICS / CREATE_TOPIC / DELETE_TOPIC)
- getMetadata/getStats: validateTopicOperationAsync
  (GET_METADATA / GET_STATS)
- create/deleteSubscription: validateTopicOperationAsync
  (SUBSCRIBE / UNSUBSCRIBE) with the subscription name
- splitSegment/mergeSegments: validateSuperUserAccessAsync
  (super-user only; reserved for operator-driven scaling, can be relaxed
  later if auto-split workflows need it)

Segments (/admin/v2/segments):
- All three endpoints (createSegment, terminateSegment, deleteSegment)
  now require validateSuperUserAccessAsync before the existing
  validateTopicOwnershipAsync routing. These endpoints are cross-broker
  coordination primitives invoked by the controller broker (which runs
  with super-user broker credentials) — they are not user-facing.
- Class-level Javadoc documents the super-user-only design boundary.
- Added 401/403 to @ApiResponses on each endpoint.

Adds ScalableTopicsAuthZTest covering nobody / tenant-admin / super-user
roles against all 12 endpoints (12 tests, all passing).
Comment thread pulsar-broker/src/main/java/org/apache/pulsar/broker/admin/v2/ScalableTopics.java Outdated
…n in helpers

Address review feedback on apache#25618: extract two private helpers in
ScalableTopics so the duplicated service-availability check and
controller-leader redirect are no longer repeated inline at each call site.

- withScalableTopicService(op): runs op against the local
  ScalableTopicService, surfacing 503 if the service is not available on
  this broker. Used by getStats (read-only, no redirect).
- onControllerLeader(tn, op): combines withScalableTopicService with
  redirectToControllerLeaderIfNeeded so endpoints requiring the elected
  controller leader (createSubscription, deleteSubscription,
  splitSegment, mergeSegments) express the operation as a single chained
  step.

No behavior change. Existing ScalableTopicsAuthZTest (12) and the
scalable suites (ConsumerSession, DagWatchSession, ScalableTopicController,
ScalableTopicService, SegmentLayout, SubscriptionCoordinator — 92 total)
still pass.
@merlimat merlimat merged commit d200fd5 into apache:master Apr 29, 2026
43 checks passed
poorbarcode pushed a commit to poorbarcode/pulsar that referenced this pull request May 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Admin API Authorization

2 participants