mattcasters opened a new issue, #8334:
URL: https://github.com/apache/hop/issues/8334
## Problem
Hop Web's `HopServerAuthorizationFilter` maps `/hop/*` paths through
`HopServerEndpointPermissionMapper` and **default-denies unknown endpoints**.
That table is a hard-coded list of built-in servlets in `hop-core`. Plugin
servlets discovered via `@HopServerServlet` / `HopServerPluginType` (the
documented extension point) are therefore **403 for every authenticated user**,
even after BASIC / OAUTH2 / EXTERNAL login.
The filter's own Javadoc calls this out:
> Unknown `/hop/*` paths (a servlet not in the built-in table, e.g. a
third-party plugin) are denied by default in the authenticated modes, so a
newly added servlet cannot silently widen the authenticated attack surface. It
becomes reachable once its path is added to the mapper.
Requiring a core patch for every plugin servlet makes the servlet plugin
system unusable on authenticated Hop Web. Community plugins cannot ship a
working `/hop/…` API without forking Hop.
Standalone Hop Server (Jetty Basic) is unaffected; this is Hop Web RBAC only.
## Proposal
Keep default-deny. Let plugins **opt in** with an explicit permission.
1. Add an optional element on `@HopServerServlet`:
```java
/**
* Hop Web RBAC permission id (e.g. {@code run.execute}, {@code file.view}).
* Empty (default) = unknown endpoint, still default-deny.
*/
String requiredPermission() default "";
```
2. Add an overlay on `HopServerEndpointPermissionMapper`:
```java
public static void register(String path, Permission permission);
public static void unregister(String path);
```
- Concurrent map, longest-prefix match as today.
- Refuse to overwrite or shadow a built-in path.
- `requiredPermission(method, path)` consults the built-in table first, then
the overlay.
3. `HopServerServlet.registerServlet()` (and `pluginRemoved`) reads the
annotation (or `IHopServerPlugin.getRequiredPermissionId()` if we add a default
method) and register/unregister using the servlet's `getContextPath()`.
Plugins that do nothing stay denied. Plugins that declare a permission
become reachable to roles that already hold it (`READ_ONLY` → `file.view`,
`OPERATOR`/`USER`/`ADMIN` → `run.execute`, etc.).
## Example (community plugin)
```java
@HopServerServlet(
id = "sourceModelData",
name = "Source model free SQL data",
requiredPermission = "run.execute")
public class SourceModelDataServlet extends BaseHttpServlet implements
IHopServerPlugin {
public String getContextPath() { return "/hop/sourceModelData"; }
}
```
## Out of scope
- Changing how BASIC / OAUTH2 authenticate (Bearer resource-server is a
separate issue).
- Per-HTTP-method permissions for path-style servlets (still path-only).
- Letting plugins invent new `Permission` enum values.
## Tests
- Register overlay path → `requiredPermission` returns that permission.
- Unregister → empty / deny again.
- Overlay cannot replace `/hop/startPipeline`.
- Filter integration: authenticated user without `run.execute` still 403;
user with it gets through to the plugin servlet.
--
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]