mattcasters commented on code in PR #8402:
URL: https://github.com/apache/hop/pull/8402#discussion_r4024060183


##########
THREAT_MODEL.md:
##########
@@ -254,6 +309,13 @@ where strict outbound TLS verification is required (see 
§9).
   pipeline execution = remote code execution.
 - Running Hop Server with `enable_auth=false` on an untrusted network →
   unauthenticated pipeline execution + metadata mutation over the JSON API.
+- Exposing **Hop Web in mode `NONE`** to an untrusted network → an open

Review Comment:
   **[suggestion]** The new §11 pattern says exposing Hop Web in mode `NONE` 
yields “an open authoring UI on `/ui`; and, if 
`HOP_WEB_ALLOW_UNAUTHENTICATED_SERVER_API` was enabled, unauthenticated 
pipeline execution over `/hop/*` as well.” That contrast implies execution is 
the flag’s problem. The GUI does not call `/hop/*` to run: 
`HopGuiPipelineGraph` uses `PipelineEngineFactory` / `LocalPipelineEngine` 
in-process. Mode `NONE` binds an unrestricted session 
(`RapSecurityContextProvider` → `HopSecurityContext.unrestricted()`), so anyone 
who can reach `/ui` can author **and** run pipelines even while `/hop/*` 
returns 403. §8 already says the session is unrestricted; §11’s “authoring UI” 
/ “execution over `/hop/*` as well” split understates the default-install 
exposure.
   
   **Suggestion:** Word the misuse pattern as: exposed `/ui` in `NONE` is an 
unrestricted GUI that can run pipelines in-process; the flag additionally opens 
the remote `/hop/*` (and `/hop/api/v1/*`) execution API.



##########
THREAT_MODEL.md:
##########
@@ -54,7 +56,8 @@ the `hop-run` CLI, or submitted to a **Hop Server** for 
local/remote execution.
 | Execution engine | `engine/`, `engine-beam/` | Runs pipelines/workflows the 
operator authored — incl. transforms that touch files, DBs, network, and 
**scripting/exec** steps. |
 | Hop Server (servlet / HTTP) | `engine/` — package `org.apache.hop.www` + 
`HopServerMeta` in `org.apache.hop.server`; launched by the `hop-server` 
command (`org.apache.hop.www.HopServer`). *(The `org.apache.hop.server` 
connection helpers `HttpUtil`/`ServerConnectionManager` — see §9 — live in 
`core/`.)* | The **network trust boundary**: an embedded Jetty server whose 
servlets accept pipeline/workflow run requests over HTTP (`/hop/execPipeline`, 
`/hop/addPipeline`+`/hop/startExec`, `/hop/registerPackage`, …). Who may 
submit/run, and with what auth, lives here (§7, §8). |
 | Hop JSON API | `engine/src/main/java/org/apache/hop/www/api/` | **Part of 
Hop Server**, not a separate deployable. Mounted on `/hop/api/v1/` 
([`WebServer.java`](engine/src/main/java/org/apache/hop/www/WebServer.java)) 
and exposes `execute/sync` (run a web service), `metadata` CRUD, `plugins` and 
`location` execution info. It sits inside the same `ConstraintSecurityHandler` 
as every servlet, so it inherits Hop Server's Basic/JAAS auth (§8). |
-| GUI (desktop / web) | `ui/` (`hop-ui`, SWT core), `rcp/` (desktop fragment), 
`rap/` (`hop-ui-rap`, RAP/RWT **web** GUI) | Authoring surface used by the 
trusted operator. `rap/` is the **web GUI**, not a server. |
+| GUI (desktop / web) | `ui/` (`hop-ui`, SWT core), `rcp/` (desktop fragment), 
`rap/` (`hop-ui-rap`, RAP/RWT **web** GUI) | Authoring surface used by the 
trusted operator. `rap/` is the **web GUI code**, not a server — but see the 
Hop Web row: the shipped web application deploys it together with Hop Server 
servlets. |
+| Hop Web (deployed web application) | `assemblies/web/` (WAR + 
`apache/hop-web` image), built from `rap/` + `engine/` | A **distinct 
network-facing deployment**, separate from both `rap/` and `hop-server`. The 
one WAR co-deploys the RAP UI on `/ui` and `/ui-dark`, `HopServerServlet` on 
`/hop/*`, and `HopApiApplication` on `/hop/api/v1/*` on the same origin 
([`web.xml`](assemblies/web/src/main/resources/WEB-INF/web.xml)). It does 
**not** use Hop Server's `enable_auth` / `hop.pwd` Basic auth; it has its own 
auth modes (§8). Docker image binds `0.0.0.0:8080`. |

Review Comment:
   **[suggestion]** The new Hop Web row correctly calls the WAR a distinct 
network-facing deployment (RAP on `/ui`, `HopServerServlet` on `/hop/*`, 
`HopApiApplication` on `/hop/api/v1/*`, own auth modes). The sentences 
immediately after the table still say in-scope is “engine + Hop Server + 
plugins + connection layer + GUI glue” and “The **network-facing Hop Server** 
is where an untrusted actor can appear.” §7 still scopes the in-model adversary 
to “a remote actor against an exposed Hop Server.” §12 still omits Hop Web 
auth/deployables even though the header revision triggers were updated. The 
JSON API family row still says that API “inherits Hop Server's Basic/JAAS 
auth,” which is true for standalone `hop-server` but not for the co-deployed 
`/hop/api/v1/*` this row now documents. A triager can treat an exposed Hop Web 
`/ui` as out of model even though §8/§11 now describe it.
   
   **Suggestion:** Extend the in-scope / untrusted-actor sentences, §7, and §12 
to name Hop Web as a second HTTP trust boundary. Qualify the JSON API row: 
standalone `hop-server` uses `ConstraintSecurityHandler`; Hop Web uses 
`HopBasicAuthFilter` / `HopOidcAuthFilter` / `HopServerAuthorizationFilter`.



##########
rap/src/main/java/org/apache/hop/ui/hopgui/HopWebEntryPoint.java:
##########
@@ -159,8 +160,23 @@ protected void createContents(Composite parent) {
           "Hop Web security: user ''{0}'' roles={1}",
           securityContext.getUsername(), securityContext.getRoleIds());
     } else {
-      LogChannel.UI.logDebug(
-          "Hop Web security: no authenticated principal (mode NONE or 
unrestricted)");
+      HopSecurityConfig.AuthMode mode = resolveAuthMode();
+      if (mode == HopSecurityConfig.AuthMode.NONE) {
+        LogChannel.UI.logDebug("Hop Web security: no authenticated principal 
(mode NONE)");
+      } else {
+        // Authentication is configured but the request carries no principal. 
In EXTERNAL mode

Review Comment:
   **[nit]** The six-line comment restates the log message and embeds EXTERNAL 
/ `web.xml` / Security-tab design rationale. The log text already explains what 
to do.
   
   **Suggestion:** Drop the block comment (or keep one line: principal-less 
non-`NONE` session is unexpected; log at error so EXTERNAL-without-constraint 
is visible).



##########
docs/hop-user-manual/modules/ROOT/pages/hop-gui/hop-web.adoc:
##########
@@ -249,6 +262,12 @@ To keep audit data across container restarts, mount a 
volume and set the same pa
 
 The default Hop Web docker image picks up `tomcat-users.xml` and `web.xml` 
files and moves them to the correct location before Hop Web starts.
 
+IMPORTANT: Mode `EXTERNAL` is *delegation, not enforcement*.
+Hop itself does not challenge anyone in this mode: it only reads the 
`Principal` the servlet container (or authenticating reverse proxy) put on the 
request.
+The `web.xml` that ships with Hop Web contains no `<security-constraint>`, so 
selecting `EXTERNAL` without supplying your own constraint over `/*` leaves 
`/ui` **completely open** while the Security tab reports authentication as 
enabled.

Review Comment:
   **[suggestion]** Both the user manual and the threat model say that 
`EXTERNAL` without a constraint leaves `/ui` open “while the Security tab 
reports authentication as enabled.” The mode combo is `EXTERNAL`, but the 
status line for a principal-less session is 
`ConfigSecurityTab.Status.Unrestricted`: “Session is unrestricted (no AuthN). 
Config mode: {0}.” Issue #8391 described this more accurately as the tab 
*showing the contradiction*. The current wording overstates what the UI claims.
   
   **Suggestion:** Say the General tab can be set to `EXTERNAL` (an 
authenticated mode) while the status line still reads unrestricted / no AuthN — 
that is the operator-visible contradiction, not a green “authentication 
enabled” indicator.



-- 
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