Add Row-Level Security (RLS) Support for ZooKeeper-Based Authentication
Summary
Currently, Row-Level Security (RLS) filters are not supported when using ZooKeeper-based authentication (ZkBasicAuthAccessControlFactory). While the RLS infrastructure exists and works with file-based authentication, the ZK authentication implementation passes an empty RLS filters.
This PR adds full RLS support to ZK-based authentication by:
- Extending
UserConfigto store RLS filters per table - Updating
BasicAuthUtilsto extract and pass RLS filters toZkBasicAuthPrincipal - Updating the REST API documentation with RLS filter examples
Background
Related commits that introduced initial RLS work:
- Adding changes for supporting RLS (#16043)
- Introduce rlsFiltersApplied in the broker response (#16208)
Problem
When creating users via the ZK-based authentication REST API, there was no way to specify RLS filters. The BasicAuthUtils.extractBasicAuthPrincipals(List<UserConfig>) method was hardcoded to pass Map.of() (empty map) for RLS filters, resulting in:
- RLS filters being ignored for all ZK-authenticated users
Proposed Solution
Goal is to implement RLS support by:
-
UserConfig Changes (
pinot-spi/src/main/java/org/apache/pinot/spi/config/user/UserConfig.java)- Added
rlsFiltersfield of typeMap<String, List<String>> - Added JSON property key
RLS_FILTERS_KEY - Added getter method and validation
- Added
-
BasicAuthUtils Changes (
pinot-core/src/main/java/org/apache/pinot/core/auth/BasicAuthUtils.java)- Modified
extractBasicAuthPrincipals(List<UserConfig>)to extract RLS filters from UserConfig - Replaced empty
Map.of()with actual RLS filter extraction - RLS filters now properly passed to
ZkBasicAuthPrincipalconstructor
- Modified
-
API Documentation (
pinot-controller/src/main/java/org/apache/pinot/controller/api/resources/PinotAccessControlUserRestletResource.java)- Updated REST API documentation with RLS filter format examples
API Usage Example
POST /users
{
"username": "userRLS",
"password": "secret",
"component": "BROKER",
"role": "USER",
"tables": ["table1", "table2"],
"permissions": ["READ"],
"rlsFilters": {
"table1": ["column1='value1'"],
"table2": ["column2='value2' AND column3='value3'"]
}
}
I am working on fixing this!