lhotari opened a new pull request, #25618:
URL: https://github.com/apache/pulsar/pull/25618

   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
   
   - [x] 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
   - [x] 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.


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to